From ab47acfec80ca851410350bef322464bff8f4c47 Mon Sep 17 00:00:00 2001 From: acolyer Date: Thu, 2 Dec 2004 12:30:29 +0000 Subject: APIs allowing 3rd parties to integrate with AspectJ's pointcut parsing and matching --- .../internal/tools/PointcutExpressionImpl.java | 193 +++++++++++++++++++++ .../org/aspectj/weaver/patterns/AndPointcut.java | 21 +++ .../org/aspectj/weaver/patterns/ArgsPointcut.java | 65 +++++-- .../org/aspectj/weaver/patterns/CflowPointcut.java | 18 ++ .../weaver/patterns/ConcreteCflowPointcut.java | 18 ++ .../aspectj/weaver/patterns/HandlerPointcut.java | 20 ++- .../org/aspectj/weaver/patterns/IfPointcut.java | 18 ++ .../aspectj/weaver/patterns/KindedPointcut.java | 21 ++- .../org/aspectj/weaver/patterns/NotPointcut.java | 17 ++ .../org/aspectj/weaver/patterns/OrPointcut.java | 21 +++ .../src/org/aspectj/weaver/patterns/Pointcut.java | 39 ++++- .../patterns/PointcutExpressionMatching.java | 40 +++++ .../aspectj/weaver/patterns/SignaturePattern.java | 54 ++++++ .../weaver/patterns/ThisOrTargetPointcut.java | 20 +++ .../aspectj/weaver/patterns/WithinPointcut.java | 19 ++ .../weaver/patterns/WithincodePointcut.java | 18 ++ .../src/org/aspectj/weaver/tools/FuzzyBoolean.java | 30 ++++ .../aspectj/weaver/tools/PointcutExpression.java | 167 ++++++++++++++++++ .../aspectj/weaver/tools/PointcutPrimitives.java | 43 +++++ 19 files changed, 823 insertions(+), 19 deletions(-) create mode 100644 weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java create mode 100644 weaver/src/org/aspectj/weaver/patterns/PointcutExpressionMatching.java create mode 100644 weaver/src/org/aspectj/weaver/tools/FuzzyBoolean.java create mode 100644 weaver/src/org/aspectj/weaver/tools/PointcutExpression.java create mode 100644 weaver/src/org/aspectj/weaver/tools/PointcutPrimitives.java 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