View Javadoc
1   package org.codehaus.plexus;
2   
3   /*
4    * Copyright 2001-2006 Codehaus Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import static org.codehaus.plexus.PlexusConstants.PLEXUS_DEFAULT_HINT;
20  import static org.codehaus.plexus.component.CastUtils.cast;
21  
22  import java.io.FileInputStream;
23  import java.io.FileNotFoundException;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.Reader;
27  import java.util.ArrayList;
28  import java.util.List;
29  import java.util.Map;
30  
31  import org.codehaus.plexus.classworlds.ClassWorld;
32  import org.codehaus.plexus.classworlds.realm.ClassRealm;
33  import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
34  import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
35  import org.codehaus.plexus.component.composition.CycleDetectedInComponentGraphException;
36  import org.codehaus.plexus.component.discovery.ComponentDiscoverer;
37  import org.codehaus.plexus.component.discovery.ComponentDiscovererManager;
38  import org.codehaus.plexus.component.discovery.ComponentDiscoveryEvent;
39  import org.codehaus.plexus.component.discovery.ComponentDiscoveryListener;
40  import org.codehaus.plexus.component.factory.ComponentFactoryManager;
41  import org.codehaus.plexus.component.repository.ComponentDescriptor;
42  import org.codehaus.plexus.component.repository.ComponentSetDescriptor;
43  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
44  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
45  import org.codehaus.plexus.component.repository.io.PlexusTools;
46  import org.codehaus.plexus.configuration.PlexusConfiguration;
47  import org.codehaus.plexus.configuration.PlexusConfigurationException;
48  import org.codehaus.plexus.configuration.PlexusConfigurationMerger;
49  import org.codehaus.plexus.configuration.source.ConfigurationSource;
50  import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
51  import org.codehaus.plexus.container.initialization.ContainerInitializationContext;
52  import org.codehaus.plexus.container.initialization.ContainerInitializationPhase;
53  import org.codehaus.plexus.context.Context;
54  import org.codehaus.plexus.context.ContextException;
55  import org.codehaus.plexus.context.ContextMapAdapter;
56  import org.codehaus.plexus.context.DefaultContext;
57  import org.codehaus.plexus.logging.AbstractLogEnabled;
58  import org.codehaus.plexus.logging.Logger;
59  import org.codehaus.plexus.logging.LoggerManager;
60  import org.codehaus.plexus.util.IOUtil;
61  import org.codehaus.plexus.util.InterpolationFilterReader;
62  import org.codehaus.plexus.util.ReaderFactory;
63  
64  /**
65   * Default implementation of PlexusContainer and MutablePlexusContainer.
66   * @author Jason van Zyl
67   * @author Kenney Westerhof
68   */
69  public class DefaultPlexusContainer
70      extends AbstractLogEnabled
71      implements MutablePlexusContainer
72  {
73      protected static final String DEFAULT_CONTAINER_NAME = "default";
74  
75      protected static final String DEFAULT_REALM_NAME = "plexus.core";
76  
77      /**
78       * Arbitrary data associated with the container.  Data in the container has highest precedence when configuring
79       * a component to create.
80       */
81      protected Context containerContext;
82  
83      protected PlexusConfiguration configuration;
84  
85      // todo: don't use a reader
86      protected Reader configurationReader;
87  
88      protected ClassWorld classWorld;
89  
90      protected ClassRealm containerRealm;
91  
92      // ----------------------------------------------------------------------------
93      // Core components
94      // ----------------------------------------------------------------------------
95  
96      private ComponentRegistry componentRegistry;
97  
98      /**
99       * Simple index (registry) of ComponentDiscovers and ComponentDiscoveryListener.
100      */
101     protected ComponentDiscovererManager componentDiscovererManager;
102 
103     /**
104      * Trivial class to look-up ComponentFactory instances in this container.
105      */
106     protected ComponentFactoryManager componentFactoryManager;
107 
108     /**
109      * Generic logger interface.
110      */
111     protected LoggerManager loggerManager;
112 
113     /**
114      * Converts a ComponentDescriptor into PlexusConfiguration.
115      */
116     protected ConfigurationSource configurationSource;
117 
118     // ----------------------------------------------------------------------------
119     //
120     // ----------------------------------------------------------------------------
121 
122     // TODO: Is there a more threadpool-friendly way to do this?
123     private ThreadLocal<ClassRealm> lookupRealm = new ThreadLocal<ClassRealm>();
124 
125     public void addComponent( Object component, String role )
126     {
127         addComponent( component, role, PLEXUS_DEFAULT_HINT );
128     }
129 
130     public <T> void addComponent( T component, Class<?> role, String roleHint ) 
131     {
132         addComponent( component, role.getName(), roleHint );
133     }
134 
135     public void addComponent( Object component, String role, String roleHint )
136     {
137         if ( roleHint == null )
138         {
139             roleHint = PLEXUS_DEFAULT_HINT;
140         }
141 
142         getComponentRegistry().addComponent( component, role, roleHint );
143     }
144 
145     public ClassRealm setLookupRealm( ClassRealm realm )
146     {
147         ClassRealm oldRealm = lookupRealm.get();
148 
149         lookupRealm.set( realm );
150 
151         return oldRealm;
152     }
153 
154     public ClassRealm getLookupRealm()
155     {
156         return lookupRealm.get();
157     }
158 
159     // ----------------------------------------------------------------------
160     // Constructors
161     // ----------------------------------------------------------------------
162 
163     public DefaultPlexusContainer()
164         throws PlexusContainerException
165     {
166         construct( new DefaultContainerConfiguration() );
167     }
168 
169     public DefaultPlexusContainer( ContainerConfiguration c )
170         throws PlexusContainerException
171     {
172         construct( c );
173     }
174 
175     public ClassRealm createChildRealm( String id )
176     {
177         try
178         {
179             return containerRealm.createChildRealm( id );
180         }
181         catch ( DuplicateRealmException e )
182         {
183             try
184             {
185                 return classWorld.getRealm( id );
186             }
187             catch ( NoSuchRealmException e1 )
188             {
189                 return null;
190             }
191         }
192     }
193 
194     private void construct( ContainerConfiguration c )
195         throws PlexusContainerException
196     {
197         configurationSource = c.getConfigurationSource();
198 
199         // ----------------------------------------------------------------------------
200         // ClassWorld
201         // ----------------------------------------------------------------------------
202 
203         classWorld = c.getClassWorld();
204 
205         // Make sure we have a valid ClassWorld
206         if ( classWorld == null )
207         {
208             classWorld = new ClassWorld( DEFAULT_REALM_NAME, Thread.currentThread().getContextClassLoader() );
209         }
210 
211         containerRealm = c.getRealm();
212 
213         if ( containerRealm == null )
214         {
215             try
216             {
217                 containerRealm = classWorld.getRealm( DEFAULT_REALM_NAME );
218             }
219             catch ( NoSuchRealmException e )
220             {
221                 containerRealm = (ClassRealm) classWorld.getRealms().iterator().next();
222 
223                 if ( containerRealm == null )
224                 {
225                     System.err.println( "No container realm! Expect errors." );
226 
227                     new Throwable().printStackTrace();
228                 }
229             }
230         }
231 
232         setLookupRealm( containerRealm );
233 
234         // ----------------------------------------------------------------------------
235         // Context
236         // ----------------------------------------------------------------------------
237 
238         if ( c.getContext() != null )
239         {
240             containerContext = new DefaultContext( c.getContext() );            
241         }
242         else
243         {                
244             containerContext = new DefaultContext();
245         }
246 
247         // ----------------------------------------------------------------------------
248         // Configuration
249         // ----------------------------------------------------------------------------
250 
251         InputStream in = null;
252 
253         if ( c.getContainerConfiguration() != null )
254         {
255             in = toStream( c.getContainerConfiguration() );
256         }
257 
258         try
259         {
260             if ( c.getContainerConfigurationURL() != null )
261             {
262                 in = c.getContainerConfigurationURL().openStream();
263             }
264         }
265         catch ( IOException e )
266         {
267             throw new PlexusContainerException( "Error reading configuration URL", e );
268         }
269 
270         try
271         {
272             configurationReader = in == null ? null : ReaderFactory.newXmlReader( in );
273         }
274         catch ( IOException e )
275         {
276             throw new PlexusContainerException( "Error reading configuration file", e );
277         }
278 
279         try
280         {
281             initialize( c );
282 
283             start();
284         }
285         finally
286         {
287             IOUtil.close( configurationReader );
288         }
289         
290         for( Class clazz : c.getComponentDiscoverers() )
291         {
292             try
293             {
294                 ComponentDiscoverer cd = (ComponentDiscoverer) lookup( clazz );
295                 componentDiscovererManager.addComponentDiscoverer( cd );
296             }
297             catch ( ComponentLookupException e )
298             {
299             }
300         }
301         
302         for( Class clazz : c.getComponentDiscoveryListeners() )
303         {
304             try
305             {
306                 ComponentDiscoveryListener cdl = (ComponentDiscoveryListener) lookup( clazz );
307                 componentDiscovererManager.registerComponentDiscoveryListener( cdl );
308             }
309             catch ( ComponentLookupException e )
310             {
311             }
312         }                
313     }
314 
315     // ----------------------------------------------------------------------------
316     // Lookup
317     // ----------------------------------------------------------------------------
318 
319     private Class<?> getInterfaceClass( String role, String hint )
320     {
321         ComponentDescriptor<?> cd;
322 
323         if ( hint == null )
324         {
325             cd = getComponentDescriptor( role );
326         }
327         else
328         {
329             cd = getComponentDescriptor( role, hint );
330         }
331         
332         if ( cd != null )
333         {                        
334             try
335             {
336                 ClassRealm realm = getLookupRealm();
337 
338                 if ( realm != null )
339                 {
340                     return realm.loadClass( role );
341                 }
342                 else
343                 {                    
344                     ClassLoader loader = cd.getImplementationClass().getClassLoader();
345 
346                     if ( loader != null )
347                     {
348                         return loader.loadClass( role );
349                     }
350                 }
351             }
352             catch ( ClassNotFoundException e )
353             {
354                 return Object.class;
355             }                        
356         }
357 
358         return Object.class;
359     }
360     
361     private Class<?> getRoleClass( String role )
362     {
363         return getInterfaceClass( role, null );        
364     }
365 
366     private Class<?> getRoleClass( String role, String hint )
367     {
368         return getInterfaceClass( role, hint );
369     }
370 
371     public Object lookup( String role ) throws ComponentLookupException
372     {
373         return componentRegistry.lookup( getRoleClass( role ), role, "" );
374     }
375 
376     public Object lookup( String role, String roleHint ) throws ComponentLookupException
377     {
378         return componentRegistry.lookup( getRoleClass( role, roleHint ), role, roleHint );
379     }
380 
381     public <T> T lookup( Class<T> type ) throws ComponentLookupException
382     {
383         return componentRegistry.lookup( type, type.getName(), "" );
384     }
385 
386     public <T> T lookup( Class<T> type, String roleHint ) throws ComponentLookupException
387     {
388         return componentRegistry.lookup( type, type.getName(), roleHint );
389     }
390 
391     public <T> T lookup( Class<T> type, String role, String roleHint ) throws ComponentLookupException
392     {
393         return componentRegistry.lookup( type, role, roleHint );
394     }
395 
396     public <T> T lookup( ComponentDescriptor<T> componentDescriptor )
397         throws ComponentLookupException
398     {
399         return componentRegistry.lookup( componentDescriptor );
400     }
401 
402     public List<Object> lookupList( String role ) throws ComponentLookupException
403     {
404         return cast(componentRegistry.lookupList( getRoleClass( role ), role, null));
405     }
406 
407     public List<Object> lookupList( String role, List<String> roleHints ) throws ComponentLookupException
408     {
409         return cast(componentRegistry.lookupList( getRoleClass( role ), role, roleHints ));
410     }
411 
412     public <T> List<T> lookupList( Class<T> type ) throws ComponentLookupException
413     {
414         return componentRegistry.lookupList( type, type.getName(), null );
415     }
416 
417     public <T> List<T> lookupList( Class<T> type, List<String> roleHints ) throws ComponentLookupException
418     {
419         return componentRegistry.lookupList( type, type.getName(), roleHints );
420     }
421 
422     public Map<String, Object> lookupMap( String role ) throws ComponentLookupException
423     {
424         return cast(componentRegistry.lookupMap(  getRoleClass( role ), role, null ));
425     }
426 
427     public Map<String, Object> lookupMap( String role, List<String> roleHints ) throws ComponentLookupException
428     {
429         return cast(componentRegistry.lookupMap( getRoleClass( role ), role, roleHints ));
430     }
431 
432     public <T> Map<String, T> lookupMap( Class<T> type ) throws ComponentLookupException
433     {
434         return componentRegistry.lookupMap( type, type.getName(), null );
435     }
436 
437     public <T> Map<String, T> lookupMap( Class<T> type, List<String> roleHints ) throws ComponentLookupException
438     {
439         return componentRegistry.lookupMap( type, type.getName(), roleHints );
440     }
441 
442     // ----------------------------------------------------------------------
443     // Component Descriptor Lookup
444     // ----------------------------------------------------------------------
445 
446     public boolean hasComponent( String role )
447     {
448         return componentRegistry.getComponentDescriptor( Object.class, role, "" ) != null;
449     }
450 
451     public boolean hasComponent( String role, String roleHint )
452     {
453         return componentRegistry.getComponentDescriptor( Object.class, role, roleHint ) != null;
454     }
455 
456     public boolean hasComponent( Class<?> type )
457     {
458         return componentRegistry.getComponentDescriptor( type, type.getName(), "" ) != null;
459     }
460 
461     public boolean hasComponent( Class<?> type, String roleHint )
462     {
463         return componentRegistry.getComponentDescriptor( type, type.getName(), roleHint ) != null;
464     }
465 
466     public boolean hasComponent( Class<?> type, String role, String roleHint )
467     {
468         return componentRegistry.getComponentDescriptor( type, role, roleHint ) != null;
469     }
470 
471     public ComponentDescriptor<?> getComponentDescriptor( String role )
472     {
473         return componentRegistry.getComponentDescriptor( Object.class, role, "" );
474     }
475 
476     public ComponentDescriptor<?> getComponentDescriptor( String role, String roleHint )
477     {
478         return componentRegistry.getComponentDescriptor( Object.class, role, roleHint );
479     }
480 
481     public <T> ComponentDescriptor<T> getComponentDescriptor( Class<T> type, String role, String roleHint )
482     {
483         return componentRegistry.getComponentDescriptor( type, role, roleHint );
484     }
485 
486     public Map<String, ComponentDescriptor<?>> getComponentDescriptorMap( String role )
487     {
488         return cast(componentRegistry.getComponentDescriptorMap( Object.class, role ));
489     }
490 
491     public <T> Map<String, ComponentDescriptor<T>> getComponentDescriptorMap( Class<T> type, String role )
492     {
493         return componentRegistry.getComponentDescriptorMap( type, role );
494     }
495 
496     public List<ComponentDescriptor<?>> getComponentDescriptorList( String role )
497     {
498         return cast(componentRegistry.getComponentDescriptorList( Object.class, role ));
499     }
500 
501     public <T> List<ComponentDescriptor<T>> getComponentDescriptorList( Class<T> type, String role )
502     {
503         return componentRegistry.getComponentDescriptorList( type, role );
504     }
505 
506     public void addComponentDescriptor( ComponentDescriptor<?> componentDescriptor ) 
507         throws CycleDetectedInComponentGraphException
508     {
509         if ( componentDescriptor.getRealm() == null )
510         {
511             componentDescriptor.setRealm( this.containerRealm );
512             // throw new ComponentImplementationNotFoundException( "ComponentDescriptor is missing realmId" );
513         }
514         componentRegistry.addComponentDescriptor( componentDescriptor );
515     }
516 
517     // ----------------------------------------------------------------------
518     // Component Release
519     // ----------------------------------------------------------------------
520 
521     public void release( Object component )
522         throws ComponentLifecycleException
523     {
524         componentRegistry.release( component );
525     }
526 
527     public void releaseAll( Map<String, ?> components )
528         throws ComponentLifecycleException
529     {
530         for ( Object component : components.values() )
531         {
532             release( component );
533         }
534     }
535 
536     public void releaseAll( List<?> components )
537         throws ComponentLifecycleException
538     {
539         for ( Object component : components )
540         {
541             release( component );
542         }
543     }
544 
545     // ----------------------------------------------------------------------
546     // Lifecycle Management
547     // ----------------------------------------------------------------------
548 
549     protected void initialize( ContainerConfiguration containerConfiguration )
550         throws PlexusContainerException
551     {
552         try
553         {
554             initializeConfiguration( containerConfiguration );
555 
556             initializePhases( containerConfiguration );
557             
558             containerContext.put( PlexusConstants.PLEXUS_KEY, this );
559             
560             discoverComponents( getContainerRealm() );   
561             
562             PlexusConfiguration[] loadOnStartComponents = getConfiguration().getChild( "load-on-start" ).getChildren( "component" );
563 
564             getLogger().debug( "Found " + loadOnStartComponents.length + " components to load on start" );
565 
566             ClassLoader prevCl = Thread.currentThread().getContextClassLoader();
567 
568             try
569             {
570                 for ( PlexusConfiguration loadOnStartComponent : loadOnStartComponents )
571                 {
572                     String role = loadOnStartComponent.getChild( "role" ).getValue( null );
573 
574                     String roleHint = loadOnStartComponent.getChild( "role-hint" ).getValue( null );
575 
576                     if ( role == null )
577                     {
578                         throw new PlexusContainerException( "Missing 'role' element from load-on-start." );
579                     }
580 
581                     if ( roleHint == null )
582                     {
583                         roleHint = PlexusConstants.PLEXUS_DEFAULT_HINT;
584                     }
585 
586                     if ( roleHint.equals( "*" ) )
587                     {
588                         getLogger().info( "Loading on start all components with [role]: " + "[" + role + "]" );
589 
590                         lookupList( role );
591                     }
592                     else
593                     {
594                         getLogger().info( "Loading on start [role,roleHint]: " + "[" + role + "," + roleHint + "]" );
595 
596                         lookup( role, roleHint );
597                     }
598                 }
599             }
600             catch ( ComponentLookupException e )
601             {
602                 throw new PlexusContainerException( "Error looking up load-on-start component.", e );
603             }
604             finally
605             {
606                 Thread.currentThread().setContextClassLoader( prevCl );
607             }
608             
609         }
610         catch ( ContextException e )
611         {
612             throw new PlexusContainerException( "Error processing configuration", e );
613         }
614         catch ( PlexusConfigurationException e )
615         {
616             throw new PlexusContainerException( "Error configuring components", e );
617         }
618         catch ( IOException e )
619         {
620             throw new PlexusContainerException( "Error reading configuration file", e );
621         }
622         catch ( CycleDetectedInComponentGraphException e )
623         {
624             throw new PlexusContainerException( "Cycle detected in component graph in the system: ", e );
625         }        
626     }
627 
628     protected void initializePhases( ContainerConfiguration containerConfiguration )
629         throws PlexusContainerException
630     {
631         ContainerInitializationPhase[] initPhases = containerConfiguration.getInitializationPhases();
632 
633         ContainerInitializationContext initializationContext = new ContainerInitializationContext(
634             this,
635             classWorld,
636             containerRealm,
637             configuration,
638             containerConfiguration );
639 
640         for ( ContainerInitializationPhase phase : initPhases )
641         {
642             try
643             {
644                 phase.execute( initializationContext );
645             }
646             catch ( Exception e )
647             {
648                 throw new PlexusContainerException( "Error initializaing container in " + phase.getClass().getName()
649                     + ".", e );
650             }
651         }
652     }
653 
654     protected void start()
655         throws PlexusContainerException
656     {
657         // XXX this is called after initializeConfiguration - is this correct?
658         configuration = null;
659     }
660 
661     public void dispose()
662     {
663         try
664         {
665             componentRegistry.dispose();
666 
667             boolean needToDisposeRealm = false;
668 
669             try
670             {
671                 containerRealm.setParentRealm( null );
672 
673                 if ( needToDisposeRealm )
674                 {
675                     classWorld.disposeRealm( containerRealm.getId() );
676                 }
677             }
678             catch ( NoSuchRealmException e )
679             {
680                 getLogger().debug( "Failed to dispose realm." );
681             }
682         }
683         finally
684         {
685             lookupRealm.set( null );
686         }
687     }
688 
689     public void addContextValue( Object key, Object value )
690     {
691         containerContext.put( key, value );
692     }
693 
694     // ----------------------------------------------------------------------
695     // Misc Configuration
696     // ----------------------------------------------------------------------
697 
698     public ClassWorld getClassWorld()
699     {
700         return classWorld;
701     }
702 
703     public void setClassWorld( ClassWorld classWorld )
704     {
705         this.classWorld = classWorld;
706     }
707 
708     public ClassRealm getContainerRealm()
709     {
710         return containerRealm;
711     }
712 
713     public void setContainerRealm( ClassRealm containerRealm )
714     {
715         this.containerRealm = containerRealm;
716     }
717 
718     // ----------------------------------------------------------------------
719     // Context
720     // ----------------------------------------------------------------------
721 
722     public Context getContext()
723     {
724         return containerContext;
725     }
726 
727     // ----------------------------------------------------------------------
728     // Configuration
729     // ----------------------------------------------------------------------
730 
731     // TODO: put this in a separate helper class and turn into a component if possible, too big.
732 
733     protected void initializeConfiguration( ContainerConfiguration c )
734     throws PlexusConfigurationException, ContextException, IOException
735 {
736     // We need an empty plexus configuration for merging. This is a function of removing the
737     // plexus-boostrap.xml file.
738     configuration = new XmlPlexusConfiguration( "plexus" );
739 
740     if ( configurationReader != null )
741     {
742         // User userConfiguration
743 
744         PlexusConfiguration userConfiguration = PlexusTools.buildConfiguration( "<User Specified Configuration Reader>", getInterpolationConfigurationReader( configurationReader ) );
745 
746         // Merger of bootstrapConfiguration and user userConfiguration
747 
748         configuration = PlexusConfigurationMerger.merge( userConfiguration, configuration );
749     }
750 }
751 
752     protected Reader getInterpolationConfigurationReader( Reader reader )
753     {
754         return new InterpolationFilterReader( reader, new ContextMapAdapter( containerContext ) );
755     }
756 
757     public Logger getLogger()
758     {
759         return super.getLogger();
760     }
761 
762     // ----------------------------------------------------------------------
763     // Discovery
764     // ----------------------------------------------------------------------
765 
766     public void registerComponentDiscoveryListener( ComponentDiscoveryListener listener )
767     {
768         componentDiscovererManager.registerComponentDiscoveryListener( listener );
769     }
770 
771     public void removeComponentDiscoveryListener( ComponentDiscoveryListener listener )
772     {
773         componentDiscovererManager.removeComponentDiscoveryListener( listener );
774     }
775 
776     // ----------------------------------------------------------------------------
777     // Mutable Container Interface
778     // ----------------------------------------------------------------------------
779 
780     public ComponentRegistry getComponentRegistry()
781     {
782         return componentRegistry;
783     }
784 
785     public void setComponentRegistry( ComponentRegistry componentRegistry )
786     {
787         this.componentRegistry = componentRegistry;
788     }
789 
790     public ComponentDiscovererManager getComponentDiscovererManager()
791     {
792         return componentDiscovererManager;
793     }
794 
795     public void setComponentDiscovererManager( ComponentDiscovererManager componentDiscovererManager )
796     {
797         this.componentDiscovererManager = componentDiscovererManager;
798     }
799 
800     public ComponentFactoryManager getComponentFactoryManager()
801     {
802         return componentFactoryManager;
803     }
804 
805     public void setComponentFactoryManager( ComponentFactoryManager componentFactoryManager )
806     {
807         this.componentFactoryManager = componentFactoryManager;
808     }
809 
810     // Configuration
811 
812     public PlexusConfiguration getConfiguration()
813     {
814         return configuration;
815     }
816 
817     public void setConfiguration( PlexusConfiguration configuration )
818     {
819         this.configuration = configuration;
820     }
821 
822     // ----------------------------------------------------------------------------
823     // Component Realms
824     // ----------------------------------------------------------------------------
825 
826     public ClassRealm getComponentRealm( String realmId )
827     {
828         ClassRealm realm = null;
829 
830         try
831         {
832             realm = classWorld.getRealm( realmId );
833         }
834         catch ( NoSuchRealmException e )
835         {
836             // This should never happen: when a component is discovered, it is discovered from a realm and
837             // it is at that point the realm id is assigned to the component descriptor.
838         }
839 
840         if ( realm == null )
841         {
842             // The core components need the container realm.
843             realm = containerRealm;
844         }
845 
846         return realm;
847     }
848 
849     public void removeComponentRealm( ClassRealm realm )
850         throws PlexusContainerException
851     {
852         if ( getContainerRealm().getId().equals( realm.getId() ) )
853         {
854             throw new IllegalArgumentException( "Cannot remove container realm: " + realm.getId()
855                 + "\n(trying to remove container realm as if it were a component realm)." );
856         }
857 
858         componentRegistry.removeComponentRealm( realm );
859 
860         ClassRealm lookupRealm = getLookupRealm();
861         if ( ( lookupRealm != null ) && lookupRealm.getId().equals( realm.getId() ) )
862         {
863             setLookupRealm( getContainerRealm() );
864         }
865     }
866 
867     private InputStream toStream( String resource )
868         throws PlexusContainerException
869     {
870         if ( resource == null )
871         {
872             return null;
873         }
874 
875         String relativeResource = resource;
876         if ( resource.startsWith( "/" ) )
877         {
878             relativeResource = resource.substring( 1 );
879         }
880 
881         InputStream is = getClass().getClassLoader().getResourceAsStream( relativeResource );
882 
883         if ( is == null )
884         {
885             try
886             {
887                 return new FileInputStream( resource );
888             }
889             catch ( FileNotFoundException e )
890             {
891                 return null;
892             }
893         }
894 
895         return is;
896     }
897 
898     /**
899      * Utility method to get a default lookup realm for a component.
900      */
901     public ClassRealm getLookupRealm( Object component )
902     {
903         if ( component.getClass().getClassLoader() instanceof ClassRealm )
904         {
905             return ( (ClassRealm) component.getClass().getClassLoader() );
906         }
907         else
908         {
909             return getLookupRealm();
910         }
911 
912     }
913 
914     public void setConfigurationSource( ConfigurationSource configurationSource )
915     {
916         this.configurationSource = configurationSource;
917     }
918 
919     public ConfigurationSource getConfigurationSource()
920     {
921         return configurationSource;
922     }
923 
924     public LoggerManager getLoggerManager()
925     {
926         // TODO Auto-generated method stub
927         return loggerManager;
928     }
929 
930     public void setLoggerManager( LoggerManager loggerManager )
931     {
932         this.loggerManager = loggerManager;
933 
934     }
935     
936     // Discovery
937 
938     public List<ComponentDescriptor<?>> discoverComponents( ClassRealm realm )
939         throws PlexusConfigurationException, CycleDetectedInComponentGraphException
940     {
941         return discoverComponents( realm, null );
942     }    
943     
944     public List<ComponentDescriptor<?>> discoverComponents( ClassRealm realm, Object data )            
945         throws PlexusConfigurationException, CycleDetectedInComponentGraphException
946     {
947         List<ComponentSetDescriptor> componentSetDescriptors = new ArrayList<ComponentSetDescriptor>();
948 
949         List<ComponentDescriptor<?>> discoveredComponentDescriptors = new ArrayList<ComponentDescriptor<?>>();
950 
951         for ( ComponentDiscoverer componentDiscoverer : getComponentDiscovererManager().getComponentDiscoverers() )
952         {
953             for ( ComponentSetDescriptor componentSetDescriptor : componentDiscoverer.findComponents( getContext(), realm ) )
954             {
955                 // Here we should collect all the urls
956                 // do the interpolation against the context
957                 // register all the components
958                 // allow interception and replacement of the components
959 
960                 componentSetDescriptors.add( componentSetDescriptor );
961 
962                 // Fire the event
963                 ComponentDiscoveryEvent event = new ComponentDiscoveryEvent( componentSetDescriptor, data );
964 
965                 componentDiscovererManager.fireComponentDiscoveryEvent( event );
966 
967                 for ( ComponentDescriptor<?> componentDescriptor : componentSetDescriptor.getComponents() )
968                 {
969                     addComponentDescriptor( componentDescriptor );
970 
971                     discoveredComponentDescriptors.add( componentDescriptor );
972                 }
973             }
974         }
975 
976         return discoveredComponentDescriptors;
977     }
978 }