001 /*****************************************************************************
002 * Copyright (C) PicoContainer Organization. All rights reserved. *
003 * ------------------------------------------------------------------------- *
004 * The software in this package is published under the terms of the BSD *
005 * style license a copy of which has been included with this distribution in *
006 * the LICENSE.txt file. *
007 * *
008 * Original code by *
009 *****************************************************************************/
010 package org.picocontainer.defaults;
011
012 import java.io.Serializable;
013 import java.util.ArrayList;
014 import java.util.Collection;
015 import java.util.Collections;
016 import java.util.HashMap;
017 import java.util.HashSet;
018 import java.util.Iterator;
019 import java.util.List;
020 import java.util.Map;
021 import java.util.Set;
022
023 import org.picocontainer.ComponentAdapter;
024 import org.picocontainer.ComponentMonitor;
025 import org.picocontainer.LifecycleManager;
026 import org.picocontainer.MutablePicoContainer;
027 import org.picocontainer.Parameter;
028 import org.picocontainer.PicoContainer;
029 import org.picocontainer.PicoException;
030 import org.picocontainer.PicoIntrospectionException;
031 import org.picocontainer.PicoVerificationException;
032 import org.picocontainer.PicoVisitor;
033 import org.picocontainer.monitors.DefaultComponentMonitor;
034
035 /**
036 * <p/>
037 * The Standard {@link PicoContainer}/{@link MutablePicoContainer} implementation.
038 * Constructing a container c with a parent p container will cause c to look up components
039 * in p if they cannot be found inside c itself.
040 * </p>
041 * <p/>
042 * Using {@link Class} objects as keys to the various registerXXX() methods makes
043 * a subtle semantic difference:
044 * </p>
045 * <p/>
046 * If there are more than one registered components of the same type and one of them are
047 * registered with a {@link java.lang.Class} key of the corresponding type, this component
048 * will take precedence over other components during type resolution.
049 * </p>
050 * <p/>
051 * Another place where keys that are classes make a subtle difference is in
052 * {@link org.picocontainer.defaults.ImplementationHidingComponentAdapter}.
053 * </p>
054 * <p/>
055 * This implementation of {@link MutablePicoContainer} also supports
056 * {@link ComponentMonitorStrategy}.
057 * </p>
058 *
059 * @author Paul Hammant
060 * @author Aslak Hellesøy
061 * @author Jon Tirsén
062 * @author Thomas Heller
063 * @author Mauro Talevi
064 * @version $Revision: 1.8 $
065 */
066 public class DefaultPicoContainer implements MutablePicoContainer, ComponentMonitorStrategy, Serializable {
067 private Map componentKeyToAdapterCache = new HashMap();
068 private ComponentAdapterFactory componentAdapterFactory;
069 private PicoContainer parent;
070 private Set children = new HashSet();
071
072 private List componentAdapters = new ArrayList();
073 // Keeps track of instantiation order.
074 private List orderedComponentAdapters = new ArrayList();
075
076 // Keeps track of the container started status
077 private boolean started = false;
078 // Keeps track of the container disposed status
079 private boolean disposed = false;
080 // Keeps track of child containers started status
081 private Set childrenStarted = new HashSet();
082
083 private LifecycleManager lifecycleManager = new OrderedComponentAdapterLifecycleManager();
084 private LifecycleStrategy lifecycleStrategyForInstanceRegistrations;
085
086 /**
087 * Creates a new container with a custom ComponentAdapterFactory and a parent container.
088 * <p/>
089 * <em>
090 * Important note about caching: If you intend the components to be cached, you should pass
091 * in a factory that creates {@link CachingComponentAdapter} instances, such as for example
092 * {@link CachingComponentAdapterFactory}. CachingComponentAdapterFactory can delegate to
093 * other ComponentAdapterFactories.
094 * </em>
095 *
096 * @param componentAdapterFactory the factory to use for creation of ComponentAdapters.
097 * @param parent the parent container (used for component dependency lookups).
098 */
099 public DefaultPicoContainer(ComponentAdapterFactory componentAdapterFactory, PicoContainer parent) {
100 this(componentAdapterFactory, new DefaultLifecycleStrategy(new DefaultComponentMonitor()), parent);
101 }
102
103 /**
104 * Creates a new container with a custom ComponentAdapterFactory, LifecycleStrategy for instance registration,
105 * and a parent container.
106 * <p/>
107 * <em>
108 * Important note about caching: If you intend the components to be cached, you should pass
109 * in a factory that creates {@link CachingComponentAdapter} instances, such as for example
110 * {@link CachingComponentAdapterFactory}. CachingComponentAdapterFactory can delegate to
111 * other ComponentAdapterFactories.
112 * </em>
113 *
114 * @param componentAdapterFactory the factory to use for creation of ComponentAdapters.
115 * @param lifecycleStrategyForInstanceRegistrations the lifecylce strategy chosen for regiered
116 * instance (not implementations!)
117 * @param parent the parent container (used for component dependency lookups).
118 */
119 public DefaultPicoContainer(ComponentAdapterFactory componentAdapterFactory,
120 LifecycleStrategy lifecycleStrategyForInstanceRegistrations,
121 PicoContainer parent) {
122 if (componentAdapterFactory == null) throw new NullPointerException("componentAdapterFactory");
123 if (lifecycleStrategyForInstanceRegistrations == null) throw new NullPointerException("lifecycleStrategyForInstanceRegistrations");
124 this.componentAdapterFactory = componentAdapterFactory;
125 this.lifecycleStrategyForInstanceRegistrations = lifecycleStrategyForInstanceRegistrations;
126 this.parent = parent == null ? null : ImmutablePicoContainerProxyFactory.newProxyInstance(parent);
127 }
128
129 /**
130 * Creates a new container with the DefaultComponentAdapterFactory using a
131 * custom ComponentMonitor
132 *
133 * @param monitor the ComponentMonitor to use
134 * @param parent the parent container (used for component dependency lookups).
135 */
136 public DefaultPicoContainer(ComponentMonitor monitor, PicoContainer parent) {
137 this(new DefaultComponentAdapterFactory(monitor), parent);
138 lifecycleStrategyForInstanceRegistrations = new DefaultLifecycleStrategy(monitor);
139 }
140
141 /**
142 * Creates a new container with the DefaultComponentAdapterFactory using a
143 * custom ComponentMonitor and lifecycle strategy
144 *
145 * @param monitor the ComponentMonitor to use
146 * @param lifecycleStrategy the lifecycle strategy to use.
147 * @param parent the parent container (used for component dependency lookups).
148 */
149 public DefaultPicoContainer(ComponentMonitor monitor, LifecycleStrategy lifecycleStrategy, PicoContainer parent) {
150 this(new DefaultComponentAdapterFactory(monitor, lifecycleStrategy), lifecycleStrategy, parent);
151 }
152
153 /**
154 * Creates a new container with the DefaultComponentAdapterFactory using a
155 * custom lifecycle strategy
156 *
157 * @param lifecycleStrategy the lifecycle strategy to use.
158 * @param parent the parent container (used for component dependency lookups).
159 */
160 public DefaultPicoContainer(LifecycleStrategy lifecycleStrategy, PicoContainer parent) {
161 this(new DefaultComponentMonitor(), lifecycleStrategy, parent);
162 }
163
164
165 /**
166 * Creates a new container with a custom ComponentAdapterFactory and no parent container.
167 *
168 * @param componentAdapterFactory the ComponentAdapterFactory to use.
169 */
170 public DefaultPicoContainer(ComponentAdapterFactory componentAdapterFactory) {
171 this(componentAdapterFactory, null);
172 }
173
174 /**
175 * Creates a new container with the DefaultComponentAdapterFactory using a
176 * custom ComponentMonitor
177 *
178 * @param monitor the ComponentMonitor to use
179 */
180 public DefaultPicoContainer(ComponentMonitor monitor) {
181 this(monitor, new DefaultLifecycleStrategy(monitor), null);
182 }
183
184 /**
185 * Creates a new container with a (caching) {@link DefaultComponentAdapterFactory}
186 * and a parent container.
187 *
188 * @param parent the parent container (used for component dependency lookups).
189 */
190 public DefaultPicoContainer(PicoContainer parent) {
191 this(new DefaultComponentAdapterFactory(), parent);
192 }
193
194 /**
195 * Creates a new container with a (caching) {@link DefaultComponentAdapterFactory} and no parent container.
196 */
197 public DefaultPicoContainer() {
198 this(new DefaultComponentAdapterFactory(), null);
199 }
200
201 public Collection getComponentAdapters() {
202 return Collections.unmodifiableList(componentAdapters);
203 }
204
205 public final ComponentAdapter getComponentAdapter(Object componentKey) {
206 ComponentAdapter adapter = (ComponentAdapter) componentKeyToAdapterCache.get(componentKey);
207 if (adapter == null && parent != null) {
208 adapter = parent.getComponentAdapter(componentKey);
209 }
210 return adapter;
211 }
212
213 public ComponentAdapter getComponentAdapterOfType(Class componentType) {
214 // See http://jira.codehaus.org/secure/ViewIssue.jspa?key=PICO-115
215 ComponentAdapter adapterByKey = getComponentAdapter(componentType);
216 if (adapterByKey != null) {
217 return adapterByKey;
218 }
219
220 List found = getComponentAdaptersOfType(componentType);
221
222 if (found.size() == 1) {
223 return ((ComponentAdapter) found.get(0));
224 } else if (found.size() == 0) {
225 if (parent != null) {
226 return parent.getComponentAdapterOfType(componentType);
227 } else {
228 return null;
229 }
230 } else {
231 Class[] foundClasses = new Class[found.size()];
232 for (int i = 0; i < foundClasses.length; i++) {
233 foundClasses[i] = ((ComponentAdapter) found.get(i)).getComponentImplementation();
234 }
235
236 throw new AmbiguousComponentResolutionException(componentType, foundClasses);
237 }
238 }
239
240 public List getComponentAdaptersOfType(Class componentType) {
241 if (componentType == null) {
242 return Collections.EMPTY_LIST;
243 }
244 List found = new ArrayList();
245 for (Iterator iterator = getComponentAdapters().iterator(); iterator.hasNext();) {
246 ComponentAdapter componentAdapter = (ComponentAdapter) iterator.next();
247
248 if (componentType.isAssignableFrom(componentAdapter.getComponentImplementation())) {
249 found.add(componentAdapter);
250 }
251 }
252 return found;
253 }
254
255 /**
256 * {@inheritDoc}
257 * This method can be used to override the ComponentAdapter created by the {@link ComponentAdapterFactory}
258 * passed to the constructor of this container.
259 */
260 public ComponentAdapter registerComponent(ComponentAdapter componentAdapter) {
261 Object componentKey = componentAdapter.getComponentKey();
262 if (componentKeyToAdapterCache.containsKey(componentKey)) {
263 throw new DuplicateComponentKeyRegistrationException(componentKey);
264 }
265 componentAdapters.add(componentAdapter);
266 componentKeyToAdapterCache.put(componentKey, componentAdapter);
267 return componentAdapter;
268 }
269
270 public ComponentAdapter unregisterComponent(Object componentKey) {
271 ComponentAdapter adapter = (ComponentAdapter) componentKeyToAdapterCache.remove(componentKey);
272 componentAdapters.remove(adapter);
273 orderedComponentAdapters.remove(adapter);
274 return adapter;
275 }
276
277 /**
278 * {@inheritDoc}
279 * The returned ComponentAdapter will be an {@link InstanceComponentAdapter}.
280 */
281 public ComponentAdapter registerComponentInstance(Object component) {
282 return registerComponentInstance(component.getClass(), component);
283 }
284
285 /**
286 * {@inheritDoc}
287 * The returned ComponentAdapter will be an {@link InstanceComponentAdapter}.
288 */
289 public ComponentAdapter registerComponentInstance(Object componentKey, Object componentInstance) {
290 ComponentAdapter componentAdapter = new InstanceComponentAdapter(componentKey, componentInstance, lifecycleStrategyForInstanceRegistrations);
291 return registerComponent(componentAdapter);
292 }
293
294 /**
295 * {@inheritDoc}
296 * The returned ComponentAdapter will be instantiated by the {@link ComponentAdapterFactory}
297 * passed to the container's constructor.
298 */
299 public ComponentAdapter registerComponentImplementation(Class componentImplementation) {
300 return registerComponentImplementation(componentImplementation, componentImplementation);
301 }
302
303 /**
304 * {@inheritDoc}
305 * The returned ComponentAdapter will be instantiated by the {@link ComponentAdapterFactory}
306 * passed to the container's constructor.
307 */
308 public ComponentAdapter registerComponentImplementation(Object componentKey, Class componentImplementation) {
309 return registerComponentImplementation(componentKey, componentImplementation, (Parameter[]) null);
310 }
311
312 /**
313 * {@inheritDoc}
314 * The returned ComponentAdapter will be instantiated by the {@link ComponentAdapterFactory}
315 * passed to the container's constructor.
316 */
317 public ComponentAdapter registerComponentImplementation(Object componentKey, Class componentImplementation, Parameter[] parameters) {
318 ComponentAdapter componentAdapter = componentAdapterFactory.createComponentAdapter(componentKey, componentImplementation, parameters);
319 return registerComponent(componentAdapter);
320 }
321
322 /**
323 * Same as {@link #registerComponentImplementation(java.lang.Object, java.lang.Class, org.picocontainer.Parameter[])}
324 * but with parameters as a {@link List}. Makes it possible to use with Groovy arrays (which are actually Lists).
325 */
326 public ComponentAdapter registerComponentImplementation(Object componentKey, Class componentImplementation, List parameters) {
327 Parameter[] parametersAsArray = (Parameter[]) parameters.toArray(new Parameter[parameters.size()]);
328 return registerComponentImplementation(componentKey, componentImplementation, parametersAsArray);
329 }
330
331 private void addOrderedComponentAdapter(ComponentAdapter componentAdapter) {
332 if (!orderedComponentAdapters.contains(componentAdapter)) {
333 orderedComponentAdapters.add(componentAdapter);
334 }
335 }
336
337 public List getComponentInstances() throws PicoException {
338 return getComponentInstancesOfType(Object.class);
339 }
340
341 public List getComponentInstancesOfType(Class componentType) {
342 if (componentType == null) {
343 return Collections.EMPTY_LIST;
344 }
345
346 Map adapterToInstanceMap = new HashMap();
347 for (Iterator iterator = componentAdapters.iterator(); iterator.hasNext();) {
348 ComponentAdapter componentAdapter = (ComponentAdapter) iterator.next();
349 if (componentType.isAssignableFrom(componentAdapter.getComponentImplementation())) {
350 Object componentInstance = getInstance(componentAdapter);
351 adapterToInstanceMap.put(componentAdapter, componentInstance);
352
353 // This is to ensure all are added. (Indirect dependencies will be added
354 // from InstantiatingComponentAdapter).
355 addOrderedComponentAdapter(componentAdapter);
356 }
357 }
358 List result = new ArrayList();
359 for (Iterator iterator = orderedComponentAdapters.iterator(); iterator.hasNext();) {
360 Object componentAdapter = iterator.next();
361 final Object componentInstance = adapterToInstanceMap.get(componentAdapter);
362 if (componentInstance != null) {
363 // may be null in the case of the "implicit" adapter
364 // representing "this".
365 result.add(componentInstance);
366 }
367 }
368 return result;
369 }
370
371 public Object getComponentInstance(Object componentKey) {
372 ComponentAdapter componentAdapter = getComponentAdapter(componentKey);
373 if (componentAdapter != null) {
374 return getInstance(componentAdapter);
375 } else {
376 return null;
377 }
378 }
379
380 public Object getComponentInstanceOfType(Class componentType) {
381 final ComponentAdapter componentAdapter = getComponentAdapterOfType(componentType);
382 return componentAdapter == null ? null : getInstance(componentAdapter);
383 }
384
385 private Object getInstance(ComponentAdapter componentAdapter) {
386 // check wether this is our adapter
387 // we need to check this to ensure up-down dependencies cannot be followed
388 final boolean isLocal = componentAdapters.contains(componentAdapter);
389
390 if (isLocal) {
391 Object instance = null;
392 try {
393 instance = componentAdapter.getComponentInstance(this);
394 } catch (CyclicDependencyException e) {
395 if (parent != null) {
396 instance = parent.getComponentInstance(componentAdapter.getComponentKey());
397 if( instance != null ) {
398 return instance;
399 }
400 }
401 throw e;
402 }
403 addOrderedComponentAdapter(componentAdapter);
404
405 return instance;
406 } else if (parent != null) {
407 return parent.getComponentInstance(componentAdapter.getComponentKey());
408 }
409
410 return null;
411 }
412
413
414 public PicoContainer getParent() {
415 return parent;
416 }
417
418 public ComponentAdapter unregisterComponentByInstance(Object componentInstance) {
419 Collection componentAdapters = getComponentAdapters();
420 for (Iterator iterator = componentAdapters.iterator(); iterator.hasNext();) {
421 ComponentAdapter componentAdapter = (ComponentAdapter) iterator.next();
422 if (getInstance(componentAdapter).equals(componentInstance)) {
423 return unregisterComponent(componentAdapter.getComponentKey());
424 }
425 }
426 return null;
427 }
428
429 /**
430 * @deprecated since 1.1 - Use "new VerifyingVisitor().traverse(this)"
431 */
432 public void verify() throws PicoVerificationException {
433 new VerifyingVisitor().traverse(this);
434 }
435
436 /**
437 * Start the components of this PicoContainer and all its logical child containers.
438 * The starting of the child container is only attempted if the parent
439 * container start successfully. The child container for which start is attempted
440 * is tracked so that upon stop, only those need to be stopped.
441 * The lifecycle operation is delegated to the component adapter,
442 * if it is an instance of {@link LifecycleManager lifecycle manager}.
443 * The actual {@link LifecycleStrategy lifecycle strategy} supported
444 * depends on the concrete implementation of the adapter.
445 *
446 * @see LifecycleManager
447 * @see LifecycleStrategy
448 * @see #makeChildContainer()
449 * @see #addChildContainer(PicoContainer)
450 * @see #removeChildContainer(PicoContainer)
451 */
452 public void start() {
453 if (disposed) throw new IllegalStateException("Already disposed");
454 if (started) throw new IllegalStateException("Already started");
455 started = true;
456 this.lifecycleManager.start(this);
457 childrenStarted.clear();
458 for (Iterator iterator = children.iterator(); iterator.hasNext();) {
459 PicoContainer child = (PicoContainer) iterator.next();
460 childrenStarted.add(new Integer(child.hashCode()));
461 child.start();
462 }
463 }
464
465 /**
466 * Stop the components of this PicoContainer and all its logical child containers.
467 * The stopping of the child containers is only attempted for those that have been
468 * started, possibly not successfully.
469 * The lifecycle operation is delegated to the component adapter,
470 * if it is an instance of {@link LifecycleManager lifecycle manager}.
471 * The actual {@link LifecycleStrategy lifecycle strategy} supported
472 * depends on the concrete implementation of the adapter.
473 *
474 * @see LifecycleManager
475 * @see LifecycleStrategy
476 * @see #makeChildContainer()
477 * @see #addChildContainer(PicoContainer)
478 * @see #removeChildContainer(PicoContainer)
479 */
480 public void stop() {
481 if (disposed) throw new IllegalStateException("Already disposed");
482 if (!started) throw new IllegalStateException("Not started");
483 for (Iterator iterator = children.iterator(); iterator.hasNext();) {
484 PicoContainer child = (PicoContainer) iterator.next();
485 if ( childStarted(child) ){
486 child.stop();
487 }
488 }
489 this.lifecycleManager.stop(this);
490 started = false;
491 }
492
493 /**
494 * Checks the status of the child container to see if it's been started
495 * to prevent IllegalStateException upon stop
496 * @param child the child PicoContainer
497 * @return A boolean, <code>true</code> if the container is started
498 */
499 private boolean childStarted(PicoContainer child) {
500 return childrenStarted.contains(new Integer(child.hashCode()));
501 }
502
503 /**
504 * Dispose the components of this PicoContainer and all its logical child containers.
505 * The lifecycle operation is delegated to the component adapter,
506 * if it is an instance of {@link LifecycleManager lifecycle manager}.
507 * The actual {@link LifecycleStrategy lifecycle strategy} supported
508 * depends on the concrete implementation of the adapter.
509 *
510 * @see LifecycleManager
511 * @see LifecycleStrategy
512 * @see #makeChildContainer()
513 * @see #addChildContainer(PicoContainer)
514 * @see #removeChildContainer(PicoContainer)
515 */
516 public void dispose() {
517 if (disposed) throw new IllegalStateException("Already disposed");
518 for (Iterator iterator = children.iterator(); iterator.hasNext();) {
519 PicoContainer child = (PicoContainer) iterator.next();
520 child.dispose();
521 }
522 this.lifecycleManager.dispose(this);
523 disposed = true;
524 }
525
526 public MutablePicoContainer makeChildContainer() {
527 DefaultPicoContainer pc = new DefaultPicoContainer(componentAdapterFactory,
528 lifecycleStrategyForInstanceRegistrations,
529 this);
530 addChildContainer(pc);
531 return pc;
532 }
533
534 public boolean addChildContainer(PicoContainer child) {
535 if (children.add(child)) {
536 // @todo Should only be added if child container has also be started
537 if (started) {
538 childrenStarted.add(new Integer(child.hashCode()));
539 }
540 return true;
541 } else {
542 return false;
543 }
544 }
545
546 public boolean removeChildContainer(PicoContainer child) {
547 final boolean result = children.remove(child);
548 childrenStarted.remove(new Integer(child.hashCode()));
549 return result;
550 }
551
552 public void accept(PicoVisitor visitor) {
553 visitor.visitContainer(this);
554 final List componentAdapters = new ArrayList(getComponentAdapters());
555 for (Iterator iterator = componentAdapters.iterator(); iterator.hasNext();) {
556 ComponentAdapter componentAdapter = (ComponentAdapter) iterator.next();
557 componentAdapter.accept(visitor);
558 }
559 final List allChildren = new ArrayList(children);
560 for (Iterator iterator = allChildren.iterator(); iterator.hasNext();) {
561 PicoContainer child = (PicoContainer) iterator.next();
562 child.accept(visitor);
563 }
564 }
565
566 /**
567 * Changes monitor in the ComponentAdapterFactory, the component adapters
568 * and the child containers, if these support a ComponentMonitorStrategy.
569 * {@inheritDoc}
570 */
571 public void changeMonitor(ComponentMonitor monitor) {
572 // will also change monitor in lifecycleStrategyForInstanceRegistrations
573 if (componentAdapterFactory instanceof ComponentMonitorStrategy) {
574 ((ComponentMonitorStrategy) componentAdapterFactory).changeMonitor(monitor);
575 }
576 for ( Iterator i = componentAdapters.iterator(); i.hasNext(); ){
577 Object adapter = i.next();
578 if ( adapter instanceof ComponentMonitorStrategy ) {
579 ((ComponentMonitorStrategy)adapter).changeMonitor(monitor);
580 }
581 }
582 for (Iterator i = children.iterator(); i.hasNext();) {
583 Object child = i.next();
584 if (child instanceof ComponentMonitorStrategy) {
585 ((ComponentMonitorStrategy) child).changeMonitor(monitor);
586 }
587 }
588 }
589
590 /**
591 * Returns the first current monitor found in the ComponentAdapterFactory, the component adapters
592 * and the child containers, if these support a ComponentMonitorStrategy.
593 * {@inheritDoc}
594 * @throws PicoIntrospectionException if no component monitor is found in container or its children
595 */
596 public ComponentMonitor currentMonitor() {
597 if (componentAdapterFactory instanceof ComponentMonitorStrategy) {
598 return ((ComponentMonitorStrategy) componentAdapterFactory).currentMonitor();
599 }
600 for ( Iterator i = componentAdapters.iterator(); i.hasNext(); ){
601 Object adapter = i.next();
602 if ( adapter instanceof ComponentMonitorStrategy ) {
603 return ((ComponentMonitorStrategy)adapter).currentMonitor();
604 }
605 }
606 for (Iterator i = children.iterator(); i.hasNext();) {
607 Object child = i.next();
608 if (child instanceof ComponentMonitorStrategy) {
609 return ((ComponentMonitorStrategy) child).currentMonitor();
610 }
611 }
612 throw new PicoIntrospectionException("No component monitor found in container or its children");
613 }
614
615 /**
616 * <p>
617 * Implementation of lifecycle manager which delegates to the container's component adapters.
618 * The component adapters will be ordered by dependency as registered in the container.
619 * This LifecycleManager will delegate calls on the lifecycle methods to the component adapters
620 * if these are themselves LifecycleManagers.
621 * </p>
622 *
623 * @author Mauro Talevi
624 * @since 1.2
625 */
626 private class OrderedComponentAdapterLifecycleManager implements LifecycleManager, Serializable {
627
628 /** List collecting the CAs which have been successfully started */
629 private List startedComponentAdapters = new ArrayList();
630
631 /**
632 * {@inheritDoc}
633 * Loops over all component adapters and invokes
634 * start(PicoContainer) method on the ones which are LifecycleManagers
635 */
636 public void start(PicoContainer node) {
637 Collection adapters = getComponentAdapters();
638 for (final Iterator iter = adapters.iterator(); iter.hasNext();) {
639 final ComponentAdapter adapter = (ComponentAdapter)iter.next();
640 if ( adapter instanceof LifecycleManager ){
641 LifecycleManager manager = (LifecycleManager)adapter;
642 if (manager.hasLifecycle()) {
643 // create an instance, it will be added to the ordered CA list
644 adapter.getComponentInstance(node);
645 addOrderedComponentAdapter(adapter);
646 }
647 }
648 }
649 adapters = orderedComponentAdapters;
650 // clear list of started CAs
651 startedComponentAdapters.clear();
652 for (final Iterator iter = adapters.iterator(); iter.hasNext();) {
653 final Object adapter = iter.next();
654 if ( adapter instanceof LifecycleManager ){
655 LifecycleManager manager = (LifecycleManager)adapter;
656 manager.start(node);
657 startedComponentAdapters.add(adapter);
658 }
659 }
660 }
661
662 /**
663 * {@inheritDoc}
664 * Loops over started component adapters (in inverse order) and invokes
665 * stop(PicoContainer) method on the ones which are LifecycleManagers
666 */
667 public void stop(PicoContainer node) {
668 List adapters = startedComponentAdapters;
669 for (int i = adapters.size() - 1; 0 <= i; i--) {
670 Object adapter = adapters.get(i);
671 if ( adapter instanceof LifecycleManager ){
672 LifecycleManager manager = (LifecycleManager)adapter;
673 manager.stop(node);
674 }
675 }
676 }
677
678 /**
679 * {@inheritDoc}
680 * Loops over all component adapters (in inverse order) and invokes
681 * dispose(PicoContainer) method on the ones which are LifecycleManagers
682 */
683 public void dispose(PicoContainer node) {
684 List adapters = orderedComponentAdapters;
685 for (int i = adapters.size() - 1; 0 <= i; i--) {
686 Object adapter = adapters.get(i);
687 if ( adapter instanceof LifecycleManager ){
688 LifecycleManager manager = (LifecycleManager)adapter;
689 manager.dispose(node);
690 }
691 }
692 }
693
694 public boolean hasLifecycle() {
695 throw new UnsupportedOperationException("Should not have been called");
696 }
697
698 }
699
700 }