diff options
Diffstat (limited to 'org.aspectj.matcher')
5 files changed, 86 insertions, 9 deletions
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutDesignatorHandlerBasedPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutDesignatorHandlerBasedPointcut.java index 9c508a1a3..e5672dede 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutDesignatorHandlerBasedPointcut.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutDesignatorHandlerBasedPointcut.java @@ -17,6 +17,8 @@ import java.util.Map; import org.aspectj.util.FuzzyBoolean; import org.aspectj.weaver.CompressingDataOutputStream; import org.aspectj.weaver.IntMap; +import org.aspectj.weaver.ReferenceType; +import org.aspectj.weaver.ReferenceTypeDelegate; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.Shadow; import org.aspectj.weaver.World; @@ -28,6 +30,7 @@ import org.aspectj.weaver.patterns.FastMatchInfo; import org.aspectj.weaver.patterns.IScope; import org.aspectj.weaver.patterns.PatternNodeVisitor; import org.aspectj.weaver.patterns.Pointcut; +import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegate; import org.aspectj.weaver.reflect.ReflectionFastMatchInfo; import org.aspectj.weaver.reflect.ReflectionShadow; import org.aspectj.weaver.reflect.ReflectionWorld; @@ -64,16 +67,25 @@ public class PointcutDesignatorHandlerBasedPointcut extends Pointcut { */ public FuzzyBoolean fastMatch(FastMatchInfo info) { if (info instanceof ReflectionFastMatchInfo) { + // Really need a reflectionworld here... + if (!(world instanceof ReflectionWorld)) { + throw new IllegalStateException("Can only match user-extension pcds with a ReflectionWorld"); + } + Class<?> clazz = null; try { - // Really need a reflectionworld here... - if (!(world instanceof ReflectionWorld)) { - throw new IllegalStateException("Can only match user-extension pcds with a ReflectionWorld"); - } - return FuzzyBoolean.fromBoolean(this.matcher.couldMatchJoinPointsInType(Class.forName(info.getType().getName(), - false, ((ReflectionWorld) world).getClassLoader()), ((ReflectionFastMatchInfo) info).getMatchingContext())); - } catch (ClassNotFoundException cnfEx) { + clazz = Class.forName(info.getType().getName(), false, ((ReflectionWorld) world).getClassLoader()); + } catch (ClassNotFoundException cnfe) { + if (info.getType() instanceof ReferenceType) { + ReferenceTypeDelegate rtd = ((ReferenceType)info.getType()).getDelegate(); + if (rtd instanceof ReflectionBasedReferenceTypeDelegate) { + clazz = ((ReflectionBasedReferenceTypeDelegate)rtd).getClazz(); + } + } + } + if (clazz == null) { return FuzzyBoolean.MAYBE; } + return FuzzyBoolean.fromBoolean(this.matcher.couldMatchJoinPointsInType(clazz, ((ReflectionFastMatchInfo) info).getMatchingContext())); } throw new IllegalStateException("Can only match user-extension pcds against Reflection FastMatchInfo objects"); } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java b/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java index 1869e9b19..822c78d9a 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java @@ -35,6 +35,7 @@ import org.aspectj.weaver.patterns.WithinAnnotationPointcut; import org.aspectj.weaver.patterns.WithinCodeAnnotationPointcut; import org.aspectj.weaver.reflect.ReflectionFastMatchInfo; import org.aspectj.weaver.reflect.ReflectionShadow; +import org.aspectj.weaver.reflect.ReflectionWorld; import org.aspectj.weaver.reflect.ShadowMatchImpl; import org.aspectj.weaver.tools.DefaultMatchingContext; import org.aspectj.weaver.tools.MatchingContext; @@ -80,6 +81,12 @@ public class PointcutExpressionImpl implements PointcutExpression { public boolean couldMatchJoinPointsInType(Class aClass) { ResolvedType matchType = world.resolve(aClass.getName()); + if (matchType.isMissing() && (world instanceof ReflectionWorld)) { + // Class is a generated class that cannot be 'looked up' via getResource. + // For example a proxy or lambda. + // Use the class itself in this case + matchType = ((ReflectionWorld)world).resolveUsingClass(aClass); + } ReflectionFastMatchInfo info = new ReflectionFastMatchInfo(matchType, null, this.matchContext, world); boolean couldMatch = pointcut.fastMatch(info).maybeTrue(); if (MATCH_INFO) { diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java index 988239e98..6110e6ceb 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java @@ -69,6 +69,10 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega this.classLoaderReference = new WeakClassLoaderReference((aClassLoader != null) ? aClassLoader : bootClassLoader); } + public Class<?> getClazz() { + return this.myClass; + } + protected Class getBaseClass() { return this.myClass; } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java index e1d709dfc..eee1b6f32 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegateFactory.java @@ -47,6 +47,17 @@ public class ReflectionBasedReferenceTypeDelegateFactory { return null; } } + + public static ReflectionBasedReferenceTypeDelegate createDelegate(ReferenceType forReferenceType, World inWorld, + Class<?> clazz) { + if (LangUtil.is15VMOrGreater()) { + ReflectionBasedReferenceTypeDelegate rbrtd = create15Delegate(forReferenceType, clazz, clazz.getClassLoader(), inWorld); + if (rbrtd != null) { + return rbrtd; // can be null if we didn't find the class the delegate logic loads + } + } + return new ReflectionBasedReferenceTypeDelegate(clazz, clazz.getClassLoader(), inWorld, forReferenceType); + } public static ReflectionBasedReferenceTypeDelegate create14Delegate(ReferenceType forReferenceType, World inWorld, ClassLoader usingClassLoader) { diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionWorld.java b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionWorld.java index 64b8d4bb0..98e800222 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionWorld.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/reflect/ReflectionWorld.java @@ -11,6 +11,9 @@ * ******************************************************************/ package org.aspectj.weaver.reflect; +import java.util.HashMap; +import java.util.Map; + import org.aspectj.bridge.AbortException; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessageHandler; @@ -34,6 +37,7 @@ public class ReflectionWorld extends World implements IReflectionWorld { private WeakClassLoaderReference classLoaderReference; private AnnotationFinder annotationFinder; private boolean mustUseOneFourDelegates = false; // for testing + private Map<String,Class<?>> inProgressResolutionClasses = new HashMap<String,Class<?>>(); private ReflectionWorld() { // super(); @@ -105,13 +109,52 @@ public class ReflectionWorld extends World implements IReflectionWorld { return world.resolve(className); } } + + /** + * Resolve a type using the specified class. Normal resolution in a reflection + * world uses Class.forName() via the classloader (attached to this world) + * in order to find a named type then builds a reference type and a reference + * type delegate based on that. For some classes generated at runtime (e.g. + * proxy or lambda representation) the forName() call will not work. In those + * situations we should just use the clazz we have. + * + * Should the whole thing switch from using forName() to using the clazz objects? + * Possibly but that introduces a lot of change and we don't have a lot + * of test coverage for this scenario (reflection world). What we are doing + * right now is that this can optionally be used if the regular resolution + * scheme did not work. + * + * Although AspectJ is *not* multi threaded or re-entrant, Spring doesn't + * always respect that. There might be an issue here if two attempts are + * made to resolve the same thing at the same time via this method. + * + * @param clazz the class to use as the delegate for the resolved type + */ + public ResolvedType resolveUsingClass(Class<?> clazz) { + String signature = UnresolvedType.forName(clazz.getName()).getSignature(); + try { + inProgressResolutionClasses.put(signature, clazz); + return resolve(clazz.getName()); + } finally { + inProgressResolutionClasses.remove(signature); + } + } protected ReferenceTypeDelegate resolveDelegate(ReferenceType ty) { + ReferenceTypeDelegate result; if (mustUseOneFourDelegates) { - return ReflectionBasedReferenceTypeDelegateFactory.create14Delegate(ty, this, classLoaderReference.getClassLoader()); + result = ReflectionBasedReferenceTypeDelegateFactory.create14Delegate(ty, this, classLoaderReference.getClassLoader()); } else { - return ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty, this, classLoaderReference.getClassLoader()); + result = ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty, this, classLoaderReference.getClassLoader()); + } + if (result == null && inProgressResolutionClasses.size() != 0) { + // Is it a class that cannot be loaded (i.e. it was generated) but we already know about? + Class<?> clazz = inProgressResolutionClasses.get(ty.getSignature()); + if (clazz != null) { + result = ReflectionBasedReferenceTypeDelegateFactory.createDelegate(ty,this,clazz); + } } + return result; } public static class ReflectionWorldException extends RuntimeException { |