/*
* 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.
*/
package org.wamblee.system.container;
-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 org.wamblee.general.Pair;
+
import org.wamblee.system.core.AbstractComponent;
import org.wamblee.system.core.Component;
import org.wamblee.system.core.DefaultScope;
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<Scope> {
-
+ /**
+ * DOCUMENT ME!
+ */
private static final Log LOG = LogFactory.getLog(Container.class);
+ /**
+ * DOCUMENT ME!
+ */
private List<Component> components;
- private CompositeEdgeFilter edgeFilter;
- private boolean sealed;
/**
+ * DOCUMENT ME!
+ */
+ private CompositeEdgeFilter edgeFilter;
+
+ /**
+ * DOCUMENT ME!
+ */
+ private boolean sealed;
+
+/**
* Constructs the container
*
* @param aName
* Required services by the container.
*/
public Container(String aName, Component[] aComponents,
- List<ProvidedInterface> aProvided, List<RequiredInterface> aRequired) {
+ List<ProvidedInterface> aProvided, List<RequiredInterface> aRequired) {
super(aName, aProvided, aRequired);
- components = new ArrayList<Component>();
+ components = new ArrayList<Component>();
+
+ edgeFilter = new CompositeEdgeFilter();
+ sealed = false;
- edgeFilter = new CompositeEdgeFilter();
- sealed = false;
for (Component component : aComponents) {
addComponent(component);
}
}
-
- /**
+
+/**
* Constructs the container
*
* @param aName
* 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);
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();
+
Component client = findComponent(aComponent);
- if ( client == null ) {
- throw new SystemAssemblyException(getQualifiedName() + ": No component '" + aComponent + "' in the container");
+
+ 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 (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 + "'");
- }
+
+ 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();
+
Component server = findComponent(aComponent);
-
-
- if ( server == null ) {
- throw new SystemAssemblyException("No component '" + aComponent + "' in the container");
+
+ 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 (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 + "'");
- }
+
+ 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));
- }
+ 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) {
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;
/**
* Checks if the container is sealed.
- *
+ *
* @return True iff the container is sealed.
*/
public boolean isSealed() {
}
/**
- * 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) {
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<ProvidedInterface,ProvidedInterface> 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<ProvidedInterface, ProvidedInterface> 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();
LOG.info("Starting '" + getQualifiedName() + "'");
List<Component> started = new ArrayList<Component>();
+
for (Component component : components) {
try {
// Start the service.
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) {
graph.addComponent(comp);
}
- for (ProvidedInterface prov: getProvidedInterfaces()) {
+
+ for (ProvidedInterface prov : getProvidedInterfaces()) {
graph.addProvidedInterface(this, prov);
}
graph.addEdgeFilter(edgeFilter);
+
return graph;
}
+ /**
+ * DOCUMENT ME!
+ *
+ * @param aStarted DOCUMENT ME!
+ * @param aScope DOCUMENT ME!
+ */
private void stopAlreadyStartedComponents(List<Component> aStarted,
- Scope aScope) {
+ Scope aScope) {
// an exception occurred, stop the successfully started
// components
for (int i = aStarted.size() - 1; i >= 0; i--) {
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);
+ Object runtime = aScope.getRuntime(component);
component.stop(runtime);
}
}
+ /**
+ * DOCUMENT ME!
+ */
private void checkSealed() {
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 extends NamedInterface> T findInterface(List<T> aInterfaces, String aInterfaceName) {
- for (T intf: aInterfaces) {
- if ( intf.getName().equals(aInterfaceName)) {
- return intf;
- }
- }
- return null;
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param <T> DOCUMENT ME!
+ * @param aInterfaces DOCUMENT ME!
+ * @param aInterfaceName DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ private static <T extends NamedInterface> T findInterface(
+ List<T> aInterfaces, String aInterfaceName) {
+ for (T intf : aInterfaces) {
+ if (intf.getName().equals(aInterfaceName)) {
+ return intf;
+ }
+ }
+
+ return null;
}
}