001    /*****************************************************************************
002     * Copyright (C) NanoContainer 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     *****************************************************************************/
009    package org.nanocontainer.integrationkit;
010    
011    import org.picocontainer.MutablePicoContainer;
012    import org.picocontainer.PicoContainer;
013    import org.picocontainer.defaults.ObjectReference;
014    
015    /**
016     * @author <a href="mailto:joe@thoughtworks.net">Joe Walnes</a>
017     * @author Aslak Helles&oslash;y
018     * @author Paul Hammant
019     * @author Mauro Talevi
020     * @version $Revision: 2816 $
021     */
022    public abstract class LifecycleContainerBuilder implements ContainerBuilder {
023    
024        public final void buildContainer(ObjectReference containerRef, ObjectReference parentContainerRef, Object assemblyScope, boolean addChildToParent) {
025            PicoContainer parentContainer = parentContainerRef == null ? null : (PicoContainer) parentContainerRef.get();
026            PicoContainer container = createContainer(parentContainer, assemblyScope);
027    
028            if (parentContainer != null && parentContainer instanceof MutablePicoContainer) {
029                MutablePicoContainer mutableParentContainer = (MutablePicoContainer) parentContainer;
030    
031                if (addChildToParent) {
032                    // this synchronization is necessary, because several servlet requests may
033                    // occur at the same time for given session, and this produce race condition
034                    // especially in framed environments
035                    synchronized (mutableParentContainer) {
036                        // register the child in the parent so that lifecycle can be propagated down the hierarchy
037                        mutableParentContainer.addChildContainer(container);
038                    }
039                }
040            }
041    
042            if (container instanceof MutablePicoContainer) {
043                composeContainer((MutablePicoContainer) container, assemblyScope);
044            }
045            autoStart(container);
046    
047            // hold on to it
048            containerRef.set(container);
049        }
050    
051        protected void autoStart(PicoContainer container) {
052            container.start();
053        }
054    
055        public void killContainer(ObjectReference containerRef) {
056            try {
057                PicoContainer pico = (PicoContainer) containerRef.get();
058                pico.stop();
059                pico.dispose();
060                PicoContainer parent = pico.getParent();
061                if (parent != null && parent instanceof MutablePicoContainer) {
062                    // see comment in buildContainer
063                    synchronized (parent) {
064                        ((MutablePicoContainer) parent).unregisterComponentByInstance(pico);
065                    }
066                }
067            } finally {
068                containerRef.set(null);
069            }
070        }
071    
072        protected abstract void composeContainer(MutablePicoContainer container, Object assemblyScope);
073    
074        protected abstract PicoContainer createContainer(PicoContainer parentContainer, Object assemblyScope);
075    }