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.

Java15PointcutExpressionTest.java 39KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. /* *******************************************************************
  2. * Copyright (c) 2005 Contributors.
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Adrian Colyer Initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.tools;
  13. import java.lang.annotation.Annotation;
  14. import java.lang.annotation.Retention;
  15. import java.lang.annotation.RetentionPolicy;
  16. import java.lang.reflect.Method;
  17. import java.util.ArrayList;
  18. import java.util.Date;
  19. import java.util.HashSet;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import java.util.Set;
  23. import java.util.StringTokenizer;
  24. import org.aspectj.lang.annotation.Pointcut;
  25. import org.aspectj.weaver.ResolvedType;
  26. import org.aspectj.weaver.internal.tools.PointcutExpressionImpl;
  27. import org.aspectj.weaver.patterns.AbstractPatternNodeVisitor;
  28. import org.aspectj.weaver.patterns.AndAnnotationTypePattern;
  29. import org.aspectj.weaver.patterns.AnnotationPatternList;
  30. import org.aspectj.weaver.patterns.AnyAnnotationTypePattern;
  31. import org.aspectj.weaver.patterns.BindingAnnotationTypePattern;
  32. import org.aspectj.weaver.patterns.ExactAnnotationTypePattern;
  33. import org.aspectj.weaver.patterns.KindedPointcut;
  34. import org.aspectj.weaver.patterns.NotAnnotationTypePattern;
  35. import org.aspectj.weaver.patterns.OrAnnotationTypePattern;
  36. import org.aspectj.weaver.patterns.SignaturePattern;
  37. import org.aspectj.weaver.patterns.TypePattern;
  38. import org.aspectj.weaver.patterns.TypePatternList;
  39. import org.aspectj.weaver.patterns.WildAnnotationTypePattern;
  40. import test.A1AnnotatedType;
  41. import test.A2AnnotatedType;
  42. import junit.framework.Test;
  43. import junit.framework.TestCase;
  44. import junit.framework.TestSuite;
  45. /**
  46. * Test parameter pointcut parsing. Extended by Andy Clement to cover parameter annotation matching.
  47. *
  48. */
  49. public class Java15PointcutExpressionTest extends TestCase {
  50. public static Test suite() {
  51. TestSuite suite = new TestSuite("Java15PointcutExpressionTest");
  52. suite.addTestSuite(Java15PointcutExpressionTest.class);
  53. return suite;
  54. }
  55. private PointcutParser parser;
  56. private Method a;
  57. private Method b;
  58. private Method c;
  59. private Method d;
  60. private Method e;
  61. private Method f;
  62. /**
  63. * Parse some expressions and ensure we capture the parameter annotations and parameter type annotations correctly.
  64. * Buckle up, this will get complicated ;)
  65. */
  66. public void testParseParameterAnnotationExpressions() {
  67. PointcutParser p = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(this.getClass().getClassLoader());
  68. PointcutExpression pexpr = null;
  69. pexpr = p.parsePointcutExpression("execution(public void foo(@MA *))");
  70. checkParameterAnnotations(pexpr,0,null,"@MA","exact[@MA:t]");
  71. pexpr = p.parsePointcutExpression("execution(public void foo(@MA (*)))");
  72. checkParameterAnnotations(pexpr,0,"@MA",null,"exact[@MA:p]");
  73. pexpr = p.parsePointcutExpression("execution(public void foo(@MA @MB *))");
  74. checkParameterAnnotations(pexpr,0,null,"@MA @MB","(exact[@MA:t] and exact[@MB:t])");
  75. pexpr = p.parsePointcutExpression("execution(public void foo(@MA (@MB *)))");
  76. checkParameterAnnotations(pexpr,0,"@MA","@MB","(exact[@MA:p] and exact[@MB:t])");
  77. pexpr = p.parsePointcutExpression("execution(public void foo(@MA @MB (@MC *)))");
  78. checkParameterAnnotations(pexpr,0,"@MA @MB","@MC","((exact[@MA:p] and exact[@MB:p]) and exact[@MC:t])");
  79. pexpr = p.parsePointcutExpression("execution(public void foo(@MA (@MB @MC @MD *)))");
  80. checkParameterAnnotations(pexpr,0,"@MA","@MB @MC @MD","(exact[@MA:p] and ((exact[@MB:t] and exact[@MC:t]) and exact[@MD:t]))");
  81. pexpr = p.parsePointcutExpression("execution(public void foo(@(MA || MB) (@MC @MD *)))");
  82. checkParameterAnnotations(pexpr,0,null/*Should be MA MB */,"@MC @MD","(wild[(MA || MB)] and (exact[@MC:t] and exact[@MD:t]))"); // I dont think WildAnnotationTypePatterns work properly...
  83. pexpr = p.parsePointcutExpression("execution(public void foo(@MA (@MB *),(@MC *),@MD (*)))");
  84. checkParameterAnnotations(pexpr,0,"@MA","@MB","(exact[@MA:p] and exact[@MB:t])");
  85. checkParameterAnnotations(pexpr,1,null,"@MC","exact[@MC:t]");
  86. checkParameterAnnotations(pexpr,2,"@MD",null,"exact[@MD:p]");
  87. }
  88. public void testMatchingAnnotationValueExpressions() throws SecurityException, NoSuchMethodException {
  89. PointcutParser p = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(this.getClass().getClassLoader());
  90. PointcutExpression pexpr = null;
  91. ShadowMatch match = null;
  92. Method n = test.AnnoValues.class.getMethod("none",null);
  93. Method r = test.AnnoValues.class.getMethod("redMethod",null);
  94. Method g = test.AnnoValues.class.getMethod("greenMethod",null);
  95. Method b = test.AnnoValues.class.getMethod("blueMethod",null);
  96. Method d = test.AnnoValues.class.getMethod("defaultMethod",null);
  97. pexpr = p.parsePointcutExpression("execution(@test.A3(test.Color.RED) public void *(..))");
  98. assertTrue("Should match", pexpr.matchesMethodExecution(n).neverMatches()); // default value RED
  99. assertTrue("Should match", pexpr.matchesMethodExecution(r).alwaysMatches());
  100. assertTrue("Should not match", pexpr.matchesMethodExecution(g).neverMatches());
  101. assertTrue("Should not match", pexpr.matchesMethodExecution(b).neverMatches());
  102. assertTrue("Should match", pexpr.matchesMethodExecution(d).alwaysMatches());
  103. pexpr = p.parsePointcutExpression("execution(@test.A3(test.Color.GREEN) public void *(..))");
  104. assertTrue("Should not match", pexpr.matchesMethodExecution(n).neverMatches()); // default value RED
  105. assertTrue("Should not match", pexpr.matchesMethodExecution(r).neverMatches());
  106. assertTrue("Should match", pexpr.matchesMethodExecution(g).alwaysMatches());
  107. assertTrue("Should not match", pexpr.matchesMethodExecution(b).neverMatches());
  108. assertTrue("Should not match", pexpr.matchesMethodExecution(d).neverMatches());
  109. pexpr = p.parsePointcutExpression("execution(@test.A3(test.Color.BLUE) public void *(..))");
  110. assertTrue("Should not match", pexpr.matchesMethodExecution(n).neverMatches()); // default value RED
  111. assertTrue("Should not match", pexpr.matchesMethodExecution(r).neverMatches());
  112. assertTrue("Should not match", pexpr.matchesMethodExecution(g).neverMatches());
  113. assertTrue("Should match", pexpr.matchesMethodExecution(b).alwaysMatches());
  114. assertTrue("Should not match", pexpr.matchesMethodExecution(d).neverMatches());
  115. pexpr = p.parsePointcutExpression("execution(@test.A3 public void *(..))");
  116. assertTrue("Should match", pexpr.matchesMethodExecution(n).neverMatches()); // default value RED
  117. assertTrue("Should match", pexpr.matchesMethodExecution(r).alwaysMatches());
  118. assertTrue("Should match", pexpr.matchesMethodExecution(g).alwaysMatches());
  119. assertTrue("Should match", pexpr.matchesMethodExecution(b).alwaysMatches());
  120. assertTrue("Should match", pexpr.matchesMethodExecution(d).alwaysMatches());
  121. }
  122. private static final Set<PointcutPrimitive> DEFAULT_SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
  123. static {
  124. DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
  125. DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
  126. DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
  127. DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
  128. DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
  129. DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
  130. DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
  131. DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
  132. DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
  133. DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
  134. }
  135. public void testPerformanceOfPointcutParsing() {
  136. String expression = "execution(public * rewards.internal.*.*Repository+.*(..))";
  137. long stime1 = System.currentTimeMillis();
  138. PointcutParser parser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(DEFAULT_SUPPORTED_PRIMITIVES);
  139. long stime2 = System.currentTimeMillis();
  140. PointcutExpression pointcutExpression = parser.parsePointcutExpression(expression, null, new PointcutParameter[0]);
  141. long etime = System.currentTimeMillis();
  142. System.out.println("Time to get a parser "+(stime2-stime1)+"ms");
  143. System.out.println("Time taken to parse expression is "+(etime-stime2)+"ms");
  144. }
  145. public void testPerformanceOfPointcutParsingWithBean() {
  146. String expression = "execution(public * rewards.internal.*.*Repository+.*(..))";
  147. PointcutParser parser = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(this.getClass().getClassLoader());
  148. BeanDesignatorHandler beanHandler = new BeanDesignatorHandler();
  149. parser.registerPointcutDesignatorHandler(beanHandler);
  150. long stime = System.currentTimeMillis();
  151. PointcutExpression pointcutExpression = parser.parsePointcutExpression(expression, null, new PointcutParameter[0]);
  152. long etime = System.currentTimeMillis();
  153. System.out.println("Time taken to parse expression is "+(etime-stime)+"ms");
  154. }
  155. private class BeanDesignatorHandler implements PointcutDesignatorHandler {
  156. private String askedToParse;
  157. public boolean simulateDynamicTest = false;
  158. public String getDesignatorName() {
  159. return "bean";
  160. }
  161. /* (non-Javadoc)
  162. * @see org.aspectj.weaver.tools.PointcutDesignatorHandler#parse(java.lang.String)
  163. */
  164. public ContextBasedMatcher parse(String expression) {
  165. this.askedToParse = expression;
  166. return null;
  167. // return new BeanPointcutExpression(expression,this.simulateDynamicTest);
  168. }
  169. public String getExpressionLastAskedToParse() {
  170. return this.askedToParse;
  171. }
  172. }
  173. /**
  174. * Test matching of pointcuts against expressions. A reflection world is being used on the backend here (not a Bcel one).
  175. */
  176. public void testMatchingParameterAnnotationExpressions() throws SecurityException, NoSuchMethodException {
  177. PointcutParser p = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(this.getClass().getClassLoader());
  178. PointcutExpression pexpr = null;
  179. ShadowMatch match = null;
  180. Method a = test.A.class.getMethod("a",new Class[] {String.class}); // public void a(String s) {}
  181. Method b = test.A.class.getMethod("b",new Class[] {String.class}); // public void b(@A1 String s) {}
  182. Method c = test.A.class.getMethod("c",new Class[] {String.class}); // public void c(@A1 @A2 String s) {}
  183. // Method d = test.A.class.getMethod("d",new Class[] {String.class,String.class});// public void d(@A1 String s,@A2 String t) {}
  184. Method e = test.A.class.getMethod("e",new Class[] {A1AnnotatedType.class}); // public void e(A1AnnotatedType s) {}
  185. Method f = test.A.class.getMethod("f",new Class[] {A2AnnotatedType.class}); // public void f(A2AnnotatedType s) {}
  186. Method g = test.A.class.getMethod("g",new Class[] {A1AnnotatedType.class}); // public void g(@A2 A1AnnotatedType s) {}
  187. Method h = test.A.class.getMethod("h",new Class[] {A1AnnotatedType.class}); // public void h(@A1 A1AnnotatedType s) {}
  188. // Method i = test.A.class.getMethod("i",new Class[] {A1AnnotatedType.class,String.class}); // public void i(A1AnnotatedType s,@A2 String t) {}
  189. // Method j = test.A.class.getMethod("j",new Class[] {String.class}); // public void j(@A1 @A2 String s) {}
  190. pexpr = p.parsePointcutExpression("execution(public void *(@test.A1 *))");
  191. assertTrue("Should not match", pexpr.matchesMethodExecution(a).neverMatches());
  192. assertTrue("Should not match", pexpr.matchesMethodExecution(b).neverMatches());
  193. assertTrue("Should not match", pexpr.matchesMethodExecution(c).neverMatches());
  194. pexpr = p.parsePointcutExpression("execution(public void *(@test.A1 (*)))");
  195. assertTrue("Should not match", pexpr.matchesMethodExecution(a).neverMatches());
  196. assertTrue("Should match", pexpr.matchesMethodExecution(b).alwaysMatches());
  197. assertTrue("Should match", pexpr.matchesMethodExecution(c).alwaysMatches());
  198. pexpr = p.parsePointcutExpression("execution(public void *(@test.A1 *))");
  199. assertTrue("Should match", pexpr.matchesMethodExecution(e).alwaysMatches());
  200. assertTrue("Should not match", pexpr.matchesMethodExecution(f).neverMatches());
  201. assertTrue("Should match", pexpr.matchesMethodExecution(g).alwaysMatches());
  202. assertTrue("Should match", pexpr.matchesMethodExecution(h).alwaysMatches());
  203. pexpr = p.parsePointcutExpression("execution(public void *(@test.A1 (*)))");
  204. assertTrue("Should not match", pexpr.matchesMethodExecution(e).neverMatches());
  205. assertTrue("Should not match", pexpr.matchesMethodExecution(f).neverMatches());
  206. assertTrue("Should not match", pexpr.matchesMethodExecution(g).neverMatches());
  207. assertTrue("Should match", pexpr.matchesMethodExecution(h).alwaysMatches());
  208. pexpr = p.parsePointcutExpression("execution(public void *(@(test.A1 || test.A2) (*)))");
  209. assertTrue("Should not match", pexpr.matchesMethodExecution(a).neverMatches());
  210. assertTrue("Should match", pexpr.matchesMethodExecution(b).alwaysMatches());
  211. assertTrue("Should match", pexpr.matchesMethodExecution(c).alwaysMatches());
  212. assertTrue("Should match", pexpr.matchesMethodExecution(g).alwaysMatches());
  213. assertTrue("Should match", pexpr.matchesMethodExecution(h).alwaysMatches());
  214. pexpr = p.parsePointcutExpression("execution(public void *(@(test.A1 && test.A2) (*),..))");
  215. assertTrue("Should not match", pexpr.matchesMethodExecution(a).neverMatches());
  216. assertTrue("Should not match", pexpr.matchesMethodExecution(b).neverMatches());
  217. assertTrue("Should not match", pexpr.matchesMethodExecution(c).neverMatches());
  218. assertTrue("Should not match", pexpr.matchesMethodExecution(g).neverMatches());
  219. assertTrue("Should not match", pexpr.matchesMethodExecution(h).neverMatches());
  220. // assertTrue("Should match", pexpr.matchesMethodExecution(j).alwaysMatches()); // should match but does not, broken implementation, old bug - see WildAnnotationTypePattern.match
  221. }
  222. private void checkParameterAnnotations(PointcutExpression pe,int parameterNumber,String expectedParameterAnnotations,String expectedParameterTypeAnnotations,String expectedNodeStructure) {
  223. org.aspectj.weaver.patterns.Pointcut p = ((PointcutExpressionImpl)pe).getUnderlyingPointcut();
  224. KindedPointcut kindedP = (KindedPointcut)p;
  225. SignaturePattern sp = kindedP.getSignature();
  226. TypePatternList tpl = sp.getParameterTypes();
  227. TypePattern[] tps = tpl.getTypePatterns();
  228. // A visitor over the annotation pattern for the parameter will break it down into parameter vs parameter type annotations
  229. MyPatternNodeVisitor mpnv = new MyPatternNodeVisitor();
  230. tps[parameterNumber].getAnnotationPattern().accept(mpnv,null);
  231. if (expectedNodeStructure==null) {
  232. // The caller hasn't worked it out yet!!
  233. System.out.println(mpnv.getStringRepresentation());
  234. } else if (!mpnv.getStringRepresentation().equals(expectedNodeStructure)) {
  235. System.out.println(mpnv.getStringRepresentation());
  236. fail("Expected annotation pattern node structure for expression "+pe.getPointcutExpression()+
  237. " was '"+expectedNodeStructure+"' but it turned out to be '"+mpnv.getStringRepresentation()+"'");
  238. }
  239. tps[parameterNumber].getAnnotationPattern().toString();
  240. // parameter type annotation checking
  241. Set<String> expected = new HashSet<String>();
  242. expected.addAll(mpnv.getParameterTypeAnnotations());
  243. StringTokenizer st = new StringTokenizer(expectedParameterTypeAnnotations==null?"":expectedParameterTypeAnnotations);
  244. while (st.hasMoreTokens()) {
  245. String nextToken = st.nextToken();
  246. if (!expected.contains(nextToken))
  247. fail("In pointcut expression "+pe.getPointcutExpression()+" parameter "+parameterNumber+". The annotation type pattern did not include parameter type annotation "+nextToken+". It's full set was "+mpnv.getParameterTypeAnnotations());
  248. expected.remove(nextToken);
  249. }
  250. if (expected.size()>0) { // we have excess ones!
  251. StringBuffer excessTokens = new StringBuffer();
  252. for (Iterator iterator = expected.iterator(); iterator.hasNext();) {
  253. String string = (String) iterator.next();
  254. excessTokens.append(string).append(" ");
  255. }
  256. fail("In pointcut expression "+pe.getPointcutExpression()+" parameter "+parameterNumber+". The annotation type pattern has these unexpected parameter type annotations "+excessTokens.toString());
  257. }
  258. // parameter annotation checking
  259. expected = new HashSet<String>();
  260. expected.addAll(mpnv.getParameterAnnotations());
  261. st = new StringTokenizer(expectedParameterAnnotations==null?"":expectedParameterAnnotations);
  262. while (st.hasMoreTokens()) {
  263. String nextToken = st.nextToken();
  264. if (!expected.contains(nextToken))
  265. fail("In pointcut expression "+pe.getPointcutExpression()+" parameter "+parameterNumber+". The annotation type pattern did not include parameter annotation "+nextToken+". It's full set was "+mpnv.getParameterAnnotations());
  266. expected.remove(nextToken);
  267. }
  268. if (expected.size()>0) { // we have excess ones!
  269. StringBuffer excessTokens = new StringBuffer();
  270. for (Iterator iterator = expected.iterator(); iterator.hasNext();) {
  271. String string = (String) iterator.next();
  272. excessTokens.append(string).append(" ");
  273. }
  274. fail("In pointcut expression "+pe.getPointcutExpression()+" parameter "+parameterNumber+". The annotation type pattern has these unexpected parameter annotations "+excessTokens.toString());
  275. }
  276. }
  277. static class MyPatternNodeVisitor extends AbstractPatternNodeVisitor {
  278. private StringBuffer stringRep = new StringBuffer();
  279. private List<String> parameterAnnotations = new ArrayList<String>();
  280. private List<String> parameterTypeAnnotations = new ArrayList<String>();
  281. public String getStringRepresentation() { return stringRep.toString(); }
  282. public List<String> getParameterAnnotations() { return parameterAnnotations; }
  283. public List<String> getParameterTypeAnnotations() { return parameterTypeAnnotations; }
  284. public Object visit(AndAnnotationTypePattern node, Object data) {
  285. stringRep.append("(");
  286. node.getLeft().accept(this, data);
  287. stringRep.append(" and ");
  288. node.getRight().accept(this, data);
  289. stringRep.append(")");
  290. return node;
  291. }
  292. public Object visit(AnyAnnotationTypePattern node, Object data) {
  293. stringRep.append("any");
  294. return node;
  295. }
  296. public Object visit(ExactAnnotationTypePattern node, Object data) {
  297. stringRep.append("exact["+stringify(node.getResolvedAnnotationType())+":"+(node.isForParameterAnnotationMatch()?"p":"t")+"]");
  298. if (node.isForParameterAnnotationMatch()) {
  299. parameterAnnotations.add(stringify(node.getResolvedAnnotationType()));
  300. } else {
  301. parameterTypeAnnotations.add(stringify(node.getResolvedAnnotationType()));
  302. }
  303. return node;
  304. }
  305. private String stringify(ResolvedType resolvedAnnotationType) {
  306. return "@"+resolvedAnnotationType.getSimpleName();
  307. }
  308. public Object visit(BindingAnnotationTypePattern node, Object data) {
  309. stringRep.append("binding");
  310. return node;
  311. }
  312. public Object visit(NotAnnotationTypePattern node, Object data) {
  313. stringRep.append("not");
  314. return node;
  315. }
  316. public Object visit(OrAnnotationTypePattern node, Object data) {
  317. stringRep.append("(");
  318. node.getLeft().accept(this, data);
  319. stringRep.append(" or ");
  320. node.getRight().accept(this, data);
  321. stringRep.append(")");
  322. return node;
  323. }
  324. public Object visit(WildAnnotationTypePattern node, Object data) {
  325. stringRep.append("wild[");
  326. stringRep.append(node.getTypePattern().toString());
  327. stringRep.append("]");
  328. return node;
  329. }
  330. public Object visit(AnnotationPatternList node, Object data) {
  331. stringRep.append("list");
  332. return node;
  333. }
  334. }
  335. public void testAtThis() {
  336. PointcutExpression atThis = parser.parsePointcutExpression("@this(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)");
  337. ShadowMatch sMatch1 = atThis.matchesMethodExecution(a);
  338. ShadowMatch sMatch2 = atThis.matchesMethodExecution(b);
  339. assertTrue("maybe matches A",sMatch1.maybeMatches());
  340. assertTrue("maybe matches B",sMatch2.maybeMatches());
  341. JoinPointMatch jp1 = sMatch1.matchesJoinPoint(new A(), new A(), new Object[0]);
  342. assertFalse("does not match",jp1.matches());
  343. JoinPointMatch jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[0]);
  344. assertTrue("matches",jp2.matches());
  345. }
  346. public void testAtTarget() {
  347. PointcutExpression atTarget = parser.parsePointcutExpression("@target(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)");
  348. ShadowMatch sMatch1 = atTarget.matchesMethodExecution(a);
  349. ShadowMatch sMatch2 = atTarget.matchesMethodExecution(b);
  350. assertTrue("maybe matches A",sMatch1.maybeMatches());
  351. assertTrue("maybe matches B",sMatch2.maybeMatches());
  352. JoinPointMatch jp1 = sMatch1.matchesJoinPoint(new A(), new A(), new Object[0]);
  353. assertFalse("does not match",jp1.matches());
  354. JoinPointMatch jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[0]);
  355. assertTrue("matches",jp2.matches());
  356. }
  357. public void testAtThisWithBinding() {
  358. PointcutParameter param = parser.createPointcutParameter("a",MyAnnotation.class);
  359. B myB = new B();
  360. MyAnnotation bAnnotation = B.class.getAnnotation(MyAnnotation.class);
  361. PointcutExpression atThis = parser.parsePointcutExpression("@this(a)",A.class,new PointcutParameter[] {param});
  362. ShadowMatch sMatch1 = atThis.matchesMethodExecution(a);
  363. ShadowMatch sMatch2 = atThis.matchesMethodExecution(b);
  364. assertTrue("maybe matches A",sMatch1.maybeMatches());
  365. assertTrue("maybe matches B",sMatch2.maybeMatches());
  366. JoinPointMatch jp1 = sMatch1.matchesJoinPoint(new A(), new A(), new Object[0]);
  367. assertFalse("does not match",jp1.matches());
  368. JoinPointMatch jp2 = sMatch2.matchesJoinPoint(myB, myB, new Object[0]);
  369. assertTrue("matches",jp2.matches());
  370. assertEquals(1,jp2.getParameterBindings().length);
  371. assertEquals("should be myB's annotation",bAnnotation,jp2.getParameterBindings()[0].getBinding());
  372. }
  373. public void testAtTargetWithBinding() {
  374. PointcutParameter param = parser.createPointcutParameter("a",MyAnnotation.class);
  375. B myB = new B();
  376. MyAnnotation bAnnotation = B.class.getAnnotation(MyAnnotation.class);
  377. PointcutExpression atThis = parser.parsePointcutExpression("@target(a)",A.class,new PointcutParameter[] {param});
  378. ShadowMatch sMatch1 = atThis.matchesMethodExecution(a);
  379. ShadowMatch sMatch2 = atThis.matchesMethodExecution(b);
  380. assertTrue("maybe matches A",sMatch1.maybeMatches());
  381. assertTrue("maybe matches B",sMatch2.maybeMatches());
  382. JoinPointMatch jp1 = sMatch1.matchesJoinPoint(new A(), new A(), new Object[0]);
  383. assertFalse("does not match",jp1.matches());
  384. JoinPointMatch jp2 = sMatch2.matchesJoinPoint(myB, myB, new Object[0]);
  385. assertTrue("matches",jp2.matches());
  386. assertEquals(1,jp2.getParameterBindings().length);
  387. assertEquals("should be myB's annotation",bAnnotation,jp2.getParameterBindings()[0].getBinding());
  388. }
  389. public void testAtArgs() {
  390. PointcutExpression atArgs = parser.parsePointcutExpression("@args(..,org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)");
  391. ShadowMatch sMatch1 = atArgs.matchesMethodExecution(a);
  392. ShadowMatch sMatch2 = atArgs.matchesMethodExecution(c);
  393. assertTrue("never matches A",sMatch1.neverMatches());
  394. assertTrue("maybe matches C",sMatch2.maybeMatches());
  395. JoinPointMatch jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[]{new A(),new B()});
  396. assertTrue("matches",jp2.matches());
  397. atArgs = parser.parsePointcutExpression("@args(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation,org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)");
  398. sMatch1 = atArgs.matchesMethodExecution(a);
  399. sMatch2 = atArgs.matchesMethodExecution(c);
  400. assertTrue("never matches A",sMatch1.neverMatches());
  401. assertTrue("maybe matches C",sMatch2.maybeMatches());
  402. JoinPointMatch jp1 = sMatch2.matchesJoinPoint(new A(), new A(), new Object[] {new A(), new B()});
  403. assertFalse("does not match",jp1.matches());
  404. jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[] {new B(),new B()});
  405. assertTrue("matches",jp2.matches());
  406. }
  407. public void testAtArgs2() {
  408. PointcutExpression atArgs = parser.parsePointcutExpression("@args(*, org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)");
  409. ShadowMatch sMatch1 = atArgs.matchesMethodExecution(c);
  410. ShadowMatch sMatch2 = atArgs.matchesMethodExecution(d);
  411. assertTrue("maybe matches c",sMatch1.maybeMatches());
  412. assertTrue("maybe matches d",sMatch2.maybeMatches());
  413. JoinPointMatch jp1 = sMatch1.matchesJoinPoint(new B(), new B(), new Object[] {new A(), new B()});
  414. assertTrue("matches",jp1.matches());
  415. JoinPointMatch jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[] {new A(),new A()});
  416. assertFalse("does not match",jp2.matches());
  417. }
  418. public void testAtArgsWithBinding() {
  419. PointcutParameter p1 = parser.createPointcutParameter("a",MyAnnotation.class);
  420. PointcutParameter p2 = parser.createPointcutParameter("b", MyAnnotation.class);
  421. PointcutExpression atArgs = parser.parsePointcutExpression("@args(..,a)",A.class,new PointcutParameter[] {p1});
  422. ShadowMatch sMatch2 = atArgs.matchesMethodExecution(c);
  423. assertTrue("maybe matches C",sMatch2.maybeMatches());
  424. JoinPointMatch jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[]{new A(),new B()});
  425. assertTrue("matches",jp2.matches());
  426. assertEquals(1,jp2.getParameterBindings().length);
  427. MyAnnotation bAnnotation = B.class.getAnnotation(MyAnnotation.class);
  428. assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[0].getBinding());
  429. atArgs = parser.parsePointcutExpression("@args(a,b)",A.class,new PointcutParameter[] {p1,p2});
  430. sMatch2 = atArgs.matchesMethodExecution(c);
  431. assertTrue("maybe matches C",sMatch2.maybeMatches());
  432. jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[] {new B(),new B()});
  433. assertTrue("matches",jp2.matches());
  434. assertEquals(2,jp2.getParameterBindings().length);
  435. assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[0].getBinding());
  436. assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[1].getBinding());
  437. }
  438. public void testAtArgsWithParamBinding() throws Exception {
  439. // B class contains: public void e(@MyAnnotation A anA, B aB) {}
  440. PointcutParameter pp = parser.createPointcutParameter("a", MyAnnotation.class);
  441. PointcutExpression atArgs = parser.parsePointcutExpression("@args(a (*),..)",A.class,new PointcutParameter[] {pp});
  442. ShadowMatch shadowMatch = atArgs.matchesMethodExecution(e);
  443. assertTrue(shadowMatch.alwaysMatches());
  444. JoinPointMatch jpm = shadowMatch.matchesJoinPoint(new B(), new B(), new Object[] {new A(), new B()});
  445. assertEquals(1,jpm.getParameterBindings().length);
  446. MyAnnotation expectedAnnotation = (MyAnnotation)B.class.getDeclaredMethod("e", A.class,B.class).getParameterAnnotations()[0][0];
  447. Object boundAnnotation = jpm.getParameterBindings()[0].getBinding();
  448. assertEquals(expectedAnnotation,boundAnnotation);
  449. pp = parser.createPointcutParameter("a", MyAnnotationWithValue.class);
  450. PointcutParameter pp2 = parser.createPointcutParameter("b", MyAnnotationWithValue.class);
  451. atArgs = parser.parsePointcutExpression("@args(a,b)",A.class,new PointcutParameter[] {pp,pp2});
  452. shadowMatch = atArgs.matchesMethodExecution(f);
  453. assertTrue(shadowMatch.alwaysMatches());
  454. jpm = shadowMatch.matchesJoinPoint(new B(), new B(), new Object[] {new A(), new B()});
  455. assertEquals(2,jpm.getParameterBindings().length);
  456. MyAnnotationWithValue expectedAnnotation1 = (MyAnnotationWithValue)B.class.getDeclaredMethod("e", A.class,B.class).getParameterAnnotations()[0][0];
  457. MyAnnotationWithValue expectedAnnotation2 = (MyAnnotationWithValue)B.class.getDeclaredMethod("e", A.class,B.class).getParameterAnnotations()[1][0];
  458. Object boundAnnotation1 = jpm.getParameterBindings()[0].getBinding();
  459. assertEquals(expectedAnnotation1,boundAnnotation1);
  460. Object boundAnnotation2 = jpm.getParameterBindings()[1].getBinding();
  461. assertEquals(expectedAnnotation2,boundAnnotation1);
  462. //
  463. // atArgs = parser.parsePointcutExpression("@args(a,b)",A.class,new PointcutParameter[] {p1,p2});
  464. // sMatch2 = atArgs.matchesMethodExecution(c);
  465. // assertTrue("maybe matches C",sMatch2.maybeMatches());
  466. // jp2 = sMatch2.matchesJoinPoint(new B(), new B(), new Object[] {new B(),new B()});
  467. // assertTrue("matches",jp2.matches());
  468. // assertEquals(2,jp2.getParameterBindings().length);
  469. // assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[0].getBinding());
  470. // assertEquals("annotation on B",bAnnotation,jp2.getParameterBindings()[1].getBinding());
  471. }
  472. public void testAtWithin() {
  473. PointcutExpression atWithin = parser.parsePointcutExpression("@within(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)");
  474. ShadowMatch sMatch1 = atWithin.matchesMethodExecution(a);
  475. ShadowMatch sMatch2 = atWithin.matchesMethodExecution(b);
  476. assertTrue("does not match a",sMatch1.neverMatches());
  477. assertTrue("matches b",sMatch2.alwaysMatches());
  478. }
  479. public void testAtWithinWithBinding() {
  480. PointcutParameter p1 = parser.createPointcutParameter("x",MyAnnotation.class);
  481. PointcutExpression atWithin = parser.parsePointcutExpression("@within(x)",B.class,new PointcutParameter[] {p1});
  482. ShadowMatch sMatch1 = atWithin.matchesMethodExecution(a);
  483. ShadowMatch sMatch2 = atWithin.matchesMethodExecution(b);
  484. assertTrue("does not match a",sMatch1.neverMatches());
  485. assertTrue("matches b",sMatch2.alwaysMatches());
  486. JoinPointMatch jpm = sMatch2.matchesJoinPoint(new B(), new B(), new Object[0]);
  487. assertTrue(jpm.matches());
  488. assertEquals(1,jpm.getParameterBindings().length);
  489. MyAnnotation bAnnotation = B.class.getAnnotation(MyAnnotation.class);
  490. assertEquals("annotation on B",bAnnotation,jpm.getParameterBindings()[0].getBinding());
  491. }
  492. public void testAtWithinCode() {
  493. PointcutExpression atWithinCode = parser.parsePointcutExpression("@withincode(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)");
  494. ShadowMatch sMatch1 = atWithinCode.matchesMethodCall(a,b);
  495. ShadowMatch sMatch2 = atWithinCode.matchesMethodCall(a,a);
  496. assertTrue("does not match from b",sMatch1.neverMatches());
  497. assertTrue("matches from a",sMatch2.alwaysMatches());
  498. }
  499. public void testAtWithinCodeWithBinding() {
  500. PointcutParameter p1 = parser.createPointcutParameter("x",MyAnnotation.class);
  501. PointcutExpression atWithinCode = parser.parsePointcutExpression("@withincode(x)",A.class,new PointcutParameter[] {p1});
  502. ShadowMatch sMatch2 = atWithinCode.matchesMethodCall(a,a);
  503. assertTrue("matches from a",sMatch2.alwaysMatches());
  504. JoinPointMatch jpm = sMatch2.matchesJoinPoint(new A(), new A(), new Object[0]);
  505. assertEquals(1,jpm.getParameterBindings().length);
  506. MyAnnotation annOna = a.getAnnotation(MyAnnotation.class);
  507. assertEquals("MyAnnotation on a",annOna,jpm.getParameterBindings()[0].getBinding());
  508. }
  509. public void testAtAnnotation() {
  510. PointcutExpression atAnnotation = parser.parsePointcutExpression("@annotation(org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation)");
  511. ShadowMatch sMatch1 = atAnnotation.matchesMethodCall(b,a);
  512. ShadowMatch sMatch2 = atAnnotation.matchesMethodCall(a,a);
  513. assertTrue("does not match call to b",sMatch1.neverMatches());
  514. assertTrue("matches call to a",sMatch2.alwaysMatches());
  515. }
  516. public void testAtAnnotationWithBinding() {
  517. PointcutParameter p1 = parser.createPointcutParameter("x",MyAnnotation.class);
  518. PointcutExpression atAnnotation = parser.parsePointcutExpression("@annotation(x)",A.class,new PointcutParameter[] {p1});
  519. ShadowMatch sMatch2 = atAnnotation.matchesMethodCall(a,a);
  520. assertTrue("matches call to a",sMatch2.alwaysMatches());
  521. JoinPointMatch jpm = sMatch2.matchesJoinPoint(new A(), new A(), new Object[0]);
  522. assertTrue(jpm.matches());
  523. assertEquals(1,jpm.getParameterBindings().length);
  524. MyAnnotation annOna = a.getAnnotation(MyAnnotation.class);
  525. assertEquals("MyAnnotation on a",annOna,jpm.getParameterBindings()[0].getBinding());
  526. }
  527. public void testReferencePointcutNoParams() {
  528. PointcutExpression pc = parser.parsePointcutExpression("foo()",C.class,new PointcutParameter[0]);
  529. ShadowMatch sMatch1 = pc.matchesMethodCall(a,b);
  530. ShadowMatch sMatch2 = pc.matchesMethodExecution(a);
  531. assertTrue("no match on call",sMatch1.neverMatches());
  532. assertTrue("match on execution",sMatch2.alwaysMatches());
  533. pc = parser.parsePointcutExpression("org.aspectj.weaver.tools.Java15PointcutExpressionTest.C.foo()");
  534. sMatch1 = pc.matchesMethodCall(a,b);
  535. sMatch2 = pc.matchesMethodExecution(a);
  536. assertTrue("no match on call",sMatch1.neverMatches());
  537. assertTrue("match on execution",sMatch2.alwaysMatches());
  538. }
  539. public void testReferencePointcutParams() {
  540. PointcutParameter p1 = parser.createPointcutParameter("x",A.class);
  541. PointcutExpression pc = parser.parsePointcutExpression("goo(x)",C.class,new PointcutParameter[] {p1});
  542. ShadowMatch sMatch1 = pc.matchesMethodCall(a,b);
  543. ShadowMatch sMatch2 = pc.matchesMethodExecution(a);
  544. assertTrue("no match on call",sMatch1.neverMatches());
  545. assertTrue("match on execution",sMatch2.maybeMatches());
  546. A anA = new A();
  547. JoinPointMatch jpm = sMatch2.matchesJoinPoint(anA, new A(), new Object[0]);
  548. assertTrue(jpm.matches());
  549. assertEquals("should be bound to anA",anA,jpm.getParameterBindings()[0].getBinding());
  550. }
  551. public void testExecutionWithClassFileRetentionAnnotation() {
  552. PointcutExpression pc1 = parser.parsePointcutExpression("execution(@org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyAnnotation * *(..))");
  553. PointcutExpression pc2 = parser.parsePointcutExpression("execution(@org.aspectj.weaver.tools.Java15PointcutExpressionTest.MyClassFileRetentionAnnotation * *(..))");
  554. ShadowMatch sMatch = pc1.matchesMethodExecution(a);
  555. assertTrue("matches",sMatch.alwaysMatches());
  556. sMatch = pc2.matchesMethodExecution(a);
  557. assertTrue("no match",sMatch.neverMatches());
  558. sMatch = pc1.matchesMethodExecution(b);
  559. assertTrue("no match",sMatch.neverMatches());
  560. sMatch = pc2.matchesMethodExecution(b);
  561. assertTrue("matches",sMatch.alwaysMatches());
  562. }
  563. public void testGenericMethodSignatures() throws Exception{
  564. PointcutExpression ex = parser.parsePointcutExpression("execution(* set*(java.util.List<org.aspectj.weaver.tools.Java15PointcutExpressionTest.C>))");
  565. Method m = TestBean.class.getMethod("setFriends",List.class);
  566. ShadowMatch sm = ex.matchesMethodExecution(m);
  567. assertTrue("should match",sm.alwaysMatches());
  568. }
  569. public void testAnnotationInExecution() throws Exception {
  570. parser.parsePointcutExpression("execution(@(org.springframework..*) * *(..))");
  571. }
  572. public void testVarArgsMatching() throws Exception {
  573. PointcutExpression ex = parser.parsePointcutExpression("execution(* *(String...))");
  574. Method usesVarArgs = D.class.getMethod("varArgs",String[].class);
  575. Method noVarArgs = D.class.getMethod("nonVarArgs", String[].class);
  576. ShadowMatch sm1 = ex.matchesMethodExecution(usesVarArgs);
  577. assertTrue("should match",sm1.alwaysMatches());
  578. ShadowMatch sm2 = ex.matchesMethodExecution(noVarArgs);
  579. assertFalse("should not match",sm2.alwaysMatches());
  580. }
  581. public void testJavaLangMatching() throws Exception {
  582. PointcutExpression ex = parser.parsePointcutExpression("@within(java.lang.Deprecated)");
  583. Method foo = GoldenOldie.class.getMethod("foo");
  584. ShadowMatch sm1 = ex.matchesMethodExecution(foo);
  585. assertTrue("should match",sm1.alwaysMatches());
  586. }
  587. public void testReferencePCsInSameType() throws Exception {
  588. PointcutExpression ex = parser.parsePointcutExpression("org.aspectj.weaver.tools.Java15PointcutExpressionTest.NamedPointcutResolution.c()",NamedPointcutResolution.class,new PointcutParameter[0]);
  589. ShadowMatch sm = ex.matchesMethodExecution(a);
  590. assertTrue("should match",sm.alwaysMatches());
  591. sm = ex.matchesMethodExecution(b);
  592. assertTrue("does not match",sm.neverMatches());
  593. }
  594. public void testReferencePCsInOtherType() throws Exception {
  595. PointcutExpression ex = parser.parsePointcutExpression("org.aspectj.weaver.tools.Java15PointcutExpressionTest.ExternalReferrer.d()",ExternalReferrer.class,new PointcutParameter[0]);
  596. ShadowMatch sm = ex.matchesMethodExecution(a);
  597. assertTrue("should match",sm.alwaysMatches());
  598. sm = ex.matchesMethodExecution(b);
  599. assertTrue("does not match",sm.neverMatches());
  600. }
  601. public void testArrayTypeInArgs() throws Exception {
  602. PointcutParameter[] params = new PointcutParameter[3];
  603. params[0] = parser.createPointcutParameter("d", Date.class);
  604. params[1] = parser.createPointcutParameter("s", String.class);
  605. params[2] = parser.createPointcutParameter("ss", String[].class);
  606. parser.parsePointcutExpression("org.aspectj.weaver.tools.Java15PointcutExpressionTest.UsesArrays.pc(d,s,ss)",UsesArrays.class,params);
  607. }
  608. protected void setUp() throws Exception {
  609. super.setUp();
  610. parser = PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(this.getClass().getClassLoader());
  611. a = A.class.getMethod("a");
  612. b = B.class.getMethod("b");
  613. c = B.class.getMethod("c",new Class[] {A.class,B.class});
  614. d = B.class.getMethod("d",new Class[] {A.class,A.class});
  615. e = B.class.getMethod("e", new Class[] {A.class, B.class});
  616. f = B.class.getMethod("f", A.class, B.class);
  617. }
  618. @Retention(RetentionPolicy.RUNTIME)
  619. private @interface MyAnnotation {}
  620. @Retention(RetentionPolicy.RUNTIME)
  621. private @interface MyAnnotationWithValue {
  622. String value();
  623. }
  624. private @interface MyClassFileRetentionAnnotation {}
  625. private static class A {
  626. @MyAnnotation public void a() {}
  627. }
  628. @MyAnnotation
  629. private static class B {
  630. @MyClassFileRetentionAnnotation public void b() {}
  631. public void c(A anA, B aB) {}
  632. public void d(A anA, A anotherA) {}
  633. public void e(@MyAnnotation A anA, B aB) {}
  634. public void f(@MyAnnotationWithValue("abc") A anA, @MyAnnotationWithValue("def") B aB) {}
  635. }
  636. private static class C {
  637. @Pointcut("execution(* *(..))")
  638. public void foo() {}
  639. @Pointcut(value="execution(* *(..)) && this(x)", argNames="x")
  640. public void goo(A x) {}
  641. }
  642. private static class D {
  643. public void nonVarArgs(String[] strings) {};
  644. public void varArgs(String... strings) {};
  645. }
  646. static class TestBean {
  647. public void setFriends(List<C> friends) {}
  648. }
  649. @Deprecated
  650. static class GoldenOldie {
  651. public void foo() {}
  652. }
  653. private static class NamedPointcutResolution {
  654. @Pointcut("execution(* *(..))")
  655. public void a() {}
  656. @Pointcut("this(org.aspectj.weaver.tools.Java15PointcutExpressionTest.A)")
  657. public void b() {}
  658. @Pointcut("a() && b()")
  659. public void c() {}
  660. }
  661. private static class ExternalReferrer {
  662. @Pointcut("org.aspectj.weaver.tools.Java15PointcutExpressionTest.NamedPointcutResolution.a() && " +
  663. "org.aspectj.weaver.tools.Java15PointcutExpressionTest.NamedPointcutResolution.b())")
  664. public void d() {}
  665. }
  666. private static class UsesArrays {
  667. @Pointcut("execution(* *(..)) && args(d,s,ss)")
  668. public void pc(Date d, String s, String[] ss) {}
  669. }
  670. }