]> source.dussan.org Git - aspectj.git/commitdiff
code from 121312: rons suggestion for changes to LTWWorld and reflection world. ...
authoraclement <aclement>
Thu, 23 Feb 2006 11:34:16 +0000 (11:34 +0000)
committeraclement <aclement>
Thu, 23 Feb 2006 11:34:16 +0000 (11:34 +0000)
weaver/src/org/aspectj/weaver/ltw/LTWWorld.java
weaver/src/org/aspectj/weaver/reflect/IReflectionWorld.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java
weaver/src/org/aspectj/weaver/reflect/ReflectionShadow.java
weaver/src/org/aspectj/weaver/reflect/ReflectionWorld.java
weaver/testsrc/org/aspectj/weaver/reflect/ReflectionWorldTest.java

index 78291089f751873f47d21a52c57106bfe7fa604e..ef26fb5a4bf15724ba0299ed35859c5ed6938dcb 100644 (file)
@@ -7,25 +7,31 @@
  * http://eclipse.org/legal/epl-v10.html 
  *  
  * Contributors: 
- *   Adrian Colyer                     Initial implementation
+ *   Ron Bodkin                Initial implementation
  * ******************************************************************/
 package org.aspectj.weaver.ltw;
 
-import org.aspectj.weaver.Advice;
-import org.aspectj.weaver.ConcreteTypeMunger;
-import org.aspectj.weaver.Member;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.util.LangUtil;
+import org.aspectj.weaver.ICrossReferenceHandler;
 import org.aspectj.weaver.ReferenceType;
 import org.aspectj.weaver.ReferenceTypeDelegate;
-import org.aspectj.weaver.ResolvedMember;
 import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.ResolvedTypeMunger;
-import org.aspectj.weaver.World;
-import org.aspectj.weaver.AjAttribute.AdviceAttribute;
-import org.aspectj.weaver.patterns.Pointcut;
-import org.aspectj.weaver.patterns.PerClause.Kind;
+import org.aspectj.weaver.bcel.BcelWorld;
+import org.aspectj.weaver.reflect.AnnotationFinder;
+import org.aspectj.weaver.reflect.IReflectionWorld;
+import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegateFactory;
+import org.aspectj.weaver.reflect.ReflectionWorld;
 
 /**
  * @author adrian
+ * @author Ron Bodkin
  * 
  * For use in LT weaving
  * 
@@ -35,42 +41,144 @@ import org.aspectj.weaver.patterns.PerClause.Kind;
  * This is the trigger for us to ditch the class from
  * Bcel and cache it in the reflective world instead.
  *
- * Problems with classes that are loaded by delegates
- * of our classloader
- * 
  * Create by passing in a classloader, message handler
  */
