KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > picocontainer > gems > adapters > PoolingComponentAdapterTest


1 /*
2  * Copyright (C) 2005 Jörg Schaible
3  * Created on 29.08.2005 by Jörg Schaible
4  */

5 package org.picocontainer.gems.adapters;
6
7 import com.thoughtworks.proxy.ProxyFactory;
8 import com.thoughtworks.proxy.factory.CglibProxyFactory;
9 import com.thoughtworks.proxy.toys.pool.Poolable;
10
11 import org.picocontainer.ComponentAdapter;
12 import org.picocontainer.LifecycleManager;
13 import org.picocontainer.MutablePicoContainer;
14 import org.picocontainer.defaults.ConstructorInjectionComponentAdapter;
15 import org.picocontainer.defaults.DefaultPicoContainer;
16 import org.picocontainer.tck.AbstractComponentAdapterTestCase;
17 import org.picocontainer.testmodel.RecordingLifecycle;
18 import org.picocontainer.testmodel.SimpleTouchable;
19 import org.picocontainer.testmodel.Touchable;
20
21 import java.io.Serializable JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Set JavaDoc;
25
26
27 /**
28  * @author Jörg Schaible
29  */

30 public class PoolingComponentAdapterTest extends AbstractComponentAdapterTestCase {
31
32     public static interface Identifiable {
33         int getId();
34     }
35
36     public static class InstanceCounter implements Identifiable, Serializable JavaDoc {
37         private static int counter = 0;
38         private int id;
39
40         public InstanceCounter() {
41             id = counter++;
42         }
43
44         public int getId() {
45             return id;
46         }
47
48         public boolean equals(Object JavaDoc arg) {
49             return arg instanceof Identifiable && id == ((Identifiable)arg).getId();
50         }
51     }
52
53     protected void setUp() throws Exception JavaDoc {
54         InstanceCounter.counter = 0;
55     }
56
57     public void testNewIsInstantiatedOnEachRequest() {
58         ComponentAdapter componentAdapter = new PoolingComponentAdapter(new ConstructorInjectionComponentAdapter(
59                 Identifiable.class, InstanceCounter.class));
60
61         Object JavaDoc borrowed0 = componentAdapter.getComponentInstance(null);
62         Object JavaDoc borrowed1 = componentAdapter.getComponentInstance(null);
63
64         assertNotSame(borrowed0, borrowed1);
65     }
66
67     public void testInstancesCanBeRecycled() {
68         ComponentAdapter componentAdapter = new PoolingComponentAdapter(new ConstructorInjectionComponentAdapter(
69                 Identifiable.class, InstanceCounter.class));
70
71         Object JavaDoc borrowed0 = componentAdapter.getComponentInstance(null);
72         Object JavaDoc borrowed1 = componentAdapter.getComponentInstance(null);
73         Object JavaDoc borrowed2 = componentAdapter.getComponentInstance(null);
74
75         assertNotSame(borrowed0, borrowed1);
76         assertNotSame(borrowed1, borrowed2);
77
78         borrowed1 = null;
79         System.gc();
80
81         Identifiable borrowed = (Identifiable)componentAdapter.getComponentInstance(null);
82         assertEquals(1, borrowed.getId());
83
84         ((Poolable)borrowed).returnInstanceToPool();
85
86         Object JavaDoc borrowedReloaded = componentAdapter.getComponentInstance(null);
87         assertEquals(borrowed, borrowedReloaded);
88     }
89
90     public void testBlocksWhenExhausted() throws InterruptedException JavaDoc {
91         final ComponentAdapter componentAdapter = new PoolingComponentAdapter(new ConstructorInjectionComponentAdapter(
92                 Identifiable.class, InstanceCounter.class), new PoolingComponentAdapter.DefaultContext() {
93             public int getMaxSize() {
94                 return 2;
95             }
96
97             public int getMaxWaitInMilliseconds() {
98                 return 3000;
99             }
100         });
101
102         final Identifiable[] borrowed = new Identifiable[3];
103         final Throwable JavaDoc[] threadException = new Throwable JavaDoc[2];
104
105         final StringBuffer JavaDoc order = new StringBuffer JavaDoc();
106         final Thread JavaDoc returner = new Thread JavaDoc() {
107             public void run() {
108                 try {
109                     synchronized (this) {
110                         notifyAll();
111                         wait(200); // ensure, that main thread is blocked
112
}
113                     order.append("returner ");
114                     ((Poolable)borrowed[0]).returnInstanceToPool();
115                 } catch (Throwable JavaDoc t) {
116                     t.printStackTrace();
117                     synchronized (componentAdapter) {
118                         componentAdapter.notify();
119                     }
120                     threadException[1] = t;
121                 }
122             }
123         };
124
125         borrowed[0] = (Identifiable)componentAdapter.getComponentInstance(null);
126         borrowed[1] = (Identifiable)componentAdapter.getComponentInstance(null);
127         synchronized (returner) {
128             returner.start();
129             returner.wait();
130         }
131
132         // should block
133
order.append("main ");
134         borrowed[2] = (Identifiable)componentAdapter.getComponentInstance(null);
135         order.append("main");
136
137         returner.join();
138
139         assertNull(threadException[0]);
140         assertNull(threadException[1]);
141
142         assertEquals("main returner main", order.toString());
143
144         assertEquals(borrowed[0].getId(), borrowed[2].getId());
145         assertFalse(borrowed[1].getId() == borrowed[2].getId());
146     }
147
148     public void testTimeoutWhenExhausted() {
149         final ComponentAdapter componentAdapter = new PoolingComponentAdapter(new ConstructorInjectionComponentAdapter(
150                 Identifiable.class, InstanceCounter.class), new PoolingComponentAdapter.DefaultContext() {
151             public int getMaxSize() {
152                 return 2;
153             }
154
155             public int getMaxWaitInMilliseconds() {
156                 return 250;
157             }
158         });
159
160         Identifiable borrowed0 = (Identifiable)componentAdapter.getComponentInstance(null);
161         Identifiable borrowed1 = (Identifiable)componentAdapter.getComponentInstance(null);
162         assertNotNull(borrowed0);
163         assertFalse(borrowed0.getId() == borrowed1.getId());
164         long time = System.currentTimeMillis();
165         try {
166             componentAdapter.getComponentInstance(null);
167             fail("Thrown " + PoolException.class.getName() + " expected");
168         } catch (final PoolException e) {
169             assertTrue(e.getMessage().indexOf("Time out") >= 0);
170             assertTrue(System.currentTimeMillis() - time >= 250);
171         }
172     }
173
174     public void testGrowsAlways() {
175         PoolingComponentAdapter componentAdapter = new PoolingComponentAdapter(
176                 new ConstructorInjectionComponentAdapter("foo", Object JavaDoc.class),
177                 new PoolingComponentAdapter.DefaultContext() {
178
179                     public ProxyFactory getProxyFactory() {
180                         return new CglibProxyFactory();
181                     }
182                 });
183
184         final Set JavaDoc set = new HashSet JavaDoc();
185         try {
186             final int max = 5;
187             int i;
188             for (i = 0; i < max; ++i) {
189                 assertEquals(i, componentAdapter.size());
190                 final Object JavaDoc object = componentAdapter.getComponentInstance(null);
191                 set.add(object);
192             }
193             assertEquals(i, componentAdapter.size());
194             assertEquals(i, set.size());
195
196             for (Iterator JavaDoc iter = set.iterator(); iter.hasNext();) {
197                 Poolable object = (Poolable)iter.next();
198                 object.returnInstanceToPool();
199                 assertEquals(max, componentAdapter.size());
200             }
201
202             for (i = 0; i < max; ++i) {
203                 assertEquals(max, componentAdapter.size());
204                 final Object JavaDoc object = componentAdapter.getComponentInstance(null);
205                 assertNotNull(object);
206                 set.add(object);
207             }
208
209             assertEquals(max, set.size());
210
211         } catch (PoolException e) {
212             fail("This pool should not get exhausted.");
213         }
214     }
215
216     public void testFailsWhenExhausted() {
217         final PoolingComponentAdapter componentAdapter = new PoolingComponentAdapter(
218                 new ConstructorInjectionComponentAdapter(Identifiable.class, InstanceCounter.class),
219                 new PoolingComponentAdapter.DefaultContext() {
220                     public int getMaxSize() {
221                         return 2;
222                     }
223                 });
224
225         assertEquals(0, componentAdapter.size());
226         Identifiable borrowed0 = (Identifiable)componentAdapter.getComponentInstance(null);
227         assertEquals(1, componentAdapter.size());
228         Identifiable borrowed1 = (Identifiable)componentAdapter.getComponentInstance(null);
229         assertEquals(2, componentAdapter.size());
230         try {
231             componentAdapter.getComponentInstance(null);
232             fail("Expected ExhaustedException, pool shouldn't be able to grow further.");
233         } catch (PoolException e) {
234             assertTrue(e.getMessage().indexOf("exhausted") >= 0);
235         }
236
237         assertFalse(borrowed0.getId() == borrowed1.getId());
238     }
239
240     public void testInternalGCCall() {
241         ComponentAdapter componentAdapter = new PoolingComponentAdapter(new ConstructorInjectionComponentAdapter(
242                 Identifiable.class, InstanceCounter.class), new PoolingComponentAdapter.DefaultContext() {
243             public int getMaxSize() {
244                 return 1;
245             }
246
247             public boolean autostartGC() {
248                 return true;
249             }
250         });
251
252         for (int i = 0; i < 5; i++) {
253             final Identifiable borrowed = (Identifiable)componentAdapter.getComponentInstance(null);
254             assertNotNull(borrowed);
255             assertEquals(0, borrowed.getId());
256         }
257     }
258
259     /**
260      * Prepare the test <em>lifecycleManagerSupport</em>. Prepare the delivered PicoContainer with an adapter, that
261      * has a lifecycle and use a StringBuffer registered in the container to record the lifecycle method invocations.
262      * The recorded String in the buffer must result in <strong>&qout;&lt;OneOne&gt;!One&qout;</strong>. The adapter
263      * top test should be registered in the container and delivered as return value.
264      * @param picoContainer the container
265      * @return the adapter to test
266      */

267     private ComponentAdapter prepDEF_lifecycleManagerSupport(MutablePicoContainer picoContainer) {
268         picoContainer.registerComponentImplementation(RecordingLifecycle.One.class);
269         return picoContainer.registerComponent(new PoolingComponentAdapter(new ConstructorInjectionComponentAdapter(
270                 RecordingLifecycle.Recorder.class, RecordingLifecycle.Two.class)));
271     }
272
273     public void testDEF_lifecycleManagerSupport() {
274         if ((getComponentAdapterNature() & RESOLVING) > 0) {
275             final Class JavaDoc type = getComponentAdapterType();
276             if (LifecycleManager.class.isAssignableFrom(type)) {
277                 final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
278                 final MutablePicoContainer picoContainer = new DefaultPicoContainer(
279                         createDefaultComponentAdapterFactory());
280                 picoContainer.registerComponentInstance(buffer);
281                 final ComponentAdapter componentAdapter = prepDEF_lifecycleManagerSupport(picoContainer);
282                 assertSame(getComponentAdapterType(), componentAdapter.getClass());
283                 assertEquals(0, buffer.length());
284                 picoContainer.start();
285                 picoContainer.stop();
286                 picoContainer.dispose();
287                 // @todo Move test to AbstractAbstractCATC
288
assertEquals("<OneOne>!One", buffer.toString());
289             }
290         }
291     }
292
293     /**
294      * Prepare the test <em>lifecycleManagerHonorsInstantiationSequence</em>. Prepare the delivered PicoContainer
295      * with adapter(s), that have dependend components, have a lifecycle and use a StringBuffer registered in the
296      * container to record the lifecycle method invocations. The recorded String in the buffer must result in
297      * <strong>&qout;&lt;One&lt;TwoTwo&gt;One&gt;!Two!One&qout;</strong>. The adapter top test should be registered in
298      * the container and delivered as return value.
299      * @param picoContainer the container
300      * @return the adapter to test
301      */

302     private ComponentAdapter prepRES_lifecycleManagerHonorsInstantiationSequence(MutablePicoContainer picoContainer) {
303         picoContainer.registerComponentImplementation(RecordingLifecycle.One.class);
304         return picoContainer.registerComponent(new PoolingComponentAdapter(new ConstructorInjectionComponentAdapter(
305                 RecordingLifecycle.Recorder.class, RecordingLifecycle.Two.class)));
306     }
307
308     public void testRES_lifecycleManagerHonorsInstantiationSequence() {
309         if ((getComponentAdapterNature() & RESOLVING) > 0) {
310             final Class JavaDoc type = getComponentAdapterType();
311             if (LifecycleManager.class.isAssignableFrom(type)) {
312                 final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
313                 final MutablePicoContainer picoContainer = new DefaultPicoContainer(
314                         createDefaultComponentAdapterFactory());
315                 picoContainer.registerComponentInstance(buffer);
316                 final ComponentAdapter componentAdapter = prepRES_lifecycleManagerHonorsInstantiationSequence(picoContainer);
317                 assertSame(getComponentAdapterType(), componentAdapter.getClass());
318                 assertEquals(0, buffer.length());
319                 picoContainer.start();
320                 picoContainer.stop();
321                 picoContainer.dispose();
322                 // @todo Move test to AbstractAbstractCATC
323
assertEquals("<One<TwoTwo>One>!Two!One", buffer.toString());
324             }
325         }
326     }
327
328     // -------- TCK -----------
329

330     protected Class JavaDoc getComponentAdapterType() {
331         return PoolingComponentAdapter.class;
332     }
333
334     protected int getComponentAdapterNature() {
335         return super.getComponentAdapterNature() & ~(INSTANTIATING | RESOLVING | VERIFYING);
336     }
337
338     private ComponentAdapter createPoolOfTouchables() {
339         return new PoolingComponentAdapter(new ConstructorInjectionComponentAdapter(
340                 Touchable.class, SimpleTouchable.class));
341     }
342
343     protected ComponentAdapter prepDEF_verifyWithoutDependencyWorks(MutablePicoContainer picoContainer) {
344         return createPoolOfTouchables();
345     }
346
347     protected ComponentAdapter prepDEF_verifyDoesNotInstantiate(MutablePicoContainer picoContainer) {
348         return createPoolOfTouchables();
349     }
350
351     protected ComponentAdapter prepDEF_visitable() {
352         return createPoolOfTouchables();
353     }
354
355     private ComponentAdapter createSerializable() {
356         return new PoolingComponentAdapter(new ConstructorInjectionComponentAdapter(
357                 Identifiable.class, InstanceCounter.class));
358     }
359
360     protected ComponentAdapter prepSER_isSerializable(MutablePicoContainer picoContainer) {
361         return createSerializable();
362     }
363
364     protected ComponentAdapter prepSER_isXStreamSerializable(MutablePicoContainer picoContainer) {
365         return createSerializable();
366     }
367
368 }
369
Popular Tags