X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=system%2Fgeneral%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsystem%2Fcontainer%2FContainer.java;h=bb69712de4df6124b75ff76a209c841d0c45591c;hb=ddd261f331280640c5b53c7128230b629ebcd268;hp=9ef2ae18d817a0e35f8fda0c20c525a29d08775e;hpb=b8c91461116e84e47d5a9aa5047d8babfc8dfa03;p=utils diff --git a/system/general/src/main/java/org/wamblee/system/container/Container.java b/system/general/src/main/java/org/wamblee/system/container/Container.java index 9ef2ae18..bb69712d 100644 --- a/system/general/src/main/java/org/wamblee/system/container/Container.java +++ b/system/general/src/main/java/org/wamblee/system/container/Container.java @@ -1,12 +1,12 @@ /* * 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. @@ -15,15 +15,11 @@ */ package org.wamblee.system.container; -import java.util.ArrayList; -import java.util.Arrays; -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 org.wamblee.general.Pair; + import org.wamblee.system.core.AbstractComponent; import org.wamblee.system.core.Component; import org.wamblee.system.core.DefaultScope; @@ -38,20 +34,38 @@ import org.wamblee.system.graph.component.ConnectExternalProvidedProvidedFilter; import org.wamblee.system.graph.component.ConnectRequiredExternallyRequiredEdgeFilter; import org.wamblee.system.graph.component.ConnectRequiredProvidedEdgeFilter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + /** * Container consisting of multiple components. - * + * * @author Erik Brakkee */ public class Container extends AbstractComponent { - + /** + * DOCUMENT ME! + */ private static final Log LOG = LogFactory.getLog(Container.class); - private List _components; - private CompositeEdgeFilter _edgeFilter; - private boolean _sealed; + /** + * DOCUMENT ME! + */ + private List components; + + /** + * DOCUMENT ME! + */ + private CompositeEdgeFilter edgeFilter; /** + * DOCUMENT ME! + */ + private boolean sealed; + +/** * Constructs the container * * @param aName @@ -64,18 +78,19 @@ public class Container extends AbstractComponent { * Required services by the container. */ public Container(String aName, Component[] aComponents, - List aProvided, List aRequired) { + List aProvided, List aRequired) { super(aName, aProvided, aRequired); - _components = new ArrayList(); + components = new ArrayList(); + + edgeFilter = new CompositeEdgeFilter(); + sealed = false; - _edgeFilter = new CompositeEdgeFilter(); - _sealed = false; for (Component component : aComponents) { addComponent(component); } } - - /** + +/** * Constructs the container * * @param aName @@ -88,184 +103,326 @@ public class Container extends AbstractComponent { * Required services by the container. */ public Container(String aName, Component[] aComponents, - ProvidedInterface[] aProvided, RequiredInterface[] aRequired) { - this(aName, aComponents, Arrays.asList(aProvided), Arrays.asList(aRequired)); + ProvidedInterface[] aProvided, RequiredInterface[] aRequired) { + this(aName, aComponents, Arrays.asList(aProvided), + Arrays.asList(aRequired)); } + /** + * Creates a new Container object. + * + * @param aName DOCUMENT ME! + */ public Container(String aName) { this(aName, new Component[0], new ProvidedInterface[0], - new RequiredInterface[0]); + new RequiredInterface[0]); } + /** + * DOCUMENT ME! + * + * @param aComponent DOCUMENT ME! + * + * @return DOCUMENT ME! + */ public Container addComponent(Component aComponent) { checkSealed(); + if (aComponent.getContext() != null) { throw new SystemAssemblyException( - "Inconsistent hierarchy, component '" - + aComponent.getName() - + "' is already part of another hierarchy"); + "Inconsistent hierarchy, component '" + aComponent.getName() + + "' is already part of another hierarchy"); } - if ( findComponent(aComponent.getName()) != null ) { + + if (findComponent(aComponent.getName()) != null) { throw new SystemAssemblyException("Duplicate component '" - + aComponent.getName() + "'"); + + aComponent.getName() + "'"); } - _components.add(aComponent); + + components.add(aComponent); aComponent.addContext(getQualifiedName()); + return this; } - + /** - * Explictly connects required and provided interfaces. - * @param aClientComponent Client component, may not be null. - * @param aRequiredInterface Required interface. If null it means all required interfaces. - * @param aServerComponent Server component to connect to. If null, it means that no server components - * may be connected to and the provider of the required interface will be null. - * @param aProvidedInterface Provided interface. If null, it means that there is no restriction on the - * name of the provided interface and that it is automatically selected. + * Explictly connects required and provided interfaces. + * + * @param aClientComponent Client component, may not be null. + * @param aRequiredInterface Required interface. If null it means all + * required interfaces. + * @param aServerComponent Server component to connect to. If null, it + * means that no server components may be connected to and the + * provider of the required interface will be null. + * @param aProvidedInterface Provided interface. If null, it means that + * there is no restriction on the name of the provided interface + * and that it is automatically selected. + * + * @throws SystemAssemblyException DOCUMENT ME! */ - public void connectRequiredProvided(String aClientComponent, String aRequiredInterface, - String aServerComponent, String aProvidedInterface) { + public void connectRequiredProvided(String aClientComponent, + String aRequiredInterface, String aServerComponent, + String aProvidedInterface) { checkSealed(); + Component client = findComponent(aClientComponent); Component server = findComponent(aServerComponent); - if ( client == null ) { - throw new SystemAssemblyException(getQualifiedName() + ": No component '" + aClientComponent + "' in the container"); + + if (client == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": No component '" + aClientComponent + "' in the container"); } - if ( aRequiredInterface != null ) { - if ( findInterface(client.getRequiredInterfaces(), aRequiredInterface) == null ) { - throw new SystemAssemblyException( - getQualifiedName() + ": Component '" + aClientComponent + "' does not have a required interface named '" - + aRequiredInterface + "'"); - } + + if (aRequiredInterface != null) { + if (findInterface(client.getRequiredInterfaces(), aRequiredInterface) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": Component '" + aClientComponent + + "' does not have a required interface named '" + + aRequiredInterface + "'"); + } } - if ( server == null ) { - throw new SystemAssemblyException("No component '" + aClientComponent + "' in the container"); + + if (server == null) { + throw new SystemAssemblyException("No component '" + + aClientComponent + "' in the container"); } - if ( aProvidedInterface != null ) { - if ( findInterface(server.getProvidedInterfaces(), aProvidedInterface) == null) { - throw new SystemAssemblyException( - getQualifiedName() + ": Component '" + aServerComponent + "' does not have a provided interface named '" - + aProvidedInterface + "'"); - } + + if (aProvidedInterface != null) { + if (findInterface(server.getProvidedInterfaces(), aProvidedInterface) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": Component '" + aServerComponent + + "' does not have a provided interface named '" + + aProvidedInterface + "'"); + } } - _edgeFilter.add(new ConnectRequiredProvidedEdgeFilter(aClientComponent, aRequiredInterface, aServerComponent, aProvidedInterface)); + + edgeFilter.add(new ConnectRequiredProvidedEdgeFilter(aClientComponent, + aRequiredInterface, aServerComponent, aProvidedInterface)); } - + /** - * Explicitly connects a externally required interface to an internally required interface. - * @param aComponent Component requiring the interface (must be non-null). - * @param aRequiredInterface Required interface of the component (must be non-null). - * @param aExternalRequiredInterface Externally required interface (must be non-null). + * Explicitly connects a externally required interface to an + * internally required interface. + * + * @param aComponent Component requiring the interface (must be non-null). + * @param aRequiredInterface Required interface of the component (must be + * non-null). + * @param aExternalRequiredInterface Externally required interface (must be + * non-null). + * + * @throws SystemAssemblyException DOCUMENT ME! */ - public void connectExternalRequired(String aComponent, String aRequiredInterface, - String aExternalRequiredInterface) { + public void connectExternalRequired(String aComponent, + String aRequiredInterface, String aExternalRequiredInterface) { checkSealed(); - // TODO validate - _edgeFilter.add(new ConnectRequiredExternallyRequiredEdgeFilter( + + Component client = findComponent(aComponent); + + if (client == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": No component '" + aComponent + "' in the container"); + } + + if (aRequiredInterface != null) { + if (findInterface(client.getRequiredInterfaces(), aRequiredInterface) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": Component '" + aComponent + + "' does not have a required interface named '" + + aRequiredInterface + "'"); + } + } + + if (aExternalRequiredInterface != null) { + if (findInterface(getRequiredInterfaces(), + aExternalRequiredInterface) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": container does not have a required interface named '" + + aExternalRequiredInterface + "'"); + } + } + + edgeFilter.add(new ConnectRequiredExternallyRequiredEdgeFilter( aComponent, aRequiredInterface, aExternalRequiredInterface)); } - - public void connectExternalProvided(String aExternalProvided, String aComponent, String aProvidedInterface) { + + /** + * DOCUMENT ME! + * + * @param aExternalProvided DOCUMENT ME! + * @param aComponent DOCUMENT ME! + * @param aProvidedInterface DOCUMENT ME! + */ + public void connectExternalProvided(String aExternalProvided, + String aComponent, String aProvidedInterface) { checkSealed(); - // TODO validate - _edgeFilter.add(new ConnectExternalProvidedProvidedFilter(aExternalProvided, aComponent, aProvidedInterface)); - } + Component server = findComponent(aComponent); + if (server == null) { + throw new SystemAssemblyException("No component '" + aComponent + + "' in the container"); + } + + if (aProvidedInterface != null) { + if (findInterface(server.getProvidedInterfaces(), aProvidedInterface) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": Component '" + aComponent + + "' does not have a provided interface named '" + + aProvidedInterface + "'"); + } + } + + if (aExternalProvided != null) { + if (findInterface(getProvidedInterfaces(), aExternalProvided) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": Container does not have a provided interface named '" + + aExternalProvided + "'"); + } + } + + edgeFilter.add(new ConnectExternalProvidedProvidedFilter( + aExternalProvided, aComponent, aProvidedInterface)); + } + + /** + * DOCUMENT ME! + * + * @param aProvided DOCUMENT ME! + * + * @return DOCUMENT ME! + */ @Override public Container addProvidedInterface(ProvidedInterface aProvided) { checkSealed(); super.addProvidedInterface(aProvided); + return this; } + /** + * DOCUMENT ME! + * + * @param aRequired DOCUMENT ME! + * + * @return DOCUMENT ME! + */ @Override public Container addRequiredInterface(RequiredInterface aRequired) { checkSealed(); super.addRequiredInterface(aRequired); + return this; } + /** + * DOCUMENT ME! + * + * @param aContext DOCUMENT ME! + */ @Override public void addContext(String aContext) { super.addContext(aContext); - for (Component component : _components) { + + for (Component component : components) { component.addContext(aContext); } } /** - * Validates the components 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. - * - * @throws SystemAssemblyException - * in case of any validation problems. + * Validates the components 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. */ public void validate() { doStartOptionalDryRun(null, true); } /** - * Seal the container, meaning that no further components or interfaces may - * be added. + * Seal the container, meaning that no further components or + * interfaces may be added. */ public void seal() { - _sealed = true; + sealed = true; } /** * Checks if the container is sealed. - * + * * @return True iff the container is sealed. */ public boolean isSealed() { - return _sealed; + return sealed; } /** - * Utility method to start with an empty external scope. This is useful for - * top-level containers which are not part of another container. - * + * Utility method to start with an empty external scope. This is + * useful for top-level containers which are not part of another + * container. + * * @return Scope. */ public Scope start() { Scope scope = new DefaultScope(getProvidedInterfaces()); + return super.start(scope); } + /** + * DOCUMENT ME! + * + * @param aExternalScope DOCUMENT ME! + * + * @return DOCUMENT ME! + */ @Override protected Scope doStart(Scope aExternalScope) { - checkSealed(); validate(); - Scope scope = new DefaultScope(getProvidedInterfaces().toArray(new ProvidedInterface[0]), aExternalScope); + + Scope scope = new DefaultScope(getProvidedInterfaces() + .toArray(new ProvidedInterface[0]), aExternalScope); ComponentGraph graph = doStartOptionalDryRun(scope, false); exposeProvidedInterfaces(graph, aExternalScope, scope); seal(); + return scope; } - private void exposeProvidedInterfaces(ComponentGraph aGraph, Scope aExternalScope, - Scope aInternalScope) { - for (Pair mapping: - aGraph.findExternalProvidedInterfaceMapping()) { - Object svc = aInternalScope.getInterfaceImplementation(mapping.getSecond(), Object.class); + /** + * DOCUMENT ME! + * + * @param aGraph DOCUMENT ME! + * @param aExternalScope DOCUMENT ME! + * @param aInternalScope DOCUMENT ME! + */ + private void exposeProvidedInterfaces(ComponentGraph aGraph, + Scope aExternalScope, Scope aInternalScope) { + for (Pair mapping : aGraph + .findExternalProvidedInterfaceMapping()) { + Object svc = aInternalScope.getInterfaceImplementation(mapping + .getSecond(), Object.class); addInterface(mapping.getFirst(), svc, aExternalScope); } } + /** + * DOCUMENT ME! + * + * @param aScope DOCUMENT ME! + * @param aDryRun DOCUMENT ME! + * + * @return DOCUMENT ME! + */ private ComponentGraph doStartOptionalDryRun(Scope aScope, boolean aDryRun) { ComponentGraph graph = createComponentGraph(); graph.validate(); - if (!aDryRun) { - graph.link(); - } + graph.link(); LOG.info("Starting '" + getQualifiedName() + "'"); List started = new ArrayList(); - for (Component component : _components) { + + for (Component component : components) { try { // Start the service. if (!aDryRun) { @@ -277,32 +434,48 @@ public class Container extends AbstractComponent { throw e; } catch (RuntimeException e) { LOG.error(getQualifiedName() + ": could not start '" - + component.getQualifiedName() + "'", e); + + component.getQualifiedName() + "'", e); stopAlreadyStartedComponents(started, aScope); throw e; } } + return graph; } + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ private ComponentGraph createComponentGraph() { ComponentGraph graph = new ComponentGraph(); + for (RequiredInterface req : getRequiredInterfaces()) { graph.addRequiredInterface(this, req); } - for (Component comp : _components) { + + for (Component comp : components) { graph.addComponent(comp); } - for (ProvidedInterface prov: getProvidedInterfaces()) { + + for (ProvidedInterface prov : getProvidedInterfaces()) { graph.addProvidedInterface(this, prov); } - graph.addEdgeFilter(_edgeFilter); + graph.addEdgeFilter(edgeFilter); + return graph; } + /** + * DOCUMENT ME! + * + * @param aStarted DOCUMENT ME! + * @param aScope DOCUMENT ME! + */ private void stopAlreadyStartedComponents(List aStarted, - Scope aScope) { + Scope aScope) { // an exception occurred, stop the successfully started // components for (int i = aStarted.size() - 1; i >= 0; i--) { @@ -311,46 +484,69 @@ public class Container extends AbstractComponent { aStarted.get(i).stop(aScope.getRuntime(component)); } catch (Throwable t) { LOG.error(getQualifiedName() + ": error stopping " - + aStarted.get(i).getQualifiedName()); + + aStarted.get(i).getQualifiedName()); } } } + /** + * DOCUMENT ME! + * + * @param aScope DOCUMENT ME! + */ @Override protected void doStop(Scope aScope) { - for (int i = _components.size() - 1; i >= 0; i--) { - Component component = _components.get(i); - Object runtime = aScope.getRuntime(component); + for (int i = components.size() - 1; i >= 0; i--) { + Component component = components.get(i); + Object runtime = aScope.getRuntime(component); component.stop(runtime); } } + /** + * DOCUMENT ME! + */ private void checkSealed() { - if (_sealed) { + if (sealed) { throw new SystemAssemblyException("Container is sealed"); } } - + /** - * Finds a component based on the non-qualified name of the component. - * @param aName Component name. - * @return Component or null if not found. + * Finds a component based on the non-qualified name of the + * component. + * + * @param aName Component name. + * + * @return Component or null if not found. */ - public Component findComponent(String aName) { - for (Component component: _components) { - if ( component.getName().equals(aName)) { - return component; - } - } - return null; + public Component findComponent(String aName) { + for (Component component : components) { + if (component.getName().equals(aName)) { + return component; + } + } + + return null; } - - private static T findInterface(List aInterfaces, String aInterfaceName) { - for (T intf: aInterfaces) { - if ( intf.getName().equals(aInterfaceName)) { - return intf; - } - } - return null; + + /** + * DOCUMENT ME! + * + * @param DOCUMENT ME! + * @param aInterfaces DOCUMENT ME! + * @param aInterfaceName DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private static T findInterface( + List aInterfaces, String aInterfaceName) { + for (T intf : aInterfaces) { + if (intf.getName().equals(aInterfaceName)) { + return intf; + } + } + + return null; } }