001 /*******************************************************************************
002 * Copyright (C) PicoContainer Organization. All rights reserved.
003 * ---------------------------------------------------------------------------
004 * The software in this package is published under the terms of the BSD style
005 * license a copy of which has been included with this distribution in the
006 * LICENSE.txt file.
007 ******************************************************************************/
008 package org.picocontainer.script;
009
010 import org.picocontainer.MutablePicoContainer;
011 import org.picocontainer.PicoContainer;
012 import org.picocontainer.Startable;
013 import org.picocontainer.Disposable;
014
015 /**
016 * @author Joe Walnes
017 * @author Aslak Hellesøy
018 * @author Paul Hammant
019 * @author Mauro Talevi
020 */
021 // TODO -- Perhaps the start/stop behavior should be moved to a decorator?
022 public abstract class AbstractContainerBuilder implements ContainerBuilder {
023
024 private final LifecycleMode startMode;
025
026 public AbstractContainerBuilder() {
027 this(LifecycleMode.AUTO_LIFECYCLE);
028 }
029
030 public AbstractContainerBuilder(LifecycleMode startMode) {
031 this.startMode = startMode;
032 }
033
034 public final PicoContainer buildContainer(PicoContainer parentContainer, Object assemblyScope,
035 boolean addChildToParent) {
036 PicoContainer container = createContainer(parentContainer, assemblyScope);
037
038 if (parentContainer != null && parentContainer instanceof MutablePicoContainer) {
039 MutablePicoContainer mutableParentContainer = (MutablePicoContainer) parentContainer;
040
041 if (addChildToParent) {
042 // this synchronization is necessary to avoid
043 // race conditions for concurrent requests
044 synchronized (mutableParentContainer) {
045 // register the child in the parent so that lifecycle can be
046 // propagated down the hierarchy
047 mutableParentContainer.addChildContainer(container);
048 }
049 }
050 }
051
052 autoStart(container);
053
054 return container;
055 }
056
057 protected void autoStart(PicoContainer container) {
058 if (!startMode.isInvokeLifecycle()) {
059 return;
060 }
061
062 if (container instanceof Startable) {
063 ((Startable) container).start();
064 }
065 }
066
067 public void killContainer(PicoContainer container) {
068 if (startMode.isInvokeLifecycle()) {
069 if (container instanceof Startable) {
070 ((Startable) container).stop();
071 }
072 }
073
074 if (container instanceof Disposable) {
075 ((Disposable) container).dispose();
076 }
077 PicoContainer parent = container.getParent();
078 if (parent != null && parent instanceof MutablePicoContainer) {
079 // see comment in buildContainer
080 synchronized (parent) {
081 ((MutablePicoContainer) parent).removeChildContainer(container);
082 }
083 }
084 }
085
086 protected abstract PicoContainer createContainer(PicoContainer parentContainer, Object assemblyScope);
087 }