diff options
author | acolyer <acolyer> | 2004-12-02 12:30:29 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2004-12-02 12:30:29 +0000 |
commit | ab47acfec80ca851410350bef322464bff8f4c47 (patch) | |
tree | 1abdacfb4a69d642a7523870d724f96f00df031b | |
parent | 489e9a0aff588c158b3b1c8555307affbd87a1eb (diff) | |
download | aspectj-ab47acfec80ca851410350bef322464bff8f4c47.tar.gz aspectj-ab47acfec80ca851410350bef322464bff8f4c47.zip |
APIs allowing 3rd parties to integrate with AspectJ's pointcut parsing and matching
19 files changed, 823 insertions, 19 deletions
diff --git a/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java b/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java new file mode 100644 index 000000000..60d1e1294 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java @@ -0,0 +1,193 @@ +/* ******************************************************************* + * 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.internal.tools; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.weaver.patterns.Pointcut; +import org.aspectj.weaver.tools.FuzzyBoolean; +import org.aspectj.weaver.tools.PointcutExpression; + +/** + * Map from weaver.tools interface to internal Pointcut implementation... + */ +public class PointcutExpressionImpl implements PointcutExpression { + + private Pointcut pointcut; + + public PointcutExpressionImpl(Pointcut pointcut) { + this.pointcut = pointcut; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesMethodCall(java.lang.reflect.Method, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesMethodCall(Method aMethod, Class thisClass, + Class targetClass, Member withinCode) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.METHOD_CALL, + aMethod, + thisClass, + targetClass, + withinCode)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesMethodExecution(java.lang.reflect.Method, java.lang.Class) + */ + public FuzzyBoolean matchesMethodExecution(Method aMethod, Class thisClass) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.METHOD_EXECUTION, + aMethod, + thisClass, + thisClass, + null)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesConstructorCall(java.lang.reflect.Constructor, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesConstructorCall(Constructor aConstructor, + Class thisClass, Member withinCode) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.CONSTRUCTOR_CALL, + aConstructor, + thisClass, + aConstructor.getDeclaringClass(), + withinCode)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesConstructorExecution(java.lang.reflect.Constructor) + */ + public FuzzyBoolean matchesConstructorExecution(Constructor aConstructor, Class thisClass) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.CONSTRUCTOR_EXECUTION, + aConstructor, + thisClass, + thisClass, + null)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesAdviceExecution(java.lang.reflect.Method, java.lang.Class) + */ + public FuzzyBoolean matchesAdviceExecution(Method anAdviceMethod, + Class thisClass) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.ADVICE_EXECUTION, + anAdviceMethod, + thisClass, + thisClass, + null)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesHandler(java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesHandler(Class exceptionType, Class inClass, + Member withinCode) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.EXCEPTION_HANDLER, + null, + inClass, + exceptionType, + withinCode)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesInitialization(java.lang.reflect.Constructor) + */ + public FuzzyBoolean matchesInitialization(Constructor aConstructor) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.INITIALIZATION, + aConstructor, + aConstructor.getDeclaringClass(), + aConstructor.getDeclaringClass(), + null)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesPreInitialization(java.lang.reflect.Constructor) + */ + public FuzzyBoolean matchesPreInitialization(Constructor aConstructor) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.PREINTIALIZATION, + aConstructor, + aConstructor.getDeclaringClass(), + aConstructor.getDeclaringClass(), + null)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesStaticInitialization(java.lang.Class) + */ + public FuzzyBoolean matchesStaticInitialization(Class aClass) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.STATICINITIALIZATION, + null, + aClass, + aClass, + null + )); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesFieldSet(java.lang.reflect.Field, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesFieldSet(Field aField, Class thisClass, + Class targetClass, Member withinCode) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.FIELD_SET, + aField, + thisClass, + targetClass, + withinCode)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesFieldGet(java.lang.reflect.Field, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesFieldGet(Field aField, Class thisClass, + Class targetClass, Member withinCode) { + return fuzzyMatch(pointcut.matchesStatically( + JoinPoint.FIELD_GET, + aField, + thisClass, + targetClass, + withinCode)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + return pointcut.matchesDynamically(thisObject,targetObject,args); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#getPointcutExpression() + */ + public String getPointcutExpression() { + return pointcut.toString(); + } + + private FuzzyBoolean fuzzyMatch(org.aspectj.util.FuzzyBoolean fb) { + if (fb == org.aspectj.util.FuzzyBoolean.YES) return FuzzyBoolean.YES; + if (fb == org.aspectj.util.FuzzyBoolean.NO) return FuzzyBoolean.NO; + if (fb == org.aspectj.util.FuzzyBoolean.MAYBE) return FuzzyBoolean.MAYBE; + throw new IllegalArgumentException("Cant match FuzzyBoolean " + fb); + } +} diff --git a/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java b/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java index 05952f593..b904b8396 100644 --- a/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java @@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Member; import org.aspectj.lang.JoinPoint; import org.aspectj.util.FuzzyBoolean; @@ -51,6 +52,26 @@ public class AndPointcut extends Pointcut { return left.match(jpsp).and(right.match(jpsp)); } + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + return left.matchesDynamically(thisObject,targetObject,args) && + right.matchesDynamically(thisObject,targetObject,args); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically( + String joinpointKind, Member member, Class thisClass, + Class targetClass, Member withinCode) { + return left.matchesStatically(joinpointKind,member,thisClass,targetClass,withinCode) + .and( + right.matchesStatically(joinpointKind,member,thisClass,targetClass,withinCode)); + } + public String toString() { return "(" + left.toString() + " && " + right.toString() + ")"; } diff --git a/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java index 179684bc3..1e53c0b0c 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java @@ -16,6 +16,9 @@ package org.aspectj.weaver.patterns; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; import java.util.Collection; import java.util.Iterator; @@ -66,26 +69,58 @@ public class ArgsPointcut extends NameBindingPointcut { // are the sigs compatible too... CodeSignature sig = (CodeSignature)jp.getSignature(); Class[] pTypes = sig.getParameterTypes(); - Collection tps = arguments.getExactTypes(); - int sigIndex = 0; - for (Iterator iter = tps.iterator(); iter.hasNext();) { - TypeX tp = (TypeX) iter.next(); - Class lookForClass = getPossiblyBoxed(tp); - if (lookForClass != null) { - boolean foundMatchInSig = false; - while (sigIndex < pTypes.length && !foundMatchInSig) { - if (pTypes[sigIndex++] == lookForClass) foundMatchInSig = true; - } - if (!foundMatchInSig) { - ret = FuzzyBoolean.NO; - break; - } + ret = checkSignatureMatch(pTypes); + } + return ret; + } + + /** + * @param ret + * @param pTypes + * @return + */ + private FuzzyBoolean checkSignatureMatch(Class[] pTypes) { + Collection tps = arguments.getExactTypes(); + int sigIndex = 0; + for (Iterator iter = tps.iterator(); iter.hasNext();) { + TypeX tp = (TypeX) iter.next(); + Class lookForClass = getPossiblyBoxed(tp); + if (lookForClass != null) { + boolean foundMatchInSig = false; + while (sigIndex < pTypes.length && !foundMatchInSig) { + if (pTypes[sigIndex++] == lookForClass) foundMatchInSig = true; + } + if (!foundMatchInSig) { + return FuzzyBoolean.NO; } } } - return ret; + return FuzzyBoolean.YES; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + return (arguments.matches(args,TypePattern.DYNAMIC) == FuzzyBoolean.YES); } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically(String joinpointKind, Member member, + Class thisClass, Class targetClass, Member withinCode) { + Class[] paramTypes = new Class[0]; + if (member instanceof Method) { + paramTypes = ((Method)member).getParameterTypes(); + } else if (member instanceof Constructor) { + paramTypes = ((Constructor)member).getParameterTypes(); + } else { + return FuzzyBoolean.NO; + } + return arguments.matches(paramTypes,TypePattern.DYNAMIC); + } private Class getPossiblyBoxed(TypeX tp) { Class ret = (Class) ExactTypePattern.primitiveTypesMap.get(tp.getName()); if (ret == null) ret = (Class) ExactTypePattern.boxedPrimitivesMap.get(tp.getName()); diff --git a/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java b/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java index 422fda50e..5f56e2a9b 100644 --- a/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java @@ -75,6 +75,24 @@ public class CflowPointcut extends Pointcut { return FuzzyBoolean.MAYBE; } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + throw new UnsupportedOperationException("cflow pointcut matching not supported by this operation"); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically( + String joinpointKind, java.lang.reflect.Member member, + Class thisClass, Class targetClass, + java.lang.reflect.Member withinCode) { + throw new UnsupportedOperationException("cflow pointcut matching not supported by this operation"); + } + public void write(DataOutputStream s) throws IOException { s.writeByte(Pointcut.CFLOW); entry.write(s); diff --git a/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java index e02d6f7d2..b88bb7a50 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java @@ -51,6 +51,24 @@ public class ConcreteCflowPointcut extends Pointcut { return FuzzyBoolean.MAYBE; } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + throw new UnsupportedOperationException("cflow pointcut matching not supported by this operation"); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically( + String joinpointKind, java.lang.reflect.Member member, + Class thisClass, Class targetClass, + java.lang.reflect.Member withinCode) { + throw new UnsupportedOperationException("cflow pointcut matching not supported by this operation"); + } + public void write(DataOutputStream s) throws IOException { throw new RuntimeException("unimplemented"); } diff --git a/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java b/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java index c1fcfdbd3..f376851fb 100644 --- a/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java @@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Member; import org.aspectj.lang.JoinPoint; import org.aspectj.util.FuzzyBoolean; @@ -63,7 +64,24 @@ public class HandlerPointcut extends Pointcut { } } - + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + if (args.length > 0) { + return (exceptionType.matches(args[0],TypePattern.STATIC) == FuzzyBoolean.YES); + } else return false; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + 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); + } public boolean equals(Object other) { if (!(other instanceof HandlerPointcut)) return false; diff --git a/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java b/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java index 62f65f485..2a40e3e10 100644 --- a/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java @@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Member; import java.util.ArrayList; import java.util.List; @@ -61,6 +62,23 @@ public class IfPointcut extends Pointcut { return FuzzyBoolean.MAYBE; } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + throw new UnsupportedOperationException("If pointcut matching not supported by this operation"); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically( + String joinpointKind, Member member, Class thisClass, + Class targetClass, Member withinCode) { + throw new UnsupportedOperationException("If pointcut matching not supported by this operation"); + } + public void write(DataOutputStream s) throws IOException { s.writeByte(Pointcut.IF); testMethod.write(s); diff --git a/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java b/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java index 65da3efac..b7b9d6e44 100644 --- a/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java @@ -24,7 +24,6 @@ import org.aspectj.weaver.Checker; import org.aspectj.weaver.ISourceContext; import org.aspectj.weaver.IntMap; import org.aspectj.weaver.Member; -import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedTypeX; import org.aspectj.weaver.Shadow; import org.aspectj.weaver.ShadowMunger; @@ -90,6 +89,26 @@ public class KindedPointcut extends Pointcut { return FuzzyBoolean.NO; } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + return true; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically(String joinpointKind, + 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.NO; + } + private void warnOnConfusingSig(Shadow shadow) { // no warnings for declare error/warning if (munger instanceof Checker) return; diff --git a/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java b/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java index f57d2475d..292bf92ee 100644 --- a/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java @@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Member; import org.aspectj.lang.JoinPoint; import org.aspectj.util.FuzzyBoolean; @@ -54,6 +55,22 @@ public class NotPointcut extends Pointcut { return body.match(jpsp).not(); } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + return !body.matchesDynamically(thisObject,targetObject,args); + } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically( + String joinpointKind, Member member, Class thisClass, + Class targetClass, Member withinCode) { + return body.matchesStatically(joinpointKind,member,thisClass,targetClass,withinCode).not(); + } + public String toString() { return "!" + body.toString(); diff --git a/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java b/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java index 225b100d7..bb7285003 100644 --- a/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java @@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Member; import org.aspectj.lang.JoinPoint; import org.aspectj.util.FuzzyBoolean; @@ -51,7 +52,27 @@ public class OrPointcut extends Pointcut { public FuzzyBoolean match(JoinPoint.StaticPart jpsp) { return left.match(jpsp).or(right.match(jpsp)); } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + return left.matchesDynamically(thisObject,targetObject,args) + || + right.matchesDynamically(thisObject,targetObject,args); + } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically( + String joinpointKind, Member member, Class thisClass, + Class targetClass, Member withinCode) { + return left.matchesStatically(joinpointKind,member,thisClass,targetClass,withinCode) + .or( + right.matchesStatically(joinpointKind,member,thisClass,targetClass,withinCode)); + } public String toString() { return "(" + left.toString() + " || " + right.toString() + ")"; } diff --git a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java index 31afd6039..b7ebca222 100644 --- a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java @@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Member; import org.aspectj.lang.JoinPoint; import org.aspectj.util.FuzzyBoolean; @@ -40,7 +41,7 @@ import org.aspectj.weaver.ast.Test; * @author Erik Hilsdale * @author Jim Hugunin */ -public abstract class Pointcut extends PatternNode { +public abstract class Pointcut extends PatternNode implements PointcutExpressionMatching { public static final class State extends TypeSafeEnum { public State(String name, int key) { super(name, key); @@ -90,7 +91,24 @@ public abstract class Pointcut extends PatternNode { public FuzzyBoolean match(JoinPoint.StaticPart jpsp) { throw new UnsupportedOperationException("Pointcut expression " + this.toString() + "cannot be matched at runtime"); } - + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesDynamically(java.lang.String, java.lang.reflect.Member, java.lang.Object, java.lang.Object, java.lang.reflect.Member) + */ + public boolean matchesDynamically( + Object thisObject, Object targetObject, Object[] args) { + throw new UnsupportedOperationException("Pointcut expression " + this.toString() + "cannot be matched by this operation"); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.tools.PointcutExpression#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically( + String joinpointKind, Member member, Class thisClass, + Class targetClass, Member withinCode) { + throw new UnsupportedOperationException("Pointcut expression " + this.toString() + "cannot be matched by this operation"); + } + public static final byte KINDED = 1; public static final byte WITHIN = 2; public static final byte THIS_OR_TARGET = 3; @@ -257,6 +275,23 @@ public abstract class Pointcut extends PatternNode { return FuzzyBoolean.NO; } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, + Object targetObject, Object[] args) { + return false; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically( + String joinpointKind, Member member, Class thisClass, + Class targetClass, Member withinCode) { + return FuzzyBoolean.NO; + } + public void resolveBindings(IScope scope, Bindings bindings) { } diff --git a/weaver/src/org/aspectj/weaver/patterns/PointcutExpressionMatching.java b/weaver/src/org/aspectj/weaver/patterns/PointcutExpressionMatching.java new file mode 100644 index 000000000..0e054ed45 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/PointcutExpressionMatching.java @@ -0,0 +1,40 @@ +/* ******************************************************************* + * 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.patterns; + +import java.lang.reflect.Member; + +import org.aspectj.util.FuzzyBoolean; + + +/** + * Interface used by PointcutExpressionImpl to determine matches. + */ +public interface PointcutExpressionMatching { + + FuzzyBoolean matchesStatically( + String joinpointKind, + Member member, + Class thisClass, + Class targetClass, + Member withinCode); + + /** + * Only considers this, target, and args primitives, returns + * true for all others. + * @param thisObject + * @param targetObject + * @param args + * @return + */ + boolean matchesDynamically( + Object thisObject, + Object targetObject, + Object[] args); +} diff --git a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java index edaa45d8a..fef2dc122 100644 --- a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java @@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns; 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.Method; import java.util.ArrayList; @@ -266,6 +267,49 @@ public class SignaturePattern extends PatternNode { return false; } + public boolean matches(Class declaringClass, java.lang.reflect.Member member) { + if (kind == Member.ADVICE) return true; + if (kind == Member.POINTCUT) return false; + if ((member != null) && !(modifiers.matches(member.getModifiers()))) return false; + if (kind == Member.STATIC_INITIALIZATION) { + return declaringType.matchesStatically(declaringClass); + } + if (kind == Member.FIELD) { + if (!(member instanceof Field)) return false; + + Class fieldTypeClass = ((Field)member).getType(); + if (!returnType.matchesStatically(fieldTypeClass)) return false; + if (!name.matches(member.getName())) return false; + return declaringTypeMatch(member.getDeclaringClass()); + } + if (kind == Member.METHOD) { + if (! (member instanceof Method)) return false; + + Class returnTypeClass = ((Method)member).getReturnType(); + Class[] params = ((Method)member).getParameterTypes(); + Class[] exceptionTypes = ((Method)member).getExceptionTypes(); + if (!returnType.matchesStatically(returnTypeClass)) return false; + if (!name.matches(member.getName())) return false; + if (!parameterTypes.matches(params, TypePattern.STATIC).alwaysTrue()) { + return false; + } + if (!throwsPattern.matches(exceptionTypes)) return false; + return declaringTypeMatch(member.getDeclaringClass()); // XXXAJ5 - Need to make this a covariant aware version for dynamic JP matching to work + } + if (kind == Member.CONSTRUCTOR) { + if (! (member instanceof Constructor)) return false; + + Class[] params = ((Constructor)member).getParameterTypes(); + Class[] exceptionTypes = ((Constructor)member).getExceptionTypes(); + if (!parameterTypes.matches(params, TypePattern.STATIC).alwaysTrue()) { + return false; + } + if (!throwsPattern.matches(exceptionTypes)) return false; + return declaringType.matchesStatically(declaringClass); + } + return false; + } + // For methods, the above covariant aware version (declaringTypeMatchAllowingForCovariance) is used - this version is still here for fields private boolean declaringTypeMatch(TypeX onTypeUnresolved, Member member, World world) { ResolvedTypeX onType = onTypeUnresolved.resolve(world); @@ -296,6 +340,16 @@ public class SignaturePattern extends PatternNode { return false; } + private boolean declaringTypeMatch(Class clazz) { + if (clazz == null) return false; + if (declaringType.matchesStatically(clazz)) return true; + Class[] ifs = clazz.getInterfaces(); + for (int i = 0; i<ifs.length; i++) { + if (declaringType.matchesStatically(ifs[i])) return true; + } + return declaringTypeMatch(clazz.getSuperclass()); + } + private Collection getDeclaringTypes(Signature sig) { List l = new ArrayList(); Class onType = sig.getDeclaringType(); diff --git a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java index 31fe527e3..f1592f161 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java @@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Member; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; @@ -77,6 +78,25 @@ public class ThisOrTargetPointcut extends NameBindingPointcut { return type.matches(toMatch.getClass(), TypePattern.DYNAMIC); } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + Object toMatch = isThis ? thisObject : targetObject; + if (toMatch == null) return false; + return (type.matches(toMatch.getClass(), TypePattern.DYNAMIC)).alwaysTrue(); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically(String joinpointKind, Member member, + Class thisClass, Class targetClass, Member withinCode) { + Class typeToMatch = isThis ? thisClass : targetClass; + return type.matches(typeToMatch, TypePattern.DYNAMIC); + } + public void write(DataOutputStream s) throws IOException { s.writeByte(Pointcut.THIS_OR_TARGET); s.writeBoolean(isThis); diff --git a/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java index 92e24803f..582d39757 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java @@ -16,6 +16,7 @@ package org.aspectj.weaver.patterns; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Member; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; @@ -67,6 +68,24 @@ public class WithinPointcut extends Pointcut { return isWithinType(encJp.getSignature().getDeclaringType()); } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + return true; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically( + String joinpointKind, Member member, Class thisClass, + Class targetClass, Member withinCode) { + return isWithinType(thisClass); + } + private FuzzyBoolean isWithinType(Class type) { while (type != null) { if (typePattern.matchesStatically(type)) { diff --git a/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java index c666d53ac..3467d6eb6 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java @@ -16,8 +16,10 @@ package org.aspectj.weaver.patterns; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Member; import org.aspectj.lang.JoinPoint; +import org.aspectj.runtime.reflect.Factory; import org.aspectj.util.FuzzyBoolean; import org.aspectj.weaver.ISourceContext; import org.aspectj.weaver.IntMap; @@ -48,6 +50,22 @@ public class WithincodePointcut extends Pointcut { return FuzzyBoolean.fromBoolean(signature.matches(encJP)); } + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesDynamically(java.lang.Object, java.lang.Object, java.lang.Object[]) + */ + public boolean matchesDynamically(Object thisObject, Object targetObject, + Object[] args) { + return true; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#matchesStatically(java.lang.String, java.lang.reflect.Member, java.lang.Class, java.lang.Class, java.lang.reflect.Member) + */ + public FuzzyBoolean matchesStatically(String joinpointKind, Member member, + Class thisClass, Class targetClass, Member withinCode) { + return FuzzyBoolean.fromBoolean(signature.matches(Factory.makeEncSJP(withinCode))); + } + public void write(DataOutputStream s) throws IOException { s.writeByte(Pointcut.WITHINCODE); signature.write(s); diff --git a/weaver/src/org/aspectj/weaver/tools/FuzzyBoolean.java b/weaver/src/org/aspectj/weaver/tools/FuzzyBoolean.java new file mode 100644 index 000000000..fbf0f16a6 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/tools/FuzzyBoolean.java @@ -0,0 +1,30 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * 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; + +/** This class implements a boolean that includes a "maybe" + */ +public class FuzzyBoolean { + + // Note :- this implementation is not safe under serialization / deserialization + + 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 fromBoolean(boolean b) { + return b ? YES : NO; + } + + private FuzzyBoolean() {} +} diff --git a/weaver/src/org/aspectj/weaver/tools/PointcutExpression.java b/weaver/src/org/aspectj/weaver/tools/PointcutExpression.java new file mode 100644 index 000000000..2da27a246 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/tools/PointcutExpression.java @@ -0,0 +1,167 @@ +/* ******************************************************************* + * 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.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +/** + * Represents an AspectJ pointcut expression and provides convenience methods to determine + * whether or not the pointcut matches join points specified in terms of the + * java.lang.reflect interfaces. + */ +public interface PointcutExpression { + + /** + * Determine whether or not this pointcut matches a method call to the given method. + * @param aMethod the method being called + * @param thisClass the type making the method call + * @param targetClass the static type of the target of the call + * (may be a subtype of aMethod.getDeclaringClass() ) + * @param withinCode the Method or Constructor from within which the call is made + * @return a FuzzyBoolean indicating whether the pointcut always matches such a join point (YES), + * never matches such a join point (NO), or may match such a join point (MAYBE) depending on the runtime + * types of the arguments, caller, and called object. + */ + FuzzyBoolean matchesMethodCall(Method aMethod, Class thisClass, Class targetClass, Member withinCode); + + /** + * Determine whether or not this pointcut matches the execution of a given method. + * @param aMethod the method being executed + * @param thisClass the static type of the object in which the method is executing + * (may be a subtype of aMethod.getDeclaringClass()) + * @return a FuzzyBoolean indicating whether the pointcut always matches such a join point (YES), + * never matches such a join point (NO), or may match such a join point (MAYBE) depending on the + * runtime types of the arguments and executing object. + */ + FuzzyBoolean matchesMethodExecution(Method aMethod, Class thisClass); + + /** + * Determine whether or not this pointcut matches a call to the given constructor. + * @param aConstructor the constructor being called + * @param thisClass the type making the constructor call + * @param withinCode the Method or Constructor from within which the call is made + * @return a FuzzyBoolean indicating whether the pointcut always matches such a join point (YES), + * never matches such a join point (NO), or may match such a join point (MAYBE) depending on the runtime + * types of the arguments and caller. + */ + FuzzyBoolean matchesConstructorCall(Constructor aConstructor, Class thisClass, Member withinCode); + + /** + * Determine whether or not this pointcut matches the execution of a given constructor. + * @param aConstructor the constructor being executed + * @param thisClass the static type of the object in which the constructor is executing + * (may be a subtype of aConstructor.getDeclaringClass()) + * @return a FuzzyBoolean indicating whether the pointcut always matches such a join point (YES), + * never matches such a join point (NO), or may match such a join point (MAYBE) depending on the + * runtime types of the arguments and executing object. + */ + FuzzyBoolean matchesConstructorExecution(Constructor aConstructor, Class thisClass); + + /** + * Determine whether or not this pointcut matches the execution of a given piece of advice. + * @param anAdviceMethod a method representing the advice being executed + * @param thisClass the static type of the aspect in which the advice is executing + * (may be a subtype of anAdviceMethod.getDeclaringClass()) + * @return a FuzzyBoolean indicating whether the pointcut always matches such a join point (YES), + * never matches such a join point (NO), or may match such a join point (MAYBE) depending on the + * runtime type of the executing aspect. + */ + FuzzyBoolean matchesAdviceExecution(Method anAdviceMethod, Class thisClass); + + /** + * Determine whether or not this pointcut matches the execution of a given exception + * handler + * @param exceptionType the static type of the exception being handled + * @param inClass the class in which the catch block is declared + * @param withinCode the method or constructor in which the catch block is declared + * @return a FuzzyBoolean indicating whether the pointcut always matches such a join point (YES), + * never matches such a join point (NO), or may match such a join point (MAYBE) depending on the + * runtime types of the exception and exception-handling object. + */ + FuzzyBoolean matchesHandler(Class exceptionType, Class inClass, Member withinCode); + + /** + * Determine whether or not this pointcut matches the initialization of an + * object initiated by a call to the given constructor. + * @param aConstructor the constructor initiating the initialization + * @return a FuzzyBoolean indicating whether the pointcut always matches such a join point (YES), + * never matches such a join point (NO), or may match such a join point (MAYBE) depending on the + * runtime types of the arguments. + */ + FuzzyBoolean matchesInitialization(Constructor aConstructor); + + /** + * Determine whether or not this pointcut matches the preinitialization of an + * object initiated by a call to the given constructor. + * @param aConstructor the constructor initiating the initialization + * @return a FuzzyBoolean indicating whether the pointcut always matches such a join point (YES), + * never matches such a join point (NO), or may match such a join point (MAYBE) depending on the + * runtime types of the arguments. + */ + FuzzyBoolean matchesPreInitialization(Constructor aConstructor); + + /** + * Determine whether or not this pointcut matches the static initialization + * of the given class. + * @param aClass the class being statically initialized + * @return FuzzyBoolean.YES is the pointcut always matches, FuzzyBoolean.NO if the + * pointcut never matches. + */ + FuzzyBoolean matchesStaticInitialization(Class aClass); + + /** + * Determine whether or not this pointcut matches a set of the given field. + * @param aField the field being updated + * @param thisClass the type sending the update message + * @param targetClass the static type of the target of the field update message + * (may be a subtype of aField.getDeclaringClass() ) + * @param withinCode the Method or Constructor from within which the update message is sent + * @return a FuzzyBoolean indicating whether the pointcut always matches such a join point (YES), + * never matches such a join point (NO), or may match such a join point (MAYBE) depending on the runtime + * types of the caller and called object. + */ + FuzzyBoolean matchesFieldSet(Field aField, Class thisClass, Class targetClass, Member withinCode); + + /** + * Determine whether or not this pointcut matches a get of the given field. + * @param aField the field being accessed + * @param thisClass the type accessing the field + * @param targetClass the static type of the target of the field access message + * (may be a subtype of aField.getDeclaringClass() ) + * @param withinCode the Method or Constructor from within which the field is accessed + * @return a FuzzyBoolean indicating whether the pointcut always matches such a join point (YES), + * never matches such a join point (NO), or may match such a join point (MAYBE) depending on the runtime + * types of the caller and called object. + */ + FuzzyBoolean matchesFieldGet(Field aField, Class thisClass, Class targetClass, Member withinCode); + + /** + * Returns true iff the dynamic portions of the pointcut expression (this, target, and + * args) match the given this, target, and args objects. This method only needs to be + * called if a previous call to a FuzzyBoolean-returning matching method returned + * FuzzyBoolean.MAYBE. Even if this method returns true, the pointcut can only be + * considered to match the join point if the appropriate matches method for the join + * point kind has also returned FuzzyBoolean.YES or FuzzyBoolean.MAYBE. + * @param thisObject + * @param targetObject + * @param args + * @return + */ + boolean matchesDynamically(Object thisObject, Object targetObject, Object[] args); + + /** + * Return a string representation of this pointcut expression. + */ + String getPointcutExpression(); +} diff --git a/weaver/src/org/aspectj/weaver/tools/PointcutPrimitives.java b/weaver/src/org/aspectj/weaver/tools/PointcutPrimitives.java new file mode 100644 index 000000000..d6c13e186 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/tools/PointcutPrimitives.java @@ -0,0 +1,43 @@ +/* ******************************************************************* + * 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 org.aspectj.util.TypeSafeEnum; + +/** + * An enumeration of the different kinds of pointcut primitives + * supported by AspectJ. + */ +public class PointcutPrimitives extends TypeSafeEnum { + + public static final PointcutPrimitives CALL = new PointcutPrimitives("call",1); + public static final PointcutPrimitives EXECUTION = new PointcutPrimitives("execution",2); + public static final PointcutPrimitives GET = new PointcutPrimitives("get",3); + public static final PointcutPrimitives SET = new PointcutPrimitives("set",4); + public static final PointcutPrimitives INITIALIZATION = new PointcutPrimitives("initialization",5); + public static final PointcutPrimitives PRE_INITIALIZATION = new PointcutPrimitives("preinitialization",6); + public static final PointcutPrimitives STATIC_INITIALIZATION = new PointcutPrimitives("staticinitialization",7); + public static final PointcutPrimitives HANDLER = new PointcutPrimitives("handler",8); + public static final PointcutPrimitives ADVICE_EXECUTION = new PointcutPrimitives("adviceexecution",9); + public static final PointcutPrimitives WITHIN = new PointcutPrimitives("within",10); + public static final PointcutPrimitives WITHIN_CODE = new PointcutPrimitives("withincode",11); + public static final PointcutPrimitives CFLOW = new PointcutPrimitives("cflow",12); + public static final PointcutPrimitives CFLOW_BELOW = new PointcutPrimitives("cflowbelow",13); + public static final PointcutPrimitives IF = new PointcutPrimitives("if",14); + public static final PointcutPrimitives THIS = new PointcutPrimitives("this",15); + public static final PointcutPrimitives TARGET = new PointcutPrimitives("target",16); + public static final PointcutPrimitives ARGS = new PointcutPrimitives("args",17); + + private PointcutPrimitives(String name, int key) { + super(name, key); + } + +} |