X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=system%2Fgeneral%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsystem%2Fcore%2FContainer.java;h=a0130f7cf3420094198d72b616f3b281a1973987;hb=ffa7b72359ee0587112cf94b10bf2d3acdb9d80d;hp=8e98755b5e7b02b8d8c33c2243150fac045660a5;hpb=463048842cf881c2ba688a4d5c7549edad00fbaa;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 8e98755b..a0130f7c 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 @@ -25,6 +25,9 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wamblee.collections.CollectionFilter; +import org.wamblee.conditions.Condition; +import org.wamblee.general.Pair; /** * Container consisting of multiple components. @@ -37,29 +40,22 @@ public class Container extends AbstractComponent { private List _components; private Set _componentNames; + private CompositeInterfaceRestriction _restriction; private boolean _sealed; - - public static RequiredInterface[] filterRequiredServices( - ProvidedInterface aProvided, - Collection aDescriptors) { - List required = new ArrayList(); - for (RequiredInterface descriptor : aDescriptors) { - if (descriptor.implementedBy(aProvided)) { - required.add(descriptor); - } - } - return required.toArray(new RequiredInterface[0]); - } - - public static ProvidedInterface[] filterProvidedServices( - RequiredInterface aRequired, Collection aProvided) { - List provided = new ArrayList(); - for (ProvidedInterface descriptor : aProvided) { - if (aRequired.implementedBy(descriptor)) { - provided.add(descriptor); + + static ProvidedInterface[] filterProvidedServices( + Component aClient, RequiredInterface aRequired, Collection> aProvided, + InterfaceRestriction aRestriction) { + List result = new ArrayList(); + for (Pair descriptor : aProvided) { + ProvidedInterface provided = descriptor.getFirst(); + Component server = descriptor.getSecond(); + if (aRequired.implementedBy(provided) && + !aRestriction.isViolated(aClient, aRequired, server, provided)) { + result.add(provided); } } - return provided.toArray(new ProvidedInterface[0]); + return result.toArray(new ProvidedInterface[0]); } /** @@ -80,6 +76,7 @@ public class Container extends AbstractComponent { _components = new ArrayList(); _componentNames = new HashSet(); + _restriction = new CompositeInterfaceRestriction(); _sealed = false; for (Component component : aComponents) { addComponent(component); @@ -108,6 +105,18 @@ public class Container extends AbstractComponent { aComponent.addContext(getQualifiedName()); return this; } + + /** + * Adds an interface restriction for explicitly configuring the + * relations between components. + * @param aRestriction Restriction to add. + * @return Reference to this to allow call chaining. + */ + public Container addRestriction(InterfaceRestriction aRestriction) { + checkSealed(); + _restriction.add(aRestriction); + return this; + } @Override public Container addProvidedInterface(ProvidedInterface aProvided) { @@ -133,47 +142,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())); - } - - List required = new ArrayList(); - for (Component component : _components) { - required.addAll(Arrays.asList(component.getRequiredInterfaces())); - } + validateProvidedInterfacesArePresent(); - validateProvidedInterfacesArePresent(provided); + validateRequiredInterfaces(); - validateRequiredInterfaces(required); - - addProvidersOfRequiredInterfaces(provided); - validateRequiredProvidedMatch(provided, required); + doStartOptionalDryRun(null, true); } - /** - * - * @param aProvided - * All provided interfaces. - * @param aRequired - * All required interfaces. - * @return - */ - private void validateRequiredProvidedMatch( - List aProvided, List aRequired) { - + private void validateRequiredInterfaces() { + List required = new ArrayList(); for (Component component : _components) { - initializeProvidersForRequiredInterfaces(aProvided, component, true); + required.addAll(Arrays.asList(component.getRequiredInterfaces())); } - } - 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"); @@ -182,7 +169,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 @@ -197,14 +184,17 @@ public class Container extends AbstractComponent { } } - private void validateProvidedInterfacesArePresent( - 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"); @@ -246,29 +236,37 @@ 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(); - + List> allProvided = new ArrayList>(); + addProvidersOfRequiredInterfaces(allProvided); List started = new ArrayList(); for (Component component : _components) { try { initializeProvidersForRequiredInterfaces(allProvided, - component, false); + 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 .getProvidedInterfaces(); - allProvided.addAll(Arrays.asList(provided)); + for (ProvidedInterface prov: provided) { + allProvided.add(new Pair(prov, component)); + } } catch (SystemAssemblyException e) { throw e; } catch (RuntimeException e) { @@ -282,14 +280,14 @@ public class Container extends AbstractComponent { } private void addProvidersOfRequiredInterfaces( - List allProvided) { + 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); + allProvided.add(new Pair(provider, null)); } else { if (!intf.isOptional()) { throw new SystemAssemblyException(getQualifiedName() @@ -306,7 +304,8 @@ public class Container extends AbstractComponent { // 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,15 +325,15 @@ public class Container extends AbstractComponent { * interfaces. */ private void initializeProvidersForRequiredInterfaces( - List aAllProvided, Component aComponent, + List> aAllProvided, Component aComponent, boolean aValidateOnly) { // Check if all required services are already provided by // earlier // systems. for (RequiredInterface descriptor : aComponent.getRequiredInterfaces()) { - ProvidedInterface[] filtered = filterProvidedServices(descriptor, - aAllProvided); + ProvidedInterface[] filtered = filterProvidedServices(aComponent, descriptor, + aAllProvided, _restriction); if (filtered.length == 1) { if (!aValidateOnly) { descriptor.setProvider(filtered[0]);