* 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
*
* 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;
+ }
+
}
--- /dev/null
+/* *******************************************************************
+ * 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);
+}
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;
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;
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>",
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;
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;
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");
}
}
- 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;
}
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();
}
}
* (creation of mungers etc..).
*
*/
-public class ReflectionWorld extends World {
+public class ReflectionWorld extends World implements IReflectionWorld {
private ClassLoader classLoader;
private AnnotationFinder annotationFinder;
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) {
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) {
} catch(InstantiationException ex) {
throw new BCException("AspectJ internal error",ex);
}
+ return annotationFinder;
}
public ClassLoader getClassLoader() {
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);
}
}
}
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));
}