diff options
author | acolyer <acolyer> | 2004-12-03 11:53:29 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2004-12-03 11:53:29 +0000 |
commit | 63e5dc2ba8b7bad4ceb4c472f4d289ef9b446761 (patch) | |
tree | 4b4fa61fc1b5f3f45f7faaf3228cbeb639eb3e92 | |
parent | c6f7ba2782307c17dcf4cf9aabc3770cae09a3a2 (diff) | |
download | aspectj-63e5dc2ba8b7bad4ceb4c472f4d289ef9b446761.tar.gz aspectj-63e5dc2ba8b7bad4ceb4c472f4d289ef9b446761.zip |
APIs allowing 3rd parties to integrate with AspectJ's pointcut parsing and matching
- final fixes and test cases
21 files changed, 908 insertions, 20 deletions
diff --git a/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java b/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java index 60d1e1294..107229496 100644 --- a/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java +++ b/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java @@ -25,9 +25,11 @@ import org.aspectj.weaver.tools.PointcutExpression; public class PointcutExpressionImpl implements PointcutExpression { private Pointcut pointcut; + private String expression; - public PointcutExpressionImpl(Pointcut pointcut) { + public PointcutExpressionImpl(Pointcut pointcut, String expression) { this.pointcut = pointcut; + this.expression = expression; } /* (non-Javadoc) @@ -100,9 +102,9 @@ public class PointcutExpressionImpl implements PointcutExpression { Member withinCode) { return fuzzyMatch(pointcut.matchesStatically( JoinPoint.EXCEPTION_HANDLER, - null, + new Handler(inClass,exceptionType), + inClass, inClass, - exceptionType, withinCode)); } @@ -181,7 +183,7 @@ public class PointcutExpressionImpl implements PointcutExpression { * @see org.aspectj.weaver.tools.PointcutExpression#getPointcutExpression() */ public String getPointcutExpression() { - return pointcut.toString(); + return expression; } private FuzzyBoolean fuzzyMatch(org.aspectj.util.FuzzyBoolean fb) { @@ -190,4 +192,31 @@ public class PointcutExpressionImpl implements PointcutExpression { if (fb == org.aspectj.util.FuzzyBoolean.MAYBE) return FuzzyBoolean.MAYBE; throw new IllegalArgumentException("Cant match FuzzyBoolean " + fb); } + + public static class Handler implements Member { + + private Class decClass; + private Class exType; + + public Handler(Class decClass, Class exType) { + this.decClass = decClass; + this.exType = exType; + } + + public int getModifiers() { + return 0; + } + + public Class getDeclaringClass() { + return decClass; + } + + public String getName() { + return null; + } + + public Class getHandledExceptionType() { + return exType; + } + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java b/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java index b904b8396..812c5e0d5 100644 --- a/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java @@ -33,6 +33,7 @@ public class AndPointcut extends Pointcut { super(); this.left = left; this.right = right; + this.pointcutKind = AND; setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); } diff --git a/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java index 1e53c0b0c..70f8535c7 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java @@ -17,6 +17,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.Collection; @@ -37,6 +38,7 @@ import org.aspectj.weaver.TypeX; import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.ast.Literal; import org.aspectj.weaver.ast.Test; +import org.aspectj.weaver.internal.tools.PointcutExpressionImpl; /** * args(arguments) @@ -49,6 +51,7 @@ public class ArgsPointcut extends NameBindingPointcut { public ArgsPointcut(TypePatternList arguments) { this.arguments = arguments; + this.pointcutKind = ARGS; } public FuzzyBoolean fastMatch(FastMatchInfo type) { @@ -116,10 +119,15 @@ public class ArgsPointcut extends NameBindingPointcut { paramTypes = ((Method)member).getParameterTypes(); } else if (member instanceof Constructor) { paramTypes = ((Constructor)member).getParameterTypes(); + } else if (member instanceof PointcutExpressionImpl.Handler){ + paramTypes = new Class[] {((PointcutExpressionImpl.Handler)member).getHandledExceptionType()}; + } else if (member instanceof Field) { + if (joinpointKind.equals(Shadow.FieldGet.getName())) return FuzzyBoolean.NO; // no args here + paramTypes = new Class[] {((Field)member).getType()}; } else { return FuzzyBoolean.NO; } - return arguments.matches(paramTypes,TypePattern.DYNAMIC); + return arguments.matchesArgsPatternSubset(paramTypes); } private Class getPossiblyBoxed(TypeX tp) { Class ret = (Class) ExactTypePattern.primitiveTypesMap.get(tp.getName()); diff --git a/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java b/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java index 5f56e2a9b..5a94ec668 100644 --- a/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java @@ -64,6 +64,7 @@ public class CflowPointcut extends Pointcut { this.entry = entry; this.isBelow = isBelow; this.freeVars = freeVars; + this.pointcutKind = CFLOW; } public FuzzyBoolean fastMatch(FastMatchInfo type) { diff --git a/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java index b88bb7a50..a536dd4fa 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java @@ -40,6 +40,7 @@ public class ConcreteCflowPointcut extends Pointcut { this.cflowField = cflowField; this.slots = slots; this.usesCounter = usesCounter; + this.pointcutKind = CFLOW; } public FuzzyBoolean fastMatch(FastMatchInfo type) { diff --git a/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java index ac59cef52..aa77747bf 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java @@ -119,6 +119,28 @@ public class ExactTypePattern extends TypePattern { } } + /** + * Return YES if any subtype of the static type would match, + * MAYBE if some subtypes could match + * NO if there could never be a match + * @param staticType + * @return + */ + public FuzzyBoolean willMatchDynamically(Class staticType) { + if (matchesExactly(staticType)) return FuzzyBoolean.YES; + if (matchesInstanceof(staticType) == FuzzyBoolean.YES) return FuzzyBoolean.YES; + + try { + String typeName = type.getName(); + Class toMatchAgainst = getClassFor(typeName); + if (toMatchAgainst.isInterface()) return FuzzyBoolean.MAYBE; + if (staticType.isAssignableFrom(toMatchAgainst)) return FuzzyBoolean.MAYBE; + return FuzzyBoolean.NO; + } catch (ClassNotFoundException cnfEx) { + return FuzzyBoolean.NO; + } + } + private Class getClassFor(String typeName) throws ClassNotFoundException { Class ret = null; ret = (Class) primitiveTypesMap.get(typeName); diff --git a/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java b/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java index f376851fb..ce6163055 100644 --- a/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java @@ -26,6 +26,7 @@ import org.aspectj.weaver.ResolvedTypeX; import org.aspectj.weaver.Shadow; import org.aspectj.weaver.ast.Literal; import org.aspectj.weaver.ast.Test; +import org.aspectj.weaver.internal.tools.PointcutExpressionImpl; /** * This is a kind of KindedPointcut. This belongs either in @@ -38,6 +39,7 @@ public class HandlerPointcut extends Pointcut { public HandlerPointcut(TypePattern exceptionType) { this.exceptionType = exceptionType; + this.pointcutKind = HANDLER; } public FuzzyBoolean fastMatch(FastMatchInfo type) { @@ -79,8 +81,12 @@ public class HandlerPointcut extends Pointcut { */ public FuzzyBoolean matchesStatically(String joinpointKind, Member member, Class thisClass, Class targetClass, Member withinCode) { - // Note: use targetClass parameter to represent the handled exception type - return exceptionType.matches(targetClass,TypePattern.STATIC); + if (!(member instanceof PointcutExpressionImpl.Handler)) { + return FuzzyBoolean.NO; + } else { + Class exceptionClass = ((PointcutExpressionImpl.Handler)member).getHandledExceptionType(); + return exceptionType.matches(exceptionClass,TypePattern.STATIC); + } } public boolean equals(Object other) { diff --git a/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java b/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java index 2a40e3e10..1336adb2f 100644 --- a/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java @@ -51,6 +51,7 @@ public class IfPointcut extends Pointcut { public IfPointcut(ResolvedMember testMethod, int extraParameterFlags) { this.testMethod = testMethod; this.extraParameterFlags = extraParameterFlags; + this.pointcutKind = IF; } public FuzzyBoolean fastMatch(FastMatchInfo type) { diff --git a/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java b/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java index b7b9d6e44..5b30dac43 100644 --- a/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java @@ -43,6 +43,7 @@ public class KindedPointcut extends Pointcut { SignaturePattern signature) { this.kind = kind; this.signature = signature; + this.pointcutKind = KINDED; } public KindedPointcut( Shadow.Kind kind, @@ -104,7 +105,7 @@ public class KindedPointcut extends Pointcut { java.lang.reflect.Member member, Class thisClass, Class targetClass, java.lang.reflect.Member withinCode) { if (joinpointKind.equals(kind.getName())) { - return FuzzyBoolean.fromBoolean(signature.matches(thisClass,member)); + return FuzzyBoolean.fromBoolean(signature.matches(targetClass,member)); } return FuzzyBoolean.NO; } diff --git a/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java b/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java index 6bf9c9d73..688f2e9c0 100644 --- a/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java @@ -28,9 +28,10 @@ import org.aspectj.weaver.ast.Test; public class NotPointcut extends Pointcut { private Pointcut body; - public NotPointcut(Pointcut left) { + public NotPointcut(Pointcut negated) { super(); - this.body = left; + this.body = negated; + this.pointcutKind = NOT; } public NotPointcut(Pointcut pointcut, int startPos) { diff --git a/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java b/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java index bb7285003..fa9efda07 100644 --- a/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java @@ -34,6 +34,7 @@ public class OrPointcut extends Pointcut { this.left = left; this.right = right; setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); + this.pointcutKind = OR; } diff --git a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java index 2c42179bc..4f8ddba3f 100644 --- a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java @@ -52,7 +52,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression public static final State RESOLVED = new State("resolved", 1); public static final State CONCRETE = new State("concrete", 2); - private byte pointcutKind; + protected byte pointcutKind; public State state; diff --git a/weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java b/weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java index 30b0cfbf6..2d848f0fb 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java @@ -48,12 +48,14 @@ public class ReferencePointcut extends Pointcut { this.onTypeSymbolic = onTypeSymbolic; this.name = name; this.arguments = arguments; + this.pointcutKind = REFERENCE; } public ReferencePointcut(TypeX onType, String name, TypePatternList arguments) { this.onType = onType; this.name = name; this.arguments = arguments; + this.pointcutKind = REFERENCE; } diff --git a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java index c7784e2b3..4530c933a 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java @@ -54,6 +54,7 @@ public class ThisOrTargetPointcut extends NameBindingPointcut { public ThisOrTargetPointcut(boolean isThis, TypePattern type) { this.isThis = isThis; this.type = type; + this.pointcutKind = THIS_OR_TARGET; } public boolean isThis() { return isThis; } @@ -87,7 +88,7 @@ public class ThisOrTargetPointcut extends NameBindingPointcut { Object[] args) { Object toMatch = isThis ? thisObject : targetObject; if (toMatch == null) return false; - return (type.matches(toMatch.getClass(), TypePattern.DYNAMIC)).alwaysTrue(); + return type.matchesSubtypes(toMatch.getClass()); } /* (non-Javadoc) @@ -95,8 +96,11 @@ public class ThisOrTargetPointcut extends NameBindingPointcut { */ public FuzzyBoolean matchesStatically(String joinpointKind, Member member, Class thisClass, Class targetClass, Member withinCode) { - Class typeToMatch = isThis ? thisClass : targetClass; - return type.matches(typeToMatch, TypePattern.DYNAMIC); + Class staticType = isThis ? thisClass : targetClass; + if (joinpointKind.equals(Shadow.StaticInitialization.getName())) { + return FuzzyBoolean.NO; // no this or target at these jps + } + return(((ExactTypePattern)type).willMatchDynamically(staticType)); } public void write(DataOutputStream s) throws IOException { diff --git a/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java b/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java index 25111cf15..3aa4f9cf8 100644 --- a/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java +++ b/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java @@ -74,6 +74,48 @@ public class TypePatternList extends PatternNode { return buf.toString(); } + + /** + * Used by reflection-based matching for args pcds. + * Returns YES if types will always be matched by the pattern, + * NO if types do not match the pattern, + * MAYBE if types may match the pattern dependent on a runtime test + */ + public FuzzyBoolean matchesArgsPatternSubset(Class[] types) { + int argsLength = types.length; + int patternLength = typePatterns.length; + int argsIndex = 0; + + if ((argsLength < patternLength) && (ellipsisCount == 0)) return FuzzyBoolean.NO; + if (argsLength < (patternLength -1)) return FuzzyBoolean.NO; + + int ellipsisMatchCount = argsLength - (patternLength - ellipsisCount); + + FuzzyBoolean ret = FuzzyBoolean.YES; + + for (int i = 0; i < typePatterns.length; i++) { + if (typePatterns[i] == TypePattern.ELLIPSIS) { + // match ellipsisMatchCount args + argsIndex += ellipsisMatchCount; + } else if (typePatterns[i] == TypePattern.ANY) { + argsIndex++; + } else { + // match the argument type at argsIndex with the ExactTypePattern + // we it is exact because nothing else is allowed in args + ExactTypePattern tp = (ExactTypePattern)typePatterns[i]; + FuzzyBoolean matches = tp.willMatchDynamically(types[argsIndex]); + if (matches == FuzzyBoolean.NO) { + return FuzzyBoolean.NO; + } else { + argsIndex++; + ret = ret.and(matches); + } + } + } + + return ret; + } + //XXX shares much code with WildTypePattern and with NamePattern /** * When called with TypePattern.STATIC this will always return either diff --git a/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java index 582d39757..50181a6c7 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java @@ -36,6 +36,7 @@ public class WithinPointcut extends Pointcut { public WithinPointcut(TypePattern type) { this.typePattern = type; + this.pointcutKind = WITHIN; } private FuzzyBoolean isWithinType(ResolvedTypeX type) { @@ -83,7 +84,16 @@ public class WithinPointcut extends Pointcut { public FuzzyBoolean matchesStatically( String joinpointKind, Member member, Class thisClass, Class targetClass, Member withinCode) { - return isWithinType(thisClass); + if ((member != null) && + !(joinpointKind.equals(Shadow.ConstructorCall.getName()) || + joinpointKind.equals(Shadow.MethodCall.getName()) || + joinpointKind.equals(Shadow.FieldGet.getName()) || + joinpointKind.equals(Shadow.FieldSet.getName())) + ) { + return isWithinType(member.getDeclaringClass()); + } else { + return isWithinType(thisClass); + } } private FuzzyBoolean isWithinType(Class type) { diff --git a/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java index 3467d6eb6..8778a679e 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java @@ -33,6 +33,7 @@ public class WithincodePointcut extends Pointcut { public WithincodePointcut(SignaturePattern signature) { this.signature = signature; + this.pointcutKind = WITHINCODE; } public FuzzyBoolean fastMatch(FastMatchInfo type) { @@ -63,6 +64,7 @@ public class WithincodePointcut extends Pointcut { */ public FuzzyBoolean matchesStatically(String joinpointKind, Member member, Class thisClass, Class targetClass, Member withinCode) { + if (withinCode == null) return FuzzyBoolean.NO; return FuzzyBoolean.fromBoolean(signature.matches(Factory.makeEncSJP(withinCode))); } diff --git a/weaver/src/org/aspectj/weaver/tools/FuzzyBoolean.java b/weaver/src/org/aspectj/weaver/tools/FuzzyBoolean.java index fbf0f16a6..c60357d3f 100644 --- a/weaver/src/org/aspectj/weaver/tools/FuzzyBoolean.java +++ b/weaver/src/org/aspectj/weaver/tools/FuzzyBoolean.java @@ -17,14 +17,20 @@ package org.aspectj.weaver.tools; public class FuzzyBoolean { // Note :- this implementation is not safe under serialization / deserialization + private String name; - public static final FuzzyBoolean YES = new FuzzyBoolean(); - public static final FuzzyBoolean NO = new FuzzyBoolean(); - public static final FuzzyBoolean MAYBE = new FuzzyBoolean(); + public static final FuzzyBoolean YES = new FuzzyBoolean("YES"); + public static final FuzzyBoolean NO = new FuzzyBoolean("NO"); + public static final FuzzyBoolean MAYBE = new FuzzyBoolean("MAYBE"); + public static final FuzzyBoolean fromBoolean(boolean b) { return b ? YES : NO; } + public String toString() { return name; } + private FuzzyBoolean() {} + + private FuzzyBoolean(String n) { this.name = n; } } diff --git a/weaver/src/org/aspectj/weaver/tools/PointcutParser.java b/weaver/src/org/aspectj/weaver/tools/PointcutParser.java index 87a50e80c..949165053 100644 --- a/weaver/src/org/aspectj/weaver/tools/PointcutParser.java +++ b/weaver/src/org/aspectj/weaver/tools/PointcutParser.java @@ -14,8 +14,10 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import org.aspectj.weaver.Shadow; import org.aspectj.weaver.internal.tools.PointcutExpressionImpl; import org.aspectj.weaver.patterns.AndPointcut; +import org.aspectj.weaver.patterns.KindedPointcut; import org.aspectj.weaver.patterns.NotPointcut; import org.aspectj.weaver.patterns.OrPointcut; import org.aspectj.weaver.patterns.ParserException; @@ -110,13 +112,19 @@ public class PointcutParser { try { Pointcut pc = new PatternParser(expression).parsePointcut(); validateAgainstSupportedPrimitives(pc); - pcExpr = new PointcutExpressionImpl(pc); + pc.resolve(); + pcExpr = new PointcutExpressionImpl(pc,expression); } catch (ParserException pEx) { throw new IllegalArgumentException(pEx.getMessage()); } return pcExpr; } + /* for testing */ + Set getSupportedPrimitives() { + return supportedPrimitives; + } + private void validateAgainstSupportedPrimitives(Pointcut pc) { switch(pc.getPointcutKind()) { case Pointcut.AND: @@ -138,6 +146,7 @@ public class PointcutParser { case Pointcut.IF_TRUE: throw new UnsupportedOperationException("if is not supported by this parser"); case Pointcut.KINDED: + validateKindedPointcut(((KindedPointcut)pc)); break; case Pointcut.NOT: validateAgainstSupportedPrimitives(((NotPointcut)pc).getNegatedPointcut()); @@ -147,7 +156,7 @@ public class PointcutParser { validateAgainstSupportedPrimitives(((OrPointcut)pc).getRight()); break; case Pointcut.REFERENCE: - throw new UnsupportedOperationException("reference pointcuts are not supported by this parser"); + throw new UnsupportedOperationException("if pointcuts and reference pointcuts are not supported by this parser"); case Pointcut.THIS_OR_TARGET: boolean isThis = ((ThisOrTargetPointcut)pc).isThis(); if (isThis && !supportedPrimitives.contains(PointcutPrimitives.THIS)) { @@ -169,4 +178,33 @@ public class PointcutParser { throw new UnsupportedOperationException("Unknown pointcut kind: " + pc.getPointcutKind()); } } + + private void validateKindedPointcut(KindedPointcut pc) { + Shadow.Kind kind = pc.getKind(); + if ((kind == Shadow.MethodCall) || (kind == Shadow.ConstructorCall)) { + if (!supportedPrimitives.contains(PointcutPrimitives.CALL)) + throw new UnsupportedOperationException("call is not supported by this parser"); + } else if ((kind == Shadow.MethodExecution) || (kind == Shadow.ConstructorExecution)) { + if (!supportedPrimitives.contains(PointcutPrimitives.EXECUTION)) + throw new UnsupportedOperationException("execution is not supported by this parser"); + } else if (kind == Shadow.AdviceExecution) { + if (!supportedPrimitives.contains(PointcutPrimitives.ADVICE_EXECUTION)) + throw new UnsupportedOperationException("adviceexecution is not supported by this parser"); + } else if (kind == Shadow.FieldGet) { + if (!supportedPrimitives.contains(PointcutPrimitives.GET)) + throw new UnsupportedOperationException("get is not supported by this parser"); + } else if (kind == Shadow.FieldSet) { + if (!supportedPrimitives.contains(PointcutPrimitives.SET)) + throw new UnsupportedOperationException("set is not supported by this parser"); + } else if (kind == Shadow.Initialization) { + if (!supportedPrimitives.contains(PointcutPrimitives.INITIALIZATION)) + throw new UnsupportedOperationException("initialization is not supported by this parser"); + } else if (kind == Shadow.PreInitialization) { + if (!supportedPrimitives.contains(PointcutPrimitives.PRE_INITIALIZATION)) + throw new UnsupportedOperationException("preinitialization is not supported by this parser"); + } else if (kind == Shadow.StaticInitialization) { + if (!supportedPrimitives.contains(PointcutPrimitives.STATIC_INITIALIZATION)) + throw new UnsupportedOperationException("staticinitialization is not supported by this parser"); + } + } } diff --git a/weaver/testsrc/org/aspectj/weaver/tools/PointcutExpressionTest.java b/weaver/testsrc/org/aspectj/weaver/tools/PointcutExpressionTest.java new file mode 100644 index 000000000..411716b95 --- /dev/null +++ b/weaver/testsrc/org/aspectj/weaver/tools/PointcutExpressionTest.java @@ -0,0 +1,511 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.aspectj.weaver.tools; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +public class PointcutExpressionTest extends TestCase { + + PointcutParser p; + Constructor asCons; + Constructor bsCons; + Constructor bsStringCons; + Method a; + Method aa; + Method aaa; + Field x; + Field y; + Method b; + Method bsaa; + Field n; + Method foo; + Method bar; + + public void testMatchesMethodCall() { + PointcutExpression ex = p.parsePointcutExpression("call(* *..A.a*(..))"); + assertEquals("Should match call to A.a()",FuzzyBoolean.YES,ex.matchesMethodCall(a,Client.class,A.class,null)); + assertEquals("Should match call to A.aaa()",FuzzyBoolean.YES,ex.matchesMethodCall(aaa,Client.class,A.class,null)); + assertEquals("Should match call to B.aa()",FuzzyBoolean.YES,ex.matchesMethodCall(bsaa,Client.class,A.class,null)); + assertEquals("Should not match call to B.b()",FuzzyBoolean.NO,ex.matchesMethodCall(b,Client.class,A.class,null)); + ex = p.parsePointcutExpression("call(* *..A.a*(int))"); + assertEquals("Should match call to A.aa()",FuzzyBoolean.YES,ex.matchesMethodCall(aa,Client.class,A.class,null)); + assertEquals("Should not match call to A.a()",FuzzyBoolean.NO,ex.matchesMethodCall(a,Client.class,A.class,null)); + ex = p.parsePointcutExpression("call(void aaa(..)) && this(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("Should match call to A.aaa() from Client",FuzzyBoolean.YES,ex.matchesMethodCall(aaa,Client.class,A.class,null)); + ex = p.parsePointcutExpression("call(void aaa(..)) && this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Should match call to A.aaa() from B",FuzzyBoolean.YES,ex.matchesMethodCall(aaa,B.class,A.class,null)); + assertEquals("May match call to A.aaa() from A",FuzzyBoolean.MAYBE,ex.matchesMethodCall(aaa,A.class,A.class,null)); + ex = p.parsePointcutExpression("execution(* *.*(..))"); + assertEquals("Should not match call to A.aa",FuzzyBoolean.NO,ex.matchesMethodCall(aa,A.class,A.class,null)); + // this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("Should match Client",FuzzyBoolean.YES,ex.matchesMethodCall(a,Client.class,A.class,null)); + assertEquals("Should not match A",FuzzyBoolean.NO,ex.matchesMethodCall(a,A.class,A.class,null)); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Should maybe match B",FuzzyBoolean.MAYBE,ex.matchesMethodCall(bsaa,A.class,B.class,null)); + // target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("Should not match Client",FuzzyBoolean.NO,ex.matchesMethodCall(a,Client.class,A.class,null)); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("Should match A",FuzzyBoolean.YES,ex.matchesMethodCall(a,Client.class,A.class,null)); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Should maybe match A",FuzzyBoolean.MAYBE,ex.matchesMethodCall(aa,A.class,A.class,null)); + // test args + ex = p.parsePointcutExpression("args(..,int)"); + assertEquals("Should match A.aa",FuzzyBoolean.YES,ex.matchesMethodCall(aa,A.class,A.class,null)); + assertEquals("Should match A.aaa",FuzzyBoolean.YES,ex.matchesMethodCall(aaa,A.class,A.class,null)); + assertEquals("Should not match A.a",FuzzyBoolean.NO,ex.matchesMethodCall(a,A.class,A.class,null)); + // within + ex = p.parsePointcutExpression("within(*..A)"); + assertEquals("Matches in class A",FuzzyBoolean.YES,ex.matchesMethodCall(a,A.class,A.class,null)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesMethodCall(a,B.class,A.class,null)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Should match",FuzzyBoolean.YES,ex.matchesMethodCall(b,B.class,B.class,bsaa)); + assertEquals("Should not match",FuzzyBoolean.NO,ex.matchesMethodCall(b,B.class,B.class,b)); + } + + public void testMatchesMethodExecution() { + PointcutExpression ex = p.parsePointcutExpression("execution(* *..A.aa(..))"); + assertEquals("Should match execution of A.aa",FuzzyBoolean.YES,ex.matchesMethodExecution(aa,A.class)); + assertEquals("Should match execution of B.aa",FuzzyBoolean.YES,ex.matchesMethodExecution(bsaa,B.class)); + assertEquals("Should not match execution of A.a",FuzzyBoolean.NO,ex.matchesMethodExecution(a,B.class)); + ex = p.parsePointcutExpression("call(* *..A.a*(int))"); + assertEquals("Should not match execution of A.a",FuzzyBoolean.NO,ex.matchesMethodExecution(a,B.class)); + // test this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("Should match A",FuzzyBoolean.YES,ex.matchesMethodExecution(a,A.class)); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesMethodExecution(a,A.class)); + assertEquals("Should match B",FuzzyBoolean.YES,ex.matchesMethodExecution(a,B.class)); + assertEquals("Does not match client",FuzzyBoolean.NO,ex.matchesMethodExecution(a,Client.class)); + // test target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("Should match A",FuzzyBoolean.YES,ex.matchesMethodExecution(a,A.class)); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesMethodExecution(a,A.class)); + assertEquals("Should match B",FuzzyBoolean.YES,ex.matchesMethodExecution(a,B.class)); + assertEquals("Does not match client",FuzzyBoolean.NO,ex.matchesMethodExecution(a,Client.class)); + // test args + ex = p.parsePointcutExpression("args(..,int)"); + assertEquals("Should match A.aa",FuzzyBoolean.YES,ex.matchesMethodExecution(aa,A.class)); + assertEquals("Should match A.aaa",FuzzyBoolean.YES,ex.matchesMethodExecution(aaa,A.class)); + assertEquals("Should not match A.a",FuzzyBoolean.NO,ex.matchesMethodExecution(a,A.class)); + // within + ex = p.parsePointcutExpression("within(*..A)"); + assertEquals("Matches in class A",FuzzyBoolean.YES,ex.matchesMethodExecution(a,A.class)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesMethodExecution(bsaa,B.class)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Should not match",FuzzyBoolean.NO,ex.matchesMethodExecution(a,A.class)); + } + + public void testMatchesConstructorCall() { + PointcutExpression ex = p.parsePointcutExpression("call(new(String))"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesConstructorCall(asCons,A.class,null)); + assertEquals("Should match B(String)", FuzzyBoolean.YES, ex.matchesConstructorCall(bsStringCons,Client.class,null)); + assertEquals("Should not match B()", FuzzyBoolean.NO,ex.matchesConstructorCall(bsCons,Client.class,null)); + ex = p.parsePointcutExpression("call(*..A.new(String))"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesConstructorCall(asCons,A.class,null)); + assertEquals("Should not match B(String)", FuzzyBoolean.NO, ex.matchesConstructorCall(bsStringCons,Client.class,null)); + // this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("Should match Client",FuzzyBoolean.YES,ex.matchesConstructorCall(asCons,Client.class,null)); + assertEquals("Should not match A",FuzzyBoolean.NO,ex.matchesConstructorCall(asCons,A.class,null)); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Should maybe match B",FuzzyBoolean.MAYBE,ex.matchesConstructorCall(asCons,A.class,null)); + // target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("Should not match Client",FuzzyBoolean.NO,ex.matchesConstructorCall(asCons,Client.class,null)); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("Should match A",FuzzyBoolean.YES,ex.matchesConstructorCall(asCons,A.class,null)); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Should maybe match A",FuzzyBoolean.MAYBE,ex.matchesConstructorCall(asCons,A.class,null)); + // args + ex = p.parsePointcutExpression("args(String)"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesConstructorCall(asCons,A.class,null)); + assertEquals("Should match B(String)", FuzzyBoolean.YES, ex.matchesConstructorCall(bsStringCons,Client.class,null)); + assertEquals("Should not match B()", FuzzyBoolean.NO,ex.matchesConstructorCall(bsCons,Client.class,null)); + // within + ex = p.parsePointcutExpression("within(*..A)"); + assertEquals("Matches in class A",FuzzyBoolean.YES,ex.matchesConstructorCall(asCons,A.class,null)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesConstructorCall(asCons,B.class,null)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Should match",FuzzyBoolean.YES,ex.matchesConstructorCall(bsCons,B.class,aa)); + assertEquals("Should not match",FuzzyBoolean.NO,ex.matchesConstructorCall(bsCons,B.class,b)); + } + + public void testMatchesConstructorExecution() { + PointcutExpression ex = p.parsePointcutExpression("execution(new(String))"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesConstructorExecution(asCons,A.class)); + assertEquals("Should match B(String)", FuzzyBoolean.YES, ex.matchesConstructorExecution(bsStringCons,Client.class)); + assertEquals("Should not match B()", FuzzyBoolean.NO,ex.matchesConstructorExecution(bsCons,Client.class)); + ex = p.parsePointcutExpression("execution(*..A.new(String))"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesConstructorExecution(asCons,A.class)); + assertEquals("Should not match B(String)", FuzzyBoolean.NO, ex.matchesConstructorExecution(bsStringCons,Client.class)); + // test this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("Should match A",FuzzyBoolean.YES,ex.matchesConstructorExecution(asCons,A.class)); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesConstructorExecution(asCons,A.class)); + assertEquals("Should match B",FuzzyBoolean.YES,ex.matchesConstructorExecution(asCons,B.class)); + assertEquals("Does not match client",FuzzyBoolean.NO,ex.matchesConstructorExecution(asCons,Client.class)); + // test target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("Should match A",FuzzyBoolean.YES,ex.matchesConstructorExecution(asCons,A.class)); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesConstructorExecution(asCons,A.class)); + assertEquals("Should match B",FuzzyBoolean.YES,ex.matchesConstructorExecution(asCons,B.class)); + assertEquals("Does not match client",FuzzyBoolean.NO,ex.matchesConstructorExecution(asCons,Client.class)); + // within + ex = p.parsePointcutExpression("within(*..A)"); + assertEquals("Matches in class A",FuzzyBoolean.YES,ex.matchesConstructorExecution(asCons,B.class)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesConstructorExecution(bsCons,B.class)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Does not match",FuzzyBoolean.NO,ex.matchesConstructorExecution(bsCons,B.class)); + // args + ex = p.parsePointcutExpression("args(String)"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesConstructorExecution(asCons,A.class)); + assertEquals("Should match B(String)", FuzzyBoolean.YES, ex.matchesConstructorExecution(bsStringCons,Client.class)); + assertEquals("Should not match B()", FuzzyBoolean.NO,ex.matchesConstructorExecution(bsCons,Client.class)); + } + + public void testMatchesAdviceExecution() { + PointcutExpression ex = p.parsePointcutExpression("adviceexecution()"); + assertEquals("Should match (advice) A.a",FuzzyBoolean.YES,ex.matchesAdviceExecution(a,A.class)); + // test this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("Should match Client",FuzzyBoolean.YES,ex.matchesAdviceExecution(a,Client.class)); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesAdviceExecution(a,A.class)); + assertEquals("Does not match client",FuzzyBoolean.NO,ex.matchesAdviceExecution(a,Client.class)); + // test target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("Should match Client",FuzzyBoolean.YES,ex.matchesAdviceExecution(a,Client.class)); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesAdviceExecution(a,A.class)); + assertEquals("Does not match client",FuzzyBoolean.NO,ex.matchesAdviceExecution(a,Client.class)); + // test within + ex = p.parsePointcutExpression("within(*..A)"); + assertEquals("Matches in class A",FuzzyBoolean.YES,ex.matchesAdviceExecution(a,A.class)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesAdviceExecution(b,B.class)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Does not match",FuzzyBoolean.NO,ex.matchesAdviceExecution(a,A.class)); + // test args + ex = p.parsePointcutExpression("args(..,int)"); + assertEquals("Should match A.aa",FuzzyBoolean.YES,ex.matchesAdviceExecution(aa,A.class)); + assertEquals("Should match A.aaa",FuzzyBoolean.YES,ex.matchesAdviceExecution(aaa,A.class)); + assertEquals("Should not match A.a",FuzzyBoolean.NO,ex.matchesAdviceExecution(a,A.class)); + } + + public void testMatchesHandler() { + PointcutExpression ex = p.parsePointcutExpression("handler(Exception)"); + assertEquals("Should match catch(Exception)",FuzzyBoolean.YES,ex.matchesHandler(Exception.class,Client.class,null)); + assertEquals("Should not match catch(Throwable)",FuzzyBoolean.NO,ex.matchesHandler(Throwable.class,Client.class,null)); + // test this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("Should match Client",FuzzyBoolean.YES,ex.matchesHandler(Exception.class,Client.class,null)); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesHandler(Exception.class,A.class,null)); + assertEquals("Does not match client",FuzzyBoolean.NO,ex.matchesHandler(Exception.class,Client.class,null)); + // target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("Should match Client",FuzzyBoolean.YES,ex.matchesHandler(Exception.class,Client.class,null)); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesHandler(Exception.class,A.class,null)); + assertEquals("Does not match client",FuzzyBoolean.NO,ex.matchesHandler(Exception.class,Client.class,null)); + // args + ex = p.parsePointcutExpression("args(Exception)"); + assertEquals("Should match Exception",FuzzyBoolean.YES, ex.matchesHandler(Exception.class,Client.class,null)); + assertEquals("Should match RuntimeException",FuzzyBoolean.YES, ex.matchesHandler(RuntimeException.class,Client.class,null)); + assertEquals("Should not match String",FuzzyBoolean.NO,ex.matchesHandler(String.class,Client.class,null)); + assertEquals("Maybe matches Throwable",FuzzyBoolean.MAYBE,ex.matchesHandler(Throwable.class,Client.class,null)); + // within + ex = p.parsePointcutExpression("within(*..Client)"); + assertEquals("Matches in class Client",FuzzyBoolean.YES,ex.matchesHandler(Exception.class,Client.class,null)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesHandler(Exception.class,B.class,null)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Matches within aa",FuzzyBoolean.YES,ex.matchesHandler(Exception.class,Client.class,aa)); + assertEquals("Does not match within b",FuzzyBoolean.NO,ex.matchesHandler(Exception.class,Client.class,b)); + } + + public void testMatchesInitialization() { + PointcutExpression ex = p.parsePointcutExpression("initialization(new(String))"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesInitialization(asCons)); + assertEquals("Should match B(String)", FuzzyBoolean.YES, ex.matchesInitialization(bsStringCons)); + assertEquals("Should not match B()", FuzzyBoolean.NO,ex.matchesInitialization(bsCons)); + ex = p.parsePointcutExpression("initialization(*..A.new(String))"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesInitialization(asCons)); + assertEquals("Should not match B(String)", FuzzyBoolean.NO, ex.matchesInitialization(bsStringCons)); + // test this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("Should match A",FuzzyBoolean.YES,ex.matchesInitialization(asCons)); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesInitialization(asCons)); + // test target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("Should match A",FuzzyBoolean.YES,ex.matchesInitialization(asCons)); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesInitialization(asCons)); + // within + ex = p.parsePointcutExpression("within(*..A)"); + assertEquals("Matches in class A",FuzzyBoolean.YES,ex.matchesInitialization(asCons)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesInitialization(bsCons)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Does not match",FuzzyBoolean.NO,ex.matchesInitialization(bsCons)); + // args + ex = p.parsePointcutExpression("args(String)"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesInitialization(asCons)); + assertEquals("Should match B(String)", FuzzyBoolean.YES, ex.matchesInitialization(bsStringCons)); + assertEquals("Should not match B()", FuzzyBoolean.NO,ex.matchesInitialization(bsCons)); + } + + public void testMatchesPreInitialization() { + PointcutExpression ex = p.parsePointcutExpression("preinitialization(new(String))"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesPreInitialization(asCons)); + assertEquals("Should match B(String)", FuzzyBoolean.YES, ex.matchesPreInitialization(bsStringCons)); + assertEquals("Should not match B()", FuzzyBoolean.NO,ex.matchesPreInitialization(bsCons)); + ex = p.parsePointcutExpression("preinitialization(*..A.new(String))"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesPreInitialization(asCons)); + assertEquals("Should not match B(String)", FuzzyBoolean.NO, ex.matchesPreInitialization(bsStringCons)); + // test this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("Should match A",FuzzyBoolean.YES,ex.matchesPreInitialization(asCons)); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesPreInitialization(asCons)); + // test target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("Should match A",FuzzyBoolean.YES,ex.matchesPreInitialization(asCons)); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("Maybe matches B",FuzzyBoolean.MAYBE,ex.matchesPreInitialization(asCons)); + // within + ex = p.parsePointcutExpression("within(*..A)"); + assertEquals("Matches in class A",FuzzyBoolean.YES,ex.matchesPreInitialization(asCons)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesPreInitialization(bsCons)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Does not match",FuzzyBoolean.NO,ex.matchesPreInitialization(bsCons)); + // args + ex = p.parsePointcutExpression("args(String)"); + assertEquals("Should match A(String)",FuzzyBoolean.YES, ex.matchesPreInitialization(asCons)); + assertEquals("Should match B(String)", FuzzyBoolean.YES, ex.matchesPreInitialization(bsStringCons)); + assertEquals("Should not match B()", FuzzyBoolean.NO,ex.matchesPreInitialization(bsCons)); } + + public void testMatchesStaticInitialization() { + // staticinit + PointcutExpression ex = p.parsePointcutExpression("staticinitialization(*..A+)"); + assertEquals("Matches A",FuzzyBoolean.YES,ex.matchesStaticInitialization(A.class)); + assertEquals("Matches B",FuzzyBoolean.YES,ex.matchesStaticInitialization(B.class)); + assertEquals("Doesn't match Client",FuzzyBoolean.NO,ex.matchesStaticInitialization(Client.class)); + // this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("No this",FuzzyBoolean.NO,ex.matchesStaticInitialization(A.class)); + // target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertEquals("No target",FuzzyBoolean.NO,ex.matchesStaticInitialization(A.class)); + // args + ex = p.parsePointcutExpression("args()"); + assertEquals("No args",FuzzyBoolean.NO,ex.matchesStaticInitialization(A.class)); + // within + ex = p.parsePointcutExpression("within(*..A)"); + assertEquals("Matches in class A",FuzzyBoolean.YES,ex.matchesStaticInitialization(A.class)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesStaticInitialization(B.class)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Does not match",FuzzyBoolean.NO,ex.matchesStaticInitialization(A.class)); + } + + public void testMatchesFieldSet() { + PointcutExpression ex = p.parsePointcutExpression("set(* *..A+.*)"); + assertEquals("matches x",FuzzyBoolean.YES,ex.matchesFieldSet(x,Client.class,A.class,null)); + assertEquals("matches y",FuzzyBoolean.YES,ex.matchesFieldSet(y,Client.class,B.class,null)); + assertEquals("does not match n",FuzzyBoolean.NO,ex.matchesFieldSet(n,A.class,Client.class,null)); + // this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("matches Client",FuzzyBoolean.YES,ex.matchesFieldSet(x,Client.class,A.class,null)); + assertEquals("does not match A",FuzzyBoolean.NO,ex.matchesFieldSet(n,A.class,Client.class,null)); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("maybe matches A",FuzzyBoolean.MAYBE,ex.matchesFieldSet(x,A.class,A.class,null)); + // target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("matches B",FuzzyBoolean.YES,ex.matchesFieldSet(y,Client.class,B.class,null)); + assertEquals("maybe matches A",FuzzyBoolean.MAYBE,ex.matchesFieldSet(x,Client.class,A.class,null)); + // args + ex = p.parsePointcutExpression("args(int)"); + assertEquals("matches x",FuzzyBoolean.YES,ex.matchesFieldSet(x,Client.class,A.class,null)); + assertEquals("matches y",FuzzyBoolean.YES,ex.matchesFieldSet(y,Client.class,B.class,null)); + assertEquals("does not match n",FuzzyBoolean.NO,ex.matchesFieldSet(n,A.class,Client.class,null)); + // within + ex = p.parsePointcutExpression("within(*..A)"); + assertEquals("Matches in class A",FuzzyBoolean.YES,ex.matchesFieldSet(x,A.class,A.class,null)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesFieldSet(x,B.class,A.class,null)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Should match",FuzzyBoolean.YES,ex.matchesFieldSet(x,A.class,A.class,aa)); + assertEquals("Should not match",FuzzyBoolean.NO,ex.matchesFieldSet(x,A.class,A.class,b)); + } + + public void testMatchesFieldGet() { + PointcutExpression ex = p.parsePointcutExpression("get(* *..A+.*)"); + assertEquals("matches x",FuzzyBoolean.YES,ex.matchesFieldGet(x,Client.class,A.class,null)); + assertEquals("matches y",FuzzyBoolean.YES,ex.matchesFieldGet(y,Client.class,B.class,null)); + assertEquals("does not match n",FuzzyBoolean.NO,ex.matchesFieldGet(n,A.class,Client.class,null)); + // this + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.Client)"); + assertEquals("matches Client",FuzzyBoolean.YES,ex.matchesFieldGet(x,Client.class,A.class,null)); + assertEquals("does not match A",FuzzyBoolean.NO,ex.matchesFieldGet(n,A.class,Client.class,null)); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("maybe matches A",FuzzyBoolean.MAYBE,ex.matchesFieldGet(x,A.class,A.class,null)); + // target + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.B)"); + assertEquals("matches B",FuzzyBoolean.YES,ex.matchesFieldGet(y,Client.class,B.class,null)); + assertEquals("maybe matches A",FuzzyBoolean.MAYBE,ex.matchesFieldGet(x,Client.class,A.class,null)); + // args + ex = p.parsePointcutExpression("args(int)"); + assertEquals("matches x",FuzzyBoolean.NO,ex.matchesFieldGet(x,Client.class,A.class,null)); + assertEquals("matches y",FuzzyBoolean.NO,ex.matchesFieldGet(y,Client.class,B.class,null)); + assertEquals("does not match n",FuzzyBoolean.NO,ex.matchesFieldGet(n,A.class,Client.class,null)); + // within + ex = p.parsePointcutExpression("within(*..A)"); + assertEquals("Matches in class A",FuzzyBoolean.YES,ex.matchesFieldGet(x,A.class,A.class,null)); + assertEquals("Does not match in class B",FuzzyBoolean.NO,ex.matchesFieldGet(x,B.class,A.class,null)); + // withincode + ex = p.parsePointcutExpression("withincode(* a*(..))"); + assertEquals("Should match",FuzzyBoolean.YES,ex.matchesFieldGet(x,A.class,A.class,aa)); + assertEquals("Should not match",FuzzyBoolean.NO,ex.matchesFieldGet(x,A.class,A.class,b)); + } + + public void testArgsMatching() { + // too few args + PointcutExpression ex = p.parsePointcutExpression("args(*,*,*,*)"); + assertEquals("Too few args",FuzzyBoolean.NO,ex.matchesMethodExecution(foo,Client.class)); + assertEquals("Matching #args",FuzzyBoolean.YES,ex.matchesMethodExecution(bar,Client.class)); + // one too few + ellipsis + ex = p.parsePointcutExpression("args(*,*,*,..)"); + assertEquals("Matches with ellipsis",FuzzyBoolean.YES,ex.matchesMethodExecution(foo,Client.class)); + // exact number + ellipsis + assertEquals("Matches with ellipsis",FuzzyBoolean.YES,ex.matchesMethodExecution(bar,Client.class)); + assertEquals("Does not match with ellipsis",FuzzyBoolean.NO,ex.matchesMethodExecution(a,A.class)); + // too many + ellipsis + ex = p.parsePointcutExpression("args(*,..,*)"); + assertEquals("Matches with ellipsis",FuzzyBoolean.YES,ex.matchesMethodExecution(bar,Client.class)); + assertEquals("Does not match with ellipsis",FuzzyBoolean.NO,ex.matchesMethodExecution(a,A.class)); + assertEquals("Matches with ellipsis",FuzzyBoolean.YES,ex.matchesMethodExecution(aaa,A.class)); + // exact match + ex = p.parsePointcutExpression("args(String,int,Number)"); + assertEquals("Matches exactly",FuzzyBoolean.YES,ex.matchesMethodExecution(foo,Client.class)); + // maybe match + ex = p.parsePointcutExpression("args(String,int,Double)"); + assertEquals("Matches maybe",FuzzyBoolean.MAYBE,ex.matchesMethodExecution(foo,Client.class)); + // never match + ex = p.parsePointcutExpression("args(String,Integer,Number)"); + assertEquals("Does not match",FuzzyBoolean.NO,ex.matchesMethodExecution(foo,Client.class)); + } + + public void testMatchesDynamically() { + // everything other than this,target,args should just return true + PointcutExpression ex = p.parsePointcutExpression("call(* *.*(..)) && execution(* *.*(..)) &&" + + "get(* *) && set(* *) && initialization(new(..)) && preinitialization(new(..)) &&" + + "staticinitialization(X) && adviceexecution() && within(Y) && withincode(* *.*(..)))"); + assertTrue("Matches dynamically",ex.matchesDynamically(a,b,new Object[0])); + // this + ex = p.parsePointcutExpression("this(String)"); + assertTrue("String matches",ex.matchesDynamically("",this,new Object[0])); + assertFalse("Object doesn't match",ex.matchesDynamically(new Object(),this,new Object[0])); + ex = p.parsePointcutExpression("this(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertTrue("A matches",ex.matchesDynamically(new A(""),this,new Object[0])); + assertTrue("B matches",ex.matchesDynamically(new B(""),this,new Object[0])); + // target + ex = p.parsePointcutExpression("target(String)"); + assertTrue("String matches",ex.matchesDynamically(this,"",new Object[0])); + assertFalse("Object doesn't match",ex.matchesDynamically(this,new Object(),new Object[0])); + ex = p.parsePointcutExpression("target(org.aspectj.weaver.tools.PointcutExpressionTest.A)"); + assertTrue("A matches",ex.matchesDynamically(this,new A(""),new Object[0])); + assertTrue("B matches",ex.matchesDynamically(this,new B(""),new Object[0])); + // args + ex = p.parsePointcutExpression("args(*,*,*,*)"); + assertFalse("Too few args",ex.matchesDynamically(null,null,new Object[]{a,b})); + assertTrue("Matching #args",ex.matchesDynamically(null,null,new Object[]{a,b,aa,aaa})); + // one too few + ellipsis + ex = p.parsePointcutExpression("args(*,*,*,..)"); + assertTrue("Matches with ellipsis",ex.matchesDynamically(null,null,new Object[]{a,b,aa,aaa})); + // exact number + ellipsis + assertTrue("Matches with ellipsis",ex.matchesDynamically(null,null,new Object[]{a,b,aa})); + assertFalse("Does not match with ellipsis",ex.matchesDynamically(null,null,new Object[]{a,b})); + // too many + ellipsis + ex = p.parsePointcutExpression("args(*,..,*)"); + assertTrue("Matches with ellipsis",ex.matchesDynamically(null,null,new Object[]{a,b,aa,aaa})); + assertFalse("Does not match with ellipsis",ex.matchesDynamically(null,null,new Object[]{a})); + assertTrue("Matches with ellipsis",ex.matchesDynamically(null,null,new Object[]{a,b})); + // exact match + ex = p.parsePointcutExpression("args(String,int,Number)"); + assertTrue("Matches exactly",ex.matchesDynamically(null,null,new Object[]{"",new Integer(5),new Double(5.0)})); + ex = p.parsePointcutExpression("args(String,Integer,Number)"); + assertTrue("Matches exactly",ex.matchesDynamically(null,null,new Object[]{"",new Integer(5),new Double(5.0)})); + // never match + ex = p.parsePointcutExpression("args(String,Integer,Number)"); + assertFalse("Does not match",ex.matchesDynamically(null,null,new Object[]{a,b,aa})); +} + + public void testGetPointcutExpression() { + PointcutExpression ex = p.parsePointcutExpression("staticinitialization(*..A+)"); + assertEquals("staticinitialization(*..A+)",ex.getPointcutExpression()); + } + + protected void setUp() throws Exception { + super.setUp(); + p = new PointcutParser(); + asCons = A.class.getConstructor(new Class[]{String.class}); + bsCons = B.class.getConstructor(new Class[0]); + bsStringCons = B.class.getConstructor(new Class[]{String.class}); + a = A.class.getMethod("a",new Class[0]); + aa = A.class.getMethod("aa",new Class[]{int.class}); + aaa = A.class.getMethod("aaa",new Class[]{String.class,int.class}); + x = A.class.getDeclaredField("x"); + y = B.class.getDeclaredField("y"); + b = B.class.getMethod("b",new Class[0]); + bsaa = B.class.getMethod("aa",new Class[]{int.class}); + n = Client.class.getDeclaredField("n"); + foo = Client.class.getDeclaredMethod("foo",new Class[]{String.class,int.class,Number.class}); + bar = Client.class.getDeclaredMethod("bar",new Class[]{String.class,int.class,Integer.class,Number.class}); + } + + static class A { + public A(String s) {} + public void a() {} + public void aa(int i) {} + public void aaa(String s, int i) {} + int x; + } + + static class B extends A { + public B() {super("");} + public B(String s) {super(s);} + public String b() { return null; } + public void aa(int i) {} + int y; + } + + static class Client { + Number n; + public void foo(String s, int i, Number n) {} + public void bar(String s, int i, Integer i2, Number n) {} + } +} diff --git a/weaver/testsrc/org/aspectj/weaver/tools/PointcutParserTest.java b/weaver/testsrc/org/aspectj/weaver/tools/PointcutParserTest.java new file mode 100644 index 000000000..aea55aaf3 --- /dev/null +++ b/weaver/testsrc/org/aspectj/weaver/tools/PointcutParserTest.java @@ -0,0 +1,201 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM Corporation. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * ******************************************************************/ +package org.aspectj.weaver.tools; + +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; + +/** + * Test cases for the PointcutParser class + */ +public class PointcutParserTest extends TestCase { + + public void testGetAllSupportedPointcutPrimitives() { + Set s = PointcutParser.getAllSupportedPointcutPrimitives(); + assertEquals("Should be 14 elements in the set",14,s.size()); + assertFalse("Should not contain if pcd",s.contains(PointcutPrimitives.IF)); + assertFalse("Should not contain cflow pcd",s.contains(PointcutPrimitives.CFLOW)); + assertFalse("Should not contain cflowbelow pcd",s.contains(PointcutPrimitives.CFLOW_BELOW)); + } + + public void testEmptyConstructor() { + PointcutParser parser = new PointcutParser(); + Set s = parser.getSupportedPrimitives(); + assertEquals("Should be 14 elements in the set",14,s.size()); + assertFalse("Should not contain if pcd",s.contains(PointcutPrimitives.IF)); + assertFalse("Should not contain cflow pcd",s.contains(PointcutPrimitives.CFLOW)); + assertFalse("Should not contain cflowbelow pcd",s.contains(PointcutPrimitives.CFLOW_BELOW)); + } + + public void testSetConstructor() { + Set p = PointcutParser.getAllSupportedPointcutPrimitives(); + PointcutParser parser = new PointcutParser(p); + assertEquals("Should use the set we pass in",p,parser.getSupportedPrimitives()); + Set q = new HashSet(); + q.add(PointcutPrimitives.ARGS); + parser = new PointcutParser(q); + assertEquals("Should have only one element in set",1,parser.getSupportedPrimitives().size()); + assertEquals("Should only have ARGS pcd",PointcutPrimitives.ARGS, + parser.getSupportedPrimitives().iterator().next()); + } + + public void testParsePointcutExpression() { + PointcutParser p = new PointcutParser(); + PointcutExpression pEx = p.parsePointcutExpression( + "(adviceexecution() || execution(* *.*(..)) || handler(Exception) || " + + "call(Foo Bar+.*(Goo)) || get(* foo) || set(Foo+ (Goo||Moo).s*) || " + + "initialization(Foo.new(..)) || preinitialization(*.new(Foo,..)) || " + + "staticinitialization(org.xzy.abc..*)) && (this(Foo) || target(Boo) ||" + + "args(A,B,C)) && !handler(X)"); + try { + pEx = p.parsePointcutExpression("gobble-de-gook()"); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException ex) {} + } + + public void testParseIfPCD() { + PointcutParser p = new PointcutParser(); + try { + p.parsePointcutExpression("if(true)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("if pointcuts and reference pointcuts are not supported")); + } + } + + public void testParseCflowPCDs() { + PointcutParser p = new PointcutParser(); + try { + p.parsePointcutExpression("cflow(this(t))"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("cflow and cflowbelow are not supported")); + } + try { + p.parsePointcutExpression("cflowbelow(this(t))"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("cflow and cflowbelow are not supported")); + } + } + + public void testParseReferencePCDs() { + PointcutParser p = new PointcutParser(); + try { + p.parsePointcutExpression("bananas(x)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("if pointcuts and reference pointcuts are not supported")); + } + } + + public void testParseUnsupportedPCDs() { + Set s = new HashSet(); + PointcutParser p = new PointcutParser(s); + try { + p.parsePointcutExpression("args(x)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("args is not supported")); + } + try { + p.parsePointcutExpression("within(x)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("within is not supported")); + } + try { + p.parsePointcutExpression("withincode(new(..))"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("withincode is not supported")); + } + try { + p.parsePointcutExpression("handler(Exception)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("handler is not supported")); + } + try { + p.parsePointcutExpression("this(X)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("this is not supported")); + } + try { + p.parsePointcutExpression("target(X)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("target is not supported")); + } + try { + p.parsePointcutExpression("this(X) && target(Y)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("this is not supported")); + } + try { + p.parsePointcutExpression("this(X) || target(Y)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("this is not supported")); + } + try { + p.parsePointcutExpression("!this(X)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("this is not supported")); + } + try { + p.parsePointcutExpression("call(* *.*(..))"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("call is not supported")); + } + try { + p.parsePointcutExpression("execution(* *.*(..))"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("execution is not supported")); + } + try { + p.parsePointcutExpression("get(* *)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("get is not supported")); + } + try { + p.parsePointcutExpression("set(* *)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("set is not supported")); + } + try { + p.parsePointcutExpression("initialization(new(..))"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("initialization is not supported")); + } + try { + p.parsePointcutExpression("preinitialization(new(..))"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("preinitialization is not supported")); + } + try { + p.parsePointcutExpression("staticinitialization(T)"); + fail("Expected UnsupportedOperationException"); + } catch(UnsupportedOperationException ex) { + assertTrue(ex.getMessage().startsWith("staticinitialization is not supported")); + } + } +} |