KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > component > test > ExcaliburComponentManagerTestCase


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

17 package org.apache.avalon.excalibur.component.test;
18
19 import junit.framework.TestCase;
20 import junit.framework.TestSuite;
21
22 import org.apache.avalon.excalibur.component.DefaultComponentPool;
23 import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
24 import org.apache.avalon.excalibur.pool.Poolable;
25 import org.apache.avalon.framework.activity.Disposable;
26 import org.apache.avalon.framework.component.Component;
27 import org.apache.avalon.framework.component.ComponentException;
28 import org.apache.avalon.framework.component.ComponentManager;
29 import org.apache.avalon.framework.component.Composable;
30 import org.apache.avalon.framework.configuration.Configuration;
31 import org.apache.avalon.framework.configuration.DefaultConfiguration;
32 import org.apache.avalon.framework.context.DefaultContext;
33 import org.apache.avalon.framework.logger.AbstractLogEnabled;
34 import org.apache.avalon.framework.logger.LogKitLogger;
35 import org.apache.avalon.framework.logger.Logger;
36 import org.apache.avalon.framework.thread.SingleThreaded;
37 import org.apache.avalon.framework.thread.ThreadSafe;
38 import org.apache.avalon.excalibur.testcase.ComponentStateValidator;
39 import org.apache.log.Hierarchy;
40 import org.apache.log.LogTarget;
41 import org.apache.log.Priority;
42 import org.apache.log.format.PatternFormatter;
43 import org.apache.log.output.io.StreamTarget;
44
45 /**
46  * This class is for testing the ExcaliburComponentManager to verify that
47  * it is correctly handling component lifestyle management.
48  *
49  * @deprecated ECM is no longer supported
50  *
51  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
52  * @version $Revision: 1.5 $
53  */

