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.

ReflectionWorld.java 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /* *******************************************************************
  2. * Copyright (c) 2005-2017 Contributors.
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. * ******************************************************************/
  9. package org.aspectj.weaver.reflect;
  10. import java.lang.reflect.InvocationTargetException;
  11. import java.util.Collections;
  12. import java.util.HashMap;
  13. import java.util.Map;
  14. import org.aspectj.bridge.AbortException;
  15. import org.aspectj.bridge.IMessage;
  16. import org.aspectj.bridge.IMessageHandler;
  17. import org.aspectj.weaver.BCException;
  18. import org.aspectj.weaver.IWeavingSupport;
  19. import org.aspectj.weaver.ReferenceType;
  20. import org.aspectj.weaver.ReferenceTypeDelegate;
  21. import org.aspectj.weaver.ResolvedType;
  22. import org.aspectj.weaver.UnresolvedType;
  23. import org.aspectj.weaver.WeakClassLoaderReference;
  24. import org.aspectj.weaver.World;
  25. /**
  26. * A ReflectionWorld is used solely for purposes of type resolution based on the runtime classpath (java.lang.reflect). It does not
  27. * support weaving operations (creation of mungers etc..).
  28. *
  29. * @author Adrian Colyer
  30. * @author Andy Clement
  31. */
  32. public class ReflectionWorld extends World implements IReflectionWorld {
  33. private static Map<WeakClassLoaderReference, ReflectionWorld> rworlds = Collections.synchronizedMap(new HashMap<>());
  34. private WeakClassLoaderReference classLoaderReference;
  35. private AnnotationFinder annotationFinder;
  36. private boolean mustUseOneFourDelegates = false; // for testing
  37. private Map<String,Class<?>> inProgressResolutionClasses = new HashMap<>();
  38. public static ReflectionWorld getReflectionWorldFor(WeakClassLoaderReference classLoaderReference) {
  39. // Temporarily do as before. Although the cache makes things faster it needs a bit more thought because
  40. // if the world has pointcutdesignators registered then someone may inadvertently register additional
  41. // ones on reusing a world (when they would be expecting a clean world). We can't automatically
  42. // clear them because we don't know when they are finished with.
  43. return new ReflectionWorld(classLoaderReference);
  44. /*
  45. synchronized (rworlds) {
  46. // Tidyup any no longer relevant entries...
  47. for (Iterator<Map.Entry<WeakClassLoaderReference, ReflectionWorld>> it = rworlds.entrySet().iterator();
  48. it.hasNext();) {
  49. Map.Entry<WeakClassLoaderReference, ReflectionWorld> entry = it.next();
  50. if (entry.getKey().getClassLoader() == null) {
  51. it.remove();
  52. }
  53. }
  54. ReflectionWorld rworld = null;
  55. if (classLoaderReference.getClassLoader() != null) {
  56. rworld = rworlds.get(classLoaderReference);
  57. if (rworld == null) {
  58. rworld = new ReflectionWorld(classLoaderReference);
  59. rworlds.put(classLoaderReference, rworld);
  60. }
  61. }
  62. return rworld;
  63. }
  64. */
  65. }
  66. public static void cleanUpWorlds() {
  67. synchronized (rworlds) {
  68. rworlds.clear();
  69. }
  70. }
  71. private ReflectionWorld() {
  72. // super();
  73. // this.setMessageHandler(new ExceptionBasedMessageHandler());
  74. // setBehaveInJava5Way(LangUtil.isVMGreaterOrEqual(15));
  75. // this.classLoaderReference = new
  76. // WeakClassLoaderReference(ReflectionWorld.class.getClassLoader());
  77. // this.annotationFinder =
  78. // makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(),
  79. // this);
  80. }
  81. public ReflectionWorld(WeakClassLoaderReference classloaderRef) {
  82. this.setMessageHandler(new ExceptionBasedMessageHandler());
  83. setBehaveInJava5Way(true);
  84. classLoaderReference = classloaderRef;
  85. annotationFinder = makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(), this);
  86. }
  87. public ReflectionWorld(ClassLoader aClassLoader) {
  88. super();
  89. this.setMessageHandler(new ExceptionBasedMessageHandler());
  90. setBehaveInJava5Way(true);
  91. classLoaderReference = new WeakClassLoaderReference(aClassLoader);
  92. annotationFinder = makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(), this);
  93. }
  94. public ReflectionWorld(boolean forceUseOf14Delegates, ClassLoader aClassLoader) {
  95. this(aClassLoader);
  96. this.mustUseOneFourDelegates = forceUseOf14Delegates;
  97. if (forceUseOf14Delegates) {
  98. // Dont use 1.4 delegates and yet allow autoboxing
  99. this.setBehaveInJava5Way(false);
  100. }
  101. }
  102. public static AnnotationFinder makeAnnotationFinderIfAny(ClassLoader loader, World world) {
  103. AnnotationFinder annotationFinder = null;
  104. try {
  105. Class<?> java15AnnotationFinder = Class.forName("org.aspectj.weaver.reflect.Java15AnnotationFinder");
  106. annotationFinder = (AnnotationFinder) java15AnnotationFinder.getDeclaredConstructor().newInstance();
  107. annotationFinder.setClassLoader(loader);
  108. annotationFinder.setWorld(world);
  109. } catch (ClassNotFoundException ex) {
  110. // must be on 1.4 or earlier
  111. } catch (IllegalAccessException | InstantiationException | NoSuchMethodException ex) {
  112. // not so good
  113. throw new BCException("AspectJ internal error", ex);
  114. }
  115. catch (InvocationTargetException e) {
  116. e.printStackTrace();
  117. }
  118. return annotationFinder;
  119. }
  120. public ClassLoader getClassLoader() {
  121. return classLoaderReference.getClassLoader();
  122. }
  123. public AnnotationFinder getAnnotationFinder() {
  124. return annotationFinder;
  125. }
  126. public ResolvedType resolve(Class aClass) {
  127. return resolve(this, aClass);
  128. }
  129. public static ResolvedType resolve(World world, Class<?> aClass) {
  130. // classes that represent arrays return a class name that is the
  131. // signature of the array type, ho-hum...
  132. String className = aClass.getName();
  133. if (aClass.isArray()) {
  134. return world.resolve(UnresolvedType.forSignature(className.replace('.', '/')));
  135. } else {
  136. return world.resolve(className);
  137. }
  138. }
  139. /**
  140. * Resolve a type using the specified class. Normal resolution in a reflection
  141. * world uses Class.forName() via the classloader (attached to this world)
  142. * in order to find a named type then builds a reference type and a reference
  143. * type delegate based on that. For some classes generated at runtime (e.g.
  144. * proxy or lambda representation) the forName() call will not work. In those
  145. * situations we should just use the clazz we have.
  146. *
  147. * Should the whole thing switch from using forName() to using the clazz objects?
  148. * Possibly but that introduces a lot of change and we don't have a lot
  149. * of test coverage for this scenario (reflection world). What we are doing
  150. * right now is that this can optionally be used if the regular resolution
  151. * scheme did not work.
  152. *
  153. * Although AspectJ is *not* multi threaded or re-entrant, Spring doesn't
  154. * always respect that. There might be an issue here if two attempts are
  155. * made to resolve the same thing at the same time via this method.
  156. *
  157. * @param clazz the class to use as the delegate for the resolved type
  158. */
  159. public ResolvedType resolveUsingClass(Class<?> clazz) {
  160. String signature = UnresolvedType.forName(clazz.getName()).getSignature();
  161. try {
  162. inProgressResolutionClasses.put(signature, clazz);
  163. return resolve(clazz.getName());
  164. } finally {
  165. inProgressResolutionClasses.remove(signature);
  166. }
  167. }
  168. protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
  169. ReferenceTypeDelegate result;
  170. if (mustUseOneFourDelegates) {
  171. result = ReflectionBasedReferenceTypeDelegateFactory.create14Delegate(ty, this, classLoaderReference.getClassLoader());
  172. } else {
  173. result = ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty, this, classLoaderReference.getClassLoader());
  174. }
  175. if (result == null && inProgressResolutionClasses.size() != 0) {
  176. // Is it a class that cannot be loaded (i.e. it was generated) but we already know about?
  177. Class<?> clazz = inProgressResolutionClasses.get(ty.getSignature());
  178. if (clazz != null) {
  179. result = ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty,this,clazz);
  180. }
  181. }
  182. return result;
  183. }
  184. public static class ReflectionWorldException extends RuntimeException {
  185. private static final long serialVersionUID = -3432261918302793005L;
  186. public ReflectionWorldException(String message) {
  187. super(message);
  188. }
  189. }
  190. private static class ExceptionBasedMessageHandler implements IMessageHandler {
  191. public boolean handleMessage(IMessage message) throws AbortException {
  192. throw new ReflectionWorldException(message.toString());
  193. }
  194. public boolean isIgnoring(org.aspectj.bridge.IMessage.Kind kind) {
  195. if (kind == IMessage.INFO) {
  196. return true;
  197. } else {
  198. return false;
  199. }
  200. }
  201. public void dontIgnore(org.aspectj.bridge.IMessage.Kind kind) {
  202. // empty
  203. }
  204. public void ignore(org.aspectj.bridge.IMessage.Kind kind) {
  205. // empty
  206. }
  207. }
  208. public IWeavingSupport getWeavingSupport() {
  209. return null;
  210. }
  211. public boolean isLoadtimeWeaving() {
  212. return true;
  213. }
  214. }