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            try {
069                if (startMode.isInvokeLifecycle()) {
070                    if (container instanceof Startable) {
071                        ((Startable) container).stop();
072                    }
073                }
074    
075                if (container instanceof Disposable) {
076                    ((Disposable) container).dispose();
077                }
078                PicoContainer parent = container.getParent();
079                if (parent != null && parent instanceof MutablePicoContainer) {
080                    // see comment in buildContainer
081                    synchronized (parent) {
082                        ((MutablePicoContainer) parent).removeChildContainer(container);
083                    }
084                }
085            } finally {
086                container = null;
087            }
088        }
089    
090        protected abstract PicoContainer createContainer(PicoContainer parentContainer, Object assemblyScope);
091    }