package org.wamblee.system; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import sun.util.LocaleServiceProviderPool.LocalizedObjectGetter; /** * Composite system consisting of multiple subsystems. * * @author Erik Brakkee */ public class Container extends AbstractComponent { private static final Log LOG = LogFactory.getLog(Container.class); private Component[] _systems; /** * Construcst the composite system. * @param aName Name of the system. * @param aRegistry Service registry. * @param aSystems Subsystems. * @param aProvided Provided services of the system. * @param aRequired Required services by the system. */ public Container(String aName, Component[] aSystems, ProvidedInterface[] aProvided, RequiredInterface[] aRequired) { super(aName, aProvided, aRequired); _systems = aSystems; validate(aRequired); } /** * Validates the subsystems 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. */ private void validate(RequiredInterface[] aRequired) { List provided = new ArrayList(); for (Component system : _systems) { provided.addAll(Arrays.asList(system.getProvidedServices())); } List required = new ArrayList(); for (Component system : _systems) { required.addAll(Arrays.asList(system.getRequiredServices())); } for (ProvidedInterface service : getProvidedServices()) { if (!(provided.contains(service))) { throw new SystemAssemblyException(getName() + ": Service '" + service + "' is not provided by any of the subsystems"); } } for (RequiredInterface service : getRequiredServices()) { if (!(required.contains(service))) { info("Service '" + service + "' indicated as required is not actually required by any of the subsystems"); } } List reallyRequired = new ArrayList( required); // Compute all required interfaces that are not provided for (ProvidedInterface service : provided) { List fulfilled = Arrays.asList(SystemAssembler.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 (RequiredInterface service: reallyRequired) { missingRequired += service + "\n"; } if ( missingRequired.length() > 0 ) { throw new SystemAssemblyException(getName() + ": missing required services\n" + missingRequired); } } @Override protected void doStart(String aContext) { 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(aContext + ": required interface '" + intf +"' is not provided"); } provided.add(intf.getProvider()); } SystemAssembler assembler = new SystemAssembler( _systems, provided.toArray(new ProvidedInterface[0])); assembler.start(); } @Override protected void doStop() { for (int i = _systems.length-1; i >= 0; i--) { _systems[i].stop(); } } private void info(String aMsg) { LOG.info(getName() + ": " + aMsg); } }