KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > aop > framework > AbstractAopProxyTests


1 /*
2  * Copyright 2002-2005 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.aop.framework;
18
19 import java.lang.reflect.Method JavaDoc;
20 import java.lang.reflect.UndeclaredThrowableException JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.LinkedList JavaDoc;
23 import java.util.List JavaDoc;
24
25 import javax.servlet.ServletException JavaDoc;
26 import javax.transaction.TransactionRequiredException JavaDoc;
27
28 import junit.framework.TestCase;
29 import org.aopalliance.aop.Advice;
30 import org.aopalliance.aop.AspectException;
31 import org.aopalliance.intercept.MethodInterceptor;
32 import org.aopalliance.intercept.MethodInvocation;
33
34 import org.springframework.aop.Advisor;
35 import org.springframework.aop.AfterReturningAdvice;
36 import org.springframework.aop.DynamicIntroductionAdvice;
37 import org.springframework.aop.MethodBeforeAdvice;
38 import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptorTests;
39 import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
40 import org.springframework.aop.interceptor.NopInterceptor;
41 import org.springframework.aop.interceptor.SerializableNopInterceptor;
42 import org.springframework.aop.support.AopUtils;
43 import org.springframework.aop.support.DefaultIntroductionAdvisor;
44 import org.springframework.aop.support.DefaultPointcutAdvisor;
45 import org.springframework.aop.support.DelegatingIntroductionInterceptor;
46 import org.springframework.aop.support.DynamicMethodMatcherPointcutAdvisor;
47 import org.springframework.aop.support.NameMatchMethodPointcut;
48 import org.springframework.aop.support.Pointcuts;
49 import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
50 import org.springframework.aop.target.HotSwappableTargetSource;
51 import org.springframework.aop.target.SingletonTargetSource;
52 import org.springframework.beans.IOther;
53 import org.springframework.beans.ITestBean;
54 import org.springframework.beans.Person;
55 import org.springframework.beans.SerializablePerson;
56 import org.springframework.beans.TestBean;
57 import org.springframework.util.SerializationTestUtils;
58 import org.springframework.util.StopWatch;
59
60 /**
61  * @author Rod Johnson
62  * @author Juergen Hoeller
63  * @since 13.03.2003
64  */

