KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > system > AbstractContainer


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE.txt file.
7  */

8 package org.apache.avalon.excalibur.system;
9
10 import org.apache.avalon.framework.activity.*;
11 import org.apache.avalon.framework.component.*;
12 import org.apache.avalon.framework.configuration.*;
13 import org.apache.avalon.framework.context.*;
14 import org.apache.avalon.framework.logger.*;
15
16 import org.apache.avalon.excalibur.collections.FixedSizeBuffer;
17 import org.apache.avalon.excalibur.command.*;
18 import org.apache.avalon.excalibur.system.handler.*;
19 import org.apache.avalon.excalibur.logger.LoggerManager;
20 import org.apache.avalon.excalibur.event.Queue;
21 import org.apache.avalon.excalibur.pool.PoolManager;
22 import org.apache.avalon.excalibur.util.ComponentStateValidator;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30
31 import java.lang.reflect.Constructor JavaDoc;
32
33 /**
34  * The Container is an interface used to mark the Containers in your system. It
35  * exposes a protected getComponentManager() method so that the Container's
36  * Manager can expose that to the instantiating class.
37  *
38  * @author <a HREF="mailto:bloritsch@apache.org">Berin Loritsch</a>
39  * @version CVS $Revision: 1.4 $ $Date: 2002/01/30 15:44:06 $
40  */

