JoinPoint (as opposed to a Shadow).
import java.io.DataOutputStream;
import java.io.IOException;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
return left.match(shadow).and(right.match(shadow));
}
+ public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart encJP) {
+ return left.match(jp,encJP).and(right.match(jp,encJP));
+ }
+
+ public FuzzyBoolean match(JoinPoint.StaticPart jpsp) {
+ return left.match(jpsp).and(right.match(jpsp));
+ }
+
public String toString() {
return "(" + left.toString() + " && " + right.toString() + ")";
}
left.resolveBindings(scope, bindings);
right.resolveBindings(scope, bindings);
}
-
-
+
+ public void resolveBindingsFromRTTI() {
+ left.resolveBindingsFromRTTI();
+ right.resolveBindingsFromRTTI();
+ }
public void write(DataOutputStream s) throws IOException {
s.writeByte(Pointcut.AND);
return left.matchesExactly(type) && right.matchesExactly(type);
}
- public boolean matchesStatically(ResolvedTypeX type) {
+ public boolean matchesStatically(Class type) {
return left.matchesStatically(type) && right.matchesStatically(type);
}
+ public FuzzyBoolean matchesInstanceof(Class type) {
+ return left.matchesInstanceof(type).and(right.matchesInstanceof(type));
+ }
+
+ protected boolean matchesExactly(Class type) {
+ //??? if these had side-effects, this sort-circuit could be a mistake
+ return left.matchesExactly(type) && right.matchesExactly(type);
+ }
+
+ public boolean matchesStatically(ResolvedTypeX type) {
+ return left.matchesStatically(type) && right.matchesStatically(type);
+ }
+
public void write(DataOutputStream s) throws IOException {
s.writeByte(TypePattern.AND);
left.write(s);
return this;
}
+ public TypePattern resolveBindingsFromRTTI(boolean allowBinding, boolean requireExactType) {
+ if (requireExactType) return TypePattern.NO;
+ left = left.resolveBindingsFromRTTI(allowBinding,requireExactType);
+ right = right.resolveBindingsFromRTTI(allowBinding,requireExactType);
+ return this;
+ }
+
public String toString() {
return "(" + left.toString() + " && " + right.toString() + ")";
}
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.BetaException;
import org.aspectj.weaver.ISourceContext;
* @author Erik Hilsdale
* @author Jim Hugunin
*/
-public class ArgsPointcut extends NameBindingPointcut {
+public class ArgsPointcut extends NameBindingPointcut {
TypePatternList arguments;
public ArgsPointcut(TypePatternList arguments) {
arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()), TypePattern.DYNAMIC);
return ret;
}
+
+ public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart jpsp) {
+ return arguments.matches(jp.getArgs(),TypePattern.DYNAMIC);
+ }
public void write(DataOutputStream s) throws IOException {
s.writeByte(Pointcut.ARGS);
}
}
+ public void resolveBindingsFromRTTI() {
+ arguments.resolveBindingsFromRTTI(true, true);
+ if (arguments.ellipsisCount > 1) {
+ throw new UnsupportedOperationException("uses more than one .. in args (compiler limitation)");
+ }
+ }
+
public void postRead(ResolvedTypeX enclosingType) {
arguments.postRead(enclosingType);
}
}
}
+ public void resolveBindingsFromRTTI() {
+ if (entry.state != RESOLVED) {
+ entry.resolveBindingsFromRTTI();
+ }
+ }
+
public boolean equals(Object other) {
if (!(other instanceof CflowPointcut)) return false;
CflowPointcut o = (CflowPointcut)other;
throw new RuntimeException("unimplemented");
}
+ public void resolveBindingsFromRTTI() {
+ throw new RuntimeException("unimplemented");
+ }
public boolean equals(Object other) {
if (!(other instanceof ConcreteCflowPointcut)) return false;
return matchType.isCoerceableFrom(type) ? FuzzyBoolean.MAYBE : FuzzyBoolean.NO;
}
+ public boolean matchesExactly(Class matchType) {
+ try {
+ Class toMatchAgainst = Class.forName(type.getName());
+ return matchType == toMatchAgainst;
+ } catch (ClassNotFoundException cnfEx) {
+ return false;
+ }
+ }
+
+ public FuzzyBoolean matchesInstanceof(Class matchType) {
+ if (matchType.equals(Object.class)) return FuzzyBoolean.YES;
+
+ try {
+ Class toMatchAgainst = Class.forName(type.getName());
+ return toMatchAgainst.isAssignableFrom(matchType) ? FuzzyBoolean.YES : FuzzyBoolean.NO;
+ } catch (ClassNotFoundException cnfEx) {
+ return FuzzyBoolean.NO;
+ }
+ }
+
public boolean equals(Object other) {
if (!(other instanceof ExactTypePattern)) return false;
ExactTypePattern o = (ExactTypePattern)other;
throw new BCException("trying to re-resolve");
}
+
+ public TypePattern resolveBindingsFromRTTI(boolean allowBinding, boolean requireExactType) {
+ throw new IllegalStateException("trying to re-resolve");
+ }
}
import java.io.DataOutputStream;
import java.io.IOException;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
TypePattern.STATIC);
}
+ public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart jpsp) {
+ if (!jp.getKind().equals(JoinPoint.EXCEPTION_HANDLER)) return FuzzyBoolean.NO;
+ if (jp.getArgs().length > 0) {
+ Object caughtException = jp.getArgs()[0];
+ return exceptionType.matches(caughtException,TypePattern.STATIC);
+ } else {
+ return FuzzyBoolean.NO;
+ }
+ }
+
+
+
public boolean equals(Object other) {
if (!(other instanceof HandlerPointcut)) return false;
HandlerPointcut o = (HandlerPointcut)other;
exceptionType = exceptionType.resolveBindings(scope, bindings, false, false);
//XXX add error if exact binding and not an exception
}
+
+ public void resolveBindingsFromRTTI() {
+ exceptionType = exceptionType.resolveBindingsFromRTTI(false,false);
+ }
+
public Test findResidue(Shadow shadow, ExposedState state) {
return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
}
//??? all we need is good error messages in here in cflow contexts
}
+ public void resolveBindingsFromRTTI() {}
+
public boolean equals(Object other) {
if (!(other instanceof IfPointcut)) return false;
IfPointcut o = (IfPointcut)other;
import java.io.IOException;
import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.Checker;
import org.aspectj.weaver.ISourceContext;
return FuzzyBoolean.YES;
}
+ public FuzzyBoolean match(JoinPoint.StaticPart jpsp) {
+ if (jpsp.getKind().equals(kind.getName())) {
+ if (signature.matches(jpsp)) {
+ return FuzzyBoolean.YES;
+ }
+ }
+ return FuzzyBoolean.NO;
+ }
+
private void warnOnConfusingSig(Shadow shadow) {
// no warnings for declare error/warning
if (munger instanceof Checker) return;
}
}
}
+
+ public void resolveBindingsFromRTTI() {
+ signature = signature.resolveBindingsFromRTTI();
+ }
+
public Test findResidue(Shadow shadow, ExposedState state) {
return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
}
import java.io.DataOutputStream;
import java.io.IOException;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
public FuzzyBoolean match(Shadow shadow) {
return body.match(shadow).not();
}
+
+ public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart encJP) {
+ return body.match(jp,encJP).not();
+ }
+
+ public FuzzyBoolean match(JoinPoint.StaticPart jpsp) {
+ return body.match(jpsp).not();
+ }
public String toString() {
return "!" + body.toString();
}
+ public void resolveBindingsFromRTTI() {
+ body.resolveBindingsFromRTTI();
+ }
+
public void write(DataOutputStream s) throws IOException {
s.writeByte(Pointcut.NOT);
return !pattern.matchesExactly(type);
}
- public boolean matchesStatically(ResolvedTypeX type) {
+ public boolean matchesStatically(Class type) {
return !pattern.matchesStatically(type);
}
+ public FuzzyBoolean matchesInstanceof(Class type) {
+ return pattern.matchesInstanceof(type).not();
+ }
+
+ protected boolean matchesExactly(Class type) {
+ return !pattern.matchesExactly(type);
+ }
+
+ public boolean matchesStatically(ResolvedTypeX type) {
+ return !pattern.matchesStatically(type);
+ }
+
public void write(DataOutputStream s) throws IOException {
s.writeByte(TypePattern.NOT);
pattern.write(s);
pattern = pattern.resolveBindings(scope, bindings, false, false);
return this;
}
+
+ public TypePattern resolveBindingsFromRTTI(boolean allowBinding, boolean requireExactType) {
+ if (requireExactType) return TypePattern.NO;
+ pattern = pattern.resolveBindingsFromRTTI(allowBinding,requireExactType);
+ return this;
+ }
public String toString() {
return "!" + pattern;
import java.io.DataOutputStream;
import java.io.IOException;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
return left.match(shadow).or(right.match(shadow));
}
+ public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart encJP) {
+ return left.match(jp,encJP).or(right.match(jp,encJP));
+ }
+
+ public FuzzyBoolean match(JoinPoint.StaticPart jpsp) {
+ return left.match(jpsp).or(right.match(jpsp));
+ }
+
public String toString() {
return "(" + left.toString() + " || " + right.toString() + ")";
}
if (bindings != null) bindings.checkEquals(old, scope);
}
+
+ public void resolveBindingsFromRTTI() {
+ left.resolveBindingsFromRTTI();
+ right.resolveBindingsFromRTTI();
+ }
public void write(DataOutputStream s) throws IOException {
s.writeByte(Pointcut.OR);
return left.matchesStatically(type) || right.matchesStatically(type);
}
+ public FuzzyBoolean matchesInstanceof(Class type) {
+ return left.matchesInstanceof(type).or(right.matchesInstanceof(type));
+ }
+
+ protected boolean matchesExactly(Class type) {
+ //??? if these had side-effects, this sort-circuit could be a mistake
+ return left.matchesExactly(type) || right.matchesExactly(type);
+ }
+
+ public boolean matchesStatically(Class type) {
+ return left.matchesStatically(type) || right.matchesStatically(type);
+ }
+
public void write(DataOutputStream s) throws IOException {
s.writeByte(TypePattern.OR);
left.write(s);
return this;
}
+ public TypePattern resolveBindingsFromRTTI(boolean allowBinding, boolean requireExactType) {
+ if (requireExactType) return TypePattern.NO;
+ left = left.resolveBindingsFromRTTI(allowBinding,requireExactType);
+ right = right.resolveBindingsFromRTTI(allowBinding,requireExactType);
+ return this;
+ }
+
public String toString() {
return "(" + left.toString() + " || " + right.toString() + ")";
}
// assert bindings == null;
entry.resolve(scope);
}
-
+
public Test findResidue(Shadow shadow, ExposedState state) {
Expr myInstance =
Expr.makeCallExpr(AjcMemberMaker.perCflowAspectOfMethod(inAspect),
throw new BCException("weird kind " + key);
}
}
-
+
+ public void resolveBindingsFromRTTI() {
+ throw new UnsupportedOperationException("Can't resolve per-clauses at runtime");
+ }
+
public static final Kind SINGLETON = new Kind("issingleton", 1);
public static final Kind PERCFLOW = new Kind("percflow", 2);
public static final Kind PEROBJECT = new Kind("perobject", 3);
import java.io.DataOutputStream;
import java.io.IOException;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.util.TypeSafeEnum;
import org.aspectj.weaver.Advice;
* XXX implementors need to handle state
*/
public abstract FuzzyBoolean match(Shadow shadow);
+
+ /*
+ * for runtime / dynamic pointcuts.
+ * Default implementation delegates to StaticPart matcher
+ */
+ public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart enclosingJoinPoint) {
+ return match(jp.getStaticPart());
+ }
+ /*
+ * for runtime / dynamic pointcuts.
+ * Not all pointcuts can be matched at runtime, those that can should overide either
+ * match(JoinPoint), or this method, or both.
+ */
+ public FuzzyBoolean match(JoinPoint.StaticPart jpsp) {
+ throw new UnsupportedOperationException("Pointcut expression " + this.toString() + "cannot be matched at runtime");
+ }
public static final byte KINDED = 1;
public static final byte WITHIN = 2;
// internal, only called from resolve
protected abstract void resolveBindings(IScope scope, Bindings bindings);
+ // internal, only called from resolve
+ protected abstract void resolveBindingsFromRTTI();
+
/**
* Returns this pointcut mutated
*/
this.state = RESOLVED;
return this;
}
+
+ /**
+ * Returns this pointcut with type patterns etc resolved based on available RTTI
+ */
+ public Pointcut resolve() {
+ assertState(SYMBOLIC);
+ this.resolveBindingsFromRTTI();
+ this.state = RESOLVED;
+ return this;
+ }
/**
* Returns a new pointcut
public FuzzyBoolean match(Shadow shadow) {
return FuzzyBoolean.NO;
}
+
+ public FuzzyBoolean match(JoinPoint.StaticPart jpsp) {
+ return FuzzyBoolean.NO;
+ }
public void resolveBindings(IScope scope, Bindings bindings) {
}
+
+ public void resolveBindingsFromRTTI() {
+ }
public void postRead(ResolvedTypeX enclosingType) {
}
}
}
+ public void resolveBindingsFromRTTI() {
+ throw new UnsupportedOperationException("Referenced pointcuts are not supported in runtime evaluation");
+ }
+
public void postRead(ResolvedTypeX enclosingType) {
arguments.postRead(enclosingType);
}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.reflect.AdviceSignature;
+import org.aspectj.lang.reflect.ConstructorSignature;
+import org.aspectj.lang.reflect.FieldSignature;
+import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.NameMangler;
return this;
}
+ public SignaturePattern resolveBindingsFromRTTI() {
+ if (returnType != null) {
+ returnType = returnType.resolveBindingsFromRTTI(false, false);
+ }
+ if (declaringType != null) {
+ declaringType = declaringType.resolveBindingsFromRTTI(false, false);
+ }
+ if (parameterTypes != null) {
+ parameterTypes = parameterTypes.resolveBindingsFromRTTI(false, false);
+ }
+ if (throwsPattern != null) {
+ throwsPattern = throwsPattern.resolveBindingsFromRTTI();
+ }
+
+ return this;
+ }
+
public void postRead(ResolvedTypeX enclosingType) {
if (returnType != null) {
return false;
}
+ // for dynamic join point matching
+ public boolean matches(JoinPoint.StaticPart jpsp) {
+ Signature sig = jpsp.getSignature();
+ if (kind == Member.ADVICE && !(sig instanceof AdviceSignature)) return false;
+ if (kind == Member.CONSTRUCTOR && !(sig instanceof ConstructorSignature)) return false;
+ if (kind == Member.FIELD && !(sig instanceof FieldSignature)) return false;
+ if (kind == Member.METHOD && !(sig instanceof MethodSignature)) return false;
+ if (kind == Member.STATIC_INITIALIZATION && !(jpsp.getKind().equals(JoinPoint.STATICINITIALIZATION))) return false;
+ if (kind == Member.POINTCUT) return false;
+
+ if (kind == Member.ADVICE) return true;
+
+ if (!modifiers.matches(sig.getModifiers())) return false;
+
+ if (kind == Member.STATIC_INITIALIZATION) {
+ //System.err.println("match static init: " + sig.getDeclaringType() + " with " + this);
+ return declaringType.matchesStatically(sig.getDeclaringType());
+ } else if (kind == Member.FIELD) {
+ Class returnTypeClass = ((FieldSignature)sig).getFieldType();
+ if (!returnType.matchesStatically(returnTypeClass)) return false;
+ if (!name.matches(sig.getName())) return false;
+ boolean ret = declaringTypeMatch(sig);
+ //System.out.println(" ret: " + ret);
+ return ret;
+ } else if (kind == Member.METHOD) {
+ MethodSignature msig = ((MethodSignature)sig);
+ Class returnTypeClass = msig.getReturnType();
+ Class[] params = msig.getParameterTypes();
+ Class[] exceptionTypes = msig.getExceptionTypes();
+ if (!returnType.matchesStatically(returnTypeClass)) return false;
+ if (!name.matches(sig.getName())) return false;
+ if (!parameterTypes.matches(params, TypePattern.STATIC).alwaysTrue()) {
+ return false;
+ }
+ if (!throwsPattern.matches(exceptionTypes)) return false;
+ return declaringTypeMatch(sig);
+ } else if (kind == Member.CONSTRUCTOR) {
+ ConstructorSignature csig = (ConstructorSignature)sig;
+ Class[] params = csig.getParameterTypes();
+ Class[] exceptionTypes = csig.getExceptionTypes();
+ if (!parameterTypes.matches(params, TypePattern.STATIC).alwaysTrue()) {
+ return false;
+ }
+ if (!throwsPattern.matches(exceptionTypes)) return false;
+ return declaringType.matchesStatically(sig.getDeclaringType());
+ //return declaringTypeMatch(member.getDeclaringType(), member, world);
+ }
+
+ return false;
+ }
+
private boolean declaringTypeMatch(TypeX onTypeUnresolved, Member member, World world) {
ResolvedTypeX onType = onTypeUnresolved.resolve(world);
return false;
}
-
+ private boolean declaringTypeMatch(Signature sig) {
+ Class onType = sig.getDeclaringType();
+ if (declaringType.matchesStatically(onType)) return true;
+
+ Collection declaringTypes = getDeclaringTypes(sig);
+
+ for (Iterator it = declaringTypes.iterator(); it.hasNext(); ) {
+ Class pClass = (Class) it.next();
+ if (declaringType.matchesStatically(pClass)) return true;
+ }
+
+ return false;
+ }
+
+ private Collection getDeclaringTypes(Signature sig) {
+ List l = new ArrayList();
+ Class onType = sig.getDeclaringType();
+ String memberName = sig.getName();
+ if (sig instanceof FieldSignature) {
+ Class fieldType = ((FieldSignature)sig).getFieldType();
+ Class superType = onType;
+ while(superType != null) {
+ try {
+ Field f = (superType.getDeclaredField(memberName));
+ if (f.getType() == fieldType) {
+ l.add(superType);
+ }
+ } catch (NoSuchFieldException nsf) {}
+ superType = superType.getSuperclass();
+ }
+ } else if (sig instanceof MethodSignature) {
+ Class[] paramTypes = ((MethodSignature)sig).getParameterTypes();
+ Class superType = onType;
+ while(superType != null) {
+ try {
+ Method m = (superType.getDeclaredMethod(memberName,paramTypes));
+ l.add(superType);
+ } catch (NoSuchMethodException nsm) {}
+ superType = superType.getSuperclass();
+ }
+ }
+ return l;
+ }
+
public NamePattern getName() { return name; }
public TypePattern getDeclaringType() { return declaringType; }
import java.io.IOException;
import org.aspectj.bridge.IMessage;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
return type.matches(typeToMatch.resolve(shadow.getIWorld()), TypePattern.DYNAMIC);
}
+ public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart encJP) {
+ Object toMatch = isThis ? jp.getThis() : jp.getTarget();
+ if (toMatch == null) return FuzzyBoolean.NO;
+ return type.matches(toMatch.getClass(), TypePattern.DYNAMIC);
+ }
+
public void write(DataOutputStream s) throws IOException {
s.writeByte(Pointcut.THIS_OR_TARGET);
s.writeBoolean(isThis);
// ??? handle non-formal
}
+ public void resolveBindingsFromRTTI() {
+ type = type.resolveBindingsFromRTTI(true,true);
+ }
+
public void postRead(ResolvedTypeX enclosingType) {
type.postRead(enclosingType);
}
return this;
}
+ public ThrowsPattern resolveBindingsFromRTTI() {
+ required = required.resolveBindingsFromRTTI(false,false);
+ forbidden = forbidden.resolveBindingsFromRTTI(false,false);
+ return this;
+ }
+
public boolean matches(TypeX[] tys, World world) {
if (this == ANY) return true;
}
return true;
}
+
+ public boolean matches(Class[] onTypes) {
+ if (this == ANY) return true;
+
+ //System.out.println("matching: " + this + " with " + Arrays.asList(tys));
+
+ for (int j=0, lenj = required.size(); j < lenj; j++) {
+ if (! matchesAny(required.get(j), onTypes)) {
+ return false;
+ }
+ }
+ for (int j=0, lenj = forbidden.size(); j < lenj; j++) {
+ if (matchesAny(forbidden.get(j), onTypes)) {
+ return false;
+ }
+ }
+ return true;
+
+ }
private boolean matchesAny(
TypePattern typePattern,
}
return false;
}
+
+ private boolean matchesAny(TypePattern typePattern, Class[] types) {
+ for (int i = types.length - 1; i >= 0; i--) {
+ if (typePattern.matchesStatically(types[i])) return true;
+ }
+ return false;
+ }
public static ThrowsPattern read(DataInputStream s, ISourceContext context) throws IOException {
TypePatternList required = TypePatternList.read(s, context);
}
+ // methods for dynamic pc matching...
+ public final FuzzyBoolean matches(Class toMatch, MatchKind kind) {
+ if (kind == STATIC) {
+ return FuzzyBoolean.fromBoolean(matchesStatically(toMatch));
+ } else if (kind == DYNAMIC) {
+ //System.err.println("matching: " + this + " with " + type);
+ FuzzyBoolean ret = matchesInstanceof(toMatch);
+ //System.err.println(" got: " + ret);
+ return ret;
+ } else {
+ throw new IllegalArgumentException("kind must be DYNAMIC or STATIC");
+ }
+ }
+
+ public final FuzzyBoolean matches(Object o, MatchKind kind) {
+ if (kind == STATIC) {
+ return FuzzyBoolean.fromBoolean(matchesStatically(o.getClass()));
+ } else if (kind == DYNAMIC) {
+ return FuzzyBoolean.fromBoolean(matchesSubtypes(o.getClass()));
+ } else {
+ throw new IllegalArgumentException("kind must be DYNAMIC or STATIC");
+ }
+ }
+
+ public boolean matchesStatically(Class toMatch) {
+ if (includeSubtypes) {
+ return matchesSubtypes(toMatch);
+ } else {
+ return matchesExactly(toMatch);
+ }
+ }
+ public abstract FuzzyBoolean matchesInstanceof(Class toMatch);
+
+ protected abstract boolean matchesExactly(Class toMatch);
+ protected boolean matchesSubtypes(Class toMatch) {
+ if (matchesExactly(toMatch)) {
+ return true;
+ }
+ Class superClass = toMatch.getSuperclass();
+ if (superClass != null) {
+ return matchesSubtypes(superClass);
+ }
+ return false;
+ }
+
protected abstract boolean matchesExactly(ResolvedTypeX type);
protected boolean matchesSubtypes(ResolvedTypeX type) {
//System.out.println("matching: " + this + " to " + type);
return this;
}
+ public TypePattern resolveBindingsFromRTTI(boolean allowBindng, boolean requireExactType) {
+ return this;
+ }
+
public void postRead(ResolvedTypeX enclosingType) {
}
return FuzzyBoolean.NO;
}
+ /**
+ * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
+ */
+ protected boolean matchesExactly(Class type) {
+ return false;
+ }
+
+ /**
+ * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
+ */
+ public FuzzyBoolean matchesInstanceof(Class type) {
+ return FuzzyBoolean.NO;
+ }
/**
* @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
*/
return FuzzyBoolean.YES;
}
+ /**
+ * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
+ */
+ protected boolean matchesExactly(Class type) {
+ return true;
+ }
+
+ /**
+ * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
+ */
+ public FuzzyBoolean matchesInstanceof(Class type) {
+ return FuzzyBoolean.YES;
+ }
/**
* @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
*/
return FuzzyBoolean.NO;
}
+ /**
+ * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
+ */
+ protected boolean matchesExactly(Class type) {
+ return false;
+ }
+
+ /**
+ * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
+ */
+ public FuzzyBoolean matchesInstanceof(Class type) {
+ return FuzzyBoolean.NO;
+ }
/**
* @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
*/
return b;
}
}
+
+
+ // TODO Add TypePatternList.matches(Object[] objs)
+ public FuzzyBoolean matches(Object[] objs, TypePattern.MatchKind kind) {
+ int nameLength = objs.length;
+ int patternLength = typePatterns.length;
+
+ int nameIndex = 0;
+ int patternIndex = 0;
+
+ if (ellipsisCount == 0) {
+ if (nameLength != patternLength) return FuzzyBoolean.NO;
+ FuzzyBoolean finalReturn = FuzzyBoolean.YES;
+ while (patternIndex < patternLength) {
+ FuzzyBoolean ret = typePatterns[patternIndex++].matches(objs[nameIndex++],kind);
+ if (ret == FuzzyBoolean.NO) return ret;
+ if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
+ }
+ return finalReturn;
+ } else if (ellipsisCount == 1) {
+ if (nameLength < patternLength-1) return FuzzyBoolean.NO;
+ FuzzyBoolean finalReturn = FuzzyBoolean.YES;
+ while (patternIndex < patternLength) {
+ TypePattern p = typePatterns[patternIndex++];
+ if (p == TypePattern.ELLIPSIS) {
+ nameIndex = nameLength - (patternLength-patternIndex);
+ } else {
+ FuzzyBoolean ret = p.matches(objs[nameIndex++],kind);
+ if (ret == FuzzyBoolean.NO) return ret;
+ if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
+ }
+ }
+ return finalReturn;
+ } else {
+// System.err.print("match(" + arguments + ", " + types + ") -> ");
+ FuzzyBoolean b = outOfStar(typePatterns, objs, 0, 0, patternLength - ellipsisCount, nameLength, ellipsisCount, kind);
+// System.err.println(b);
+ return b;
+ }
+ }
+
+ // XXX run-time signature matching, too much duplicated code
+ public FuzzyBoolean matches(Class[] types, TypePattern.MatchKind kind) {
+ int nameLength = types.length;
+ int patternLength = typePatterns.length;
+
+ int nameIndex = 0;
+ int patternIndex = 0;
+
+ if (ellipsisCount == 0) {
+ if (nameLength != patternLength) return FuzzyBoolean.NO;
+ FuzzyBoolean finalReturn = FuzzyBoolean.YES;
+ while (patternIndex < patternLength) {
+ FuzzyBoolean ret = typePatterns[patternIndex++].matches(types[nameIndex++], kind);
+ if (ret == FuzzyBoolean.NO) return ret;
+ if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
+ }
+ return finalReturn;
+ } else if (ellipsisCount == 1) {
+ if (nameLength < patternLength-1) return FuzzyBoolean.NO;
+ FuzzyBoolean finalReturn = FuzzyBoolean.YES;
+ while (patternIndex < patternLength) {
+ TypePattern p = typePatterns[patternIndex++];
+ if (p == TypePattern.ELLIPSIS) {
+ nameIndex = nameLength - (patternLength-patternIndex);
+ } else {
+ FuzzyBoolean ret = p.matches(types[nameIndex++], kind);
+ if (ret == FuzzyBoolean.NO) return ret;
+ if (ret == FuzzyBoolean.MAYBE) finalReturn = ret;
+ }
+ }
+ return finalReturn;
+ } else {
+// System.err.print("match(" + arguments + ", " + types + ") -> ");
+ FuzzyBoolean b = outOfStar(typePatterns, types, 0, 0, patternLength - ellipsisCount, nameLength, ellipsisCount, kind);
+// System.err.println(b);
+ return b;
+ }
+ }
+
private static FuzzyBoolean outOfStar(final TypePattern[] pattern, final ResolvedTypeX[] target,
int pi, int ti,
int pLeft, int tLeft,
ti++; tLeft--;
}
}
+
+
+
+ private static FuzzyBoolean outOfStar(final TypePattern[] pattern,
+ final Class[] target, int pi, int ti, int pLeft, int tLeft,
+ final int starsLeft, TypePattern.MatchKind kind) {
+ if (pLeft > tLeft)
+ return FuzzyBoolean.NO;
+ FuzzyBoolean finalReturn = FuzzyBoolean.YES;
+ while (true) {
+ // invariant: if (tLeft > 0) then (ti < target.length && pi <
+ // pattern.length)
+ if (tLeft == 0)
+ return finalReturn;
+ if (pLeft == 0) {
+ if (starsLeft > 0) {
+ return finalReturn;
+ } else {
+ return FuzzyBoolean.NO;
+ }
+ }
+ if (pattern[pi] == TypePattern.ELLIPSIS) {
+ return inStar(pattern, target, pi + 1, ti, pLeft, tLeft,
+ starsLeft - 1, kind);
+ }
+ FuzzyBoolean ret = pattern[pi].matches(target[ti], kind);
+ if (ret == FuzzyBoolean.NO)
+ return ret;
+ if (ret == FuzzyBoolean.MAYBE)
+ finalReturn = ret;
+ pi++;
+ ti++;
+ pLeft--;
+ tLeft--;
+ }
+ }
+
+ private static FuzzyBoolean inStar(final TypePattern[] pattern,
+ final Class[] target, int pi, int ti, final int pLeft,
+ int tLeft, int starsLeft, TypePattern.MatchKind kind) {
+ // invariant: pLeft > 0, so we know we'll run out of stars and find a
+ // real char in pattern
+ TypePattern patternChar = pattern[pi];
+ while (patternChar == TypePattern.ELLIPSIS) {
+ starsLeft--;
+ patternChar = pattern[++pi];
+ }
+ while (true) {
+ // invariant: if (tLeft > 0) then (ti < target.length)
+ if (pLeft > tLeft)
+ return FuzzyBoolean.NO;
+ FuzzyBoolean ff = patternChar.matches(target[ti], kind);
+ if (ff.maybeTrue()) {
+ FuzzyBoolean xx = outOfStar(pattern, target, pi + 1, ti + 1,
+ pLeft - 1, tLeft - 1, starsLeft, kind);
+ if (xx.maybeTrue())
+ return ff.and(xx);
+ }
+ ti++;
+ tLeft--;
+ }
+ }
+
+ private static FuzzyBoolean outOfStar(final TypePattern[] pattern,
+ final Object[] target, int pi, int ti, int pLeft, int tLeft,
+ final int starsLeft, TypePattern.MatchKind kind) {
+ if (pLeft > tLeft)
+ return FuzzyBoolean.NO;
+ FuzzyBoolean finalReturn = FuzzyBoolean.YES;
+ while (true) {
+ // invariant: if (tLeft > 0) then (ti < target.length && pi <
+ // pattern.length)
+ if (tLeft == 0)
+ return finalReturn;
+ if (pLeft == 0) {
+ if (starsLeft > 0) {
+ return finalReturn;
+ } else {
+ return FuzzyBoolean.NO;
+ }
+ }
+ if (pattern[pi] == TypePattern.ELLIPSIS) {
+ return inStar(pattern, target, pi + 1, ti, pLeft, tLeft,
+ starsLeft - 1,kind);
+ }
+ FuzzyBoolean ret = pattern[pi].matches(target[ti],kind);
+ if (ret == FuzzyBoolean.NO)
+ return ret;
+ if (ret == FuzzyBoolean.MAYBE)
+ finalReturn = ret;
+ pi++;
+ ti++;
+ pLeft--;
+ tLeft--;
+ }
+ }
+
+ private static FuzzyBoolean inStar(final TypePattern[] pattern,
+ final Object[] target, int pi, int ti, final int pLeft,
+ int tLeft, int starsLeft, TypePattern.MatchKind kind) {
+ // invariant: pLeft > 0, so we know we'll run out of stars and find a
+ // real char in pattern
+ TypePattern patternChar = pattern[pi];
+ while (patternChar == TypePattern.ELLIPSIS) {
+ starsLeft--;
+ patternChar = pattern[++pi];
+ }
+ while (true) {
+ // invariant: if (tLeft > 0) then (ti < target.length)
+ if (pLeft > tLeft)
+ return FuzzyBoolean.NO;
+ FuzzyBoolean ff = patternChar.matches(target[ti],kind);
+ if (ff.maybeTrue()) {
+ FuzzyBoolean xx = outOfStar(pattern, target, pi + 1, ti + 1,
+ pLeft - 1, tLeft - 1, starsLeft,kind);
+ if (xx.maybeTrue())
+ return ff.and(xx);
+ }
+ ti++;
+ tLeft--;
+ }
+ }
+
+
public TypePatternList resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
for (int i=0; i<typePatterns.length; i++) {
return this;
}
+ public TypePatternList resolveBindingsFromRTTI(boolean allowBinding, boolean requireExactType) {
+ for (int i=0; i<typePatterns.length; i++) {
+ TypePattern p = typePatterns[i];
+ if (p != null) {
+ typePatterns[i] = typePatterns[i].resolveBindingsFromRTTI(allowBinding, requireExactType);
+ }
+ }
+ return this;
+ }
+
public TypePatternList resolveReferences(IntMap bindings) {
int len = typePatterns.length;
TypePattern[] ret = new TypePattern[len];
//System.err.println("match: " + targetTypeName + ", " + knownMatches); //Arrays.asList(importedPrefixes));
+ return matchesExactlyByName(targetTypeName);
+ }
+
+ /**
+ * @param targetTypeName
+ * @return
+ */
+ private boolean matchesExactlyByName(String targetTypeName) {
//XXX hack
if (knownMatches == null && importedPrefixes == null) {
return innerMatchesExactly(targetTypeName);
return innerMatchesExactly(targetTypeName);
}
- private int lastIndexOfDotOrDollar(String string) {
+ private int lastIndexOfDotOrDollar(String string) {
int dot = string.lastIndexOf('.');
int dollar = string.lastIndexOf('$');
return Math.max(dot, dollar);
return this;
}
+ public TypePattern resolveBindingsFromRTTI(boolean allowBinding, boolean requireExactType) {
+ if (isStar()) {
+ return TypePattern.ANY; //??? loses source location
+ }
+
+ String cleanName = maybeGetCleanName();
+ if (cleanName != null) {
+ Class clazz = null;
+
+ while (clazz == null) {
+ try {
+ clazz = Class.forName(cleanName);
+ } catch (ClassNotFoundException cnf) {
+ int lastDotIndex = cleanName.lastIndexOf('.');
+ if (lastDotIndex == -1) break;
+ cleanName = cleanName.substring(0, lastDotIndex) + '$' + cleanName.substring(lastDotIndex+1);
+ }
+ }
+
+ if (clazz == null) {
+ try {
+ clazz = Class.forName("java.lang." + cleanName);
+ } catch (ClassNotFoundException cnf) {
+ }
+ }
+
+ if (clazz == null) {
+ if (requireExactType) {
+ return NO;
+ }
+ } else {
+ TypeX type = TypeX.forName(clazz.getName());
+ if (dim != 0) type = TypeX.makeArray(type,dim);
+ TypePattern ret = new ExactTypePattern(type, includeSubtypes);
+ ret.copyLocationFrom(this);
+ return ret;
+ }
+ } else if (requireExactType) {
+ return NO;
+ }
+
+ importedPrefixes = SimpleScope.javaLangPrefixArray;
+ knownMatches = new String[0];
+
+ return this;
+ }
+
public boolean isStar() {
return namePatterns.length == 1 && namePatterns[0].isAny();
}
}
return result;
}
+
+
+ public FuzzyBoolean matchesInstanceof(Class type) {
+ return FuzzyBoolean.NO;
+ }
+
+ public boolean matchesExactly(Class type) {
+ return matchesExactlyByName(type.getName());
+ }
/**
* @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
import java.io.DataOutputStream;
import java.io.IOException;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
return isWithinType(enclosingType);
}
+ public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart encJp) {
+ return isWithinType(encJp.getSignature().getDeclaringType());
+ }
+
+ private FuzzyBoolean isWithinType(Class type) {
+ while (type != null) {
+ if (typePattern.matchesStatically(type)) {
+ return FuzzyBoolean.YES;
+ }
+ type = type.getDeclaringClass();
+ }
+ return FuzzyBoolean.NO;
+ }
+
+
public void write(DataOutputStream s) throws IOException {
s.writeByte(Pointcut.WITHIN);
typePattern.write(s);
typePattern = typePattern.resolveBindings(scope, bindings, false, false);
}
+ public void resolveBindingsFromRTTI() {
+ typePattern = typePattern.resolveBindingsFromRTTI(false,false);
+ }
+
public void postRead(ResolvedTypeX enclosingType) {
typePattern.postRead(enclosingType);
}
import java.io.DataOutputStream;
import java.io.IOException;
+import org.aspectj.lang.JoinPoint;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
signature.matches(shadow.getEnclosingCodeSignature(), shadow.getIWorld()));
}
+ public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart encJP) {
+ return FuzzyBoolean.fromBoolean(signature.matches(encJP));
+ }
+
public void write(DataOutputStream s) throws IOException {
s.writeByte(Pointcut.WITHINCODE);
signature.write(s);
public void resolveBindings(IScope scope, Bindings bindings) {
signature = signature.resolveBindings(scope, bindings);
}
+
+ public void resolveBindingsFromRTTI() {
+ signature = signature.resolveBindingsFromRTTI();
+ }
public void postRead(ResolvedTypeX enclosingType) {
signature.postRead(enclosingType);