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

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