X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=system%2Fgeneral%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsystem%2Fcore%2FContainer.java;h=a4b0620fccc589ab5fd48796aa3ca8ba34d17768;hb=c210d3c212308d3c5a84f4c19e84a95175e4f172;hp=df92c0d099dcb4a61e219bb6047a7b5bea672783;hpb=2768257dc89eeac0398e8b5ec42b0ff031e0e344;p=utils diff --git a/system/general/src/main/java/org/wamblee/system/core/Container.java b/system/general/src/main/java/org/wamblee/system/core/Container.java index df92c0d0..a4b0620f 100644 --- a/system/general/src/main/java/org/wamblee/system/core/Container.java +++ b/system/general/src/main/java/org/wamblee/system/core/Container.java @@ -29,11 +29,12 @@ import org.apache.commons.logging.LogFactory; * * @author Erik Brakkee */ -public class Container extends AbstractComponent { +public class Container extends AbstractComponent { private static final Log LOG = LogFactory.getLog(Container.class); - private Component[] _components; + private List _components; + private boolean _sealed; public static RequiredInterface[] filterRequiredServices( ProvidedInterface aProvided, @@ -59,7 +60,7 @@ public class Container extends AbstractComponent { } /** - * Construcst the container + * Constructs the container * * @param aName * Name of the container @@ -73,20 +74,46 @@ public class Container extends AbstractComponent { public Container(String aName, Component[] aComponents, ProvidedInterface[] aProvided, RequiredInterface[] aRequired) { super(aName, aProvided, aRequired); - _components = aComponents; + _components = new ArrayList(Arrays.asList(aComponents)); for (Component component : aComponents) { component.addContext(getQualifiedName()); } + _sealed = false; validate(); } + + public Container(String aName) { + this(aName, new Component[0], new ProvidedInterface[0], new RequiredInterface[0]); + } + + public Container addComponent(Component aComponent) { + checkSealed(); + _components.add(aComponent); + return this; + } + @Override + protected Container addProvidedInterface(ProvidedInterface aProvided) { + checkSealed(); + super.addProvidedInterface(aProvided); + return this; + } + + @Override + protected Container addRequiredInterface(RequiredInterface aRequired) { + checkSealed(); + super.addRequiredInterface(aRequired); + return this; + } + /** * Validates the components together to check that there are no required * services not in the required list and no services in the provided list * that cannot be provided. Also logs a warning in case of superfluous * requirements. + * @throws SystemAssemblyException in case of any validation problems. */ - private void validate() { + public void validate() { List provided = new ArrayList(); for (Component component : _components) { provided.addAll(Arrays.asList(component.getProvidedInterfaces())); @@ -176,10 +203,42 @@ public class Container extends AbstractComponent { } } } + + /** + * Starts the container. After the container is started, the container becomes sealed + * meaning that no further components, required or provided interfaces may be added. + * @return Scope. + */ + public Scope start() { + checkSealed(); + validate(); + Scope scope = super.start(new DefaultScope(new ProvidedInterface[0])); + seal(); + return scope; + } + + /** + * Seal the container, meaning that no further components or interfaces may be added. + */ + public void seal() { + _sealed = true; + } + + /** + * Checks if the container is sealed. + * @return True iff the container is sealed. + */ + public boolean isSealed() { + return _sealed; + } @Override - protected void doStart() { + protected Scope doStart(Scope aExternalScope) { LOG.info("Starting '" + getQualifiedName() + "'"); + + Scope scope = new DefaultScope(getProvidedInterfaces(), + aExternalScope); + List allProvided = new ArrayList(); // all interfaces from the required list of this container are @@ -203,7 +262,8 @@ public class Container extends AbstractComponent { checkAllRequiredServicesAlreadyProvided(allProvided, component); // Start the service. - component.start(); + Object runtime = component.start(scope); + scope.addRuntime(component, runtime); started.add(component); // add all provided services @@ -214,19 +274,19 @@ public class Container extends AbstractComponent { } catch (RuntimeException e) { LOG.error(getQualifiedName() + ": could not start '" + component.getQualifiedName() + "'", e); - stopAlreadyStartedComponents(started); + stopAlreadyStartedComponents(started, scope); throw e; } } - + return scope; } - private void stopAlreadyStartedComponents(List aStarted) { + private void stopAlreadyStartedComponents(List aStarted, Scope aScope) { // an exception occurred, stop the successfully started // components for (int i = aStarted.size() - 1; i >= 0; i--) { try { - aStarted.get(i).stop(); + aStarted.get(i).stop(aScope); } catch (Throwable t) { LOG.error(getQualifiedName() + ": error stopping " + aStarted.get(i).getQualifiedName()); @@ -268,9 +328,11 @@ public class Container extends AbstractComponent { } @Override - protected void doStop() { - for (int i = _components.length - 1; i >= 0; i--) { - _components[i].stop(); + protected void doStop(Scope aScope) { + for (int i = _components.size() - 1; i >= 0; i--) { + Component component = _components.get(i); + Object runtime = aScope.getRuntime(component); + component.stop(runtime); } } @@ -309,4 +371,10 @@ public class Container extends AbstractComponent { } return clients; } + + private void checkSealed() { + if ( _sealed ) { + throw new SystemAssemblyException("Container is sealed"); + } + } }