41 public abstract class AbstractContainer
42    extends AbstractLogEnabled
43    implements Contextualizable, Composable, Configurable, Initializable, Disposable
44 {
45     private final ComponentStateValidator m_validator = new ComponentStateValidator( this );
46
47     private Context m_context;
48     private ComponentManager m_manager;
49     private ComponentManager m_childManager;
50     private LoggerManager m_logManager;
51     private PoolManager m_poolManager;
52     private Queue m_commandQueue;
53     private ClassLoader JavaDoc m_classLoader;
54     private RoleManager m_roleManager;
55     private Configuration m_configuration;
56     private List JavaDoc m_components;
57     private Map JavaDoc m_configs;
58
59     /**
60      * Wrap this so that ComponentStateValidator functions properly.
61      */

62     public void enableLogging( Logger logger )
63     {
64         m_validator.checkLogEnabled();
65         super.enableLogging( logger );
66     }
67
68     /**
69      * Pull the manager items from the context so we can use them to set up the
70      * system.
71      */

72     public void contextualize( Context containerContext )
73         throws ContextException
74     {
75         m_validator.checkContextualized();
76
77         m_context = containerContext;
78
79         m_logManager = (LoggerManager) m_context.get(Container.LOGGER_MANAGER);
80         m_poolManager = (PoolManager) m_context.get(Container.POOL_MANAGER);
81
82         try
83         {
84             m_classLoader = (ClassLoader JavaDoc) m_context.get(Container.CONTEXT_CLASSLOADER);
85         }
86         catch ( ContextException ce )
87         {
88             m_classLoader = Thread.currentThread().getContextClassLoader();
89         }
90
91         try
92         {
93             m_commandQueue = (Queue) m_context.get(Container.COMMAND_QUEUE);
94         }
95         catch ( ContextException ce )
96         {
97             m_commandQueue = null;
98             getLogger().warn("No Container.COMMAND_QUEUE is given, all management will be performed synchronously");
99         }
100
101         try
102         {
103             m_roleManager = (RoleManager) m_context.get(Container.ROLE_MANAGER);
104         }
105         catch ( ContextException ce )
106         {
107             m_roleManager = new ExcaliburRoleManager();
108         }
109     }
110
111     /**
112      * Process the configuration and set up the components and their mappings.
113      * At this point, all components are prepared and all mappings are made.
114      * However, nothing is initialized.
115      */

116     public void configure( Configuration configElement )
117         throws ConfigurationException
118     {
119         m_validator.checkConfigured();
120         m_configuration = configElement;
121         Map JavaDoc managerMap = new HashMap JavaDoc();
122         m_childManager = new ContainerComponentManager( managerMap, m_manager );
123
124         Configuration[] components = configElement.getChildren();
125
126         for ( int i = 0; i < components.length; i++ )
127         {
128             final String JavaDoc name = components[ i ].getName();
129             String JavaDoc role;
130             Class JavaDoc klass;
131             Class JavaDoc handlerKlass;
132             Configuration config = null;
133
134             if ( name.equals( "component" ) )
135             {
136                 config = components[ i ];
137                 role = config.getAttribute( "role" );
138
139                 try
140                 {
141                     klass = m_classLoader.loadClass( config.getAttribute( "class" ) );
142                     handlerKlass = m_classLoader.loadClass( config.getAttribute( "handler" ) );
143                 }
144                 catch ( Exception JavaDoc e )
145                 {
146                     if ( getLogger().isDebugEnabled() )
147                     {
148                         getLogger().debug( "Component class '" + config.getAttribute( "class" ) +
149                                            "' is not valid.", e );
150                     }
151                     continue;
152                 }
153
154                 assignHandler( getHandler( handlerKlass, klass, config ), config, managerMap );
155             }
156             else
157             {
158                 handleConfiguration( components[ i ], managerMap );
159             }
160         }
161     }
162
163     /**
164      * Handles when a configuration name is used that is not "component", so it
165      * makes it easier to handle ComponentSelector hierarchies. It is meant to
166      * either return a ComponentHandler or a ComponentSelector
167      */

168     protected void handleConfiguration( final Configuration configItem,
169                                         final Map JavaDoc managerMap )
170         throws ConfigurationException
171     {
172         DefaultConfiguration temp = new DefaultConfiguration( "component", "AbstractContainer-rewrite" );
173         Class JavaDoc klass = m_roleManager.getClassForName( configItem.getName() );
174         Class JavaDoc handlerKlass = m_roleManager.getHandlerClassForClass( klass );
175         String JavaDoc role = m_roleManager.getRoleForClass( klass );
176
177         temp.setAttribute( "role", role );
178         temp.setAttribute( "class", klass.getName() );
179         temp.setAttribute( "handler", handlerKlass.getName() );
180
181         final String JavaDoc id = configItem.getAttribute( "id", null );
182         if ( null != id )
183         {
184             temp.setAttribute( "id", id );
185         }
186
187         Configuration[] children = configItem.getChildren();
188         for ( int i = 0; i < children.length; i++ )
189         {
190             temp.addChild( children[ i ] );
191         }
192
193         temp.makeReadOnly();
194
195         assignHandler( getHandler( klass, handlerKlass, temp ), temp, managerMap );
196     }
197
198     /**
199      * Adds the ComponentHandler and Configuration to the system.
200      */

201     protected void assignHandler( ComponentHandler handler, Configuration config, Map JavaDoc managerMap )
202         throws ConfigurationException
203     {
204         m_components.add( handler );
205         m_configs.put( handler, config );
206         String JavaDoc role = config.getAttribute( "role" );
207
208         Object JavaDoc contents = managerMap.get( role );
209         if ( null == contents )
210         {
211             managerMap.put( role, handler );
212         }
213         else
214         {
215             if ( contents instanceof ComponentHandler )
216             {
217                 Map JavaDoc selectorMap = new HashMap JavaDoc( 3 );
218                 selectorMap.put( ( (Configuration) m_configs.get(contents) )
219                                  .getAttribute( "id", "1" ), contents );
220                 selectorMap.put( config.getAttribute( "id", "2" ), contents );
221
222                 assignSelector( role, new ContainerComponentSelector( selectorMap ), managerMap );
223             }
224             else if ( contents instanceof ContainerComponentSelector )
225             {
226                 ( (ContainerComponentSelector) contents )
227                     .addComponentHandler( config.getAttribute( "id", null ),
228                                           handler);
229             }
230         }
231     }
232
233     /**
234      * Adds the ComponentHandler and Configuration to the system.
235      */

236     protected void assignSelector( String JavaDoc role, ComponentSelector selector, Map JavaDoc managerMap )
237         throws ConfigurationException
238     {
239         managerMap.put( role, selector );
240     }
241
242     /**
243      * Get a ComponentHandler with the standard <code>HANDLER_CONSTRUCTOR</code>
244      * for the component class passed in.
245      */

246     protected ComponentHandler getHandler( Class JavaDoc handlerKlass,
247                                            Class JavaDoc klass,
248                                            Configuration configuration )
249     {
250         Constructor JavaDoc constructor;
251         ComponentHandler handler = null;
252
253         try
254         {
255             constructor = handlerKlass.getConstructor( ComponentHandler.HANDLER_CONSTRUCTOR );
256             handler = (ComponentHandler) constructor.newInstance(new Object JavaDoc[] {
257                 klass, configuration, m_childManager, m_context
258             });
259         }
260         catch ( Exception JavaDoc e )
261         {
262             if ( getLogger().isDebugEnabled() )
263             {
264                 getLogger().debug( "Could not create the '" + handlerKlass.getName() +
265                                    "' handler for the '" + klass.getName() +
266                                    "' component.", e );
267             }
268         }
269
270         return handler;
271     }
272
273     /**
274      * Root ComponentManager. The Container may choose to have it's ComponentManager
275      * delegate to the root manager, or it may choose to be entirely self contained.
276      */

277     public void compose( ComponentManager manager )
278         throws ComponentException
279     {
280         m_validator.checkComposed();
281         m_manager = manager;
282     }
283
284     /**
285      * Initializes all components so that the system is ready to be used.
286      */

287     public void initialize()
288         throws Exception JavaDoc
289     {
290         m_validator.checkInitialized();
291
292         Iterator JavaDoc i = m_components.iterator();
293         FixedSizeBuffer buffer = new FixedSizeBuffer( m_components.size() );
294
295         while ( i.hasNext() )
296         {
297             try
298             {
299                 if ( null != m_commandQueue )
300                 {
301                     m_commandQueue.enqueue(
302                         new InitComponentHandlerCommand( (ComponentHandler) i.next(),
303                                                          getLogger() )
304                     );
305                 }
306                 else
307                 {
308                     ( (ComponentHandler) i.next() ).initialize();
309                 }
310             }
311             catch ( Exception JavaDoc e )
312             {
313                 getLogger().warn( "Could not initialize component", e );
314                 buffer.add( e );
315             }
316         }
317
318         if ( buffer.size() > 0 )
319         {
320             StringBuffer JavaDoc message = new StringBuffer JavaDoc();
321
322             while ( ! buffer.isEmpty() )
323             {
324                 message.append( ( (Exception JavaDoc) buffer.remove() ).getMessage() );
325             }
326
327             throw new Exception JavaDoc( message.toString() );
328         }
329     }
330
331     /**
332      * Disposes of all components and frees resources that they consume.
333      */

334     public void dispose()
335     {
336         m_validator.checkDisposed();
337
338         Iterator JavaDoc i = m_components.iterator();
339
340         while ( i.hasNext() )
341         {
342             if ( null != m_commandQueue )
343             {
344                 try
345                 {
346                     m_commandQueue.enqueue(
347                         new DisposeComponentHandlerCommand( (ComponentHandler) i.next(),
348                                                             getLogger() )
349                     );
350
351                     i.remove();
352                 }
353                 catch ( Exception JavaDoc e )
354                 {
355                     if ( getLogger().isWarnEnabled() )
356                     {
357                         getLogger().warn( "Could not dispose component", e );
358                     }
359                 }
360             }
361             else
362             {
363                 ( (ComponentHandler) i.next() ).dispose();
364             }
365         }
366     }
367
368     /**
369      * This is the Default ComponentManager for the Container. It provides
370      * a very simple abstraction, and makes it easy for the Container to manage
371      * the references.
372      */

373     protected final static class ContainerComponentManager
374         implements ComponentManager
375     {
376         private final Map JavaDoc m_components;
377         private final Map JavaDoc m_used;
378         private final ComponentManager m_parent;
379
380         /**
381          * This constructor is for a ContainerComponentManager with no parent
382          * ComponentManager
383          */

384         protected ContainerComponentManager( Map JavaDoc componentMap )
385         {
386             this( componentMap, null );
387         }
388
389         /**
390          * This constructor is for a ContainerComponentManager with a parent
391          * ComponentManager
392          */

393         protected ContainerComponentManager( Map JavaDoc componentMap, ComponentManager parent )
394         {
395             m_parent = null;
396             m_components = componentMap;
397             m_used = new HashMap JavaDoc( m_components.size() );
398         }
399
400         public Component lookup( String JavaDoc role )
401             throws ComponentException
402         {
403             Object JavaDoc temp = m_components.get( role );
404
405             if ( temp instanceof ComponentSelector )
406             {
407                 return (ComponentSelector) temp;
408             }
409
410             if ( ! ( temp instanceof ComponentHandler ) )
411             {
412                 throw new ComponentException( "Invalid entry in component manager: " + temp );
413             }
414
415             ComponentHandler handler = (ComponentHandler) temp;
416
417             if ( null == handler )
418             {
419                 if ( null != m_parent )
420                 {
421                     return m_parent.lookup( role );
422                 }
423                 else
424                 {
425                     throw new ComponentException( "The role does not exist in the ComponentManager" );
426                 }
427             }
428
429             final Component component;
430
431             try
432             {
433                 if ( ! handler.isInitialized() )
434                 {
435                     handler.initialize();
436                 }
437
438                 component = handler.get();
439             }
440             catch ( Exception JavaDoc e )
441             {
442                 throw new ComponentException( "Could not return a reference to the Component", e );
443             }
444
445             synchronized ( m_used )
446             {
447                 m_used.put( component, handler );
448             }
449
450             return component;
451         }
452
453         public boolean hasComponent( String JavaDoc role )
454         {
455             final boolean hasComponent = m_components.containsKey( role );
456
457             if ( ! hasComponent && null != m_parent )
458             {
459                 return m_parent.hasComponent( role );
460             }
461
462             return hasComponent;
463         }
464
465         public void release( Component component )
466         {
467             final ComponentHandler handler;
468
469             synchronized ( m_used )
470             {
471                 handler = (ComponentHandler) m_used.remove( component );
472             }
473
474             if ( null == handler && null != m_parent )
475             {
476                 m_parent.release( component );
477                 return;
478             }
479
480             handler.put( component );
481         }
482     }
483
484     /**
485      * This is the Default ComponentSelector for the Container. It provides
486      * a very simple abstraction, and makes it easy for the Container to manage
487      * the references.
488      */

489     protected final static class ContainerComponentSelector
490         implements ComponentSelector
491     {
492         private final Map JavaDoc m_components;
493         private final Map JavaDoc m_used;
494
495         protected ContainerComponentSelector( Map JavaDoc selectorMap )
496         {
497             m_components = selectorMap;
498             m_used = new HashMap JavaDoc( m_components.size() );
499         }
500
501         public Component select( Object JavaDoc hint )
502             throws ComponentException
503         {
504             ComponentHandler handler = (ComponentHandler) m_components.get( hint );
505
506             if ( null == handler )
507             {
508                 throw new ComponentException( "The role does not exist in the ComponentSelector" );
509             }
510
511             final Component component;
512
513             try
514             {
515                 if ( ! handler.isInitialized() )
516                 {
517                     handler.initialize();
518                 }
519
520                 component = handler.get();
521             }
522             catch ( Exception JavaDoc e )
523             {
524                 throw new ComponentException( "Could not return a reference to the Component", e );
525             }
526
527             synchronized ( m_used )
528             {
529                 m_used.put( component, handler );
530             }
531
532             return component;
533         }
534
535         public boolean hasComponent( Object JavaDoc hint )
536         {
537             return m_components.containsKey( hint );
538         }
539
540         public void release( Component component )
541         {
542             final ComponentHandler handler;
543
544             synchronized ( m_used )
545             {
546                 handler = (ComponentHandler) m_used.remove( component );
547             }
548
549             handler.put( component );
550         }
551
552         protected void addComponentHandler( Object JavaDoc hint, ComponentHandler handler )
553         {
554             if ( null == hint )
555             {
556                 hint = new Integer JavaDoc( m_components.size() ).toString();
557             }
558
559             m_components.put( hint, handler );
560         }
561     }
562
563     /**
564      * This is the command class to initialize a ComponentHandler
565      */

566     private final static class InitComponentHandlerCommand implements Command
567     {
568         private final ComponentHandler m_handler;
569         private final Logger m_logger;
570
571         protected InitComponentHandlerCommand( ComponentHandler handler, Logger logger )
572         {
573             m_handler = handler;
574             m_logger = logger;
575         }
576
577         public void execute()
578             throws Exception JavaDoc
579         {
580             try
581             {
582                 if ( ! m_handler.isInitialized() )
583                 {
584                     m_handler.initialize();
585                 }
586             }
587             catch ( Exception JavaDoc e )
588             {
589                 if ( m_logger.isErrorEnabled() )
590                 {
591                     m_logger.error( "Could not initialize ComponentHandler", e );
592                 }
593
594                 throw e;
595             }
596         }
597     }
598
599     /**
600      * This is the command class to dispose a ComponentHandler
601      */

602     private final static class DisposeComponentHandlerCommand implements Command
603     {
604         private final ComponentHandler m_handler;
605         private final Logger m_logger;
606
607         protected DisposeComponentHandlerCommand( ComponentHandler handler, Logger logger )
608         {
609             m_handler = handler;
610             m_logger = logger;
611         }
612
613         public void execute()
614         {
615             m_handler.dispose();
616         }
617     }
618 }
619
620
Popular Tags