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.

StandardPointcutParser.java 21KB

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