| /* ******************************************************************* |
| * Copyright (c) 2004 IBM Corporation. |
| * All rights reserved. |
| * This program and the accompanying materials are made available |
| * under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution and is available at |
| * http://www.eclipse.org/legal/epl-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.weaver.ResolvedType; |
| import org.aspectj.weaver.Shadow; |
| import org.aspectj.weaver.World; |
| import org.aspectj.weaver.ast.Literal; |
| import org.aspectj.weaver.ast.Test; |
| import org.aspectj.weaver.patterns.AbstractPatternNodeVisitor; |
| import org.aspectj.weaver.patterns.AnnotationPointcut; |
| import org.aspectj.weaver.patterns.ArgsAnnotationPointcut; |
| import org.aspectj.weaver.patterns.ArgsPointcut; |
| import org.aspectj.weaver.patterns.CflowPointcut; |
| import org.aspectj.weaver.patterns.ExposedState; |
| import org.aspectj.weaver.patterns.IfPointcut; |
| import org.aspectj.weaver.patterns.NotAnnotationTypePattern; |
| import org.aspectj.weaver.patterns.NotPointcut; |
| import org.aspectj.weaver.patterns.Pointcut; |
| import org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut; |
| import org.aspectj.weaver.patterns.ThisOrTargetPointcut; |
| import org.aspectj.weaver.patterns.WithinAnnotationPointcut; |
| import org.aspectj.weaver.patterns.WithinCodeAnnotationPointcut; |
| import org.aspectj.weaver.reflect.ReflectionFastMatchInfo; |
| import org.aspectj.weaver.reflect.ReflectionShadow; |
| import org.aspectj.weaver.reflect.ReflectionWorld; |
| import org.aspectj.weaver.reflect.ShadowMatchImpl; |
| import org.aspectj.weaver.tools.DefaultMatchingContext; |
| import org.aspectj.weaver.tools.MatchingContext; |
| import org.aspectj.weaver.tools.PointcutExpression; |
| import org.aspectj.weaver.tools.PointcutParameter; |
| import org.aspectj.weaver.tools.ShadowMatch; |
| |
| /** |
| * Map from weaver.tools interface to internal Pointcut implementation... |
| */ |
| public class PointcutExpressionImpl implements PointcutExpression { |
| |
| private final static boolean MATCH_INFO = false; |
| |
| private World world; |
| private Pointcut pointcut; |
| private String expression; |
| private PointcutParameter[] parameters; |
| private MatchingContext matchContext = new DefaultMatchingContext(); |
| |
| public PointcutExpressionImpl(Pointcut pointcut, String expression, PointcutParameter[] params, World inWorld) { |
| this.pointcut = pointcut; |
| this.expression = expression; |
| this.world = inWorld; |
| this.parameters = params; |
| if (this.parameters == null) { |
| this.parameters = new PointcutParameter[0]; |
| } |
| } |
| |
| public Pointcut getUnderlyingPointcut() { |
| return this.pointcut; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.aspectj.weaver.tools.PointcutExpression#setMatchingContext(org.aspectj.weaver.tools.MatchingContext) |
| */ |
| public void setMatchingContext(MatchingContext aMatchContext) { |
| this.matchContext = aMatchContext; |
| } |
| |
| public boolean couldMatchJoinPointsInType(Class aClass) { |
| ResolvedType matchType = world.resolve(aClass.getName()); |
| if (matchType.isMissing() && (world instanceof ReflectionWorld)) { |
| // Class is a generated class that cannot be 'looked up' via getResource. |
| // For example a proxy or lambda. |
| // Use the class itself in this case |
| matchType = ((ReflectionWorld)world).resolveUsingClass(aClass); |
| } |
| ReflectionFastMatchInfo info = new ReflectionFastMatchInfo(matchType, null, this.matchContext, world); |
| boolean couldMatch = pointcut.fastMatch(info).maybeTrue(); |
| if (MATCH_INFO) { |
| System.out.println("MATCHINFO: fast match for '" + this.expression + "' against '" + aClass.getName() + "': " |
| + couldMatch); |
| } |
| return couldMatch; |
| } |
| |
| public boolean mayNeedDynamicTest() { |
| HasPossibleDynamicContentVisitor visitor = new HasPossibleDynamicContentVisitor(); |
| pointcut.traverse(visitor, null); |
| return visitor.hasDynamicContent(); |
| } |
| |
| private ExposedState getExposedState() { |
| return new ExposedState(parameters.length); |
| } |
| |
| public ShadowMatch matchesMethodExecution(Method aMethod) { |
| ShadowMatch match = matchesExecution(aMethod); |
| if (MATCH_INFO && match.maybeMatches()) { |
| System.out.println("MATCHINFO: method execution match on '" + aMethod + "' for '" + this.expression + "': " |
| + (match.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return match; |
| } |
| |
| public ShadowMatch matchesConstructorExecution(Constructor aConstructor) { |
| ShadowMatch match = matchesExecution(aConstructor); |
| if (MATCH_INFO && match.maybeMatches()) { |
| System.out.println("MATCHINFO: constructor execution match on '" + aConstructor + "' for '" + this.expression + "': " |
| + (match.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return match; |
| } |
| |
| private ShadowMatch matchesExecution(Member aMember) { |
| Shadow s = ReflectionShadow.makeExecutionShadow(world, aMember, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aMember); |
| sm.setWithinCode(null); |
| sm.setWithinType(aMember.getDeclaringClass()); |
| return sm; |
| } |
| |
| public ShadowMatch matchesStaticInitialization(Class aClass) { |
| Shadow s = ReflectionShadow.makeStaticInitializationShadow(world, aClass, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(null); |
| sm.setWithinCode(null); |
| sm.setWithinType(aClass); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: static initialization match on '" + aClass.getName() + "' for '" + this.expression |
| + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesAdviceExecution(Method aMethod) { |
| Shadow s = ReflectionShadow.makeAdviceExecutionShadow(world, aMethod, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aMethod); |
| sm.setWithinCode(null); |
| sm.setWithinType(aMethod.getDeclaringClass()); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: advice execution match on '" + aMethod + "' for '" + this.expression + "': " |
| + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesInitialization(Constructor aConstructor) { |
| Shadow s = ReflectionShadow.makeInitializationShadow(world, aConstructor, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aConstructor); |
| sm.setWithinCode(null); |
| sm.setWithinType(aConstructor.getDeclaringClass()); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: initialization match on '" + aConstructor + "' for '" + this.expression + "': " |
| + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesPreInitialization(Constructor aConstructor) { |
| Shadow s = ReflectionShadow.makePreInitializationShadow(world, aConstructor, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aConstructor); |
| sm.setWithinCode(null); |
| sm.setWithinType(aConstructor.getDeclaringClass()); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: preinitialization match on '" + aConstructor + "' for '" + this.expression + "': " |
| + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesMethodCall(Method aMethod, Member withinCode) { |
| Shadow s = ReflectionShadow.makeCallShadow(world, aMethod, withinCode, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aMethod); |
| sm.setWithinCode(withinCode); |
| sm.setWithinType(withinCode.getDeclaringClass()); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: method call match on '" + aMethod + "' withinCode='" + withinCode + "' for '" |
| + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesMethodCall(Method aMethod, Class callerType) { |
| Shadow s = ReflectionShadow.makeCallShadow(world, aMethod, callerType, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aMethod); |
| sm.setWithinCode(null); |
| sm.setWithinType(callerType); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: method call match on '" + aMethod + "' callerType='" + callerType.getName() + "' for '" |
| + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesConstructorCall(Constructor aConstructor, Class callerType) { |
| Shadow s = ReflectionShadow.makeCallShadow(world, aConstructor, callerType, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aConstructor); |
| sm.setWithinCode(null); |
| sm.setWithinType(callerType); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: constructor call match on '" + aConstructor + "' callerType='" + callerType.getName() |
| + "' for '" + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesConstructorCall(Constructor aConstructor, Member withinCode) { |
| Shadow s = ReflectionShadow.makeCallShadow(world, aConstructor, withinCode, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aConstructor); |
| sm.setWithinCode(withinCode); |
| sm.setWithinType(withinCode.getDeclaringClass()); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: constructor call match on '" + aConstructor + "' withinCode='" + withinCode + "' for '" |
| + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesHandler(Class exceptionType, Class handlingType) { |
| Shadow s = ReflectionShadow.makeHandlerShadow(world, exceptionType, handlingType, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(null); |
| sm.setWithinCode(null); |
| sm.setWithinType(handlingType); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: handler match on '" + exceptionType.getName() + "' handlingType='" + handlingType |
| + "' for '" + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesHandler(Class exceptionType, Member withinCode) { |
| Shadow s = ReflectionShadow.makeHandlerShadow(world, exceptionType, withinCode, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(null); |
| sm.setWithinCode(withinCode); |
| sm.setWithinType(withinCode.getDeclaringClass()); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: handler match on '" + exceptionType.getName() + "' withinCode='" + withinCode |
| + "' for '" + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesFieldGet(Field aField, Class withinType) { |
| Shadow s = ReflectionShadow.makeFieldGetShadow(world, aField, withinType, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aField); |
| sm.setWithinCode(null); |
| sm.setWithinType(withinType); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: field get match on '" + aField + "' withinType='" + withinType.getName() + "' for '" |
| + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesFieldGet(Field aField, Member withinCode) { |
| Shadow s = ReflectionShadow.makeFieldGetShadow(world, aField, withinCode, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aField); |
| sm.setWithinCode(withinCode); |
| sm.setWithinType(withinCode.getDeclaringClass()); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: field get match on '" + aField + "' withinCode='" + withinCode + "' for '" |
| + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesFieldSet(Field aField, Class withinType) { |
| Shadow s = ReflectionShadow.makeFieldSetShadow(world, aField, withinType, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aField); |
| sm.setWithinCode(null); |
| sm.setWithinType(withinType); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: field set match on '" + aField + "' withinType='" + withinType.getName() + "' for '" |
| + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| public ShadowMatch matchesFieldSet(Field aField, Member withinCode) { |
| Shadow s = ReflectionShadow.makeFieldSetShadow(world, aField, withinCode, this.matchContext); |
| ShadowMatchImpl sm = getShadowMatch(s); |
| sm.setSubject(aField); |
| sm.setWithinCode(withinCode); |
| sm.setWithinType(withinCode.getDeclaringClass()); |
| if (MATCH_INFO && sm.maybeMatches()) { |
| System.out.println("MATCHINFO: field set match on '" + aField + "' withinCode='" + withinCode + "' for '" |
| + this.expression + "': " + (sm.alwaysMatches() ? "YES" : "MAYBE")); |
| } |
| return sm; |
| } |
| |
| private ShadowMatchImpl getShadowMatch(Shadow forShadow) { |
| org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow); |
| Test residueTest = Literal.TRUE; |
| ExposedState state = getExposedState(); |
| if (match.maybeTrue()) { |
| residueTest = pointcut.findResidue(forShadow, state); |
| } |
| ShadowMatchImpl sm = new ShadowMatchImpl(match, residueTest, state, parameters); |
| sm.setMatchingContext(this.matchContext); |
| return sm; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.aspectj.weaver.tools.PointcutExpression#getPointcutExpression() |
| */ |
| public String getPointcutExpression() { |
| return expression; |
| } |
| |
| private static class HasPossibleDynamicContentVisitor extends AbstractPatternNodeVisitor { |
| private boolean hasDynamicContent = false; |
| |
| public boolean hasDynamicContent() { |
| return hasDynamicContent; |
| } |
| |
| @Override |
| public Object visit(WithinAnnotationPointcut node, Object data) { |
| hasDynamicContent = true; |
| return null; |
| } |
| |
| @Override |
| public Object visit(WithinCodeAnnotationPointcut node, Object data) { |
| hasDynamicContent = true; |
| return null; |
| } |
| |
| @Override |
| public Object visit(AnnotationPointcut node, Object data) { |
| hasDynamicContent = true; |
| return null; |
| } |
| |
| @Override |
| public Object visit(ArgsAnnotationPointcut node, Object data) { |
| hasDynamicContent = true; |
| return null; |
| } |
| |
| @Override |
| public Object visit(ArgsPointcut node, Object data) { |
| hasDynamicContent = true; |
| return null; |
| } |
| |
| @Override |
| public Object visit(CflowPointcut node, Object data) { |
| hasDynamicContent = true; |
| return null; |
| } |
| |
| @Override |
| public Object visit(IfPointcut node, Object data) { |
| hasDynamicContent = true; |
| return null; |
| } |
| |
| @Override |
| public Object visit(NotAnnotationTypePattern node, Object data) { |
| return node.getNegatedPattern().accept(this, data); |
| } |
| |
| @Override |
| public Object visit(NotPointcut node, Object data) { |
| return node.getNegatedPointcut().accept(this, data); |
| } |
| |
| @Override |
| public Object visit(ThisOrTargetAnnotationPointcut node, Object data) { |
| hasDynamicContent = true; |
| return null; |
| } |
| |
| @Override |
| public Object visit(ThisOrTargetPointcut node, Object data) { |
| hasDynamicContent = true; |
| return null; |
| } |
| |
| } |
| |
| public static class Handler implements Member { |
| |
| private Class decClass; |
| private Class exType; |
| |
| public Handler(Class decClass, Class exType) { |
| this.decClass = decClass; |
| this.exType = exType; |
| } |
| |
| public int getModifiers() { |
| return 0; |
| } |
| |
| public Class getDeclaringClass() { |
| return decClass; |
| } |
| |
| public String getName() { |
| return null; |
| } |
| |
| public Class getHandledExceptionType() { |
| return exType; |
| } |
| |
| public boolean isSynthetic() { |
| return false; |
| } |
| } |
| } |