You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Aspects.java 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*******************************************************************************
  2. * Copyright (c) 2005 Contributors.
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * initial implementation Alexandre Vasseur
  11. * generic signature update Adrian Colyer
  12. *******************************************************************************/
  13. package org.aspectj.lang;
  14. import java.lang.reflect.Method;
  15. import java.lang.reflect.Modifier;
  16. import java.lang.reflect.InvocationTargetException;
  17. /**
  18. * Handles generic aspectOf method when those are not available in the aspects but added later on
  19. * thru load time weaving.
  20. * <p/>
  21. * Aspects.aspectOf(..) is doing reflective calls to the aspect aspectOf, so for better performance
  22. * consider using ajc compilation of the aspects and using them as a binary dependancies in your project.
  23. *
  24. * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
  25. */
  26. public class Aspects {
  27. private final static Class[] EMPTY_CLASS_ARRAY = new Class[0];
  28. private final static Class[] PEROBJECT_CLASS_ARRAY = new Class[]{Object.class};
  29. private final static Class[] PERTYPEWITHIN_CLASS_ARRAY = new Class[]{Class.class};
  30. private final static Object[] EMPTY_OBJECT_ARRAY = new Object[0];
  31. private final static String ASPECTOF = "aspectOf";
  32. private final static String HASASPECT = "hasAspect";
  33. /**
  34. * Returns the singleton aspect or the percflow / percflowbelow associated with the current thread
  35. *
  36. * @param aspectClass
  37. * @return
  38. * @throws NoAspectBoundException if no such aspect
  39. */
  40. public static <T> T aspectOf(Class<T> aspectClass) throws NoAspectBoundException {
  41. try {
  42. return (T) getSingletonOrThreadAspectOf(aspectClass).invoke(null, EMPTY_OBJECT_ARRAY);
  43. } catch (InvocationTargetException e) {
  44. //FIXME asc Highly temporary change to see what the build makes of it - dont use 1.4 APIs
  45. throw new NoAspectBoundException(aspectClass.getName(), e);//e.getCause());
  46. } catch (Exception e) {
  47. throw new NoAspectBoundException(aspectClass.getName(), e);
  48. }
  49. }
  50. /**
  51. * Returns the perthis / pertarget aspect
  52. * @param aspectClass
  53. * @param perObject
  54. * @return
  55. * @throws NoAspectBoundException if no such aspect, or no aspect bound
  56. */
  57. public static <T> T aspectOf(Class<T> aspectClass, Object perObject) throws NoAspectBoundException {
  58. try {
  59. return (T) getPerObjectAspectOf(aspectClass).invoke(null, new Object[]{perObject});
  60. } catch (InvocationTargetException e) {
  61. //FIXME asc Highly temporary change to see what the build makes of it - dont use 1.4 APIs
  62. throw new NoAspectBoundException(aspectClass.getName(), e);//e.getCause());
  63. } catch (Exception e) {
  64. throw new NoAspectBoundException(aspectClass.getName(), e);
  65. }
  66. }
  67. /**
  68. * Returns the pertypewithin aspect
  69. * @param aspectClass
  70. * @param perTypeWithin class
  71. * @return
  72. * @throws NoAspectBoundException if no such aspect, or no aspect bound
  73. */
  74. public static <T> T aspectOf(Class<T> aspectClass, Class<?> perTypeWithin) throws NoAspectBoundException {
  75. try {
  76. return (T) getPerTypeWithinAspectOf(aspectClass).invoke(null, new Object[]{perTypeWithin});
  77. } catch (InvocationTargetException e) {
  78. // FIXME asc Highly temporary change to see what the build makes of it - dont use 1.4 APIs
  79. throw new NoAspectBoundException(aspectClass.getName(), e);//e.getCause());
  80. } catch (Exception e) {
  81. throw new NoAspectBoundException(aspectClass.getName(), e);
  82. }
  83. }
  84. /**
  85. * Returns true if singleton aspect or percflow / percflowbelow aspect is bound
  86. *
  87. * @param aspectClass
  88. * @return
  89. * @throws NoAspectBoundException if not bound
  90. */
  91. public static boolean hasAspect(Class<?> aspectClass) throws NoAspectBoundException {
  92. try {
  93. return ((Boolean)getSingletonOrThreadHasAspect(aspectClass).invoke(null, EMPTY_OBJECT_ARRAY)).booleanValue();
  94. } catch (Exception e) {
  95. return false;
  96. }
  97. }
  98. /**
  99. * Returns true if the perthis / pertarget aspect is bound
  100. * @param aspectClass
  101. * @param perObject
  102. * @return
  103. * @throws NoAspectBoundException if not bound
  104. */
  105. public static boolean hasAspect(Class<?> aspectClass, Object perObject) throws NoAspectBoundException {
  106. try {
  107. return ((Boolean)getPerObjectHasAspect(aspectClass).invoke(null, new Object[]{perObject})).booleanValue();
  108. } catch (Exception e) {
  109. return false;
  110. }
  111. }
  112. /**
  113. * Returns true if the pertypewithin aspect is bound
  114. * @param aspectClass
  115. * @param perTypeWithin class
  116. * @return
  117. * @throws NoAspectBoundException if not bound
  118. */
  119. public static boolean hasAspect(Class<?> aspectClass, Class<?> perTypeWithin) throws NoAspectBoundException {
  120. try {
  121. return ((Boolean)getPerTypeWithinHasAspect(aspectClass).invoke(null, new Object[]{perTypeWithin})).booleanValue();
  122. } catch (Exception e) {
  123. return false;
  124. }
  125. }
  126. // -- aspectOf
  127. private static Method getSingletonOrThreadAspectOf(Class<?> aspectClass) throws NoSuchMethodException {
  128. Method method = aspectClass.getDeclaredMethod(ASPECTOF, EMPTY_CLASS_ARRAY);
  129. return checkAspectOf(method, aspectClass);
  130. }
  131. private static Method getPerObjectAspectOf(Class<?> aspectClass) throws NoSuchMethodException {
  132. Method method = aspectClass.getDeclaredMethod(ASPECTOF, PEROBJECT_CLASS_ARRAY);
  133. return checkAspectOf(method, aspectClass);
  134. }
  135. private static Method getPerTypeWithinAspectOf(Class<?> aspectClass) throws NoSuchMethodException {
  136. Method method = aspectClass.getDeclaredMethod(ASPECTOF, PERTYPEWITHIN_CLASS_ARRAY);
  137. return checkAspectOf(method, aspectClass);
  138. }
  139. private static Method checkAspectOf(Method method, Class<?> aspectClass) throws NoSuchMethodException {
  140. method.setAccessible(true);
  141. if (!method.isAccessible()
  142. || !Modifier.isPublic(method.getModifiers())
  143. || !Modifier.isStatic(method.getModifiers())) {
  144. throw new NoSuchMethodException(aspectClass.getName() + ".aspectOf(..) is not accessible public static");
  145. }
  146. return method;
  147. }
  148. // -- hasAspect
  149. private static Method getSingletonOrThreadHasAspect(Class aspectClass) throws NoSuchMethodException {
  150. Method method = aspectClass.getDeclaredMethod(HASASPECT, EMPTY_CLASS_ARRAY);
  151. return checkHasAspect(method, aspectClass);
  152. }
  153. private static Method getPerObjectHasAspect(Class aspectClass) throws NoSuchMethodException {
  154. Method method = aspectClass.getDeclaredMethod(HASASPECT, PEROBJECT_CLASS_ARRAY);
  155. return checkHasAspect(method, aspectClass);
  156. }
  157. private static Method getPerTypeWithinHasAspect(Class aspectClass) throws NoSuchMethodException {
  158. Method method = aspectClass.getDeclaredMethod(HASASPECT, PERTYPEWITHIN_CLASS_ARRAY);
  159. return checkHasAspect(method, aspectClass);
  160. }
  161. private static Method checkHasAspect(Method method, Class aspectClass) throws NoSuchMethodException {
  162. method.setAccessible(true);
  163. if (!method.isAccessible()
  164. || !Modifier.isPublic(method.getModifiers())
  165. || !Modifier.isStatic(method.getModifiers())) {
  166. throw new NoSuchMethodException(aspectClass.getName() + ".hasAspect(..) is not accessible public static");
  167. }
  168. return method;
  169. }
  170. }