65 public abstract class AbstractAopProxyTests extends TestCase {
66     
67     protected MockTargetSource mockTargetSource = new MockTargetSource();
68
69     /**
70      * Make a clean target source available if code wants to use it.
71      * The target must be set. Verification will be automatic in tearDown
72      * to ensure that it was used appropriately by code.
73      * @see junit.framework.TestCase#setUp()
74      */

75     protected void setUp() {
76         mockTargetSource.reset();
77     }
78
79     protected void tearDown() {
80         mockTargetSource.verify();
81     }
82     
83     /**
84      * Set in CGLIB or JDK mode.
85      */

86     protected abstract Object JavaDoc createProxy(AdvisedSupport as);
87     
88     protected abstract AopProxy createAopProxy(AdvisedSupport as);
89     
90     /**
91      * Is a target always required?
92      */

93     protected boolean requiresTarget() {
94         return false;
95     }
96     
97     public void testNoInterceptorsAndNoTarget() {
98         AdvisedSupport pc =
99             new AdvisedSupport(new Class JavaDoc[] { ITestBean.class });
100         // Add no interceptors
101
try {
102             AopProxy aop = createAopProxy(pc);
103             aop.getProxy();
104             fail("Shouldn't allow no interceptors");
105         } catch (AopConfigException ex) {
106             // Ok
107
}
108     }
109     
110     /**
111      * Simple test that if we set values we can get them out again.
112      */

113     public void testValuesStick() {
114         int age1 = 33;
115         int age2 = 37;
116         String JavaDoc name = "tony";
117     
118         TestBean target1 = new TestBean();
119         target1.setAge(age1);
120         ProxyFactory pf1 = new ProxyFactory(target1);
121         pf1.addAdvisor(new DefaultPointcutAdvisor(new NopInterceptor()));
122         pf1.addAdvisor(new DefaultPointcutAdvisor(new TimestampIntroductionInterceptor()));
123         ITestBean tb = target1;
124         
125         assertEquals(age1, tb.getAge());
126         tb.setAge(age2);
127         assertEquals(age2, tb.getAge());
128         assertNull(tb.getName());
129         tb.setName(name);
130         assertEquals(name, tb.getName());
131     }
132     
133     /**
134      * This is primarily a test for the efficiency of our
135      * usage of CGLIB. If we create too many classes with
136      * CGLIB this will be slow or will run out of memory.
137      */

138     public void testManyProxies() {
139         int howMany = 10000;
140         StopWatch sw = new StopWatch();
141         sw.start(getClass() + "." + getName() + ": create " + howMany + " proxies");
142         testManyProxies(howMany);
143         sw.stop();
144         System.out.println(sw);
145         // Set a performance benchmark.
146
// It's pretty generous so as not to cause failures on slow machines.
147
assertTrue("Proxy creation was too slow", sw.getTotalTimeSeconds() < 25);
148     }
149     
150     private void testManyProxies(int howMany) {
151         int age1 = 33;
152         TestBean target1 = new TestBean();
153         target1.setAge(age1);
154         ProxyFactory pf1 = new ProxyFactory(target1);
155         pf1.addAdvice(new NopInterceptor());
156         pf1.addAdvice(new NopInterceptor());
157         ITestBean proxies[] = new ITestBean[howMany];
158         for (int i = 0; i < howMany; i++) {
159             proxies[i] = (ITestBean) createAopProxy(pf1).getProxy();
160             assertEquals(age1, proxies[i].getAge());
161         }
162     }
163
164     public void testSerializationAdviceAndTargetNotSerializable() throws Exception JavaDoc {
165         TestBean tb = new TestBean();
166         assertFalse(SerializationTestUtils.isSerializable(tb));
167         
168         ProxyFactory pf = new ProxyFactory(tb);
169         
170         pf.addAdvice(new NopInterceptor());
171         ITestBean proxy = (ITestBean) createAopProxy(pf).getProxy();
172         
173         assertFalse(SerializationTestUtils.isSerializable(proxy));
174     }
175     
176     public void testSerializationAdviceNotSerializable() throws Exception JavaDoc {
177         SerializablePerson sp = new SerializablePerson();
178         assertTrue(SerializationTestUtils.isSerializable(sp));
179         
180         ProxyFactory pf = new ProxyFactory(sp);
181         
182         // This isn't serializable
183
Advice i = new NopInterceptor();
184         pf.addAdvice(i);
185         assertFalse(SerializationTestUtils.isSerializable(i));
186         Object JavaDoc proxy = createAopProxy(pf).getProxy();
187         
188         assertFalse(SerializationTestUtils.isSerializable(proxy));
189     }
190     
191     public void testSerializationSerializableTargetAndAdvice() throws Throwable JavaDoc {
192         SerializablePerson personTarget = new SerializablePerson();
193         personTarget.setName("jim");
194         personTarget.setAge(26);
195         
196         assertTrue(SerializationTestUtils.isSerializable(personTarget));
197         
198         ProxyFactory pf = new ProxyFactory(personTarget);
199         
200         CountingThrowsAdvice cta = new CountingThrowsAdvice();
201         
202         pf.addAdvice(new SerializableNopInterceptor());
203         // Try various advice types
204
pf.addAdvice(new CountingBeforeAdvice());
205         pf.addAdvice(new CountingAfterReturningAdvice());
206         pf.addAdvice(cta);
207         Person p = (Person) createAopProxy(pf).getProxy();
208         
209         p.echo(null);
210         assertEquals(0, cta.getCalls());
211         try {
212             p.echo(new ServletException JavaDoc());
213         }
214         catch (ServletException JavaDoc ex) {
215             
216         }
217         assertEquals(1, cta.getCalls());
218         
219         // Will throw exception if it fails
220
Person p2 = (Person) SerializationTestUtils.serializeAndDeserialize(p);
221         assertNotSame(p, p2);
222         assertEquals(p.getName(), p2.getName());
223         assertEquals(p.getAge(), p2.getAge());
224         assertTrue("Deserialized object is an AOP proxy", AopUtils.isAopProxy(p2));
225         
226         Advised a1 = (Advised) p;
227         Advised a2 = (Advised) p2;
228         // Check we can manipulate state of p2
229
assertEquals(a1.getAdvisors().length, a2.getAdvisors().length);
230         
231         // This should work as SerializablePerson is equal
232
assertEquals("Proxies should be equal, even after one was serialized", p, p2);
233         assertEquals("Proxies should be equal, even after one was serialized", p2, p);
234         
235         // Check we can add a new advisor to the target
236
NopInterceptor ni = new NopInterceptor();
237         p2.getAge();
238         assertEquals(0, ni.getCount());
239         a2.addAdvice(ni);
240         p2.getAge();
241         assertEquals(1, ni.getCount());
242         
243         cta = (CountingThrowsAdvice) a2.getAdvisors()[3].getAdvice();
244         p2.echo(null);
245         assertEquals(1, cta.getCalls());
246         try {
247             p2.echo(new ServletException JavaDoc());
248         }
249         catch (ServletException JavaDoc ex) {
250             
251         }
252         assertEquals(2, cta.getCalls());
253         
254     }
255     
256     /**
257      * Check that the two MethodInvocations necessary are independent and
258      * don't conflict.
259      * Check also proxy exposure.
260      */

261     public void testOneAdvisedObjectCallsAnother() {
262         int age1 = 33;
263         int age2 = 37;
264         
265         TestBean target1 = new TestBean();
266         ProxyFactory pf1 = new ProxyFactory(target1);
267         // Permit proxy and invocation checkers to get context from AopContext
268
pf1.setExposeProxy(true);
269         NopInterceptor di1 = new NopInterceptor();
270         pf1.addAdvice(0, di1);
271         pf1.addAdvice(1, new ProxyMatcherInterceptor());
272         pf1.addAdvice(2, new CheckMethodInvocationIsSameInAndOutInterceptor());
273         pf1.addAdvice(1, new CheckMethodInvocationViaThreadLocalIsSameInAndOutInterceptor());
274         // Must be first
275
pf1.addAdvice(0, ExposeInvocationInterceptor.INSTANCE);
276         ITestBean advised1 = (ITestBean) pf1.getProxy();
277         advised1.setAge(age1); // = 1 invocation
278

279         TestBean target2 = new TestBean();
280         ProxyFactory pf2 = new ProxyFactory(target2);
281         pf2.setExposeProxy(true);
282         NopInterceptor di2 = new NopInterceptor();
283         pf2.addAdvice(0, di2);
284         pf2.addAdvice(1, new ProxyMatcherInterceptor());
285         pf2.addAdvice(2, new CheckMethodInvocationIsSameInAndOutInterceptor());
286         pf2.addAdvice(1, new CheckMethodInvocationViaThreadLocalIsSameInAndOutInterceptor());
287         pf2.addAdvice(0, ExposeInvocationInterceptor.INSTANCE);
288         //System.err.println(pf2.toProxyConfigString());
289
ITestBean advised2 = (ITestBean) createProxy(pf2);
290         advised2.setAge(age2);
291         advised1.setSpouse(advised2); // = 2 invocations
292

293         assertEquals("Advised one has correct age", age1, advised1.getAge()); // = 3 invocations
294
assertEquals("Advised two has correct age", age2, advised2.getAge());
295         // Means extra call on advised 2
296
assertEquals("Advised one spouse has correct age", age2, advised1.getSpouse().getAge()); // = 4 invocations on 1 and another one on 2
297

298         assertEquals("one was invoked correct number of times", 4, di1.getCount());
299         // Got hit by call to advised1.getSpouse().getAge()
300
assertEquals("one was invoked correct number of times", 3, di2.getCount());
301     }
302     
303     
304     public void testReentrance() {
305         int age1 = 33;
306     
307         TestBean target1 = new TestBean();
308         ProxyFactory pf1 = new ProxyFactory(target1);
309         NopInterceptor di1 = new NopInterceptor();
310         pf1.addAdvice(0, di1);
311         ITestBean advised1 = (ITestBean) createProxy(pf1);
312         advised1.setAge(age1); // = 1 invocation
313
advised1.setSpouse(advised1); // = 2 invocations
314

315         assertEquals("one was invoked correct number of times", 2, di1.getCount());
316         
317         assertEquals("Advised one has correct age", age1, advised1.getAge()); // = 3 invocations
318
assertEquals("one was invoked correct number of times", 3, di1.getCount());
319         
320         // = 5 invocations, as reentrant call to spouse is advised also
321
assertEquals("Advised spouse has correct age", age1, advised1.getSpouse().getAge());
322         
323         assertEquals("one was invoked correct number of times", 5, di1.getCount());
324     }
325
326     public void testTargetCanGetProxy() {
327         NopInterceptor di = new NopInterceptor();
328         INeedsToSeeProxy target = new TargetChecker();
329         ProxyFactory proxyFactory = new ProxyFactory(target);
330         proxyFactory.setExposeProxy(true);
331         assertTrue(proxyFactory.isExposeProxy());
332     
333         proxyFactory.addAdvice(0, di);
334         INeedsToSeeProxy proxied = (INeedsToSeeProxy) createProxy(proxyFactory);
335         assertEquals(0, di.getCount());
336         assertEquals(0, target.getCount());
337         proxied.incrementViaThis();
338         assertEquals("Increment happened", 1, target.getCount());
339         
340         assertEquals("Only one invocation via AOP as use of this wasn't proxied", 1, di.getCount());
341         // 1 invocation
342
assertEquals("Increment happened", 1, proxied.getCount());
343         proxied.incrementViaProxy(); // 2 invoocations
344
assertEquals("Increment happened", 2, target.getCount());
345         assertEquals("3 more invocations via AOP as the first call was reentrant through the proxy", 4, di.getCount());
346     }
347
348             
349     public void testTargetCantGetProxyByDefault() {
350         NeedsToSeeProxy et = new NeedsToSeeProxy();
351         ProxyFactory pf1 = new ProxyFactory(et);
352         assertFalse(pf1.isExposeProxy());
353         INeedsToSeeProxy proxied = (INeedsToSeeProxy) createProxy(pf1);
354         try {
355             proxied.incrementViaProxy();
356             fail("Should have failed to get proxy as exposeProxy wasn't set to true");
357         }
358         catch (AspectException ex) {
359             // Ok
360
}
361     }
362
363     public void testContext() throws Throwable JavaDoc {
364         testContext(true);
365     }
366
367     public void testNoContext() throws Throwable JavaDoc {
368         testContext(false);
369     }
370
371     /**
372      * @param context if true, want context
373      */

374     private void testContext(final boolean context) throws Throwable JavaDoc {
375         final String JavaDoc s = "foo";
376         // Test return value
377
MethodInterceptor mi = new MethodInterceptor() {
378             public Object JavaDoc invoke(MethodInvocation invocation) throws Throwable JavaDoc {
379                 if (!context) {
380                     assertNoInvocationContext();
381                 } else {
382                     assertTrue("have context", ExposeInvocationInterceptor.currentInvocation() != null);
383                 }
384                 return s;
385             }
386         };
387         AdvisedSupport pc = new AdvisedSupport(new Class JavaDoc[] { ITestBean.class });
388         if (context) {
389             pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
390         }
391         pc.addAdvice(mi);
392         // Keep CGLIB happy
393
if (requiresTarget()) {
394             pc.setTarget(new TestBean());
395         }
396         AopProxy aop = createAopProxy(pc);
397
398         assertNoInvocationContext();
399         ITestBean tb = (ITestBean) aop.getProxy();
400         assertNoInvocationContext();
401         assertTrue("correct return value", tb.getName() == s);
402     }
403     
404     /**
405      * Test that the proxy returns itself when the
406      * target returns <code>this</code>
407      */

408     public void testTargetReturnsThis() throws Throwable JavaDoc {
409         // Test return value
410
TestBean raw = new OwnSpouse();
411     
412         AdvisedSupport pc = new AdvisedSupport(new Class JavaDoc[] { ITestBean.class });
413         pc.setTarget(raw);
414
415         ITestBean tb = (ITestBean) createProxy(pc);
416         assertTrue("this return is wrapped in proxy", tb.getSpouse() == tb);
417     }
418
419 /*
420     public void testCanAttach() throws Throwable {
421         final TrapInterceptor tii = new TrapInvocationInterceptor();
422
423         ProxyConfig pc = new ProxyConfigSupport(new Class[] { ITestBean.class }, false);
424         pc.addAdvice(tii);
425         pc.addAdvice(new MethodInterceptor() {
426             public Object invoke(MethodInvocation invocation) throws Throwable {
427                 assertTrue("Saw same interceptor", invocation == tii.invocation);
428                 return null;
429             }
430         });
431         AopProxy aop = new AopProxy(pc, new MethodInvocationFactorySupport());
432
433         ITestBean tb = (ITestBean) aop.getProxy();
434         tb.getSpouse();
435         assertTrue(tii.invocation != null);
436         
437         // TODO strengthen this
438     // assertTrue(tii.invocation.getProxy() == tb);
439         assertTrue(tii.invocation.getThis() == null);
440     }
441 */

442
443     public void testDeclaredException() throws Throwable JavaDoc {
444         final Exception JavaDoc expectedException = new Exception JavaDoc();
445         // Test return value
446
MethodInterceptor mi = new MethodInterceptor() {
447             public Object JavaDoc invoke(MethodInvocation invocation) throws Throwable JavaDoc {
448                 throw expectedException;
449             }
450         };
451         AdvisedSupport pc = new AdvisedSupport(new Class JavaDoc[] { ITestBean.class });
452         pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
453         pc.addAdvice(mi);
454         
455         // We don't care about the object
456
mockTargetSource.setTarget(new Object JavaDoc());
457         pc.setTargetSource(mockTargetSource);
458         AopProxy aop = createAopProxy(pc);
459
460         try {
461             ITestBean tb = (ITestBean) aop.getProxy();
462             // Note: exception param below isn't used
463
tb.exceptional(expectedException);
464             fail("Should have thrown exception raised by interceptor");
465         }
466         catch (Exception JavaDoc thrown) {
467             assertEquals("exception matches", expectedException, thrown);
468         }
469     }
470     
471     /**
472      * An interceptor throws a checked exception not on the method signature.
473      * For efficiency, we don't bother unifying java.lang.reflect and
474      * net.sf.cglib UndeclaredThrowableException
475      */

476     public void testUndeclaredCheckedException() throws Throwable JavaDoc {
477         final Exception JavaDoc unexpectedException = new Exception JavaDoc();
478         // Test return value
479
MethodInterceptor mi = new MethodInterceptor() {
480             public Object JavaDoc invoke(MethodInvocation invocation) throws Throwable JavaDoc {
481                 throw unexpectedException;
482             }
483         };
484         AdvisedSupport pc = new AdvisedSupport(new Class JavaDoc[] { ITestBean.class });
485         pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
486         pc.addAdvice(mi);
487     
488         // We don't care about the object
489
pc.setTarget(new TestBean());
490         AopProxy aop = createAopProxy(pc);
491         ITestBean tb = (ITestBean) aop.getProxy();
492         
493         try {
494             // Note: exception param below isn't used
495
tb.getAge();
496             fail("Should have wrapped exception raised by interceptor");
497         }
498         catch (UndeclaredThrowableException JavaDoc thrown) {
499             assertEquals("exception matches", unexpectedException, thrown.getUndeclaredThrowable());
500         }
501         //catch (net.sf.cglib.proxy.UndeclaredThrowableException thrown) {
502
// assertEquals("exception matches", unexpectedException, thrown.getUndeclaredThrowable());
503
//}
504
catch (Exception JavaDoc ex) {
505             ex.printStackTrace();
506             fail("Didn't expect exception: " + ex);
507         }
508     }
509     
510     public void testUndeclaredUnheckedException() throws Throwable JavaDoc {
511         final RuntimeException JavaDoc unexpectedException = new RuntimeException JavaDoc();
512         // Test return value
513
MethodInterceptor mi = new MethodInterceptor() {
514             public Object JavaDoc invoke(MethodInvocation invocation) throws Throwable JavaDoc {
515                 throw unexpectedException;
516             }
517         };
518         AdvisedSupport pc = new AdvisedSupport(new Class JavaDoc[] { ITestBean.class });
519         pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
520         pc.addAdvice(mi);
521     
522         // We don't care about the object
523
pc.setTarget(new TestBean());
524         AopProxy aop = createAopProxy(pc);
525         ITestBean tb = (ITestBean) aop.getProxy();
526         
527         try {
528             // Note: exception param below isn't used
529
tb.getAge();
530             fail("Should have wrapped exception raised by interceptor");
531         }
532         catch (RuntimeException JavaDoc thrown) {
533             assertEquals("exception matches", unexpectedException, thrown);
534         }
535         //catch (net.sf.cglib.proxy.UndeclaredThrowableException thrown) {
536
// assertEquals("exception matches", unexpectedException, thrown.getUndeclaredThrowable());
537
//}
538
}
539     
540     /**
541      * Check that although a method is eligible for advice chain optimization and
542      * direct reflective invocation, it doesn't happen if we've asked to see the proxy,
543      * so as to guarantee a consistent programming model.
544      * @throws Throwable
545      */

546     public void testTargetCanGetInvocationEvenIfNoAdviceChain() throws Throwable JavaDoc {
547         NeedsToSeeProxy target = new NeedsToSeeProxy();
548         AdvisedSupport pc = new AdvisedSupport(new Class JavaDoc[] { INeedsToSeeProxy.class } );
549         pc.setTarget(target);
550         pc.setExposeProxy(true);
551         
552         // Now let's try it with the special target
553
AopProxy aop = createAopProxy(pc);
554         INeedsToSeeProxy proxied = (INeedsToSeeProxy) aop.getProxy();
555         // It will complain if it can't get the proxy
556
proxied.incrementViaProxy();
557     }
558     
559     public void testTargetCanGetInvocation() throws Throwable JavaDoc {
560         final InvocationCheckExposedInvocationTestBean expectedTarget = new InvocationCheckExposedInvocationTestBean();
561         
562         AdvisedSupport pc = new AdvisedSupport(new Class JavaDoc[] { ITestBean.class, IOther.class });
563         pc.addAdvice(ExposeInvocationInterceptor.INSTANCE);
564         TrapTargetInterceptor tii = new TrapTargetInterceptor() {
565             public Object JavaDoc invoke(MethodInvocation invocation) throws Throwable JavaDoc {
566                 // Assert that target matches BEFORE invocation returns
567
assertEquals("Target is correct", expectedTarget, invocation.getThis());
568                 return super.invoke(invocation);
569             }
570         };
571         pc.addAdvice(tii);
572         pc.setTarget(expectedTarget);
573         AopProxy aop = createAopProxy(pc);
574
575         ITestBean tb = (ITestBean) aop.getProxy();
576         tb.getName();
577         // Not safe to trap invocation
578
//assertTrue(tii.invocation == target.invocation);
579

580         //assertTrue(target.invocation.getProxy() == tb);
581

582     // ((IOther) tb).absquatulate();
583
//MethodInvocation minv = tii.invocation;
584
//assertTrue("invoked on iother, not " + minv.getMethod().getDeclaringClass(), minv.getMethod().getDeclaringClass() == IOther.class);
585
//assertTrue(target.invocation == tii.invocation);
586
}
587
588     /**
589      * Throw an exception if there is an Invocation.
590      */

591     private void assertNoInvocationContext() {
592         try {
593             ExposeInvocationInterceptor.currentInvocation();
594             fail("Expected no invocation context");
595         } catch (AspectException ex) {
596             // ok
597
}
598     }
599
600     /**
601      * Test stateful interceptor
602      */

603     public void testMixinWithIntroductionAdvisor() throws Throwable JavaDoc {
604         TestBean tb = new TestBean();
605         ProxyFactory pc = new ProxyFactory(new Class JavaDoc[] { ITestBean.class });
606         pc.addAdvisor(new LockMixinAdvisor());
607         pc.setTarget(tb);
608         
609         testTestBeanIntroduction(pc);
610     }
611     
612     public void testMixinWithIntroductionInfo() throws Throwable JavaDoc {
613         TestBean tb = new TestBean();
614         ProxyFactory pc = new ProxyFactory(new Class JavaDoc[] { ITestBean.class });
615         // We don't use an IntroductionAdvisor, we can just add an advice that implements IntroductionInfo
616
pc.addAdvice(new LockMixin());
617         pc.setTarget(tb);
618     
619         testTestBeanIntroduction(pc);
620     }
621     
622     private void testTestBeanIntroduction(ProxyFactory pc) {
623         int newAge = 65;
624         ITestBean itb = (ITestBean) createProxy(pc);
625         itb.setAge(newAge);
626         assertTrue(itb.getAge() == newAge);
627
628         Lockable lockable = (Lockable) itb;
629         assertFalse(lockable.locked());
630         lockable.lock();
631         
632         assertTrue(itb.getAge() == newAge);
633         try {
634             itb.setAge(1);
635             fail("Setters should fail when locked");
636         }
637         catch (LockedException ex) {
638             // ok
639
}
640         assertTrue(itb.getAge() == newAge);
641         
642         // Unlock
643
assertTrue(lockable.locked());
644         lockable.unlock();
645         itb.setAge(1);
646         assertTrue(itb.getAge() == 1);
647     }
648     
649     
650     public void testReplaceArgument() throws Throwable JavaDoc {
651         TestBean tb = new TestBean();
652         ProxyFactory pc = new ProxyFactory(new Class JavaDoc[] { ITestBean.class });
653         pc.setTarget(tb);
654         pc.addAdvisor(new StringSetterNullReplacementAdvice());
655     
656         ITestBean t = (ITestBean) pc.getProxy();
657         int newAge = 5;
658         t.setAge(newAge);
659         assertTrue(t.getAge() == newAge);
660         String JavaDoc newName = "greg";
661         t.setName(newName);
662         assertEquals(newName, t.getName());
663         
664         t.setName(null);
665         // Null replacement magic should work
666
assertTrue(t.getName().equals(""));
667     }
668     
669     public void testCanCastProxyToProxyConfig() throws Throwable JavaDoc {
670         TestBean tb = new TestBean();
671         ProxyFactory pc = new ProxyFactory(tb);
672         NopInterceptor di = new NopInterceptor();
673         pc.addAdvice(0, di);
674
675         ITestBean t = (ITestBean) createProxy(pc);
676         assertEquals(0, di.getCount());
677         t.setAge(23);
678         assertEquals(23, t.getAge());
679         assertEquals(2, di.getCount());
680         
681         Advised advised = (Advised) t;
682         assertEquals("Have 1 advisor", 1, advised.getAdvisors().length);
683         assertEquals(di, advised.getAdvisors()[0].getAdvice());
684         NopInterceptor di2 = new NopInterceptor();
685         advised.addAdvice(1, di2);
686         t.getName();
687         assertEquals(3, di.getCount());
688         assertEquals(1, di2.getCount());
689         // will remove di
690
advised.removeAdvisor(0);
691         t.getAge();
692         // Unchanged
693
assertEquals(3, di.getCount());
694         assertEquals(2, di2.getCount());
695         
696         CountingBeforeAdvice cba = new CountingBeforeAdvice();
697         assertEquals(0, cba.getCalls());
698         advised.addAdvice(cba);
699         t.setAge(16);
700         assertEquals(16, t.getAge());
701         assertEquals(2, cba.getCalls());
702     }
703         
704     public void testAdviceImplementsIntroductionInfo() throws Throwable JavaDoc {
705         TestBean tb = new TestBean();
706         String JavaDoc name = "tony";
707         tb.setName(name);
708         ProxyFactory pc = new ProxyFactory(tb);
709         NopInterceptor di = new NopInterceptor();
710         pc.addAdvice(di);
711         final long ts = 37;
712         pc.addAdvice(new DelegatingIntroductionInterceptor(new TimeStamped() {
713             public long getTimeStamp() {
714                 return ts;
715             }
716         }));
717         
718         ITestBean proxied = (ITestBean) createProxy(pc);
719         assertEquals(name, proxied.getName());
720         TimeStamped intro = (TimeStamped) proxied;
721         assertEquals(ts, intro.getTimeStamp());
722     }
723
724     public void testCannotAddDynamicIntroductionAdviceExceptInIntroductionAdvice() throws Throwable JavaDoc {
725         TestBean target = new TestBean();
726         target.setAge(21);
727         ProxyFactory pc = new ProxyFactory(target);
728         try {
729             pc.addAdvice(new DummyIntroductionAdviceImpl());
730             fail("Shouldn't be able to add introduction interceptor except via introduction advice");
731         }
732         catch (AopConfigException ex) {
733             assertTrue(ex.getMessage().indexOf("ntroduction") > -1);
734         }
735         // Check it still works: proxy factory state shouldn't have been corrupted
736
ITestBean proxied = (ITestBean) createProxy(pc);
737         assertEquals(target.getAge(), proxied.getAge());
738     }
739     
740     public void