From: aclement Date: Thu, 23 Feb 2006 11:34:16 +0000 (+0000) Subject: code from 121312: rons suggestion for changes to LTWWorld and reflection world. ... X-Git-Tag: POST_MEMORY_CHANGES~27 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=cafdecb1028a9a72bfb4beb0e57a91f42c5c35cb;p=aspectj.git code from 121312: rons suggestion for changes to LTWWorld and reflection world. would have liked some testcode... --- diff --git a/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java b/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java index 78291089f..ef26fb5a4 100644 --- a/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java +++ b/weaver/src/org/aspectj/weaver/ltw/LTWWorld.java @@ -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/*>*/ 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 + // +// 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 index 000000000..60d90d357 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/reflect/IReflectionWorld.java @@ -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); +} diff --git a/weaver/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java b/weaver/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java index 3214156cd..83cf4c20c 100644 --- a/weaver/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java +++ b/weaver/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java @@ -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, "", @@ -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), "", 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, "", "(" + 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; } diff --git a/weaver/src/org/aspectj/weaver/reflect/ReflectionShadow.java b/weaver/src/org/aspectj/weaver/reflect/ReflectionShadow.java index 6f6f98926..9d98e3ba2 100644 --- a/weaver/src/org/aspectj/weaver/reflect/ReflectionShadow.java +++ b/weaver/src/org/aspectj/weaver/reflect/ReflectionShadow.java @@ -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(); } } diff --git a/weaver/src/org/aspectj/weaver/reflect/ReflectionWorld.java b/weaver/src/org/aspectj/weaver/reflect/ReflectionWorld.java index 04ad8ed40..a37b46542 100644 --- a/weaver/src/org/aspectj/weaver/reflect/ReflectionWorld.java +++ b/weaver/src/org/aspectj/weaver/reflect/ReflectionWorld.java @@ -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); } } diff --git a/weaver/testsrc/org/aspectj/weaver/reflect/ReflectionWorldTest.java b/weaver/testsrc/org/aspectj/weaver/reflect/ReflectionWorldTest.java index d4729e9bf..39c5ccb5c 100644 --- a/weaver/testsrc/org/aspectj/weaver/reflect/ReflectionWorldTest.java +++ b/weaver/testsrc/org/aspectj/weaver/reflect/ReflectionWorldTest.java @@ -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)); }