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    }