1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.aop.aspectj;
18
19 import java.lang.reflect.Method;
20
21 import org.aopalliance.intercept.MethodInterceptor;
22 import org.aopalliance.intercept.MethodInvocation;
23 import org.aspectj.weaver.tools.PointcutExpression;
24 import org.aspectj.weaver.tools.PointcutPrimitive;
25 import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException;
26 import org.junit.Before;
27 import org.junit.Test;
28
29 import org.springframework.aop.ClassFilter;
30 import org.springframework.aop.MethodMatcher;
31 import org.springframework.aop.Pointcut;
32 import org.springframework.aop.framework.ProxyFactory;
33 import org.springframework.aop.support.DefaultPointcutAdvisor;
34 import org.springframework.tests.sample.beans.IOther;
35 import org.springframework.tests.sample.beans.ITestBean;
36 import org.springframework.tests.sample.beans.TestBean;
37 import org.springframework.tests.sample.beans.subpkg.DeepBean;
38
39 import static org.junit.Assert.*;
40
41
42
43
44
45
46 public final class AspectJExpressionPointcutTests {
47
48 public static final String MATCH_ALL_METHODS = "execution(* *(..))";
49
50 private Method getAge;
51
52 private Method setAge;
53
54 private Method setSomeNumber;
55
56 private Method isPostProcessed;
57
58
59 @Before
60 public void setUp() throws NoSuchMethodException {
61 getAge = TestBean.class.getMethod("getAge", (Class<?>[])null);
62 setAge = TestBean.class.getMethod("setAge", new Class[]{int.class});
63 setSomeNumber = TestBean.class.getMethod("setSomeNumber", new Class[]{Number.class});
64 isPostProcessed = TestBean.class.getMethod("isPostProcessed", (Class[]) null);
65 }
66
67 @Test
68 public void testMatchExplicit() {
69 String expression = "execution(int org.springframework.tests.sample.beans.TestBean.getAge())";
70
71 Pointcut pointcut = getPointcut(expression);
72 ClassFilter classFilter = pointcut.getClassFilter();
73 MethodMatcher methodMatcher = pointcut.getMethodMatcher();
74
75 assertMatchesTestBeanClass(classFilter);
76
77
78
79
80 assertFalse("Should not be a runtime match", methodMatcher.isRuntime());
81 assertMatchesGetAge(methodMatcher);
82 assertFalse("Expression should match setAge() method", methodMatcher.matches(setAge, TestBean.class));
83 }
84
85 @Test
86 public void testMatchWithTypePattern() throws Exception {
87 String expression = "execution(* *..TestBean.*Age(..))";
88
89 Pointcut pointcut = getPointcut(expression);
90 ClassFilter classFilter = pointcut.getClassFilter();
91 MethodMatcher methodMatcher = pointcut.getMethodMatcher();
92
93 assertMatchesTestBeanClass(classFilter);
94
95
96
97
98 assertFalse("Should not be a runtime match", methodMatcher.isRuntime());
99 assertMatchesGetAge(methodMatcher);
100 assertTrue("Expression should match setAge(int) method", methodMatcher.matches(setAge, TestBean.class));
101 }
102
103
104 @Test
105 public void testThis() throws SecurityException, NoSuchMethodException{
106 testThisOrTarget("this");
107 }
108
109 @Test
110 public void testTarget() throws SecurityException, NoSuchMethodException {
111 testThisOrTarget("target");
112 }
113
114 public static class OtherIOther implements IOther {
115
116 @Override
117 public void absquatulate() {
118
119 }
120
121 }
122
123
124
125
126
127
128
129
130 private void testThisOrTarget(String which) throws SecurityException, NoSuchMethodException {
131 String matchesTestBean = which + "(org.springframework.tests.sample.beans.TestBean)";
132 String matchesIOther = which + "(org.springframework.tests.sample.beans.IOther)";
133 AspectJExpressionPointcut testBeanPc = new AspectJExpressionPointcut();
134 testBeanPc.setExpression(matchesTestBean);
135
136 AspectJExpressionPointcut iOtherPc = new AspectJExpressionPointcut();
137 iOtherPc.setExpression(matchesIOther);
138
139 assertTrue(testBeanPc.matches(TestBean.class));
140 assertTrue(testBeanPc.matches(getAge, TestBean.class));
141 assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
142 OtherIOther.class));
143
144 assertFalse(testBeanPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
145 OtherIOther.class));
146 }
147
148 @Test
149 public void testWithinRootPackage() throws SecurityException, NoSuchMethodException {
150 testWithinPackage(false);
151 }
152
153 @Test
154 public void testWithinRootAndSubpackages() throws SecurityException, NoSuchMethodException {
155 testWithinPackage(true);
156 }
157
158 private void testWithinPackage(boolean matchSubpackages) throws SecurityException, NoSuchMethodException {
159 String withinBeansPackage = "within(org.springframework.tests.sample.beans.";
160
161 if (matchSubpackages) {
162 withinBeansPackage += ".";
163 }
164 withinBeansPackage = withinBeansPackage + "*)";
165 AspectJExpressionPointcut withinBeansPc = new AspectJExpressionPointcut();
166 withinBeansPc.setExpression(withinBeansPackage);
167
168 assertTrue(withinBeansPc.matches(TestBean.class));
169 assertTrue(withinBeansPc.matches(getAge, TestBean.class));
170 assertEquals(matchSubpackages, withinBeansPc.matches(DeepBean.class));
171 assertEquals(matchSubpackages, withinBeansPc.matches(
172 DeepBean.class.getMethod("aMethod", String.class), DeepBean.class));
173 assertFalse(withinBeansPc.matches(String.class));
174 assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
175 OtherIOther.class));
176 }
177
178 @Test
179 public void testFriendlyErrorOnNoLocationClassMatching() {
180 AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
181 try {
182 pc.matches(ITestBean.class);
183 fail();
184 }
185 catch (IllegalStateException ex) {
186 assertTrue(ex.getMessage().indexOf("expression") != -1);
187 }
188 }
189
190 @Test
191 public void testFriendlyErrorOnNoLocation2ArgMatching() {
192 AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
193 try {
194 pc.matches(getAge, ITestBean.class);
195 fail();
196 }
197 catch (IllegalStateException ex) {
198 assertTrue(ex.getMessage().indexOf("expression") != -1);
199 }
200 }
201
202 @Test
203 public void testFriendlyErrorOnNoLocation3ArgMatching() {
204 AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
205 try {
206 pc.matches(getAge, ITestBean.class, (Object[]) null);
207 fail();
208 }
209 catch (IllegalStateException ex) {
210 assertTrue(ex.getMessage().indexOf("expression") != -1);
211 }
212 }
213
214
215 @Test
216 public void testMatchWithArgs() throws Exception {
217 String expression = "execution(void org.springframework.tests.sample.beans.TestBean.setSomeNumber(Number)) && args(Double)";
218
219 Pointcut pointcut = getPointcut(expression);
220 ClassFilter classFilter = pointcut.getClassFilter();
221 MethodMatcher methodMatcher = pointcut.getMethodMatcher();
222
223 assertMatchesTestBeanClass(classFilter);
224
225
226
227
228 assertTrue("Should match with setSomeNumber with Double input",
229 methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Double(12)}));
230 assertFalse("Should not match setSomeNumber with Integer input",
231 methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Integer(11)}));
232 assertFalse("Should not match getAge", methodMatcher.matches(getAge, TestBean.class, null));
233 assertTrue("Should be a runtime match", methodMatcher.isRuntime());
234 }
235
236 @Test
237 public void testSimpleAdvice() {
238 String expression = "execution(int org.springframework.tests.sample.beans.TestBean.getAge())";
239
240 CallCountingInterceptor interceptor = new CallCountingInterceptor();
241
242 TestBean testBean = getAdvisedProxy(expression, interceptor);
243
244 assertEquals("Calls should be 0", 0, interceptor.getCount());
245
246 testBean.getAge();
247
248 assertEquals("Calls should be 1", 1, interceptor.getCount());
249
250 testBean.setAge(90);
251
252 assertEquals("Calls should still be 1", 1, interceptor.getCount());
253 }
254
255 @Test
256 public void testDynamicMatchingProxy() {
257 String expression = "execution(void org.springframework.tests.sample.beans.TestBean.setSomeNumber(Number)) && args(Double)";
258
259 CallCountingInterceptor interceptor = new CallCountingInterceptor();
260
261 TestBean testBean = getAdvisedProxy(expression, interceptor);
262
263 assertEquals("Calls should be 0", 0, interceptor.getCount());
264
265 testBean.setSomeNumber(new Double(30));
266
267 assertEquals("Calls should be 1", 1, interceptor.getCount());
268
269 testBean.setSomeNumber(new Integer(90));
270
271 assertEquals("Calls should be 1", 1, interceptor.getCount());
272 }
273
274 @Test
275 public void testInvalidExpression() {
276 String expression = "execution(void org.springframework.tests.sample.beans.TestBean.setSomeNumber(Number) && args(Double)";
277
278 try {
279 getPointcut(expression).getClassFilter();
280 fail("Invalid expression should throw IllegalArgumentException");
281 }
282 catch (IllegalArgumentException ex) {
283 assertTrue(true);
284 System.out.println(ex.getMessage());
285 }
286 }
287
288 private TestBean getAdvisedProxy(String pointcutExpression, CallCountingInterceptor interceptor) {
289 TestBean target = new TestBean();
290
291 Pointcut pointcut = getPointcut(pointcutExpression);
292
293 DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
294 advisor.setAdvice(interceptor);
295 advisor.setPointcut(pointcut);
296
297 ProxyFactory pf = new ProxyFactory();
298 pf.setTarget(target);
299 pf.addAdvisor(advisor);
300
301 return (TestBean) pf.getProxy();
302 }
303
304 private void assertMatchesGetAge(MethodMatcher methodMatcher) {
305 assertTrue("Expression should match getAge() method", methodMatcher.matches(getAge, TestBean.class));
306 }
307
308 private void assertMatchesTestBeanClass(ClassFilter classFilter) {
309 assertTrue("Expression should match TestBean class", classFilter.matches(TestBean.class));
310 }
311
312 @Test
313 public void testWithUnsupportedPointcutPrimitive() throws Exception {
314 String expression = "call(int org.springframework.tests.sample.beans.TestBean.getAge())";
315
316 try {
317 getPointcut(expression).getClassFilter();
318 fail("Should not support call pointcuts");
319 }
320 catch (UnsupportedPointcutPrimitiveException ex) {
321 assertEquals("Should not support call pointcut", PointcutPrimitive.CALL, ex.getUnsupportedPrimitive());
322 }
323
324 }
325
326 @Test
327 public void testAndSubstitution() {
328 Pointcut pc = getPointcut("execution(* *(..)) and args(String)");
329 PointcutExpression expr =
330 ((AspectJExpressionPointcut) pc).getPointcutExpression();
331 assertEquals("execution(* *(..)) && args(String)",expr.getPointcutExpression());
332 }
333
334 @Test
335 public void testMultipleAndSubstitutions() {
336 Pointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
337 PointcutExpression expr =
338 ((AspectJExpressionPointcut) pc).getPointcutExpression();
339 assertEquals("execution(* *(..)) && args(String) && this(Object)",expr.getPointcutExpression());
340 }
341
342 private Pointcut getPointcut(String expression) {
343 AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
344 pointcut.setExpression(expression);
345 return pointcut;
346 }
347 }
348
349
350 class CallCountingInterceptor implements MethodInterceptor {
351
352 private int count;
353
354 @Override
355 public Object invoke(MethodInvocation methodInvocation) throws Throwable {
356 count++;
357 return methodInvocation.proceed();
358 }
359
360 public int getCount() {
361 return count;
362 }
363
364 public void reset() {
365 this.count = 0;
366 }
367
368 }