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 v1.0
  6. * which accompanies this distribution and is available at
  7. * http://eclipse.org/legal/epl-v10.html
  8. * ******************************************************************/
  9. package org.aspectj.weaver.reflect;
  10. import java.util.Collections;
  11. import java.util.HashMap;
  12. import java.util.Iterator;
  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.util.LangUtil;
  18. import org.aspectj.weaver.BCException;
  19. import org.aspectj.weaver.IWeavingSupport;
  20. import org.aspectj.weaver.ReferenceType;
  21. import org.aspectj.weaver.ReferenceTypeDelegate;
  22. import org.aspectj.weaver.ResolvedType;
  23. import org.aspectj.weaver.UnresolvedType;
  24. import org.aspectj.weaver.WeakClassLoaderReference;
  25. import org.aspectj.weaver.World;
  26. /**
  27. * A ReflectionWorld is used solely for purposes of type resolution based on the runtime classpath (java.lang.reflect). It does not
  28. * support weaving operations (creation of mungers etc..).
  29. *
  30. * @author Adrian Colyer
  31. * @author Andy Clement
  32. */
  33. public class ReflectionWorld extends World implements IReflectionWorld {
  34. private static Map<WeakClassLoaderReference, ReflectionWorld> rworlds = Collections.synchronizedMap(new HashMap<>());
  35. private WeakClassLoaderReference classLoaderReference;
  36. private AnnotationFinder annotationFinder;
  37. private boolean mustUseOneFourDelegates = false; // for testing
  38. private Map<String,Class<?>> inProgressResolutionClasses = new HashMap<>();
  39. public static ReflectionWorld getReflectionWorldFor(WeakClassLoaderReference classLoaderReference) {
  40. // Temporarily do as before. Although the cache makes things faster it needs a bit more thought because
  41. // if the world has pointcutdesignators registered then someone may inadvertently register additional
  42. // ones on reusing a world (when they would be expecting a clean world). We can't automatically
  43. // clear them because we don't know when they are finished with.
  44. return new ReflectionWorld(classLoaderReference);
  45. /*
  46. synchronized (rworlds) {
  47. // Tidyup any no longer relevant entries...
  48. for (Iterator<Map.Entry<WeakClassLoaderReference, ReflectionWorld>> it = rworlds.entrySet().iterator();
  49. it.hasNext();) {
  50. Map.Entry<WeakClassLoaderReference, ReflectionWorld> entry = it.next();
  51. if (entry.getKey().getClassLoader() == null) {
  52. it.remove();
  53. }
  54. }
  55. ReflectionWorld rworld = null;
  56. if (classLoaderReference.getClassLoader() != null) {
  57. rworld = rworlds.get(classLoaderReference);
  58. if (rworld == null) {
  59. rworld = new ReflectionWorld(classLoaderReference);
  60. rworlds.put(classLoaderReference, rworld);
  61. }
  62. }
  63. return rworld;
  64. }
  65. */
  66. }
  67. public static void cleanUpWorlds() {
  68. synchronized (rworlds) {
  69. rworlds.clear();
  70. }
  71. }
  72. private ReflectionWorld() {
  73. // super();
  74. // this.setMessageHandler(new ExceptionBasedMessageHandler());
  75. // setBehaveInJava5Way(LangUtil.is15VMOrGreater());
  76. // this.classLoaderReference = new
  77. // WeakClassLoaderReference(ReflectionWorld.class.getClassLoader());
  78. // this.annotationFinder =
  79. // makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(),
  80. // this);
  81. }
  82. public ReflectionWorld(WeakClassLoaderReference classloaderRef) {
  83. this.setMessageHandler(new ExceptionBasedMessageHandler());
  84. setBehaveInJava5Way(true);
  85. classLoaderReference = classloaderRef;
  86. annotationFinder = makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(), this);
  87. }
  88. public ReflectionWorld(ClassLoader aClassLoader) {
  89. super();
  90. this.setMessageHandler(new ExceptionBasedMessageHandler());
  91. setBehaveInJava5Way(true);
  92. classLoaderReference = new WeakClassLoaderReference(aClassLoader);
  93. annotationFinder = makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(), this);
  94. }
  95. public ReflectionWorld(boolean forceUseOf14Delegates, ClassLoader aClassLoader) {
  96. this(aClassLoader);
  97. this.mustUseOneFourDelegates = forceUseOf14Delegates;
  98. if (forceUseOf14Delegates) {
  99. // Dont use 1.4 delegates and yet allow autoboxing
  100. this.setBehaveInJava5Way(false);
  101. }
  102. }
  103. public static AnnotationFinder makeAnnotationFinderIfAny(ClassLoader loader, World world) {
  104. AnnotationFinder annotationFinder = null;
  105. try {
  106. Class<?> java15AnnotationFinder = Class.forName("org.aspectj.weaver.reflect.Java15AnnotationFinder");
  107. annotationFinder = (AnnotationFinder) java15AnnotationFinder.newInstance();
  108. annotationFinder.setClassLoader(loader);
  109. annotationFinder.setWorld(world);
  110. } catch (ClassNotFoundException ex) {
  111. // must be on 1.4 or earlier
  112. } catch (IllegalAccessException ex) {
  113. // not so good
  114. throw new BCException("AspectJ internal error", ex);
  115. } catch (InstantiationException ex) {
  116. throw new BCException("AspectJ internal error", ex);
  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. }