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 25KB

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