54 public class ExcaliburComponentManagerTestCase extends TestCase
55 {
56     /**
57      * Here we create a suite lots of tests to test the interactions of
58      * various types of components. Basically there are three Roles
59      * involved: Mom, Dad, and Kid. Each of the three Roles can be
60      * implemented by a SingleThreaded, ThreadSafe, or Poolable component.
61      * The Mom and Dad components both are Composable, and they use the
62      * ComponentLocator that they are provided with to obtain references
63      * to a Kid component. The Mom and Dad components may be "Good" (they
64      * properly release their Kid) or "Bad" (they don't release their Kid).
65      *
66      * Each of the tests sets up a different combo of these component
67      * implementations and checks to make sure that everything gets disposed,
68      * and that Kids never get disposed before parents are done using them.
69      *
70      * @return a <code>TestSuite</code>
71      */

72     public static TestSuite suite()
73     {
74         TestSuite suite = new TestSuite();
75
76         String JavaDoc[] behaviors = {"Bad", "Good"};
77         String JavaDoc[] kidTypes = {""}; // , "BadCircular", "GoodCircular" };
78
String JavaDoc[] lifestyles = {"SingleThreaded", "ThreadSafe", "Poolable"};
79
80         for( int mb = 0; mb < behaviors.length; mb++ )
81         {
82             for( int db = 0; db < behaviors.length; db++ )
83             {
84                 for( int kt = 0; kt < kidTypes.length; kt++ )
85                 {
86                     for( int ml = 0; ml < lifestyles.length; ml++ )
87                     {
88                         for( int dl = 0; dl < lifestyles.length; dl++ )
89                         {
90                             for( int kl = 0; kl < lifestyles.length; kl++ )
91                             {
92                                 final String JavaDoc momClassName =
93                                     lifestyles[ ml ] + behaviors[ mb ] + "Mom";
94                                 final String JavaDoc dadClassName =
95                                     lifestyles[ dl ] + behaviors[ db ] + "Dad";
96                                 final String JavaDoc kidClassName =
97                                     lifestyles[ kl ] + kidTypes[ kt ] + "Kid";
98
99                                 final String JavaDoc prefix =
100                                     ExcaliburComponentManagerTestCase.class.getName() + "$";
101
102                                 suite.addTest
103                                     ( new ExcaliburComponentManagerTestCase( momClassName +
104                                                                              dadClassName +
105                                                                              kidClassName )
106                                     {
107                                         public void runTest() throws Exception JavaDoc
108                                         {
109                                             managerLifecycle( Class.forName
110                                                               ( prefix + momClassName ),
111                                                               Class.forName
112                                                               ( prefix + dadClassName ),
113                                                               Class.forName
114                                                               ( prefix + kidClassName ) );
115                                         }
116                                     }
117                                     );
118                             }
119                         }
120                     }
121                 }
122             }
123         }
124
125         return suite;
126     }
127
128     protected void managerLifecycle( Class JavaDoc momClass, Class JavaDoc dadClass, Class JavaDoc kidClass )
129         throws Exception JavaDoc
130     {
131         Configuration emptyConfig = new DefaultConfiguration( "", "" );
132
133         m_manager.addComponent( Mom.ROLE, momClass, emptyConfig );
134         m_manager.addComponent( Dad.ROLE, dadClass, emptyConfig );
135         m_manager.addComponent( Kid.ROLE, kidClass, emptyConfig );
136
137         m_manager.initialize();
138
139         Component mom = m_manager.lookup( Mom.ROLE );
140         Component dad = m_manager.lookup( Dad.ROLE );
141
142         m_manager.release( mom );
143         m_manager.release( dad );
144
145         m_manager.dispose();
146
147         // Auto disposal for badly behaved components aren't guaranteed.
148
// This done to fix: http://marc.theaimsgroup.com/?t=106779872700001&r=1&w=2
149
if( momClass.getName().indexOf( "Good" ) > -1 &&
150             dadClass.getName().indexOf( "Good" ) > -1 )
151         {
152             checkNumberOfDisposals( momClass, dadClass, kidClass );
153         }
154     }
155
156     private void checkNumberOfDisposals( Class JavaDoc momClass, Class JavaDoc dadClass, Class JavaDoc kidClass )
157     {
158         int momInstances = 1, dadInstances = 1;
159
160         int kidInstances = determineNumberOfKidInstances( kidClass, momInstances, dadInstances );
161
162         int expectedDisposals = momInstances + dadInstances + kidInstances;
163
164         assertEquals( expectedDisposals, m_disposals );
165     }
166
167     private int determineNumberOfKidInstances( Class JavaDoc kidClass, int momInstances, int dadInstances )
168     {
169         int parentInstances = ( momInstances + dadInstances );
170
171         if( ThreadSafe.class.isAssignableFrom( kidClass ) )
172         {
173             // parents share reference to same kid instance
174
return 1;
175         }
176         else if( Poolable.class.isAssignableFrom( kidClass ) )
177         {
178             int poolGrowParameter = DefaultComponentPool.DEFAULT_POOL_SIZE / 4;
179
180             int extraKidsNeeded = parentInstances % poolGrowParameter;
181
182             if( extraKidsNeeded > 0 )
183             {
184                 // kid pool will grow to feed parents
185
return parentInstances + ( poolGrowParameter - extraKidsNeeded );
186             }
187         }
188
189         // each parent has a single kid reference
190
return parentInstances;
191     }
192
193     /* ======================================================================== *
194      * Test Components. *
195      * ======================================================================== */

196
197     public static abstract class AbstractBadParent extends AbstractLogEnabled
198         implements Component, Composable, Disposable
199     {
200         private final ComponentStateValidator m_validator = new ComponentStateValidator( this );
201
202         protected ComponentManager m_innerManager;
203         protected Kid m_kid;
204
205         public void enableLogging( Logger logger )
206         {
207             m_validator.checkLogEnabled();
208
209             super.enableLogging( logger );
210         }
211
212         public void compose( ComponentManager manager ) throws ComponentException
213         {
214             m_validator.checkComposed();
215
216             m_innerManager = manager;
217
218             m_kid = (Kid)m_innerManager.lookup( Kid.ROLE );
219         }
220
221         public void dispose()
222         {
223             m_validator.checkDisposed();
224
225             try
226             {
227                 m_kid.getName();
228             }
229             catch( IllegalStateException JavaDoc ise )
230             {
231                 fail( ise.getMessage() );
232             }
233
234             m_disposals++;
235         }
236     }
237
238     public static abstract class AbstractGoodParent extends AbstractBadParent
239     {
240         public void dispose()
241         {
242             super.dispose();
243             m_innerManager.release( m_kid );
244         }
245     }
246
247     public interface Mom extends Component
248     {
249         String JavaDoc ROLE = "Mom";
250     }
251
252     public static class SingleThreadedBadMom extends AbstractBadParent
253         implements Mom, SingleThreaded
254     {
255     }
256     public static class SingleThreadedGoodMom extends AbstractGoodParent
257         implements Mom, SingleThreaded
258     {
259     }
260     public static class ThreadSafeBadMom extends AbstractBadParent
261         implements Mom, ThreadSafe
262     {
263     }
264     public static class ThreadSafeGoodMom extends AbstractGoodParent
265         implements Mom, ThreadSafe
266     {
267     }
268     public static class PoolableBadMom extends AbstractBadParent
269         implements Mom, Poolable
270     {
271     }
272     public static class PoolableGoodMom extends AbstractGoodParent
273         implements Mom, Poolable
274     {
275     }
276
277     public interface Dad extends Component
278     {
279         String JavaDoc ROLE = "Dad";
280     }
281
282     public static class SingleThreadedBadDad extends AbstractBadParent
283         implements Dad, SingleThreaded
284     {
285     }
286     public static class SingleThreadedGoodDad extends AbstractGoodParent
287         implements Dad, SingleThreaded
288     {
289     }
290     public static class ThreadSafeBadDad extends AbstractBadParent
291         implements Dad, ThreadSafe
292     {
293     }
294     public static class ThreadSafeGoodDad extends AbstractGoodParent
295         implements Dad, ThreadSafe
296     {
297     }
298     public static class PoolableBadDad extends AbstractBadParent
299         implements Dad, Poolable
300     {
301     }
302     public static class PoolableGoodDad extends AbstractGoodParent
303         implements Dad, Poolable
304     {
305     }
306
307     public interface Kid extends Component
308     {
309         String JavaDoc ROLE = "Kid";
310
311         String JavaDoc getName();
312     }
313
314     public static abstract class AbstractKid extends AbstractLogEnabled
315         implements Kid, Disposable
316     {
317         public static final String JavaDoc ROLE = "Kid";
318
319         protected final ComponentStateValidator m_validator = new ComponentStateValidator( this );
320
321         public void enableLogging( Logger logger )
322         {
323             m_validator.checkLogEnabled();
324
325             super.enableLogging( logger );
326         }
327
328         public void dispose()
329         {
330             m_validator.checkDisposed();
331
332             m_disposals++;
333         }
334
335         public String JavaDoc getName()
336         {
337             m_validator.checkActive();
338
339             return "Kid";
340         }
341     }
342
343     public static class SingleThreadedKid extends AbstractKid
344         implements SingleThreaded
345     {
346     }
347     public static class ThreadSafeKid extends AbstractKid
348         implements ThreadSafe
349     {
350     }
351     public static class PoolableKid extends AbstractKid
352         implements Poolable
353     {
354     }
355
356     public static abstract class AbstractBadCircularKid extends AbstractKid
357         implements Composable
358     {
359         protected ComponentManager m_innerManager;
360         protected Mom m_mom;
361         protected Dad m_dad;
362
363         public void compose( ComponentManager manager ) throws ComponentException
364         {
365             m_validator.checkComposed();
366
367             m_innerManager = manager;
368         }
369
370         public String JavaDoc getName()
371         {
372             String JavaDoc name = super.getName();
373
374             try
375             {
376                 m_mom = (Mom)m_innerManager.lookup( Mom.ROLE );
377                 m_dad = (Dad)m_innerManager.lookup( Dad.ROLE );
378             }
379             catch( ComponentException ce )
380             {
381                 fail( ce.getMessage() );
382             }
383
384             return ( name + " belongs to " + m_mom + " and " + m_dad );
385         }
386     }
387
388     public static abstract class AbstractGoodCircularKid extends AbstractBadCircularKid
389     {
390         public void dispose()
391         {
392             super.dispose();
393
394             m_innerManager.release( m_mom );
395             m_innerManager.release( m_dad );
396         }
397     }
398
399     public static class SingleThreadedBadCircularKid extends AbstractBadCircularKid
400         implements SingleThreaded
401     {
402     }
403     public static class ThreadSafeBadCircularKid extends AbstractBadCircularKid
404         implements ThreadSafe
405     {
406     }
407     public static class PoolableBadCircularKid extends AbstractBadCircularKid
408         implements Poolable
409     {
410     }
411     public static class SingleThreadedGoodCircularKid extends AbstractGoodCircularKid
412         implements SingleThreaded
413     {
414     }
415     public static class ThreadSafeGoodCircularKid extends AbstractGoodCircularKid
416         implements ThreadSafe
417     {
418     }
419     public static class PoolableGoodCircularKid extends AbstractGoodCircularKid
420         implements Poolable
421     {
422     }
423
424     /* ======================================================================== *
425      * Housekeeping. *
426      * ======================================================================== */

427
428     private static int m_disposals;
429
430     private ExcaliburComponentManager m_manager;
431
432     private Logger m_logger;
433
434     public ExcaliburComponentManagerTestCase( String JavaDoc name )
435     {
436         super( name );
437     }
438
439     public void setUp() throws Exception JavaDoc
440     {
441         m_disposals = 0;
442
443         m_manager = new ExcaliburComponentManager();
444
445         final String JavaDoc pattern =
446             ( "%5.5{priority} [%40.40{category}]: %{message}\n%{throwable}" );
447
448         org.apache.log.Logger logger = Hierarchy.getDefaultHierarchy().getLoggerFor( getName() );
449         logger.setLogTargets
450             ( new LogTarget[]
451             {new StreamTarget( System.out, new PatternFormatter( pattern ) )} );
452         logger.setPriority( Priority.INFO );
453
454         m_manager.enableLogging( new LogKitLogger( logger ) );
455         m_manager.contextualize( new DefaultContext() );
456         m_manager.configure( new DefaultConfiguration( "", "" ) );
457
458         m_logger = new LogKitLogger( logger );
459     }
460
461     public void tearDown()
462     {
463         m_manager = null;
464     }
465
466 }
467
Popular Tags