*
* @author Erik Brakkee
*/
-public class Container extends AbstractComponent {
+public class Container extends AbstractComponent<Scope> {
private static final Log LOG = LogFactory.getLog(Container.class);
- private Component[] _components;
+ private List<Component> _components;
+ private boolean _sealed;
public static RequiredInterface[] filterRequiredServices(
ProvidedInterface aProvided,
}
/**
- * Construcst the container
+ * Constructs the container
*
* @param aName
* Name of the container
public Container(String aName, Component[] aComponents,
ProvidedInterface[] aProvided, RequiredInterface[] aRequired) {
super(aName, aProvided, aRequired);
- _components = aComponents;
+ _components = new ArrayList<Component>(Arrays.asList(aComponents));
for (Component component : aComponents) {
component.addContext(getQualifiedName());
}
+ _sealed = false;
validate();
}
+
+ public Container(String aName) {
+ this(aName, new Component[0], new ProvidedInterface[0], new RequiredInterface[0]);
+ }
+
+ public Container addComponent(Component aComponent) {
+ checkSealed();
+ _components.add(aComponent);
+ return this;
+ }
+ @Override
+ protected Container addProvidedInterface(ProvidedInterface aProvided) {
+ checkSealed();
+ super.addProvidedInterface(aProvided);
+ return this;
+ }
+
+ @Override
+ protected Container addRequiredInterface(RequiredInterface aRequired) {
+ checkSealed();
+ super.addRequiredInterface(aRequired);
+ return this;
+ }
+
/**
* 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.
*/
- private void validate() {
+ public void validate() {
List<ProvidedInterface> provided = new ArrayList<ProvidedInterface>();
for (Component component : _components) {
provided.addAll(Arrays.asList(component.getProvidedInterfaces()));
}
}
}
+
+ /**
+ * Starts the container. After the container is started, the container becomes sealed
+ * meaning that no further components, required or provided interfaces may be added.
+ * @return Scope.
+ */
+ public Scope start() {
+ checkSealed();
+ validate();
+ Scope scope = super.start(new DefaultScope(new ProvidedInterface[0]));
+ seal();
+ return scope;
+ }
+
+ /**
+ * 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() {
+ return _sealed;
+ }
@Override
- protected void doStart() {
+ protected Scope doStart(Scope aExternalScope) {
LOG.info("Starting '" + getQualifiedName() + "'");
+
+ Scope scope = new DefaultScope(getProvidedInterfaces(),
+ aExternalScope);
+
List<ProvidedInterface> allProvided = new ArrayList<ProvidedInterface>();
// all interfaces from the required list of this container are
checkAllRequiredServicesAlreadyProvided(allProvided, component);
// Start the service.
- component.start();
+ Object runtime = component.start(scope);
+ scope.addRuntime(component, runtime);
started.add(component);
// add all provided services
} catch (RuntimeException e) {
LOG.error(getQualifiedName() + ": could not start '"
+ component.getQualifiedName() + "'", e);
- stopAlreadyStartedComponents(started);
+ stopAlreadyStartedComponents(started, scope);
throw e;
}
}
-
+ return scope;
}
- private void stopAlreadyStartedComponents(List<Component> aStarted) {
+ private void stopAlreadyStartedComponents(List<Component> aStarted, Scope aScope) {
// an exception occurred, stop the successfully started
// components
for (int i = aStarted.size() - 1; i >= 0; i--) {
try {
- aStarted.get(i).stop();
+ aStarted.get(i).stop(aScope);
} catch (Throwable t) {
LOG.error(getQualifiedName() + ": error stopping "
+ aStarted.get(i).getQualifiedName());
+ "' required by system '"
+ aComponent
+ "' matches multiple services provided by other systems: "
- + Arrays.asList(filtered));
+ + getServers(filtered));
} else {
// filtered.length == 0
if ( !descriptor.isOptional()) {
}
@Override
- protected void doStop() {
- for (int i = _components.length - 1; i >= 0; i--) {
- _components[i].stop();
+ protected void doStop(Scope aScope) {
+ for (int i = _components.size() - 1; i >= 0; i--) {
+ Component component = _components.get(i);
+ Object runtime = aScope.getRuntime(component);
+ component.stop(runtime);
}
}
private void warn(String aMsg) {
LOG.warn(getQualifiedName() + ": " + aMsg);
}
+
+ private String getServers(ProvidedInterface[] aProvidedList ) {
+ String result = "";
+ for (ProvidedInterface provided: aProvidedList) {
+ result += "(components ";
+ for (Component component: _components) {
+ for (ProvidedInterface provided2: component.getProvidedInterfaces()) {
+ if ( provided.equals(provided2)) {
+ result += component + " ";
+ }
+ }
+ }
+ result += ", interface " + provided + ")";
+ }
+ return result;
+ }
private List<Component> getClients(RequiredInterface aRequirement) {
List<Component> clients = new ArrayList<Component>();
}
return clients;
}
+
+ private void checkSealed() {
+ if ( _sealed ) {
+ throw new SystemAssemblyException("Container is sealed");
+ }
+ }
}