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