-public class LTWWorld extends World {
+public class LTWWorld extends BcelWorld implements IReflectionWorld {
+       
+    private AnnotationFinder annotationFinder;
+    private ClassLoader loader; // weavingContext?
+    
+    protected final static Class concurrentMapClass = makeConcurrentMapClass();
+    protected static Map/*<String, WeakReference<ReflectionBasedReferenceTypeDelegate>>*/ bootstrapTypes = makeConcurrentMap();
+    
+    /**
+     * Build a World from a ClassLoader, for LTW support
+     */
+    public LTWWorld(ClassLoader loader, IMessageHandler handler, ICrossReferenceHandler xrefHandler) {
+        super(loader, handler, xrefHandler);
+        this.loader = loader;
+        
+        setBehaveInJava5Way(LangUtil.is15VMOrGreater());
+        annotationFinder = ReflectionWorld.makeAnnotationFinderIfAny(loader, this);
+    }
+    
+       public ClassLoader getClassLoader() {
+        return this.loader;
+    }
+    
+    //TEST
+    //this is probably easier: just mark anything loaded while loading aspects as not
+    //expendible... it also fixes a possible bug whereby non-rewoven aspects are deemed expendible
+    //<exclude within="org.foo.aspects..*"/>
+//    protected boolean isExpendable(ResolvedType type) {
+//             return ((type != null) && !loadingAspects && !type.isAspect() && (!type
+//                             .isPrimitiveType()));
+//     }
+       
+    /**
+        * @Override
+        */
+    protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {        
+        String name = ty.getName();
 
-       protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) {
-               // TODO Auto-generated method stub
-               return null;
-               
-       }
+        // use reflection delegates for all bootstrap types
+        ReferenceTypeDelegate bootstrapLoaderDelegate = resolveIfBootstrapDelegate(ty);
+        if (bootstrapLoaderDelegate != null) {
+            return bootstrapLoaderDelegate;
+        }
+        
+               return super.resolveDelegate(ty);
+    }
 
-       public Advice createAdviceMunger(AdviceAttribute attribute, Pointcut pointcut, Member signature) {
-               // TODO Auto-generated method stub
-               return null;
-       }
+    protected ReferenceTypeDelegate resolveIfBootstrapDelegate(ReferenceType ty) {
+        // first check for anything available in the bootstrap loader: these types are just defined from that without allowing nondelegation
+       String name = ty.getName();
+        Reference bootRef = (Reference)bootstrapTypes.get(name);
+        if (bootRef != null) {         
+               ReferenceTypeDelegate rtd = (ReferenceTypeDelegate)bootRef.get();
+               if (rtd != null) {
+                       return rtd;
+               }
+        }
 
-       public ConcreteTypeMunger makeCflowStackFieldAdder(ResolvedMember cflowField) {
-               // TODO Auto-generated method stub
-               return null;
-       }
+        char fc = name.charAt(0);
+        if (fc=='j' || fc=='c' || fc=='o' || fc=='s') { // cheaper than imminent string startsWith tests
+               if (name.startsWith("java") || name.startsWith("com.sun.") || name.startsWith("org.w3c") || 
+                       name.startsWith("sun.") || name.startsWith("org.omg")) {
+                       ReferenceTypeDelegate bootstrapLoaderDelegate = resolveReflectionTypeDelegate(ty, null);
+                       if (bootstrapLoaderDelegate != null) {
+                           // it's always fine to load these bytes: there's no weaving into them
+                           // and since the class isn't initialized, all we are doing at this point is loading the bytes
+                           //processedRefTypes.put(ty, this); // has no effect - and probably too aggressive if we did store these in the type map            
+                               // should we share these, like we do the BCEL delegates?
+                               bootstrapTypes.put(ty.getName(), new WeakReference(bootstrapLoaderDelegate));
+                       }       
+                       return bootstrapLoaderDelegate;
+               }
+        }
+        return null;
+    }
+    
+    /**
+     * Helper method to resolve the delegate from the reflection delegate factory.
+     */
+    private ReferenceTypeDelegate resolveReflectionTypeDelegate(ReferenceType ty, ClassLoader resolutionLoader) {
+        ReferenceTypeDelegate res = ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty, this, resolutionLoader);
+        return res;
+    }
 
-       public ConcreteTypeMunger makeCflowCounterFieldAdder(ResolvedMember cflowField) {
-               // TODO Auto-generated method stub
-               return null;
-       }
+    /**
+     * Remove this class from the typeMap. Call back to be made from a publishing class loader
+     * The class loader should, ideally, make this call on each
+     * not yet working
+     * 
+     * @param clazz
+     */
+    public void loadedClass(Class clazz) {
+    }
+    
+    private static final long serialVersionUID = 1;
 
-       public ConcreteTypeMunger makePerClauseAspect(ResolvedType aspect, Kind kind) {
-               // TODO Auto-generated method stub
-               return null;
-       }
+    public AnnotationFinder getAnnotationFinder() {
+        return this.annotationFinder;
+    }
 
-       public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedType aspectType) {
-               // TODO Auto-generated method stub
-               return null;
-       }
+    /* (non-Javadoc)
+     * @see org.aspectj.weaver.reflect.IReflectionWorld#resolve(java.lang.Class)
+     */
+    public ResolvedType resolve(Class aClass) {
+        return ReflectionWorld.resolve(this, aClass); 
+    }
 
+    private static Map makeConcurrentMap() {
+       if (concurrentMapClass != null) {
+               try {
+                       return (Map)concurrentMapClass.newInstance();
+               } catch (InstantiationException _) {
+               } catch (IllegalAccessException _) {                            
+               }
+               // fall through if exceptions
+       }
+       return Collections.synchronizedMap(new HashMap());
+    }
+    
+    private static Class makeConcurrentMapClass() {
+       String betterChoices[] = { 
+                       "java.util.concurrent.ConcurrentHashMap", 
+                       "edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap", 
+                       "EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap"
+       };
+               for (int i = 0; i < betterChoices.length; i++) {
+                       try {
+                               return Class.forName(betterChoices[i]);
+                       } catch (ClassNotFoundException _) {
+                               // try the next one
+                       } catch (SecurityException _) {
+                               // you get one of these if you dare to try to load an undefined class in a 
+                               // package starting with java like java.util.concurrent
+                       }
+               }
+       return null;
+    }
+    
 }
