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 }