1 package org.codehaus.plexus;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
66
67
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
76
77
78 protected Context containerContext;
79
80 protected PlexusConfiguration configuration;
81
82
83 protected Reader configurationReader;
84
85 protected ClassWorld classWorld;
86
87 protected ClassRealm containerRealm;
88
89
90
91
92
93 private ComponentRegistry componentRegistry;
94
95
96
97
98 protected ComponentDiscovererManager componentDiscovererManager;
99
100
101
102
103 protected ComponentFactoryManager componentFactoryManager;
104
105
106
107
108 protected LoggerManager loggerManager;
109
110
111
112
113 protected ConfigurationSource configurationSource;
114
115
116
117
118
119
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
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
179
180
181 classWorld = c.getClassWorld();
182
183
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
209
210
211 if (c.getContext() != null) {
212 containerContext = new DefaultContext(c.getContext());
213 } else {
214 containerContext = new DefaultContext();
215 }
216
217
218
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
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
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
421 }
422 componentRegistry.addComponentDescriptor(componentDescriptor);
423 }
424
425
426
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
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
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
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
574
575
576 public Context getContext() {
577 return containerContext;
578 }
579
580
581
582
583
584
585
586 protected void initializeConfiguration(ContainerConfiguration c)
587 throws PlexusConfigurationException, ContextException, IOException {
588
589
590 configuration = new XmlPlexusConfiguration("plexus");
591
592 if (configurationReader != null) {
593
594
595 PlexusConfiguration userConfiguration = PlexusTools.buildConfiguration(
596 "<User Specified Configuration Reader>", getInterpolationConfigurationReader(configurationReader));
597
598
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
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
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
653
654 public PlexusConfiguration getConfiguration() {
655 return configuration;
656 }
657
658 public void setConfiguration(PlexusConfiguration configuration) {
659 this.configuration = configuration;
660 }
661
662
663
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
673
674 }
675
676 if (realm == null) {
677
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
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
742 return loggerManager;
743 }
744
745 public void setLoggerManager(LoggerManager loggerManager) {
746 this.loggerManager = loggerManager;
747 }
748
749
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
767
768
769
770
771 componentSetDescriptors.add(componentSetDescriptor);
772
773
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 }