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 }