X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=system%2Fgeneral%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsystem%2FSystemAssembler.java;h=90a98440ca877d7d98e02fed010a1a6017fa4cb1;hb=7526813969742844aefbd25e8a4a056985dc7f65;hp=5b2c0e143f0080f3a6df43a9c27eb592e5a9a9c8;hpb=47219ea21e66b5414eeb8b85049a2caa62e3547e;p=utils diff --git a/system/general/src/main/java/org/wamblee/system/SystemAssembler.java b/system/general/src/main/java/org/wamblee/system/SystemAssembler.java index 5b2c0e14..90a98440 100644 --- a/system/general/src/main/java/org/wamblee/system/SystemAssembler.java +++ b/system/general/src/main/java/org/wamblee/system/SystemAssembler.java @@ -1,17 +1,37 @@ +/* + * 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.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** - * Assembler to control multiple subsystems. It makes sure that - * all dependencies are met and controls the order in which systems - * are initialized. + * Assembler to control multiple subsystems. It makes sure that all dependencies + * are met and controls the order in which systems are initialized. + * + * @author Erik Brakkee */ public class SystemAssembler { @@ -19,48 +39,87 @@ public class SystemAssembler { private static final String ROOT_CONTEXT_NAME = "root"; private String _context; - private SubSystem[] _systems; + private Component[] _systems; + private ProvidedInterface[] _required; + + 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]); + } /** - * Constructs the assembler. - * @param aSystems Systems that must be assembled. - * @param aAvailableServices Available services from other systems - * outside of the systems that this assembler manages. + * Constructs the assembler. + * + * @param aSystems + * Systems that must be assembled. + * @param aAvailableServices + * Available services from other systems outside of the systems + * that this assembler manages. */ - public SystemAssembler(SubSystem[] aSystems, ServiceDescriptor[] aAvailableServices) { + public SystemAssembler(Component[] aSystems, + ProvidedInterface[] aAvailableServices) { this(ROOT_CONTEXT_NAME, aSystems, aAvailableServices); } /** - * Constructs the assembler. - * @param aContext Context (unique name) of the assembler. - * @param aSystems Systems that must be assembled. - * @param aAvailableServices Available services from other systems - * outside of the systems that this assembler manages. + * Constructs the assembler. + * + * @param aContext + * Context (unique name) of the assembler. + * @param aSystems + * Systems that must be assembled. + * @param aAvailableServices + * Available services from other systems outside of the systems + * that this assembler manages. */ - public SystemAssembler(String aContext, SubSystem[] aSystems, - ServiceDescriptor[] aAvailableServices) { + public SystemAssembler(String aContext, Component[] aSystems, + ProvidedInterface[] aAvailableServices) { _context = aContext; _systems = aSystems; - validate(aAvailableServices); + _required = aAvailableServices; + validate(); } /** * Determines if the systems are ordered appropriately so that all * dependencies are met. */ - private void validate(ServiceDescriptor[] aDescriptors) throws SystemAssemblyException { + private void validate() + throws SystemAssemblyException { - List allProvided = new ArrayList(); - for (ServiceDescriptor descriptor: aDescriptors) { + List allProvided = new ArrayList(); + for (ProvidedInterface descriptor : _required) { allProvided.add(descriptor); } - for (SubSystem system : _systems) { + for (Component system : _systems) { // Check if all required services are already provided by earlier // systems. - ServiceDescriptor[] required = system.getRequiredServices(); - for (ServiceDescriptor descriptor : required) { - if (!(allProvided.contains(descriptor))) { + RequiredInterface[] required = system.getRequiredServices(); + + for (RequiredInterface descriptor : required) { + ProvidedInterface[] filtered = filterProvidedServices( + descriptor, allProvided); + + if (filtered.length == 0) { throw new SystemAssemblyException( "Service '" + descriptor @@ -68,44 +127,56 @@ public class SystemAssembler { + 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)); + } } // add all provided services - ServiceDescriptor[] provided = system.getProvidedServices(); - for (ServiceDescriptor descriptor : provided) { - allProvided.add(descriptor); - } + ProvidedInterface[] provided = system.getProvidedServices(); + allProvided.addAll(Arrays.asList(provided)); } } /** * Starts the subsystems. - * @param aRegistry Service registry to which created services must be registered. - * @param aRequiredServices Services that are available from - * other systems that have been started before. + * + * @param aRequiredServices + * Services that are available from other systems that have been + * started before. */ - public void start(ServiceRegistry aRegistry, Service[] aRequiredServices) { + public void start() { LOG.info("Starting '" + _context + "'"); - Map allProvided = new HashMap(); - - for (Service service : aRequiredServices) { - allProvided.put(service.getDescriptor(), service); - } - for (SubSystem system : _systems) { - ServiceDescriptor[] descriptors = system.getRequiredServices(); - List services = new ArrayList(); - for (ServiceDescriptor descriptor : descriptors) { - Service required = allProvided.get(descriptor); - if (required == null) { - throw new SystemAssemblyException("Service '" + descriptor - + "' required by '" + system + "' is null."); - } - services.add(required); + Set allProvided = new HashSet(); + allProvided.addAll(Arrays.asList(_required)); + + for (Component system : _systems) { + + // Compose a list of the required services required for the subsystem. + + RequiredInterface[] descriptors = system + .getRequiredServices(); + List services = new ArrayList(); + for (RequiredInterface required : descriptors) { + ProvidedInterface[] provided = filterProvidedServices( + required, allProvided); + assert provided.length == 1; + services.add(provided[0]); + required.setProvider(provided[0]); } - Service[] provided = system.start(_context, aRegistry, services - .toArray(new Service[0])); - for (Service service : provided) { - allProvided.put(service.getDescriptor(), service); + + // Start the service. + system.start(_context); + + // Add started services to the set of started services. + for (ProvidedInterface service : system.getProvidedServices()) { + allProvided.add(service); } }