X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=system%2Fgeneral%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsystem%2Fcore%2FContainer.java;h=1eaebf432a0e1c239189e621e3d0a35b9275f1ed;hb=c93fd9abab341c2537b526b4a10b9f65962022c0;hp=b9056971136787a59fd09fc6f5de558ee6ed2fd6;hpb=e509700eb632776a6c14a2bf50495f733af25e5e;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 b9056971..1eaebf43 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 @@ -78,13 +78,12 @@ public class Container extends AbstractComponent { ProvidedInterface[] aProvided, RequiredInterface[] aRequired) { super(aName, aProvided, aRequired); _components = new ArrayList(); - + _componentNames = new HashSet(); _sealed = false; for (Component component : aComponents) { addComponent(component); } - validate(); } public Container(String aName) { @@ -134,65 +133,25 @@ public class Container extends AbstractComponent { * in case of any validation problems. */ public void validate() { - List provided = new ArrayList(); - for (Component component : _components) { - provided.addAll(Arrays.asList(component.getProvidedInterfaces())); - } + validateProvidedInterfacesArePresent(); - List required = new ArrayList(); - for (Component component : _components) { - required.addAll(Arrays.asList(component.getRequiredInterfaces())); - } - - validateProvidedInterfaces(provided); - - validateRequiredInterfaces(required); - - List reallyRequired = validateRequiredProvidedMatch( - provided, required); + validateRequiredInterfaces(); - String missingRequired = ""; - for (RequiredInterface service : reallyRequired) { - missingRequired += service + "\n"; - } - if (missingRequired.length() > 0) { - throw new SystemAssemblyException(getName() - + ": missing required services\n" + missingRequired); - } + doStartOptionalDryRun(null, true); } - private List validateRequiredProvidedMatch( - List aProvided, List aRequired) { - List reallyRequired = new ArrayList( - aRequired); - // Compute all required interfaces that are not provided - - for (ProvidedInterface service : aProvided) { - List fulfilled = Arrays - .asList(filterRequiredServices(service, reallyRequired)); - reallyRequired.removeAll(fulfilled); - } - // Now remove all optional interfaces from the list. - for (Iterator i = reallyRequired.iterator(); i - .hasNext();) { - RequiredInterface req = i.next(); - if (req.isOptional()) { - i.remove(); - } + private void validateRequiredInterfaces() { + List required = new ArrayList(); + for (Component component : _components) { + required.addAll(Arrays.asList(component.getRequiredInterfaces())); } - // Now the remaining interfaces should be covered by the required - // list. - reallyRequired.removeAll(Arrays.asList(getRequiredInterfaces())); - return reallyRequired; - } - private void validateRequiredInterfaces(List aRequired) { for (RequiredInterface service : getRequiredInterfaces()) { // TODO required interfaces by the component could be // subclasses or implementations of the requirements // of the contained components. The code below assumes // an exact match. - if (!(aRequired.contains(service))) { + if (!(required.contains(service))) { info("Service '" + service + "' indicated as required is not actually required by any of the components"); @@ -201,7 +160,7 @@ public class Container extends AbstractComponent { // is optional whereas the internally required service is // mandatory. if (service.isOptional()) { - for (RequiredInterface intf : aRequired) { + for (RequiredInterface intf : required) { if (intf.equals(service) && !intf.isOptional()) { warn("Required service '" + service @@ -216,13 +175,17 @@ public class Container extends AbstractComponent { } } - private void validateProvidedInterfaces(List aProvided) { + private void validateProvidedInterfacesArePresent() { + List provided = new ArrayList(); + for (Component component : _components) { + provided.addAll(Arrays.asList(component.getProvidedInterfaces())); + } for (ProvidedInterface service : getProvidedInterfaces()) { // TODO provided interfaces by components could be // provide subclasses or implementations of the // provided interfaces of the container. // The code below assumes an exact match. - if (!(aProvided.contains(service))) { + if (!(provided.contains(service))) { throw new SystemAssemblyException(getName() + ": Service '" + service + "' is not provided by any of its components"); @@ -264,37 +227,30 @@ public class Container extends AbstractComponent { @Override protected Scope doStart(Scope aExternalScope) { + return doStartOptionalDryRun(aExternalScope, false); + } + + private Scope doStartOptionalDryRun(Scope aExternalScope, boolean aDryRun) { LOG.info("Starting '" + getQualifiedName() + "'"); Scope scope = new DefaultScope(getProvidedInterfaces(), aExternalScope); List allProvided = new ArrayList(); - // all interfaces from the required list of this container are - // provided to the components inside it. - RequiredInterface[] required = getRequiredInterfaces(); - for (RequiredInterface intf : required) { - ProvidedInterface provider = intf.getProvider(); - if (provider != null) { - allProvided.add(provider); - } else { - if (!intf.isOptional()) { - throw new SystemAssemblyException(getQualifiedName() - + ": required interface '" + intf - + "' is not provided"); - } - } - } + addProvidersOfRequiredInterfaces(allProvided); List started = new ArrayList(); for (Component component : _components) { try { - checkAllRequiredServicesAlreadyProvided(allProvided, component); + initializeProvidersForRequiredInterfaces(allProvided, + component, aDryRun); // Start the service. - Object runtime = component.start(scope); - scope.addRuntime(component, runtime); - started.add(component); + if (!aDryRun) { + Object runtime = component.start(scope); + scope.addRuntime(component, runtime); + started.add(component); + } // add all provided services ProvidedInterface[] provided = component @@ -312,13 +268,33 @@ public class Container extends AbstractComponent { return scope; } + private void addProvidersOfRequiredInterfaces( + List allProvided) { + // all interfaces from the required list of this container are + // provided to the components inside it. + RequiredInterface[] required = getRequiredInterfaces(); + for (RequiredInterface intf : required) { + ProvidedInterface provider = intf.getProvider(); + if (provider != null) { + allProvided.add(provider); + } else { + if (!intf.isOptional()) { + throw new SystemAssemblyException(getQualifiedName() + + ": required interface '" + intf + + "' is not provided"); + } + } + } + } + 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(aScope); + Component component = aStarted.get(i); + aStarted.get(i).stop(aScope.getRuntime(component)); } catch (Throwable t) { LOG.error(getQualifiedName() + ": error stopping " + aStarted.get(i).getQualifiedName()); @@ -326,8 +302,20 @@ public class Container extends AbstractComponent { } } - private void checkAllRequiredServicesAlreadyProvided( - List aAllProvided, Component aComponent) { + /** + * Sets the provided interface or a component. + * + * @param aAllProvided + * All available provided interfaces. + * @param aComponent + * Component whose required interfaces we are looking at. + * @param aValidateOnly + * If true then the provider will not be set for required + * interfaces. + */ + private void initializeProvidersForRequiredInterfaces( + List aAllProvided, Component aComponent, + boolean aValidateOnly) { // Check if all required services are already provided by // earlier // systems. @@ -336,7 +324,9 @@ public class Container extends AbstractComponent { ProvidedInterface[] filtered = filterProvidedServices(descriptor, aAllProvided); if (filtered.length == 1) { - descriptor.setProvider(filtered[0]); + if (!aValidateOnly) { + descriptor.setProvider(filtered[0]); + } } else if (filtered.length > 1) { throw new SystemAssemblyException( "Service '"