diff --git a/weaver/src/org/aspectj/weaver/reflect/IReflectionWorld.java b/weaver/src/org/aspectj/weaver/reflect/IReflectionWorld.java
new file mode 100644 (file)
index 0000000..60d90d3
--- /dev/null
@@ -0,0 +1,19 @@
+/* *******************************************************************
+ * Copyright (c) 2005 Contributors
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *    Ron Bodkin     initial implementation 
+ * ******************************************************************/
+ package org.aspectj.weaver.reflect;
+
+import org.aspectj.weaver.ResolvedType;
+
+public interface IReflectionWorld {
+       public AnnotationFinder getAnnotationFinder();
+       public ResolvedType resolve(Class aClass);
+}
index 3214156cd4bdb4e89633b832d65e7e3f01a08471..83cf4c20c9ae64a809fb62355b4b5e4f455b72c1 100644 (file)
@@ -104,16 +104,16 @@ public class ReflectionBasedReferenceTypeDelegateFactory {
        
        public static ResolvedMember createResolvedMethod(Method aMethod, World inWorld) {
                ReflectionBasedResolvedMemberImpl ret = new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.METHOD,
-                               toResolvedType(aMethod.getDeclaringClass(),(ReflectionWorld)inWorld),
+                               toResolvedType(aMethod.getDeclaringClass(),(IReflectionWorld)inWorld),
                                aMethod.getModifiers(),
-                               toResolvedType(aMethod.getReturnType(),(ReflectionWorld)inWorld),
+                               toResolvedType(aMethod.getReturnType(),(IReflectionWorld)inWorld),
                                aMethod.getName(),
                                toResolvedTypeArray(aMethod.getParameterTypes(),inWorld),
                                toResolvedTypeArray(aMethod.getExceptionTypes(),inWorld),
                                aMethod
                                );
-               if (inWorld instanceof ReflectionWorld) {
-                       ret.setAnnotationFinder(((ReflectionWorld)inWorld).getAnnotationFinder());
+               if (inWorld instanceof IReflectionWorld) {
+                       ret.setAnnotationFinder(((IReflectionWorld)inWorld).getAnnotationFinder());
                }
                ret.setGenericSignatureInformationProvider(createGenericSignatureProvider(inWorld));
                return ret;
@@ -122,16 +122,16 @@ public class ReflectionBasedReferenceTypeDelegateFactory {
        public static ResolvedMember createResolvedAdviceMember(Method aMethod, World inWorld) {
                ReflectionBasedResolvedMemberImpl ret =
                        new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.ADVICE,
-                               toResolvedType(aMethod.getDeclaringClass(),(ReflectionWorld)inWorld),
+                               toResolvedType(aMethod.getDeclaringClass(),(IReflectionWorld)inWorld),
                                aMethod.getModifiers(),
-                               toResolvedType(aMethod.getReturnType(),(ReflectionWorld)inWorld),
+                               toResolvedType(aMethod.getReturnType(),(IReflectionWorld)inWorld),
                                aMethod.getName(),
                                toResolvedTypeArray(aMethod.getParameterTypes(),inWorld),
                                toResolvedTypeArray(aMethod.getExceptionTypes(),inWorld),
                                aMethod
                                );
-               if (inWorld instanceof ReflectionWorld) {
-                       ret.setAnnotationFinder(((ReflectionWorld)inWorld).getAnnotationFinder());
+               if (inWorld instanceof IReflectionWorld) {
+                       ret.setAnnotationFinder(((IReflectionWorld)inWorld).getAnnotationFinder());
                }
                ret.setGenericSignatureInformationProvider(createGenericSignatureProvider(inWorld));
                return ret;
@@ -139,7 +139,7 @@ public class ReflectionBasedReferenceTypeDelegateFactory {
        
        public static ResolvedMember createStaticInitMember(Class forType, World inWorld) {
                return new ResolvedMemberImpl(org.aspectj.weaver.Member.STATIC_INITIALIZATION,
-                               toResolvedType(forType,(ReflectionWorld)inWorld),
+                               toResolvedType(forType,(IReflectionWorld)inWorld),
                                Modifier.STATIC,
                                ResolvedType.VOID,
                                "<clinit>",
@@ -151,17 +151,17 @@ public class ReflectionBasedReferenceTypeDelegateFactory {
        public static ResolvedMember createResolvedConstructor(Constructor aConstructor, World inWorld) {
                ReflectionBasedResolvedMemberImpl ret =
                   new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.CONSTRUCTOR,
-                               toResolvedType(aConstructor.getDeclaringClass(),(ReflectionWorld)inWorld),
+                               toResolvedType(aConstructor.getDeclaringClass(),(IReflectionWorld)inWorld),
                                aConstructor.getModifiers(),
                                // to return what BCEL returns, the return type for ctor is void
-                               ResolvedType.VOID,//toResolvedType(aConstructor.getDeclaringClass(),(ReflectionWorld)inWorld),
+                               ResolvedType.VOID,//toResolvedType(aConstructor.getDeclaringClass(),(IReflectionWorld)inWorld),
                                "<init>",
                                toResolvedTypeArray(aConstructor.getParameterTypes(),inWorld),
                                toResolvedTypeArray(aConstructor.getExceptionTypes(),inWorld),
                                aConstructor
                                );
-               if (inWorld instanceof ReflectionWorld) {
-                       ret.setAnnotationFinder(((ReflectionWorld)inWorld).getAnnotationFinder());
+               if (inWorld instanceof IReflectionWorld) {
+                       ret.setAnnotationFinder(((IReflectionWorld)inWorld).getAnnotationFinder());
                }
                ret.setGenericSignatureInformationProvider(createGenericSignatureProvider(inWorld));
                return ret;
@@ -170,14 +170,14 @@ public class ReflectionBasedReferenceTypeDelegateFactory {
        public static ResolvedMember createResolvedField(Field aField, World inWorld) {
                ReflectionBasedResolvedMemberImpl ret =
                        new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.FIELD,
-                               toResolvedType(aField.getDeclaringClass(),(ReflectionWorld)inWorld),
+                               toResolvedType(aField.getDeclaringClass(),(IReflectionWorld)inWorld),
                                aField.getModifiers(),
-                               toResolvedType(aField.getType(),(ReflectionWorld)inWorld),
+                               toResolvedType(aField.getType(),(IReflectionWorld)inWorld),
                                aField.getName(),
                                new UnresolvedType[0],
                                aField);
-               if (inWorld instanceof ReflectionWorld) {
-                       ret.setAnnotationFinder(((ReflectionWorld)inWorld).getAnnotationFinder());
+               if (inWorld instanceof IReflectionWorld) {
+                       ret.setAnnotationFinder(((IReflectionWorld)inWorld).getAnnotationFinder());
                }
                ret.setGenericSignatureInformationProvider(createGenericSignatureProvider(inWorld));
                return ret;
@@ -186,7 +186,7 @@ public class ReflectionBasedReferenceTypeDelegateFactory {
        public static ResolvedMember createHandlerMember(Class exceptionType, Class inType,World inWorld) {
                return new ResolvedMemberImpl(
                                org.aspectj.weaver.Member.HANDLER,
-                               toResolvedType(inType,(ReflectionWorld)inWorld),
+                               toResolvedType(inType,(IReflectionWorld)inWorld),
                                Modifier.STATIC,
                                "<catch>",
                                "(" + inWorld.resolve(exceptionType.getName()).getSignature() + ")V");
@@ -203,14 +203,14 @@ public class ReflectionBasedReferenceTypeDelegateFactory {
                } 
        }
        
-       private static ResolvedType toResolvedType(Class aClass, ReflectionWorld aWorld) {
+       private static ResolvedType toResolvedType(Class aClass, IReflectionWorld aWorld) {
                return aWorld.resolve(aClass);
        }
 
        private static ResolvedType[] toResolvedTypeArray(Class[] classes, World inWorld) {
                ResolvedType[] ret = new ResolvedType[classes.length];
                for (int i = 0; i < ret.length; i++) {
-                       ret[i] = ((ReflectionWorld)inWorld).resolve(classes[i]);
+                       ret[i] = ((IReflectionWorld)inWorld).resolve(classes[i]);
                }
                return ret;
        }
index 6f6f98926251ecc7888287cca8623654811589ec..9d98e3ba2f39cd33a74d22e4dde54822bc9f89c3 100644 (file)
@@ -161,8 +161,8 @@ public class ReflectionShadow extends Shadow {
                this.enclosingType = enclosingType;
                this.enclosingMember = enclosingMember;
                this.matchContext = withContext;
-               if (world instanceof ReflectionWorld) {
-                       this.annotationFinder = ((ReflectionWorld)world).getAnnotationFinder();
+               if (world instanceof IReflectionWorld) {
+                       this.annotationFinder = ((IReflectionWorld)world).getAnnotationFinder();
                }
        }
        
index 04ad8ed4068de73026b82cc9d4a37ca7fefa4b69..a37b4654294f4fa5c421e6acb4cf94d97f8095e5 100644 (file)
@@ -36,7 +36,7 @@ import org.aspectj.weaver.patterns.PerClause.Kind;
  * (creation of mungers etc..).
  *
  */
-public class ReflectionWorld extends World {
+public class ReflectionWorld extends World implements IReflectionWorld {
 
        private ClassLoader classLoader;
        private AnnotationFinder annotationFinder;
@@ -46,9 +46,7 @@ public class ReflectionWorld extends World {
                this.setMessageHandler(new ExceptionBasedMessageHandler());
                setBehaveInJava5Way(LangUtil.is15VMOrGreater());
                this.classLoader = ReflectionWorld.class.getClassLoader();
-               if (LangUtil.is15VMOrGreater()) {
-                       initializeAnnotationFinder(this.classLoader);
-               }
+               this.annotationFinder = makeAnnotationFinderIfAny(classLoader, this);
        }
        
        public ReflectionWorld(ClassLoader aClassLoader) {
@@ -56,17 +54,18 @@ public class ReflectionWorld extends World {
                this.setMessageHandler(new ExceptionBasedMessageHandler());
                setBehaveInJava5Way(LangUtil.is15VMOrGreater());
                this.classLoader = aClassLoader;
-               if (LangUtil.is15VMOrGreater()) {
-                       initializeAnnotationFinder(this.classLoader);
-               }
+               this.annotationFinder = makeAnnotationFinderIfAny(classLoader, this);
        }
 
-       private void initializeAnnotationFinder(ClassLoader loader) {
+       public static AnnotationFinder makeAnnotationFinderIfAny(ClassLoader loader, World world) {
+               AnnotationFinder annotationFinder = null;
                try {
-                       Class java15AnnotationFinder = Class.forName("org.aspectj.weaver.reflect.Java15AnnotationFinder");
-                       this.annotationFinder = (AnnotationFinder) java15AnnotationFinder.newInstance();
-                       this.annotationFinder.setClassLoader(loader);
-                       this.annotationFinder.setWorld(this);
+                       if (LangUtil.is15VMOrGreater()) {
+                               Class java15AnnotationFinder = Class.forName("org.aspectj.weaver.reflect.Java15AnnotationFinder");
+                               annotationFinder = (AnnotationFinder) java15AnnotationFinder.newInstance();
+                               annotationFinder.setClassLoader(loader);
+                               annotationFinder.setWorld(world);
+                       }
                } catch(ClassNotFoundException ex) {
                        // must be on 1.4 or earlier
                } catch(IllegalAccessException ex) {
@@ -75,6 +74,7 @@ public class ReflectionWorld extends World {
                } catch(InstantiationException ex) {
                        throw new BCException("AspectJ internal error",ex);
                }
+               return annotationFinder;
        }
        
        public ClassLoader getClassLoader() {
@@ -85,14 +85,21 @@ public class ReflectionWorld extends World {
                return this.annotationFinder;
        }
        
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.reflect.IReflectionWorld#resolve(java.lang.Class)
+        */
        public ResolvedType resolve(Class aClass) {
+               return resolve(this, aClass);
+       }
+       
+       public static ResolvedType resolve(World world, Class aClass) {
                // classes that represent arrays return a class name that is the signature of the array type, ho-hum...
                String className = aClass.getName();
                if (aClass.isArray()) {
-                       return resolve(UnresolvedType.forSignature(className));
+                       return world.resolve(UnresolvedType.forSignature(className));
                }
                else{
-                       return resolve(className);
+                       return world.resolve(className);
                } 
        }
        
index d4729e9bf0cf268ad19b12b056cbac29f7b024ce..39c5ccb5c27121f6629b067daee22383b6aa4c6e 100644 (file)
@@ -26,14 +26,14 @@ public class ReflectionWorldTest extends TestCase {
        }
        
        public void testArrayTypes() {
-               ReflectionWorld world = new ReflectionWorld(getClass().getClassLoader());
+               IReflectionWorld world = new ReflectionWorld(getClass().getClassLoader());
                String[] strArray = new String[1];
                ResolvedType rt = world.resolve(strArray.getClass());
                assertTrue(rt.isArray());
        }
        
        public void testPrimitiveTypes() {
-               ReflectionWorld world = new ReflectionWorld(getClass().getClassLoader());
+               IReflectionWorld world = new ReflectionWorld(getClass().getClassLoader());
                assertEquals("int",ResolvedType.INT,world.resolve(int.class));
                assertEquals("void",ResolvedType.VOID,world.resolve(void.class));
        }