import org.aspectj.weaver.reflect.ReflectionWorld;
/**
- * A PointcutParser can be used to build PointcutExpressions for a
- * user-defined subset of AspectJ's pointcut language
+ * A PointcutParser can be used to build PointcutExpressions for a user-defined subset of AspectJ's pointcut language
*/
public class PointcutParser {
-
+
private ReflectionWorld world;
private WeakClassLoaderReference classLoaderReference;
- private Set supportedPrimitives;
- private Set pointcutDesignators = new HashSet();
-
- /**
- * @return a Set containing every PointcutPrimitive except
- * if, cflow, and cflowbelow (useful for passing to
- * PointcutParser constructor).
- */
- public static Set getAllSupportedPointcutPrimitives() {
- Set primitives = new HashSet();
- primitives.add(PointcutPrimitive.ADVICE_EXECUTION);
- primitives.add(PointcutPrimitive.ARGS);
- primitives.add(PointcutPrimitive.CALL);
- primitives.add(PointcutPrimitive.EXECUTION);
- primitives.add(PointcutPrimitive.GET);
- primitives.add(PointcutPrimitive.HANDLER);
- primitives.add(PointcutPrimitive.INITIALIZATION);
- primitives.add(PointcutPrimitive.PRE_INITIALIZATION);
- primitives.add(PointcutPrimitive.SET);
- primitives.add(PointcutPrimitive.STATIC_INITIALIZATION);
- primitives.add(PointcutPrimitive.TARGET);
- primitives.add(PointcutPrimitive.THIS);
- primitives.add(PointcutPrimitive.WITHIN);
- primitives.add(PointcutPrimitive.WITHIN_CODE);
- primitives.add(PointcutPrimitive.AT_ANNOTATION);
- primitives.add(PointcutPrimitive.AT_THIS);
- primitives.add(PointcutPrimitive.AT_TARGET);
- primitives.add(PointcutPrimitive.AT_ARGS);
- primitives.add(PointcutPrimitive.AT_WITHIN);
- primitives.add(PointcutPrimitive.AT_WITHINCODE);
- primitives.add(PointcutPrimitive.REFERENCE);
-
- return primitives;
- }
-
- /**
- * Returns a pointcut parser that can parse the full AspectJ pointcut
- * language with the following exceptions:
- * <ul>
- * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
- * <li>Pointcut expressions must be self-contained :- they cannot contain references
- * to other named pointcuts
- * <li>The pointcut expression must be anonymous with no formals allowed.
- * </ul>
- * <p>When resolving types in pointcut expressions, the context classloader is used to find types.</p>
- */
- public static PointcutParser getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution() {
- PointcutParser p = new PointcutParser();
- p.setClassLoader(Thread.currentThread().getContextClassLoader());
- return p;
- }
-
- /**
- * Returns a pointcut parser that can parse pointcut expressions built
- * from a user-defined subset of AspectJ's supported pointcut primitives.
- * The following restrictions apply:
- * <ul>
- * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
- * <li>Pointcut expressions must be self-contained :- they cannot contain references
- * to other named pointcuts
- * <li>The pointcut expression must be anonymous with no formals allowed.
- * </ul>
- * <p>When resolving types in pointcut expressions, the context classloader is used to find types.</p>
- * @param supportedPointcutKinds a set of PointcutPrimitives this parser
- * should support
- * @throws UnsupportedOperationException if the set contains if, cflow, or
- * cflow below
- */
- public static PointcutParser getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(Set supportedPointcutKinds) {
- PointcutParser p = new PointcutParser(supportedPointcutKinds);
- p.setClassLoader(Thread.currentThread().getContextClassLoader());
- return p;
- }
-
- /**
- * Returns a pointcut parser that can parse the full AspectJ pointcut
- * language with the following exceptions:
- * <ul>
- * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
- * <li>Pointcut expressions must be self-contained :- they cannot contain references
- * to other named pointcuts
- * <li>The pointcut expression must be anonymous with no formals allowed.
- * </ul>
- * <p>When resolving types in pointcut expressions, the given classloader is used to find types.</p>
- */
- public static PointcutParser getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(ClassLoader classLoader) {
- PointcutParser p = new PointcutParser();
+ private final Set supportedPrimitives;
+ private final Set pointcutDesignators = new HashSet();
+
+ /**
+ * @return a Set containing every PointcutPrimitive except if, cflow, and cflowbelow (useful for passing to PointcutParser
+ * constructor).
+ */
+ public static Set getAllSupportedPointcutPrimitives() {
+ Set primitives = new HashSet();
+ primitives.add(PointcutPrimitive.ADVICE_EXECUTION);
+ primitives.add(PointcutPrimitive.ARGS);
+ primitives.add(PointcutPrimitive.CALL);
+ primitives.add(PointcutPrimitive.EXECUTION);
+ primitives.add(PointcutPrimitive.GET);
+ primitives.add(PointcutPrimitive.HANDLER);
+ primitives.add(PointcutPrimitive.INITIALIZATION);
+ primitives.add(PointcutPrimitive.PRE_INITIALIZATION);
+ primitives.add(PointcutPrimitive.SET);
+ primitives.add(PointcutPrimitive.STATIC_INITIALIZATION);
+ primitives.add(PointcutPrimitive.TARGET);
+ primitives.add(PointcutPrimitive.THIS);
+ primitives.add(PointcutPrimitive.WITHIN);
+ primitives.add(PointcutPrimitive.WITHIN_CODE);
+ primitives.add(PointcutPrimitive.AT_ANNOTATION);
+ primitives.add(PointcutPrimitive.AT_THIS);
+ primitives.add(PointcutPrimitive.AT_TARGET);
+ primitives.add(PointcutPrimitive.AT_ARGS);
+ primitives.add(PointcutPrimitive.AT_WITHIN);
+ primitives.add(PointcutPrimitive.AT_WITHINCODE);
+ primitives.add(PointcutPrimitive.REFERENCE);
+
+ return primitives;
+ }
+
+ /**
+ * Returns a pointcut parser that can parse the full AspectJ pointcut language with the following exceptions:
+ * <ul>
+ * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+ * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+ * <li>The pointcut expression must be anonymous with no formals allowed.
+ * </ul>
+ * <p>
+ * When resolving types in pointcut expressions, the context classloader is used to find types.
+ * </p>
+ */
+ public static PointcutParser getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution() {
+ PointcutParser p = new PointcutParser();
+ p.setClassLoader(Thread.currentThread().getContextClassLoader());
+ return p;
+ }
+
+ /**
+ * Returns a pointcut parser that can parse pointcut expressions built from a user-defined subset of AspectJ's supported
+ * pointcut primitives. The following restrictions apply:
+ * <ul>
+ * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+ * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+ * <li>The pointcut expression must be anonymous with no formals allowed.
+ * </ul>
+ * <p>
+ * When resolving types in pointcut expressions, the context classloader is used to find types.
+ * </p>
+ *
+ * @param supportedPointcutKinds a set of PointcutPrimitives this parser should support
+ * @throws UnsupportedOperationException if the set contains if, cflow, or cflow below
+ */
+ public static PointcutParser getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(
+ Set supportedPointcutKinds) {
+ PointcutParser p = new PointcutParser(supportedPointcutKinds);
+ p.setClassLoader(Thread.currentThread().getContextClassLoader());
+ return p;
+ }
+
+ /**
+ * Returns a pointcut parser that can parse the full AspectJ pointcut language with the following exceptions:
+ * <ul>
+ * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+ * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+ * <li>The pointcut expression must be anonymous with no formals allowed.
+ * </ul>
+ * <p>
+ * When resolving types in pointcut expressions, the given classloader is used to find types.
+ * </p>
+ */
+ public static PointcutParser getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(
+ ClassLoader classLoader) {
+ PointcutParser p = new PointcutParser();
p.setClassLoader(classLoader);
return p;
- }
-
-
- /**
- * Returns a pointcut parser that can parse pointcut expressions built
- * from a user-defined subset of AspectJ's supported pointcut primitives.
- * The following restrictions apply:
- * <ul>
- * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
- * <li>Pointcut expressions must be self-contained :- they cannot contain references
- * to other named pointcuts
- * <li>The pointcut expression must be anonymous with no formals allowed.
- * </ul>
- * <p>When resolving types in pointcut expressions, the given classloader is used to find types.</p>
- * @param supportedPointcutKinds a set of PointcutPrimitives this parser
- * should support
- * @throws UnsupportedOperationException if the set contains if, cflow, or
- * cflow below
- */
- public static PointcutParser getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(Set supportedPointcutKinds, ClassLoader classLoader) {
- PointcutParser p = new PointcutParser(supportedPointcutKinds);
+ }
+
+ /**
+ * Returns a pointcut parser that can parse pointcut expressions built from a user-defined subset of AspectJ's supported
+ * pointcut primitives. The following restrictions apply:
+ * <ul>
+ * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+ * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+ * <li>The pointcut expression must be anonymous with no formals allowed.
+ * </ul>
+ * <p>
+ * When resolving types in pointcut expressions, the given classloader is used to find types.
+ * </p>
+ *
+ * @param supportedPointcutKinds a set of PointcutPrimitives this parser should support
+ * @throws UnsupportedOperationException if the set contains if, cflow, or cflow below
+ */
+ public static PointcutParser getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
+ Set supportedPointcutKinds, ClassLoader classLoader) {
+ PointcutParser p = new PointcutParser(supportedPointcutKinds);
p.setClassLoader(classLoader);
- return p;
- }
-
- /**
- * Create a pointcut parser that can parse the full AspectJ pointcut
- * language with the following exceptions:
- * <ul>
- * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
- * <li>Pointcut expressions must be self-contained :- they cannot contain references
- * to other named pointcuts
- * <li>The pointcut expression must be anonymous with no formals allowed.
- * </ul>
- */
- protected PointcutParser() {
- supportedPrimitives = getAllSupportedPointcutPrimitives();
- setClassLoader(PointcutParser.class.getClassLoader());
- }
-
- /**
- * Create a pointcut parser that can parse pointcut expressions built
- * from a user-defined subset of AspectJ's supported pointcut primitives.
- * The following restrictions apply:
- * <ul>
- * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
- * <li>Pointcut expressions must be self-contained :- they cannot contain references
- * to other named pointcuts
- * <li>The pointcut expression must be anonymous with no formals allowed.
- * </ul>
- * @param supportedPointcutKinds a set of PointcutPrimitives this parser
- * should support
- * @throws UnsupportedOperationException if the set contains if, cflow, or
- * cflow below
- */
- private PointcutParser(Set/*<PointcutPrimitives>*/ supportedPointcutKinds) {
- supportedPrimitives = supportedPointcutKinds;
- for (Iterator iter = supportedPointcutKinds.iterator(); iter.hasNext();) {
- PointcutPrimitive element = (PointcutPrimitive) iter.next();
- if ((element == PointcutPrimitive.IF) ||
- (element == PointcutPrimitive.CFLOW) ||
- (element == PointcutPrimitive.CFLOW_BELOW)) {
- throw new UnsupportedOperationException("Cannot handle if, cflow, and cflowbelow primitives");
- }
- }
- setClassLoader(PointcutParser.class.getClassLoader());
- }
-
- protected void setWorld(ReflectionWorld aWorld) {
- this.world = aWorld;
- }
-
- /**
- * Set the classloader that this parser should use for
- * type resolution.
- * @param aLoader
- */
- protected void setClassLoader(ClassLoader aLoader) {
- this.classLoaderReference = new WeakClassLoaderReference(aLoader);
- world = new ReflectionWorld(this.classLoaderReference.getClassLoader());
- }
-
- /**
- * Set the lint properties for this parser from the
- * given resource on the classpath.
- * @param resourcePath path to a file containing aspectj
- * lint properties
- */
- public void setLintProperties(String resourcePath)throws IOException {
- URL url = this.classLoaderReference.getClassLoader().getResource(resourcePath);
- InputStream is = url.openStream();
- Properties p = new Properties();
+ return p;
+ }
+
+ /**
+ * Create a pointcut parser that can parse the full AspectJ pointcut language with the following exceptions:
+ * <ul>
+ * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+ * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+ * <li>The pointcut expression must be anonymous with no formals allowed.
+ * </ul>
+ */
+ protected PointcutParser() {
+ supportedPrimitives = getAllSupportedPointcutPrimitives();
+ setClassLoader(PointcutParser.class.getClassLoader());
+ }
+
+ /**
+ * Create a pointcut parser that can parse pointcut expressions built from a user-defined subset of AspectJ's supported pointcut
+ * primitives. The following restrictions apply:
+ * <ul>
+ * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
+ * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
+ * <li>The pointcut expression must be anonymous with no formals allowed.
+ * </ul>
+ *
+ * @param supportedPointcutKinds a set of PointcutPrimitives this parser should support
+ * @throws UnsupportedOperationException if the set contains if, cflow, or cflow below
+ */
+ private PointcutParser(Set/* <PointcutPrimitives> */supportedPointcutKinds) {
+ supportedPrimitives = supportedPointcutKinds;
+ for (Iterator iter = supportedPointcutKinds.iterator(); iter.hasNext();) {
+ PointcutPrimitive element = (PointcutPrimitive) iter.next();
+ if ((element == PointcutPrimitive.IF) || (element == PointcutPrimitive.CFLOW)
+ || (element == PointcutPrimitive.CFLOW_BELOW)) {
+ throw new UnsupportedOperationException("Cannot handle if, cflow, and cflowbelow primitives");
+ }
+ }
+ setClassLoader(PointcutParser.class.getClassLoader());
+ }
+
+ protected void setWorld(ReflectionWorld aWorld) {
+ this.world = aWorld;
+ }
+
+ /**
+ * Set the classloader that this parser should use for type resolution.
+ *
+ * @param aLoader
+ */
+ protected void setClassLoader(ClassLoader aLoader) {
+ this.classLoaderReference = new WeakClassLoaderReference(aLoader);
+ world = new ReflectionWorld(this.classLoaderReference.getClassLoader());
+ }
+
+ /**
+ * Set the lint properties for this parser from the given resource on the classpath.
+ *
+ * @param resourcePath path to a file containing aspectj lint properties
+ */
+ public void setLintProperties(String resourcePath) throws IOException {
+ URL url = this.classLoaderReference.getClassLoader().getResource(resourcePath);
+ InputStream is = url.openStream();
+ Properties p = new Properties();
p.load(is);
setLintProperties(p);
- }
-
- /**
- * Set the lint properties for this parser from the
- * given properties set.
- * @param properties
- */
- public void setLintProperties(Properties properties) {
- getWorld().getLint().setFromProperties(properties);
- }
-
- /**
- * Register a new pointcut designator handler with this parser.
- * This provides an extension mechansim for the integration of
- * domain-specific pointcut designators with the AspectJ
- * pointcut language.
- * @param designatorHandler
- */
- public void registerPointcutDesignatorHandler(PointcutDesignatorHandler designatorHandler) {
- this.pointcutDesignators.add(designatorHandler);
- if (world != null) world.registerPointcutHandler(designatorHandler);
- }
-
- /**
- * Create a pointcut parameter of the given name and type.
- * @param name
- * @param type
- * @return
- */
- public PointcutParameter createPointcutParameter(String name, Class type) {
- return new PointcutParameterImpl(name,type);
- }
-
- /**
- * Parse the given pointcut expression.
- * A global scope is assumed for resolving any type references, and the pointcut
- * must contain no formals (variables to be bound).
- * @throws UnsupportedPointcutPrimitiveException if the parser encounters a
- * primitive pointcut expression of a kind not supported by this PointcutParser.
- * @throws IllegalArgumentException if the expression is not a well-formed
- * pointcut expression
- */
- public PointcutExpression parsePointcutExpression(String expression)
- throws UnsupportedPointcutPrimitiveException, IllegalArgumentException {
- return parsePointcutExpression(expression,null,new PointcutParameter[0]);
- }
-
- /**
- * Parse the given pointcut expression.
- * The pointcut is resolved as if it had been declared inside the inScope class
- * (this allows the pointcut to contain unqualified references to other pointcuts
- * declared in the same type for example).
- * The pointcut may contain zero or more formal parameters to be bound at matched
- * join points.
- * @throws UnsupportedPointcutPrimitiveException if the parser encounters a
- * primitive pointcut expression of a kind not supported by this PointcutParser.
- * @throws IllegalArgumentException if the expression is not a well-formed
- * pointcut expression
- */
- public PointcutExpression parsePointcutExpression(
- String expression,
- Class inScope,
- PointcutParameter[] formalParameters)
- throws UnsupportedPointcutPrimitiveException, IllegalArgumentException {
- PointcutExpressionImpl pcExpr = null;
- try {
- Pointcut pc = resolvePointcutExpression(expression,inScope,formalParameters);
- pc = concretizePointcutExpression(pc,inScope,formalParameters);
- validateAgainstSupportedPrimitives(pc,expression); // again, because we have now followed any ref'd pcuts
- pcExpr = new PointcutExpressionImpl(pc,expression,formalParameters,getWorld());
- } catch (ParserException pEx) {
- throw new IllegalArgumentException(buildUserMessageFromParserException(expression,pEx));
- } catch (ReflectionWorld.ReflectionWorldException rwEx) {
- throw new IllegalArgumentException(rwEx.getMessage());
- }
- return pcExpr;
- }
-
- protected Pointcut resolvePointcutExpression(
- String expression,
- Class inScope,
- PointcutParameter[] formalParameters) {
- try {
- PatternParser parser = new PatternParser(expression);
- parser.setPointcutDesignatorHandlers(pointcutDesignators, world);
- Pointcut pc = parser.parsePointcut();
- validateAgainstSupportedPrimitives(pc,expression);
- IScope resolutionScope = buildResolutionScope((inScope == null ? Object.class : inScope),formalParameters);
- pc = pc.resolve(resolutionScope);
- return pc;
- } catch (ParserException pEx) {
- throw new IllegalArgumentException(buildUserMessageFromParserException(expression,pEx));
- }
- }
-
- protected Pointcut concretizePointcutExpression(Pointcut pc, Class inScope, PointcutParameter[] formalParameters) {
- ResolvedType declaringTypeForResolution = null;
- if (inScope != null) {
- declaringTypeForResolution = getWorld().resolve(inScope.getName());
- } else {
- declaringTypeForResolution = ResolvedType.OBJECT.resolve(getWorld());
- }
- IntMap arity = new IntMap(formalParameters.length);
- for (int i = 0; i < formalParameters.length; i++) {
- arity.put(i, i);
- }
- return pc.concretize(declaringTypeForResolution, declaringTypeForResolution, arity);
- }
-
- /**
- * Parse the given aspectj type pattern, and return a
- * matcher that can be used to match types using it.
- * @param typePattern an aspectj type pattern
- * @return a type pattern matcher that matches using the given
- * pattern
- * @throws IllegalArgumentException if the type pattern cannot
- * be successfully parsed.
- */
- public TypePatternMatcher parseTypePattern(String typePattern)
- throws IllegalArgumentException {
- try {
- TypePattern tp = new PatternParser(typePattern).parseTypePattern();
- tp.resolve(world);
- return new TypePatternMatcherImpl(tp,world);
- } catch (ParserException pEx) {
- throw new IllegalArgumentException(buildUserMessageFromParserException(typePattern,pEx));
- } catch (ReflectionWorld.ReflectionWorldException rwEx) {
- throw new IllegalArgumentException(rwEx.getMessage());
- }
- }
-
- private World getWorld() {
- return world;
- }
-
- /* for testing */
- Set getSupportedPrimitives() {
- return supportedPrimitives;
- }
-
- /* for testing */
- IMessageHandler setCustomMessageHandler(IMessageHandler aHandler) {
- IMessageHandler current = getWorld().getMessageHandler();
- getWorld().setMessageHandler(aHandler);
- return current;
- }
-
- private IScope buildResolutionScope(Class inScope, PointcutParameter[] formalParameters) {
- if (formalParameters == null) formalParameters = new PointcutParameter[0];
- FormalBinding[] formalBindings = new FormalBinding[formalParameters.length];
- for (int i = 0; i < formalBindings.length; i++) {
- formalBindings[i] = new FormalBinding(toUnresolvedType(formalParameters[i].getType()),formalParameters[i].getName(),i);
+ }
+
+ /**
+ * Set the lint properties for this parser from the given properties set.
+ *
+ * @param properties
+ */
+ public void setLintProperties(Properties properties) {
+ getWorld().getLint().setFromProperties(properties);
+ }
+
+ /**
+ * Register a new pointcut designator handler with this parser. This provides an extension mechansim for the integration of
+ * domain-specific pointcut designators with the AspectJ pointcut language.
+ *
+ * @param designatorHandler
+ */
+ public void registerPointcutDesignatorHandler(PointcutDesignatorHandler designatorHandler) {
+ this.pointcutDesignators.add(designatorHandler);
+ if (world != null)
+ world.registerPointcutHandler(designatorHandler);
+ }
+
+ /**
+ * Create a pointcut parameter of the given name and type.
+ *
+ * @param name
+ * @param type
+ * @return
+ */
+ public PointcutParameter createPointcutParameter(String name, Class type) {
+ return new PointcutParameterImpl(name, type);
+ }
+
+ /**
+ * Parse the given pointcut expression. A global scope is assumed for resolving any type references, and the pointcut must
+ * contain no formals (variables to be bound).
+ *
+ * @throws UnsupportedPointcutPrimitiveException if the parser encounters a primitive pointcut expression of a kind not
+ * supported by this PointcutParser.
+ * @throws IllegalArgumentException if the expression is not a well-formed pointcut expression
+ */
+ public PointcutExpression parsePointcutExpression(String expression) throws UnsupportedPointcutPrimitiveException,
+ IllegalArgumentException {
+ return parsePointcutExpression(expression, null, new PointcutParameter[0]);
+ }
+
+ /**
+ * Parse the given pointcut expression. The pointcut is resolved as if it had been declared inside the inScope class (this
+ * allows the pointcut to contain unqualified references to other pointcuts declared in the same type for example). The pointcut
+ * may contain zero or more formal parameters to be bound at matched join points.
+ *
+ * @throws UnsupportedPointcutPrimitiveException if the parser encounters a primitive pointcut expression of a kind not
+ * supported by this PointcutParser.
+ * @throws IllegalArgumentException if the expression is not a well-formed pointcut expression
+ */
+ public PointcutExpression parsePointcutExpression(String expression, Class inScope, PointcutParameter[] formalParameters)
+ throws UnsupportedPointcutPrimitiveException, IllegalArgumentException {
+ PointcutExpressionImpl pcExpr = null;
+ try {
+ Pointcut pc = resolvePointcutExpression(expression, inScope, formalParameters);
+ pc = concretizePointcutExpression(pc, inScope, formalParameters);
+ validateAgainstSupportedPrimitives(pc, expression); // again, because we have now followed any ref'd pcuts
+ pcExpr = new PointcutExpressionImpl(pc, expression, formalParameters, getWorld());
+ } catch (ParserException pEx) {
+ throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
+ } catch (ReflectionWorld.ReflectionWorldException rwEx) {
+ throw new IllegalArgumentException(rwEx.getMessage());
}
- if (inScope == null) {
- return new SimpleScope(getWorld(),formalBindings);
- } else {
- ResolvedType inType = getWorld().resolve(inScope.getName());
- ISourceContext sourceContext = new ISourceContext() {
- public ISourceLocation makeSourceLocation(IHasPosition position) {
- return new SourceLocation(new File(""),0);
- }
- public ISourceLocation makeSourceLocation(int line, int offset) {
- return new SourceLocation(new File(""),line);
- }
- public int getOffset() {
- return 0;
- }
- public void tidy() {}
- };
- return new BindingScope(inType,sourceContext,formalBindings);
- }
- }
-
- private UnresolvedType toUnresolvedType(Class clazz) {
- if (clazz.isArray()) {
- return UnresolvedType.forSignature(clazz.getName().replace('.','/'));
- } else {
- return UnresolvedType.forName(clazz.getName());
- }
- }
-
- private void validateAgainstSupportedPrimitives(Pointcut pc, String expression) {
- switch(pc.getPointcutKind()) {
- case Pointcut.AND:
- validateAgainstSupportedPrimitives(((AndPointcut)pc).getLeft(),expression);
- validateAgainstSupportedPrimitives(((AndPointcut)pc).getRight(),expression);
- break;
- case Pointcut.ARGS:
- if (!supportedPrimitives.contains(PointcutPrimitive.ARGS))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.ARGS);
- break;
- case Pointcut.CFLOW:
- CflowPointcut cfp = (CflowPointcut) pc;
- if (cfp.isCflowBelow()) {
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CFLOW_BELOW);
- } else {
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CFLOW);
- }
- case Pointcut.HANDLER:
- if (!supportedPrimitives.contains(PointcutPrimitive.HANDLER))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.HANDLER);
- break;
- case Pointcut.IF:
- case Pointcut.IF_FALSE:
- case Pointcut.IF_TRUE:
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.IF);
- case Pointcut.KINDED:
- validateKindedPointcut(((KindedPointcut)pc),expression);
- break;
- case Pointcut.NOT:
- validateAgainstSupportedPrimitives(((NotPointcut)pc).getNegatedPointcut(),expression);
- break;
- case Pointcut.OR:
- validateAgainstSupportedPrimitives(((OrPointcut)pc).getLeft(),expression);
- validateAgainstSupportedPrimitives(((OrPointcut)pc).getRight(),expression);
- break;
- case Pointcut.THIS_OR_TARGET:
- boolean isThis = ((ThisOrTargetPointcut)pc).isThis();
- if (isThis && !supportedPrimitives.contains(PointcutPrimitive.THIS)) {
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.THIS);
- } else if (!supportedPrimitives.contains(PointcutPrimitive.TARGET)) {
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.TARGET);
- }
- break;
- case Pointcut.WITHIN:
- if (!supportedPrimitives.contains(PointcutPrimitive.WITHIN))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.WITHIN);
- break;
- case Pointcut.WITHINCODE:
- if (!supportedPrimitives.contains(PointcutPrimitive.WITHIN_CODE))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.WITHIN_CODE);
- break;
- case Pointcut.ATTHIS_OR_TARGET:
- isThis = ((ThisOrTargetAnnotationPointcut)pc).isThis();
- if (isThis && !supportedPrimitives.contains(PointcutPrimitive.AT_THIS)) {
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_THIS);
- } else if (!supportedPrimitives.contains(PointcutPrimitive.AT_TARGET)) {
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_TARGET);
- }
- break;
- case Pointcut.ATARGS:
- if (!supportedPrimitives.contains(PointcutPrimitive.AT_ARGS))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_ARGS);
- break;
- case Pointcut.ANNOTATION:
- if (!supportedPrimitives.contains(PointcutPrimitive.AT_ANNOTATION))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_ANNOTATION);
- break;
- case Pointcut.ATWITHIN:
- if (!supportedPrimitives.contains(PointcutPrimitive.AT_WITHIN))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_WITHIN);
- break;
- case Pointcut.ATWITHINCODE:
- if (!supportedPrimitives.contains(PointcutPrimitive.AT_WITHINCODE))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_WITHINCODE);
- break;
- case Pointcut.REFERENCE:
- if (!supportedPrimitives.contains(PointcutPrimitive.REFERENCE))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.REFERENCE);
- break;
- case Pointcut.USER_EXTENSION:
- // always ok...
- break;
- case Pointcut.NONE: // deliberate fall-through
- default:
- throw new IllegalArgumentException("Unknown pointcut kind: " + pc.getPointcutKind());
- }
- }
-
- private void validateKindedPointcut(KindedPointcut pc, String expression) {
- Shadow.Kind kind = pc.getKind();
- if ((kind == Shadow.MethodCall) || (kind == Shadow.ConstructorCall)) {
- if (!supportedPrimitives.contains(PointcutPrimitive.CALL))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CALL);
- } else if ((kind == Shadow.MethodExecution) || (kind == Shadow.ConstructorExecution)) {
- if (!supportedPrimitives.contains(PointcutPrimitive.EXECUTION))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.EXECUTION);
- } else if (kind == Shadow.AdviceExecution) {
- if (!supportedPrimitives.contains(PointcutPrimitive.ADVICE_EXECUTION))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.ADVICE_EXECUTION);
- } else if (kind == Shadow.FieldGet) {
- if (!supportedPrimitives.contains(PointcutPrimitive.GET))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.GET);
- } else if (kind == Shadow.FieldSet) {
- if (!supportedPrimitives.contains(PointcutPrimitive.SET))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.SET);
- } else if (kind == Shadow.Initialization) {
- if (!supportedPrimitives.contains(PointcutPrimitive.INITIALIZATION))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.INITIALIZATION);
- } else if (kind == Shadow.PreInitialization) {
- if (!supportedPrimitives.contains(PointcutPrimitive.PRE_INITIALIZATION))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.PRE_INITIALIZATION);
- } else if (kind == Shadow.StaticInitialization) {
- if (!supportedPrimitives.contains(PointcutPrimitive.STATIC_INITIALIZATION))
- throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.STATIC_INITIALIZATION);
- }
- }
-
+ return pcExpr;
+ }
+
+ protected Pointcut resolvePointcutExpression(String expression, Class inScope, PointcutParameter[] formalParameters) {
+ try {
+ PatternParser parser = new PatternParser(expression);
+ parser.setPointcutDesignatorHandlers(pointcutDesignators, world);
+ Pointcut pc = parser.parsePointcut();
+ validateAgainstSupportedPrimitives(pc, expression);
+ IScope resolutionScope = buildResolutionScope((inScope == null ? Object.class : inScope), formalParameters);
+ pc = pc.resolve(resolutionScope);
+ return pc;
+ } catch (ParserException pEx) {
+ throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
+ }
+ }
+
+ protected Pointcut concretizePointcutExpression(Pointcut pc, Class inScope, PointcutParameter[] formalParameters) {
+ ResolvedType declaringTypeForResolution = null;
+ if (inScope != null) {
+ declaringTypeForResolution = getWorld().resolve(inScope.getName());
+ } else {
+ declaringTypeForResolution = ResolvedType.OBJECT.resolve(getWorld());
+ }
+ IntMap arity = new IntMap(formalParameters.length);
+ for (int i = 0; i < formalParameters.length; i++) {
+ arity.put(i, i);
+ }
+ return pc.concretize(declaringTypeForResolution, declaringTypeForResolution, arity);
+ }
+
+ /**
+ * Parse the given aspectj type pattern, and return a matcher that can be used to match types using it.
+ *
+ * @param typePattern an aspectj type pattern
+ * @return a type pattern matcher that matches using the given pattern
+ * @throws IllegalArgumentException if the type pattern cannot be successfully parsed.
+ */
+ public TypePatternMatcher parseTypePattern(String typePattern) throws IllegalArgumentException {
+ try {
+ TypePattern tp = new PatternParser(typePattern).parseTypePattern();
+ tp.resolve(world);
+ return new TypePatternMatcherImpl(tp, world);
+ } catch (ParserException pEx) {
+ throw new IllegalArgumentException(buildUserMessageFromParserException(typePattern, pEx));
+ } catch (ReflectionWorld.ReflectionWorldException rwEx) {
+ throw new IllegalArgumentException(rwEx.getMessage());
+ }
+ }
+
+ private World getWorld() {
+ return world;
+ }
+
+ /* for testing */
+ Set getSupportedPrimitives() {
+ return supportedPrimitives;
+ }
+
+ /* for testing */
+ IMessageHandler setCustomMessageHandler(IMessageHandler aHandler) {
+ IMessageHandler current = getWorld().getMessageHandler();
+ getWorld().setMessageHandler(aHandler);
+ return current;
+ }
+
+ private IScope buildResolutionScope(Class inScope, PointcutParameter[] formalParameters) {
+ if (formalParameters == null)
+ formalParameters = new PointcutParameter[0];
+ FormalBinding[] formalBindings = new FormalBinding[formalParameters.length];
+ for (int i = 0; i < formalBindings.length; i++) {
+ formalBindings[i] = new FormalBinding(toUnresolvedType(formalParameters[i].getType()), formalParameters[i].getName(), i);
+ }
+ if (inScope == null) {
+ return new SimpleScope(getWorld(), formalBindings);
+ } else {
+ ResolvedType inType = getWorld().resolve(inScope.getName());
+ ISourceContext sourceContext = new ISourceContext() {
+ public ISourceLocation makeSourceLocation(IHasPosition position) {
+ return new SourceLocation(new File(""), 0);
+ }
+
+ public ISourceLocation makeSourceLocation(int line, int offset) {
+ return new SourceLocation(new File(""), line);
+ }
+
+ public int getOffset() {
+ return 0;
+ }
+
+ public void tidy() {
+ }
+ };
+ return new BindingScope(inType, sourceContext, formalBindings);
+ }
+ }
+
+ private UnresolvedType toUnresolvedType(Class clazz) {
+ if (clazz.isArray()) {
+ return UnresolvedType.forSignature(clazz.getName().replace('.', '/'));
+ } else {
+ return UnresolvedType.forName(clazz.getName());
+ }
+ }
+
+ private void validateAgainstSupportedPrimitives(Pointcut pc, String expression) {
+ switch (pc.getPointcutKind()) {
+ case Pointcut.AND:
+ validateAgainstSupportedPrimitives(((AndPointcut) pc).getLeft(), expression);
+ validateAgainstSupportedPrimitives(((AndPointcut) pc).getRight(), expression);
+ break;
+ case Pointcut.ARGS:
+ if (!supportedPrimitives.contains(PointcutPrimitive.ARGS))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.ARGS);
+ break;
+ case Pointcut.CFLOW:
+ CflowPointcut cfp = (CflowPointcut) pc;
+ if (cfp.isCflowBelow()) {
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CFLOW_BELOW);
+ } else {
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CFLOW);
+ }
+ case Pointcut.HANDLER:
+ if (!supportedPrimitives.contains(PointcutPrimitive.HANDLER))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.HANDLER);
+ break;
+ case Pointcut.IF:
+ case Pointcut.IF_FALSE:
+ case Pointcut.IF_TRUE:
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.IF);
+ case Pointcut.KINDED:
+ validateKindedPointcut(((KindedPointcut) pc), expression);
+ break;
+ case Pointcut.NOT:
+ validateAgainstSupportedPrimitives(((NotPointcut) pc).getNegatedPointcut(), expression);
+ break;
+ case Pointcut.OR:
+ validateAgainstSupportedPrimitives(((OrPointcut) pc).getLeft(), expression);
+ validateAgainstSupportedPrimitives(((OrPointcut) pc).getRight(), expression);
+ break;
+ case Pointcut.THIS_OR_TARGET:
+ boolean isThis = ((ThisOrTargetPointcut) pc).isThis();
+ if (isThis && !supportedPrimitives.contains(PointcutPrimitive.THIS)) {
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.THIS);
+ } else if (!supportedPrimitives.contains(PointcutPrimitive.TARGET)) {
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.TARGET);
+ }
+ break;
+ case Pointcut.WITHIN:
+ if (!supportedPrimitives.contains(PointcutPrimitive.WITHIN))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.WITHIN);
+ break;
+ case Pointcut.WITHINCODE:
+ if (!supportedPrimitives.contains(PointcutPrimitive.WITHIN_CODE))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.WITHIN_CODE);
+ break;
+ case Pointcut.ATTHIS_OR_TARGET:
+ isThis = ((ThisOrTargetAnnotationPointcut) pc).isThis();
+ if (isThis && !supportedPrimitives.contains(PointcutPrimitive.AT_THIS)) {
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_THIS);
+ } else if (!supportedPrimitives.contains(PointcutPrimitive.AT_TARGET)) {
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_TARGET);
+ }
+ break;
+ case Pointcut.ATARGS:
+ if (!supportedPrimitives.contains(PointcutPrimitive.AT_ARGS))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_ARGS);
+ break;
+ case Pointcut.ANNOTATION:
+ if (!supportedPrimitives.contains(PointcutPrimitive.AT_ANNOTATION))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_ANNOTATION);
+ break;
+ case Pointcut.ATWITHIN:
+ if (!supportedPrimitives.contains(PointcutPrimitive.AT_WITHIN))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_WITHIN);
+ break;
+ case Pointcut.ATWITHINCODE:
+ if (!supportedPrimitives.contains(PointcutPrimitive.AT_WITHINCODE))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_WITHINCODE);
+ break;
+ case Pointcut.REFERENCE:
+ if (!supportedPrimitives.contains(PointcutPrimitive.REFERENCE))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.REFERENCE);
+ break;
+ case Pointcut.USER_EXTENSION:
+ // always ok...
+ break;
+ case Pointcut.NONE: // deliberate fall-through
+ default:
+ throw new IllegalArgumentException("Unknown pointcut kind: " + pc.getPointcutKind());
+ }
+ }
+
+ private void validateKindedPointcut(KindedPointcut pc, String expression) {
+ Shadow.Kind kind = pc.getKind();
+ if ((kind == Shadow.MethodCall) || (kind == Shadow.ConstructorCall)) {
+ if (!supportedPrimitives.contains(PointcutPrimitive.CALL))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CALL);
+ } else if ((kind == Shadow.MethodExecution) || (kind == Shadow.ConstructorExecution)) {
+ if (!supportedPrimitives.contains(PointcutPrimitive.EXECUTION))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.EXECUTION);
+ } else if (kind == Shadow.AdviceExecution) {
+ if (!supportedPrimitives.contains(PointcutPrimitive.ADVICE_EXECUTION))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.ADVICE_EXECUTION);
+ } else if (kind == Shadow.FieldGet) {
+ if (!supportedPrimitives.contains(PointcutPrimitive.GET))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.GET);
+ } else if (kind == Shadow.FieldSet) {
+ if (!supportedPrimitives.contains(PointcutPrimitive.SET))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.SET);
+ } else if (kind == Shadow.Initialization) {
+ if (!supportedPrimitives.contains(PointcutPrimitive.INITIALIZATION))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.INITIALIZATION);
+ } else if (kind == Shadow.PreInitialization) {
+ if (!supportedPrimitives.contains(PointcutPrimitive.PRE_INITIALIZATION))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.PRE_INITIALIZATION);
+ } else if (kind == Shadow.StaticInitialization) {
+ if (!supportedPrimitives.contains(PointcutPrimitive.STATIC_INITIALIZATION))
+ throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.STATIC_INITIALIZATION);
+ }
+ }
+
private String buildUserMessageFromParserException(String pc, ParserException ex) {
StringBuffer msg = new StringBuffer();
msg.append("Pointcut is not well-formed: expecting '");
for (int i = 0; i < location.getStart(); i++) {
msg.append(" ");
}
- for (int j=location.getStart(); j <= location.getEnd(); j++) {
+ for (int j = location.getStart(); j <= location.getEnd(); j++) {
msg.append("^");
}
msg.append("\n");