X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=system%2Fgeneral%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsystem%2FContainer.java;h=65d10f06e2960d74eff34b5ed63cd560d6fa1337;hb=b0e1c060d6207c0fc06e4673764a6980da775210;hp=a80aa1a21f0c7136b2acd66d8c2b8f9eff6091bf;hpb=e055966cbba51cbf35546dbc50f29516cf6e304f;p=utils diff --git a/system/general/src/main/java/org/wamblee/system/Container.java b/system/general/src/main/java/org/wamblee/system/Container.java index a80aa1a2..65d10f06 100644 --- a/system/general/src/main/java/org/wamblee/system/Container.java +++ b/system/general/src/main/java/org/wamblee/system/Container.java @@ -1,14 +1,30 @@ +/* + * Copyright 2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wamblee.system; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import sun.util.LocaleServiceProviderPool.LocalizedObjectGetter; - /** * Composite system consisting of multiple subsystems. * @@ -20,6 +36,30 @@ public class Container extends AbstractComponent { private Component[] _systems; + 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); + } + } + return provided.toArray(new ProvidedInterface[0]); + } + /** * Construcst the composite system. * @param aName Name of the system. @@ -28,11 +68,14 @@ public class Container extends AbstractComponent { * @param aProvided Provided services of the system. * @param aRequired Required services by the system. */ - public Container(String aName, ServiceRegistry aRegistry, Component[] aSystems, - ProvidedInterfaceDescriptor[] aProvided, RequiredInterfaceDescriptor[] aRequired) { - super(aName, aRegistry, aProvided, aRequired); + public Container(String aName, Component[] aSystems, + ProvidedInterface[] aProvided, RequiredInterface[] aRequired) { + super(aName, aProvided, aRequired); _systems = aSystems; - validate(); + for (Component component: aSystems) { + component.addContext(getQualifiedName()); + } + validate(aRequired); } /** @@ -41,25 +84,25 @@ public class Container extends AbstractComponent { * no services in the provided list that cannot be provided. * Also logs a warning in case of superfluous requirements. */ - private void validate() { - List provided = new ArrayList(); + private void validate(RequiredInterface[] aRequired) { + List provided = new ArrayList(); for (Component system : _systems) { provided.addAll(Arrays.asList(system.getProvidedServices())); } - List required = new ArrayList(); + List required = new ArrayList(); for (Component system : _systems) { required.addAll(Arrays.asList(system.getRequiredServices())); } - for (InterfaceDescriptor service : getProvidedServices()) { + for (ProvidedInterface service : getProvidedServices()) { if (!(provided.contains(service))) { throw new SystemAssemblyException(getName() + ": Service '" + service + "' is not provided by any of the subsystems"); } } - for (InterfaceDescriptor service : getRequiredServices()) { + for (RequiredInterface service : getRequiredServices()) { if (!(required.contains(service))) { info("Service '" + service @@ -67,16 +110,21 @@ public class Container extends AbstractComponent { } } - List reallyRequired = new ArrayList( + List reallyRequired = new ArrayList( required); - for (InterfaceDescriptor service : provided) { - reallyRequired.remove(service); - } - for (InterfaceDescriptor service: getRequiredServices()) { - reallyRequired.remove(service); + // Compute all required interfaces that are not provided + for (ProvidedInterface service : provided) { + List fulfilled = + Arrays.asList(filterRequiredServices(service, + reallyRequired)); + reallyRequired.removeAll(fulfilled); } + // Now the remaining interfaces should be covered by the required + // list. + reallyRequired.removeAll(Arrays.asList(aRequired)); + String missingRequired = ""; - for (InterfaceDescriptor service: reallyRequired) { + for (RequiredInterface service: reallyRequired) { missingRequired += service + "\n"; } if ( missingRequired.length() > 0 ) { @@ -85,16 +133,79 @@ public class Container extends AbstractComponent { } @Override - protected void doStart(String aContext, Service[] aRequiredServices) { - List descriptors = new ArrayList(); - for (Service service : aRequiredServices) { - descriptors.add(service.getDescriptor()); + protected void doStart() { + List provided = new ArrayList(); + + // all interfaces from the required list of this container are + // provided to the components inside it. + RequiredInterface[] required = getRequiredServices(); + for (RequiredInterface intf: required) { + ProvidedInterface provider = intf.getProvider(); + if ( provider == null ) { + throw new SystemAssemblyException(getQualifiedName() + ": required interface '" + intf +"' is not provided"); + } + provided.add(intf.getProvider()); } - SystemAssembler assembler = new SystemAssembler(aContext + "." + getName(), _systems, - descriptors.toArray(new ProvidedInterfaceDescriptor[0])); - assembler.start(getRegistry(), aRequiredServices); + + startImpl(); } + /** + * Starts the subsystems. + * + * @param aRequiredServices + * Services that are available from other systems that have been + * started before. + */ + private void startImpl() { + LOG.info("Starting '" + getQualifiedName() + "'"); + List allProvided = new ArrayList(); + + // Add the provides of all externally required interfaces to the list of available + // interfaces + for (RequiredInterface required: getRequiredServices()) { + allProvided.add(required.getProvider()); + } + + for (Component system : _systems) { + // Check if all required services are already provided by earlier + // systems. + RequiredInterface[] required = system.getRequiredServices(); + + for (RequiredInterface descriptor : required) { + ProvidedInterface[] filtered = filterProvidedServices( + descriptor, allProvided); + + if (filtered.length == 0) { + throw new SystemAssemblyException( + "Service '" + + descriptor + + "' required by system '" + + system + + "' is not provided by systems that are started earlier"); + } + if (filtered.length > 1) { + throw new SystemAssemblyException( + "Service '" + + descriptor + + "' required by system '" + + system + + "' matches multiple services provided by other systems: " + + Arrays.asList(filtered)); + } + descriptor.setProvider(filtered[0]); + } + + // Start the service. + system.start(); + + // add all provided services + ProvidedInterface[] provided = system.getProvidedServices(); + allProvided.addAll(Arrays.asList(provided)); + } + } + + @Override protected void doStop() { for (int i = _systems.length-1; i >= 0; i--) {