You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PointcutParser.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. /*******************************************************************************
  2. * Copyright (c) 2004 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. *******************************************************************************/
  11. package org.aspectj.weaver.tools;
  12. import java.io.File;
  13. import java.io.IOException;
  14. import java.io.InputStream;
  15. import java.net.URL;
  16. import java.util.HashSet;
  17. import java.util.Properties;
  18. import java.util.Set;
  19. import org.aspectj.bridge.IMessageHandler;
  20. import org.aspectj.bridge.ISourceLocation;
  21. import org.aspectj.bridge.SourceLocation;
  22. import org.aspectj.weaver.BindingScope;
  23. import org.aspectj.weaver.IHasPosition;
  24. import org.aspectj.weaver.ISourceContext;
  25. import org.aspectj.weaver.IntMap;
  26. import org.aspectj.weaver.ResolvedType;
  27. import org.aspectj.weaver.Shadow;
  28. import org.aspectj.weaver.UnresolvedType;
  29. import org.aspectj.weaver.WeakClassLoaderReference;
  30. import org.aspectj.weaver.World;
  31. import org.aspectj.weaver.internal.tools.PointcutExpressionImpl;
  32. import org.aspectj.weaver.internal.tools.TypePatternMatcherImpl;
  33. import org.aspectj.weaver.patterns.AndPointcut;
  34. import org.aspectj.weaver.patterns.CflowPointcut;
  35. import org.aspectj.weaver.patterns.FormalBinding;
  36. import org.aspectj.weaver.patterns.IScope;
  37. import org.aspectj.weaver.patterns.KindedPointcut;
  38. import org.aspectj.weaver.patterns.NotPointcut;
  39. import org.aspectj.weaver.patterns.OrPointcut;
  40. import org.aspectj.weaver.patterns.ParserException;
  41. import org.aspectj.weaver.patterns.PatternParser;
  42. import org.aspectj.weaver.patterns.Pointcut;
  43. import org.aspectj.weaver.patterns.SimpleScope;
  44. import org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut;
  45. import org.aspectj.weaver.patterns.ThisOrTargetPointcut;
  46. import org.aspectj.weaver.patterns.TypePattern;
  47. import org.aspectj.weaver.reflect.PointcutParameterImpl;
  48. import org.aspectj.weaver.reflect.ReflectionWorld;
  49. /**
  50. * A PointcutParser can be used to build PointcutExpressions for a user-defined subset of AspectJ's pointcut language
  51. */
  52. public class PointcutParser {
  53. private ReflectionWorld world;
  54. private WeakClassLoaderReference classLoaderReference;
  55. private final Set<PointcutPrimitive> supportedPrimitives;
  56. private final Set<PointcutDesignatorHandler> pointcutDesignators = new HashSet<PointcutDesignatorHandler>();
  57. /**
  58. * @return a Set containing every PointcutPrimitive except if, cflow, and cflowbelow (useful for passing to PointcutParser
  59. * constructor).
  60. */
  61. public static Set<PointcutPrimitive> getAllSupportedPointcutPrimitives() {
  62. Set<PointcutPrimitive> primitives = new HashSet<PointcutPrimitive>();
  63. primitives.add(PointcutPrimitive.ADVICE_EXECUTION);
  64. primitives.add(PointcutPrimitive.ARGS);
  65. primitives.add(PointcutPrimitive.CALL);
  66. primitives.add(PointcutPrimitive.EXECUTION);
  67. primitives.add(PointcutPrimitive.GET);
  68. primitives.add(PointcutPrimitive.HANDLER);
  69. primitives.add(PointcutPrimitive.INITIALIZATION);
  70. primitives.add(PointcutPrimitive.PRE_INITIALIZATION);
  71. primitives.add(PointcutPrimitive.SET);
  72. primitives.add(PointcutPrimitive.STATIC_INITIALIZATION);
  73. primitives.add(PointcutPrimitive.TARGET);
  74. primitives.add(PointcutPrimitive.THIS);
  75. primitives.add(PointcutPrimitive.WITHIN);
  76. primitives.add(PointcutPrimitive.WITHIN_CODE);
  77. primitives.add(PointcutPrimitive.AT_ANNOTATION);
  78. primitives.add(PointcutPrimitive.AT_THIS);
  79. primitives.add(PointcutPrimitive.AT_TARGET);
  80. primitives.add(PointcutPrimitive.AT_ARGS);
  81. primitives.add(PointcutPrimitive.AT_WITHIN);
  82. primitives.add(PointcutPrimitive.AT_WITHINCODE);
  83. primitives.add(PointcutPrimitive.REFERENCE);
  84. return primitives;
  85. }
  86. /**
  87. * Returns a pointcut parser that can parse the full AspectJ pointcut language with the following exceptions:
  88. * <ul>
  89. * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
  90. * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  91. * <li>The pointcut expression must be anonymous with no formals allowed.
  92. * </ul>
  93. * <p>
  94. * When resolving types in pointcut expressions, the context classloader is used to find types.
  95. * </p>
  96. */
  97. public static PointcutParser getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution() {
  98. PointcutParser p = new PointcutParser();
  99. p.setClassLoader(Thread.currentThread().getContextClassLoader());
  100. return p;
  101. }
  102. /**
  103. * Returns a pointcut parser that can parse pointcut expressions built from a user-defined subset of AspectJ's supported
  104. * pointcut primitives. The following restrictions apply:
  105. * <ul>
  106. * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
  107. * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  108. * <li>The pointcut expression must be anonymous with no formals allowed.
  109. * </ul>
  110. * <p>
  111. * When resolving types in pointcut expressions, the context classloader is used to find types.
  112. * </p>
  113. *
  114. * @param supportedPointcutKinds a set of PointcutPrimitives this parser should support
  115. * @throws UnsupportedOperationException if the set contains if, cflow, or cflow below
  116. */
  117. public static PointcutParser getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(
  118. Set supportedPointcutKinds) {
  119. PointcutParser p = new PointcutParser(supportedPointcutKinds);
  120. p.setClassLoader(Thread.currentThread().getContextClassLoader());
  121. return p;
  122. }
  123. /**
  124. * Returns a pointcut parser that can parse the full AspectJ pointcut language with the following exceptions:
  125. * <ul>
  126. * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
  127. * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  128. * <li>The pointcut expression must be anonymous with no formals allowed.
  129. * </ul>
  130. * <p>
  131. * When resolving types in pointcut expressions, the given classloader is used to find types.
  132. * </p>
  133. */
  134. public static PointcutParser getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(
  135. ClassLoader classLoader) {
  136. PointcutParser p = new PointcutParser();
  137. p.setClassLoader(classLoader);
  138. return p;
  139. }
  140. /**
  141. * Returns a pointcut parser that can parse pointcut expressions built from a user-defined subset of AspectJ's supported
  142. * pointcut primitives. The following restrictions apply:
  143. * <ul>
  144. * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
  145. * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  146. * <li>The pointcut expression must be anonymous with no formals allowed.
  147. * </ul>
  148. * <p>
  149. * When resolving types in pointcut expressions, the given classloader is used to find types.
  150. * </p>
  151. *
  152. * @param supportedPointcutKinds a set of PointcutPrimitives this parser should support
  153. * @throws UnsupportedOperationException if the set contains if, cflow, or cflow below
  154. */
  155. public static PointcutParser getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
  156. Set supportedPointcutKinds, ClassLoader classLoader) {
  157. PointcutParser p = new PointcutParser(supportedPointcutKinds);
  158. p.setClassLoader(classLoader);
  159. return p;
  160. }
  161. /**
  162. * Create a pointcut parser that can parse the full AspectJ pointcut language with the following exceptions:
  163. * <ul>
  164. * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
  165. * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  166. * <li>The pointcut expression must be anonymous with no formals allowed.
  167. * </ul>
  168. */
  169. protected PointcutParser() {
  170. supportedPrimitives = getAllSupportedPointcutPrimitives();
  171. setClassLoader(PointcutParser.class.getClassLoader());
  172. }
  173. /**
  174. * Create a pointcut parser that can parse pointcut expressions built from a user-defined subset of AspectJ's supported pointcut
  175. * primitives. The following restrictions apply:
  176. * <ul>
  177. * <li>The <code>if, cflow, and cflowbelow</code> pointcut designators are not supported
  178. * <li>Pointcut expressions must be self-contained :- they cannot contain references to other named pointcuts
  179. * <li>The pointcut expression must be anonymous with no formals allowed.
  180. * </ul>
  181. *
  182. * @param supportedPointcutKinds a set of PointcutPrimitives this parser should support
  183. * @throws UnsupportedOperationException if the set contains if, cflow, or cflow below
  184. */
  185. private PointcutParser(Set<PointcutPrimitive> supportedPointcutKinds) {
  186. supportedPrimitives = supportedPointcutKinds;
  187. for (PointcutPrimitive pointcutPrimitive : supportedPointcutKinds) {
  188. if ((pointcutPrimitive == PointcutPrimitive.IF) || (pointcutPrimitive == PointcutPrimitive.CFLOW)
  189. || (pointcutPrimitive == PointcutPrimitive.CFLOW_BELOW)) {
  190. throw new UnsupportedOperationException("Cannot handle if, cflow, and cflowbelow primitives");
  191. }
  192. }
  193. setClassLoader(PointcutParser.class.getClassLoader());
  194. }
  195. protected void setWorld(ReflectionWorld aWorld) {
  196. this.world = aWorld;
  197. }
  198. /**
  199. * Set the classloader that this parser should use for type resolution.
  200. *
  201. * @param aLoader
  202. */
  203. protected void setClassLoader(ClassLoader aLoader) {
  204. this.classLoaderReference = new WeakClassLoaderReference(aLoader);
  205. world = new ReflectionWorld(this.classLoaderReference.getClassLoader());
  206. }
  207. /**
  208. * Set the lint properties for this parser from the given resource on the classpath.
  209. *
  210. * @param resourcePath path to a file containing aspectj lint properties
  211. */
  212. public void setLintProperties(String resourcePath) throws IOException {
  213. URL url = this.classLoaderReference.getClassLoader().getResource(resourcePath);
  214. InputStream is = url.openStream();
  215. Properties p = new Properties();
  216. p.load(is);
  217. setLintProperties(p);
  218. }
  219. /**
  220. * Set the lint properties for this parser from the given properties set.
  221. *
  222. * @param properties
  223. */
  224. public void setLintProperties(Properties properties) {
  225. getWorld().getLint().setFromProperties(properties);
  226. }
  227. /**
  228. * Register a new pointcut designator handler with this parser. This provides an extension mechansim for the integration of
  229. * domain-specific pointcut designators with the AspectJ pointcut language.
  230. *
  231. * @param designatorHandler
  232. */
  233. public void registerPointcutDesignatorHandler(PointcutDesignatorHandler designatorHandler) {
  234. this.pointcutDesignators.add(designatorHandler);
  235. if (world != null) {
  236. world.registerPointcutHandler(designatorHandler);
  237. }
  238. }
  239. /**
  240. * Create a pointcut parameter of the given name and type.
  241. *
  242. * @param name
  243. * @param type
  244. * @return
  245. */
  246. public PointcutParameter createPointcutParameter(String name, Class type) {
  247. return new PointcutParameterImpl(name, type);
  248. }
  249. /**
  250. * Parse the given pointcut expression. A global scope is assumed for resolving any type references, and the pointcut must
  251. * contain no formals (variables to be bound).
  252. *
  253. * @throws UnsupportedPointcutPrimitiveException if the parser encounters a primitive pointcut expression of a kind not
  254. * supported by this PointcutParser.
  255. * @throws IllegalArgumentException if the expression is not a well-formed pointcut expression
  256. */
  257. public PointcutExpression parsePointcutExpression(String expression) throws UnsupportedPointcutPrimitiveException,
  258. IllegalArgumentException {
  259. return parsePointcutExpression(expression, null, new PointcutParameter[0]);
  260. }
  261. /**
  262. * Parse the given pointcut expression. The pointcut is resolved as if it had been declared inside the inScope class (this
  263. * allows the pointcut to contain unqualified references to other pointcuts declared in the same type for example). The pointcut
  264. * may contain zero or more formal parameters to be bound at matched join points.
  265. *
  266. * @throws UnsupportedPointcutPrimitiveException if the parser encounters a primitive pointcut expression of a kind not
  267. * supported by this PointcutParser.
  268. * @throws IllegalArgumentException if the expression is not a well-formed pointcut expression
  269. */
  270. public PointcutExpression parsePointcutExpression(String expression, Class inScope, PointcutParameter[] formalParameters)
  271. throws UnsupportedPointcutPrimitiveException, IllegalArgumentException {
  272. PointcutExpressionImpl pcExpr = null;
  273. try {
  274. Pointcut pc = resolvePointcutExpression(expression, inScope, formalParameters);
  275. pc = concretizePointcutExpression(pc, inScope, formalParameters);
  276. validateAgainstSupportedPrimitives(pc, expression); // again, because we have now followed any ref'd pcuts
  277. pcExpr = new PointcutExpressionImpl(pc, expression, formalParameters, getWorld());
  278. } catch (ParserException pEx) {
  279. throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
  280. } catch (ReflectionWorld.ReflectionWorldException rwEx) {
  281. throw new IllegalArgumentException(rwEx.getMessage());
  282. }
  283. return pcExpr;
  284. }
  285. protected Pointcut resolvePointcutExpression(String expression, Class inScope, PointcutParameter[] formalParameters) {
  286. try {
  287. PatternParser parser = new PatternParser(expression);
  288. parser.setPointcutDesignatorHandlers(pointcutDesignators, world);
  289. Pointcut pc = parser.parsePointcut();
  290. validateAgainstSupportedPrimitives(pc, expression);
  291. IScope resolutionScope = buildResolutionScope((inScope == null ? Object.class : inScope), formalParameters);
  292. pc = pc.resolve(resolutionScope);
  293. return pc;
  294. } catch (ParserException pEx) {
  295. throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
  296. }
  297. }
  298. protected Pointcut concretizePointcutExpression(Pointcut pc, Class inScope, PointcutParameter[] formalParameters) {
  299. ResolvedType declaringTypeForResolution = null;
  300. if (inScope != null) {
  301. declaringTypeForResolution = getWorld().resolve(inScope.getName());
  302. } else {
  303. declaringTypeForResolution = ResolvedType.OBJECT.resolve(getWorld());
  304. }
  305. IntMap arity = new IntMap(formalParameters.length);
  306. for (int i = 0; i < formalParameters.length; i++) {
  307. arity.put(i, i);
  308. }
  309. return pc.concretize(declaringTypeForResolution, declaringTypeForResolution, arity);
  310. }
  311. /**
  312. * Parse the given aspectj type pattern, and return a matcher that can be used to match types using it.
  313. *
  314. * @param typePattern an aspectj type pattern
  315. * @return a type pattern matcher that matches using the given pattern
  316. * @throws IllegalArgumentException if the type pattern cannot be successfully parsed.
  317. */
  318. public TypePatternMatcher parseTypePattern(String typePattern) throws IllegalArgumentException {
  319. try {
  320. TypePattern tp = new PatternParser(typePattern).parseTypePattern();
  321. tp.resolve(world);
  322. return new TypePatternMatcherImpl(tp, world);
  323. } catch (ParserException pEx) {
  324. throw new IllegalArgumentException(buildUserMessageFromParserException(typePattern, pEx));
  325. } catch (ReflectionWorld.ReflectionWorldException rwEx) {
  326. throw new IllegalArgumentException(rwEx.getMessage());
  327. }
  328. }
  329. private World getWorld() {
  330. return world;
  331. }
  332. /* for testing */
  333. Set getSupportedPrimitives() {
  334. return supportedPrimitives;
  335. }
  336. /* for testing */
  337. IMessageHandler setCustomMessageHandler(IMessageHandler aHandler) {
  338. IMessageHandler current = getWorld().getMessageHandler();
  339. getWorld().setMessageHandler(aHandler);
  340. return current;
  341. }
  342. private IScope buildResolutionScope(Class inScope, PointcutParameter[] formalParameters) {
  343. if (formalParameters == null) {
  344. formalParameters = new PointcutParameter[0];
  345. }
  346. FormalBinding[] formalBindings = new FormalBinding[formalParameters.length];
  347. for (int i = 0; i < formalBindings.length; i++) {
  348. formalBindings[i] = new FormalBinding(toUnresolvedType(formalParameters[i].getType()), formalParameters[i].getName(), i);
  349. }
  350. if (inScope == null) {
  351. return new SimpleScope(getWorld(), formalBindings);
  352. } else {
  353. ResolvedType inType = getWorld().resolve(inScope.getName());
  354. ISourceContext sourceContext = new ISourceContext() {
  355. public ISourceLocation makeSourceLocation(IHasPosition position) {
  356. return new SourceLocation(new File(""), 0);
  357. }
  358. public ISourceLocation makeSourceLocation(int line, int offset) {
  359. return new SourceLocation(new File(""), line);
  360. }
  361. public int getOffset() {
  362. return 0;
  363. }
  364. public void tidy() {
  365. }
  366. };
  367. return new BindingScope(inType, sourceContext, formalBindings);
  368. }
  369. }
  370. private UnresolvedType toUnresolvedType(Class clazz) {
  371. if (clazz.isArray()) {
  372. return UnresolvedType.forSignature(clazz.getName().replace('.', '/'));
  373. } else {
  374. return UnresolvedType.forName(clazz.getName());
  375. }
  376. }
  377. private void validateAgainstSupportedPrimitives(Pointcut pc, String expression) {
  378. switch (pc.getPointcutKind()) {
  379. case Pointcut.AND:
  380. validateAgainstSupportedPrimitives(((AndPointcut) pc).getLeft(), expression);
  381. validateAgainstSupportedPrimitives(((AndPointcut) pc).getRight(), expression);
  382. break;
  383. case Pointcut.ARGS:
  384. if (!supportedPrimitives.contains(PointcutPrimitive.ARGS)) {
  385. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.ARGS);
  386. }
  387. break;
  388. case Pointcut.CFLOW:
  389. CflowPointcut cfp = (CflowPointcut) pc;
  390. if (cfp.isCflowBelow()) {
  391. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CFLOW_BELOW);
  392. } else {
  393. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CFLOW);
  394. }
  395. case Pointcut.HANDLER:
  396. if (!supportedPrimitives.contains(PointcutPrimitive.HANDLER)) {
  397. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.HANDLER);
  398. }
  399. break;
  400. case Pointcut.IF:
  401. case Pointcut.IF_FALSE:
  402. case Pointcut.IF_TRUE:
  403. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.IF);
  404. case Pointcut.KINDED:
  405. validateKindedPointcut(((KindedPointcut) pc), expression);
  406. break;
  407. case Pointcut.NOT:
  408. validateAgainstSupportedPrimitives(((NotPointcut) pc).getNegatedPointcut(), expression);
  409. break;
  410. case Pointcut.OR:
  411. validateAgainstSupportedPrimitives(((OrPointcut) pc).getLeft(), expression);
  412. validateAgainstSupportedPrimitives(((OrPointcut) pc).getRight(), expression);
  413. break;
  414. case Pointcut.THIS_OR_TARGET:
  415. boolean isThis = ((ThisOrTargetPointcut) pc).isThis();
  416. if (isThis && !supportedPrimitives.contains(PointcutPrimitive.THIS)) {
  417. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.THIS);
  418. } else if (!supportedPrimitives.contains(PointcutPrimitive.TARGET)) {
  419. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.TARGET);
  420. }
  421. break;
  422. case Pointcut.WITHIN:
  423. if (!supportedPrimitives.contains(PointcutPrimitive.WITHIN)) {
  424. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.WITHIN);
  425. }
  426. break;
  427. case Pointcut.WITHINCODE:
  428. if (!supportedPrimitives.contains(PointcutPrimitive.WITHIN_CODE)) {
  429. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.WITHIN_CODE);
  430. }
  431. break;
  432. case Pointcut.ATTHIS_OR_TARGET:
  433. isThis = ((ThisOrTargetAnnotationPointcut) pc).isThis();
  434. if (isThis && !supportedPrimitives.contains(PointcutPrimitive.AT_THIS)) {
  435. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_THIS);
  436. } else if (!supportedPrimitives.contains(PointcutPrimitive.AT_TARGET)) {
  437. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_TARGET);
  438. }
  439. break;
  440. case Pointcut.ATARGS:
  441. if (!supportedPrimitives.contains(PointcutPrimitive.AT_ARGS)) {
  442. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_ARGS);
  443. }
  444. break;
  445. case Pointcut.ANNOTATION:
  446. if (!supportedPrimitives.contains(PointcutPrimitive.AT_ANNOTATION)) {
  447. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_ANNOTATION);
  448. }
  449. break;
  450. case Pointcut.ATWITHIN:
  451. if (!supportedPrimitives.contains(PointcutPrimitive.AT_WITHIN)) {
  452. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_WITHIN);
  453. }
  454. break;
  455. case Pointcut.ATWITHINCODE:
  456. if (!supportedPrimitives.contains(PointcutPrimitive.AT_WITHINCODE)) {
  457. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.AT_WITHINCODE);
  458. }
  459. break;
  460. case Pointcut.REFERENCE:
  461. if (!supportedPrimitives.contains(PointcutPrimitive.REFERENCE)) {
  462. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.REFERENCE);
  463. }
  464. break;
  465. case Pointcut.USER_EXTENSION:
  466. // always ok...
  467. break;
  468. case Pointcut.NONE: // deliberate fall-through
  469. default:
  470. throw new IllegalArgumentException("Unknown pointcut kind: " + pc.getPointcutKind());
  471. }
  472. }
  473. private void validateKindedPointcut(KindedPointcut pc, String expression) {
  474. Shadow.Kind kind = pc.getKind();
  475. if ((kind == Shadow.MethodCall) || (kind == Shadow.ConstructorCall)) {
  476. if (!supportedPrimitives.contains(PointcutPrimitive.CALL)) {
  477. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.CALL);
  478. }
  479. } else if ((kind == Shadow.MethodExecution) || (kind == Shadow.ConstructorExecution)) {
  480. if (!supportedPrimitives.contains(PointcutPrimitive.EXECUTION)) {
  481. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.EXECUTION);
  482. }
  483. } else if (kind == Shadow.AdviceExecution) {
  484. if (!supportedPrimitives.contains(PointcutPrimitive.ADVICE_EXECUTION)) {
  485. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.ADVICE_EXECUTION);
  486. }
  487. } else if (kind == Shadow.FieldGet) {
  488. if (!supportedPrimitives.contains(PointcutPrimitive.GET)) {
  489. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.GET);
  490. }
  491. } else if (kind == Shadow.FieldSet) {
  492. if (!supportedPrimitives.contains(PointcutPrimitive.SET)) {
  493. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.SET);
  494. }
  495. } else if (kind == Shadow.Initialization) {
  496. if (!supportedPrimitives.contains(PointcutPrimitive.INITIALIZATION)) {
  497. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.INITIALIZATION);
  498. }
  499. } else if (kind == Shadow.PreInitialization) {
  500. if (!supportedPrimitives.contains(PointcutPrimitive.PRE_INITIALIZATION)) {
  501. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.PRE_INITIALIZATION);
  502. }
  503. } else if (kind == Shadow.StaticInitialization) {
  504. if (!supportedPrimitives.contains(PointcutPrimitive.STATIC_INITIALIZATION)) {
  505. throw new UnsupportedPointcutPrimitiveException(expression, PointcutPrimitive.STATIC_INITIALIZATION);
  506. }
  507. }
  508. }
  509. private String buildUserMessageFromParserException(String pc, ParserException ex) {
  510. StringBuffer msg = new StringBuffer();
  511. msg.append("Pointcut is not well-formed: expecting '");
  512. msg.append(ex.getMessage());
  513. msg.append("'");
  514. IHasPosition location = ex.getLocation();
  515. msg.append(" at character position ");
  516. msg.append(location.getStart());
  517. msg.append("\n");
  518. msg.append(pc);
  519. msg.append("\n");
  520. for (int i = 0; i < location.getStart(); i++) {
  521. msg.append(" ");
  522. }
  523. for (int j = location.getStart(); j <= location.getEnd(); j++) {
  524. msg.append("^");
  525. }
  526. msg.append("\n");
  527. return msg.toString();
  528. }
  529. }