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 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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. * Adrian Colyer Initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.reflect;
  13. import java.util.HashMap;
  14. import java.util.Map;
  15. import org.aspectj.bridge.AbortException;
  16. import org.aspectj.bridge.IMessage;
  17. import org.aspectj.bridge.IMessageHandler;
  18. import org.aspectj.util.LangUtil;
  19. import org.aspectj.weaver.BCException;
  20. import org.aspectj.weaver.IWeavingSupport;
  21. import org.aspectj.weaver.ReferenceType;
  22. import org.aspectj.weaver.ReferenceTypeDelegate;
  23. import org.aspectj.weaver.ResolvedType;
  24. import org.aspectj.weaver.UnresolvedType;
  25. import org.aspectj.weaver.WeakClassLoaderReference;
  26. import org.aspectj.weaver.World;
  27. /**
  28. * A ReflectionWorld is used solely for purposes of type resolution based on the runtime classpath (java.lang.reflect). It does not
  29. * support weaving operations (creation of mungers etc..).
  30. *
  31. */
  32. public class ReflectionWorld extends World implements IReflectionWorld {
  33. private WeakClassLoaderReference classLoaderReference;
  34. private AnnotationFinder annotationFinder;
  35. private boolean mustUseOneFourDelegates = false; // for testing
  36. private Map<String,Class<?>> inProgressResolutionClasses = new HashMap<String,Class<?>>();
  37. private ReflectionWorld() {
  38. // super();
  39. // this.setMessageHandler(new ExceptionBasedMessageHandler());
  40. // setBehaveInJava5Way(LangUtil.is15VMOrGreater());
  41. // this.classLoaderReference = new
  42. // WeakClassLoaderReference(ReflectionWorld.class.getClassLoader());
  43. // this.annotationFinder =
  44. // makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(),
  45. // this);
  46. }
  47. public ReflectionWorld(ClassLoader aClassLoader) {
  48. super();
  49. this.setMessageHandler(new ExceptionBasedMessageHandler());
  50. setBehaveInJava5Way(LangUtil.is15VMOrGreater());
  51. classLoaderReference = new WeakClassLoaderReference(aClassLoader);
  52. annotationFinder = makeAnnotationFinderIfAny(classLoaderReference.getClassLoader(), this);
  53. }
  54. public ReflectionWorld(boolean forceUseOf14Delegates, ClassLoader aClassLoader) {
  55. this(aClassLoader);
  56. this.mustUseOneFourDelegates = forceUseOf14Delegates;
  57. if (forceUseOf14Delegates) {
  58. // Dont use 1.4 delegates and yet allow autoboxing
  59. this.setBehaveInJava5Way(false);
  60. }
  61. }
  62. public static AnnotationFinder makeAnnotationFinderIfAny(ClassLoader loader, World world) {
  63. AnnotationFinder annotationFinder = null;
  64. try {
  65. if (LangUtil.is15VMOrGreater()) {
  66. Class java15AnnotationFinder = Class.forName("org.aspectj.weaver.reflect.Java15AnnotationFinder");
  67. annotationFinder = (AnnotationFinder) java15AnnotationFinder.newInstance();
  68. annotationFinder.setClassLoader(loader);
  69. annotationFinder.setWorld(world);
  70. }
  71. } catch (ClassNotFoundException ex) {
  72. // must be on 1.4 or earlier
  73. } catch (IllegalAccessException ex) {
  74. // not so good
  75. throw new BCException("AspectJ internal error", ex);
  76. } catch (InstantiationException ex) {
  77. throw new BCException("AspectJ internal error", ex);
  78. }
  79. return annotationFinder;
  80. }
  81. public ClassLoader getClassLoader() {
  82. return classLoaderReference.getClassLoader();
  83. }
  84. public AnnotationFinder getAnnotationFinder() {
  85. return annotationFinder;
  86. }
  87. public ResolvedType resolve(Class aClass) {
  88. return resolve(this, aClass);
  89. }
  90. public static ResolvedType resolve(World world, Class aClass) {
  91. // classes that represent arrays return a class name that is the
  92. // signature of the array type, ho-hum...
  93. String className = aClass.getName();
  94. if (aClass.isArray()) {
  95. return world.resolve(UnresolvedType.forSignature(className.replace('.', '/')));
  96. } else {
  97. return world.resolve(className);
  98. }
  99. }
  100. /**
  101. * Resolve a type using the specified class. Normal resolution in a reflection
  102. * world uses Class.forName() via the classloader (attached to this world)
  103. * in order to find a named type then builds a reference type and a reference
  104. * type delegate based on that. For some classes generated at runtime (e.g.
  105. * proxy or lambda representation) the forName() call will not work. In those
  106. * situations we should just use the clazz we have.
  107. *
  108. * Should the whole thing switch from using forName() to using the clazz objects?
  109. * Possibly but that introduces a lot of change and we don't have a lot
  110. * of test coverage for this scenario (reflection world). What we are doing
  111. * right now is that this can optionally be used if the regular resolution
  112. * scheme did not work.
  113. *
  114. * Although AspectJ is *not* multi threaded or re-entrant, Spring doesn't
  115. * always respect that. There might be an issue here if two attempts are
  116. * made to resolve the same thing at the same time via this method.
  117. *
  118. * @param clazz the class to use as the delegate for the resolved type
  119. */
  120. public ResolvedType resolveUsingClass(Class<?> clazz) {
  121. String signature = UnresolvedType.forName(clazz.getName()).getSignature();
  122. try {
  123. inProgressResolutionClasses.put(signature, clazz);
  124. return resolve(clazz.getName());
  125. } finally {
  126. inProgressResolutionClasses.remove(signature);
  127. }
  128. }
  129. protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
  130. ReferenceTypeDelegate result;
  131. if (mustUseOneFourDelegates) {
  132. result = ReflectionBasedReferenceTypeDelegateFactory.create14Delegate(ty, this, classLoaderReference.getClassLoader());
  133. } else {
  134. result = ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty, this, classLoaderReference.getClassLoader());
  135. }
  136. if (result == null && inProgressResolutionClasses.size() != 0) {
  137. // Is it a class that cannot be loaded (i.e. it was generated) but we already know about?
  138. Class<?> clazz = inProgressResolutionClasses.get(ty.getSignature());
  139. if (clazz != null) {
  140. result = ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty,this,clazz);
  141. }
  142. }
  143. return result;
  144. }
  145. public static class ReflectionWorldException extends RuntimeException {
  146. private static final long serialVersionUID = -3432261918302793005L;
  147. public ReflectionWorldException(String message) {
  148. super(message);
  149. }
  150. }
  151. private static class ExceptionBasedMessageHandler implements IMessageHandler {
  152. public boolean handleMessage(IMessage message) throws AbortException {
  153. throw new ReflectionWorldException(message.toString());
  154. }
  155. public boolean isIgnoring(org.aspectj.bridge.IMessage.Kind kind) {
  156. if (kind == IMessage.INFO) {
  157. return true;
  158. } else {
  159. return false;
  160. }
  161. }
  162. public void dontIgnore(org.aspectj.bridge.IMessage.Kind kind) {
  163. // empty
  164. }
  165. public void ignore(org.aspectj.bridge.IMessage.Kind kind) {
  166. // empty
  167. }
  168. }
  169. public IWeavingSupport getWeavingSupport() {
  170. return null;
  171. }
  172. public boolean isLoadtimeWeaving() {
  173. return true;
  174. }
  175. }