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=ce71ffcb89bd0ed7f1fc73cebec1b0e7659e6028;hp=fd322c6bbd49aabd10187501d630f2db762a2204;hpb=684ac768ff69c436aefd2b07fc94cc61a1e5bdb8;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 fd322c6b..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()); @@ -252,7 +312,7 @@ public class Container extends AbstractComponent { + "' required by system '" + aComponent + "' matches multiple services provided by other systems: " - + Arrays.asList(filtered)); + + getServers(filtered)); } else { // filtered.length == 0 if ( !descriptor.isOptional()) { @@ -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); } } @@ -281,6 +343,22 @@ public class Container extends AbstractComponent { private void warn(String aMsg) { LOG.warn(getQualifiedName() + ": " + aMsg); } + + private String getServers(ProvidedInterface[] aProvidedList ) { + String result = ""; + for (ProvidedInterface provided: aProvidedList) { + result += "(components "; + for (Component component: _components) { + for (ProvidedInterface provided2: component.getProvidedInterfaces()) { + if ( provided.equals(provided2)) { + result += component + " "; + } + } + } + result += ", interface " + provided + ")"; + } + return result; + } private List getClients(RequiredInterface aRequirement) { List clients = new ArrayList(); @@ -293,4 +371,10 @@ public class Container extends AbstractComponent { } return clients; } + + private void checkSealed() { + if ( _sealed ) { + throw new SystemAssemblyException("Container is sealed"); + } + } }