Copyright (c) 2004, 2017 Contributors 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 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2004, 2017 Contributors * 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 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.aspectj.weaver.tools; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.HashSet; import java.util.Properties; import java.util.Set; import org.aspectj.bridge.IMessageHandler; import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.SourceLocation; import org.aspectj.weaver.BindingScope; import org.aspectj.weaver.IHasPosition; import org.aspectj.weaver.ISourceContext; import org.aspectj.weaver.IntMap; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.Shadow; import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.WeakClassLoaderReference; import org.aspectj.weaver.World; import org.aspectj.weaver.internal.tools.PointcutExpressionImpl; import org.aspectj.weaver.internal.tools.TypePatternMatcherImpl; import org.aspectj.weaver.patterns.AndPointcut; import org.aspectj.weaver.patterns.CflowPointcut; import org.aspectj.weaver.patterns.FormalBinding; import org.aspectj.weaver.patterns.IScope; import org.aspectj.weaver.patterns.KindedPointcut; import org.aspectj.weaver.patterns.NotPointcut; import org.aspectj.weaver.patterns.OrPointcut; import org.aspectj.weaver.patterns.ParserException; import org.aspectj.weaver.patterns.PatternParser; import org.aspectj.weaver.patterns.Pointcut; import org.aspectj.weaver.patterns.SimpleScope; import org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut; import org.aspectj.weaver.patterns.ThisOrTargetPointcut; import org.aspectj.weaver.patterns.TypePattern; import org.aspectj.weaver.reflect.PointcutParameterImpl; import org.aspectj.weaver.reflect.ReflectionWorld;
A PointcutParser can be used to build PointcutExpressions for a user-defined subset of AspectJ's pointcut language
Author:Adrian Colyer, Andy Clement
/** * A PointcutParser can be used to build PointcutExpressions for a user-defined subset of AspectJ's pointcut language * * @author Adrian Colyer * @author Andy Clement */
public class PointcutParser { private ReflectionWorld world; private WeakClassLoaderReference classLoaderReference; private final Set<PointcutPrimitive> supportedPrimitives; private final Set<PointcutDesignatorHandler> pointcutDesignators = new HashSet<PointcutDesignatorHandler>();
Returns:a Set containing every PointcutPrimitive except if, cflow, and cflowbelow (useful for passing to PointcutParser constructor).
/** * @return a Set containing every PointcutPrimitive except if, cflow, and cflowbelow (useful for passing to PointcutParser * constructor). */
public static Set<PointcutPrimitive> getAllSupportedPointcutPrimitives() { Set<PointcutPrimitive> primitives = new HashSet<PointcutPrimitive>(); 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:
  • The if, cflow, and cflowbelow pointcut designators are not supported
  • Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  • The pointcut expression must be anonymous with no formals allowed.

When resolving types in pointcut expressions, the context classloader is used to find types.

/** * 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:
  • The if, cflow, and cflowbelow pointcut designators are not supported
  • Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  • The pointcut expression must be anonymous with no formals allowed.

When resolving types in pointcut expressions, the context classloader is used to find types.

Params:
  • supportedPointcutKinds – a set of PointcutPrimitives this parser should support
Throws:
/** * 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<PointcutPrimitive> 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:
  • The if, cflow, and cflowbelow pointcut designators are not supported
  • Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  • The pointcut expression must be anonymous with no formals allowed.

When resolving types in pointcut expressions, the given classloader is used to find types.

/** * 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:
  • The if, cflow, and cflowbelow pointcut designators are not supported
  • Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  • The pointcut expression must be anonymous with no formals allowed.

When resolving types in pointcut expressions, the given classloader is used to find types.

Params:
  • supportedPointcutKinds – a set of PointcutPrimitives this parser should support
Throws:
/** * 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<PointcutPrimitive> 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:
  • The if, cflow, and cflowbelow pointcut designators are not supported
  • Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  • The pointcut expression must be anonymous with no formals allowed.
/** * 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:
  • The if, cflow, and cflowbelow pointcut designators are not supported
  • Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  • The pointcut expression must be anonymous with no formals allowed.
Params:
  • supportedPointcutKinds – a set of PointcutPrimitives this parser should support
Throws:
/** * 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<PointcutPrimitive> supportedPointcutKinds) { supportedPrimitives = supportedPointcutKinds; for (PointcutPrimitive pointcutPrimitive : supportedPointcutKinds) { if ((pointcutPrimitive == PointcutPrimitive.IF) || (pointcutPrimitive == PointcutPrimitive.CFLOW) || (pointcutPrimitive == 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.
Params:
  • aLoader –
/** * Set the classloader that this parser should use for type resolution. * * @param aLoader */
protected void setClassLoader(ClassLoader aLoader) { this.classLoaderReference = new WeakClassLoaderReference(aLoader); world = ReflectionWorld.getReflectionWorldFor(this.classLoaderReference); }
Set the classloader that this parser should use for type resolution.
Params:
  • aLoader –
  • shareWorlds – if true then two PointcutParsers operating using the same classloader will share a ReflectionWorld
/** * Set the classloader that this parser should use for type resolution. * * @param aLoader * @param shareWorlds if true then two PointcutParsers operating using the same classloader will share a ReflectionWorld */
protected void setClassLoader(ClassLoader aLoader, boolean shareWorlds) { this.classLoaderReference = new WeakClassLoaderReference(aLoader); if (shareWorlds) { world = ReflectionWorld.getReflectionWorldFor(this.classLoaderReference); } else { world = new ReflectionWorld(classLoaderReference); } }
Set the lint properties for this parser from the given resource on the classpath.
Params:
  • resourcePath – path to a file containing aspectj lint properties
/** * 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.
Params:
  • properties –
/** * 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.
Params:
  • designatorHandler –
/** * 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.
Params:
  • name –
  • type –
Returns:
/** * 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.
  • IllegalArgumentException – if the expression is not a well-formed pointcut expression
/** * 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.
  • IllegalArgumentException – if the expression is not a well-formed pointcut expression
/** * 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(); // more correctly: parsePointcut(true) 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.
Params:
  • typePattern – an aspectj type pattern
Throws:
Returns:a type pattern matcher that matches using the given pattern
/** * 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<PointcutPrimitive> 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 '"); msg.append(ex.getMessage()); msg.append("'"); IHasPosition location = ex.getLocation(); msg.append(" at character position "); msg.append(location.getStart()); msg.append("\n"); msg.append(pc); msg.append("\n"); for (int i = 0; i < location.getStart(); i++) { msg.append(" "); } for (int j = location.getStart(); j <= location.getEnd(); j++) { msg.append("^"); } msg.append("\n"); return msg.toString(); } }