import org.apache.commons.logging.LogFactory;
/**
- * Composite system consisting of multiple subsystems.
+ * Container consisting of multiple components.
*
* @author Erik Brakkee
*/
private static final Log LOG = LogFactory.getLog(Container.class);
- private Component[] _systems;
+ private Component[] _components;
public static RequiredInterface[] filterRequiredServices(
ProvidedInterface aProvided,
}
/**
- * Construcst the composite system.
+ * Construcst the container
*
* @param aName
- * Name of the system.
- * @param aRegistry
- * Service registry.
- * @param aSystems
- * Subsystems.
+ * Name of the container
+ * @param aComponents
+ * Components.
* @param aProvided
- * Provided services of the system.
+ * Provided services of the container
* @param aRequired
- * Required services by the system.
+ * Required services by the container.
*/
- public Container(String aName, Component[] aSystems,
+ public Container(String aName, Component[] aComponents,
ProvidedInterface[] aProvided, RequiredInterface[] aRequired) {
super(aName, aProvided, aRequired);
- _systems = aSystems;
- for (Component component : aSystems) {
+ _components = aComponents;
+ for (Component component : aComponents) {
component.addContext(getQualifiedName());
}
validate();
}
/**
- * Validates the subsystems together to check that there are no required
+ * 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.
*/
private void validate() {
List<ProvidedInterface> provided = new ArrayList<ProvidedInterface>();
- for (Component system : _systems) {
- provided.addAll(Arrays.asList(system.getProvidedInterfaces()));
+ for (Component component : _components) {
+ provided.addAll(Arrays.asList(component.getProvidedInterfaces()));
}
List<RequiredInterface> required = new ArrayList<RequiredInterface>();
- for (Component system : _systems) {
- required.addAll(Arrays.asList(system.getRequiredInterfaces()));
+ for (Component component : _components) {
+ required.addAll(Arrays.asList(component.getRequiredInterfaces()));
}
validateProvidedInterfaces(provided);
}
private List<RequiredInterface> validateRequiredProvidedMatch(
- List<ProvidedInterface> provided, List<RequiredInterface> required) {
+ List<ProvidedInterface> aProvided, List<RequiredInterface> aRequired) {
List<RequiredInterface> reallyRequired = new ArrayList<RequiredInterface>(
- required);
+ aRequired);
// Compute all required interfaces that are not provided
- for (ProvidedInterface service : provided) {
+ for (ProvidedInterface service : aProvided) {
List<RequiredInterface> fulfilled = Arrays
.asList(filterRequiredServices(service, reallyRequired));
reallyRequired.removeAll(fulfilled);
return reallyRequired;
}
- private void validateRequiredInterfaces(List<RequiredInterface> required) {
+ private void validateRequiredInterfaces(List<RequiredInterface> aRequired) {
for (RequiredInterface service : getRequiredInterfaces()) {
- // TODO required services by the subsystem could be
+ // TODO required interfaces by the component could be
// subclasses or implementations of the requirements
- // of the contained systems. The code below assumes
+ // of the contained components. The code below assumes
// an exact match.
- if (!(required.contains(service))) {
+ if (!(aRequired.contains(service))) {
info("Service '"
+ service
- + "' indicated as required is not actually required by any of the subsystems");
+ + "' indicated as required is not actually required by any of the components");
}
// Check for the case that the externally required service
// is optional whereas the internally required service is
// mandatory.
if ( service.isOptional()) {
- for (RequiredInterface intf: required) {
- if ( intf.equals(service) && !intf.isOptional()) {
- // TODO indicate which subsystem this is.
- warn("Required service '" + service + "' indicated as optional is mandatory by one of its subsystems (" + getClients(intf) + ", " + intf + "), this can lead to problems when the system is started and the service is not there.");
+ for (RequiredInterface intf: aRequired) {
+ if ( intf.equals(service) && !intf.isOptional()) {
+ warn("Required service '" + service + "' indicated as optional is mandatory by one of its components (" + getClients(intf) + ", " + intf + "), this can lead to problems when the container is started and the interface is not provided to the container.");
}
}
}
}
}
- private void validateProvidedInterfaces(List<ProvidedInterface> provided) {
+ private void validateProvidedInterfaces(List<ProvidedInterface> aProvided) {
for (ProvidedInterface service : getProvidedInterfaces()) {
- // TODO provided interfaces by subsystems could be
+ // TODO provided interfaces by components could be
// provide subclasses or implementations of the
// provided interfaces of the container.
// The code below assumes an exact match.
- if (!(provided.contains(service))) {
+ if (!(aProvided.contains(service))) {
throw new SystemAssemblyException(getName() + ": Service '"
+ service
- + "' is not provided by any of the subsystems");
+ + "' is not provided by any of its components");
}
}
}
}
List<Component> started = new ArrayList<Component>();
- for (Component system : _systems) {
+ for (Component component : _components) {
try {
- // Check if all required services are already provided by
- // earlier
- // systems.
-
- for (RequiredInterface descriptor : system.getRequiredInterfaces()) {
- ProvidedInterface[] filtered = filterProvidedServices(
- descriptor, allProvided);
- if ( filtered.length == 1 ) {
- descriptor.setProvider(filtered[0]);
- } else if ( filtered.length > 1 ) {
- throw new SystemAssemblyException(
- "Service '"
- + descriptor
- + "' required by system '"
- + system
- + "' matches multiple services provided by other systems: "
- + Arrays.asList(filtered));
- } else {
- // filtered.length == 0
- if ( !descriptor.isOptional()) {
- throw new SystemAssemblyException(
- "Service '"
- + descriptor
- + "' required by system '"
- + system
- + "' is not provided by systems that are started earlier");
- }
- }
- }
+ checkAllRequiredServicesAlreadyProvided(allProvided, component);
// Start the service.
- system.start();
- started.add(system);
+ component.start();
+ started.add(component);
// add all provided services
- ProvidedInterface[] provided = system.getProvidedInterfaces();
+ ProvidedInterface[] provided = component.getProvidedInterfaces();
allProvided.addAll(Arrays.asList(provided));
} catch (SystemAssemblyException e) {
throw e;
} catch (RuntimeException e) {
LOG.error(getQualifiedName() + ": could not start '"
- + system.getQualifiedName() + "'", e);
- // an exception occurred, stop the successfully started
- // systems
- for (int i = started.size() - 1; i >= 0; i--) {
- try {
- started.get(i).stop();
- } catch (Throwable t) {
- LOG.error(getQualifiedName() + ": error stopping "
- + started.get(i).getQualifiedName());
- }
- }
+ + component.getQualifiedName() + "'", e);
+ stopAlreadyStartedComponents(started);
throw e;
}
}
}
+ private void stopAlreadyStartedComponents(List<Component> aStarted) {
+ // an exception occurred, stop the successfully started
+ // components
+ for (int i = aStarted.size() - 1; i >= 0; i--) {
+ try {
+ aStarted.get(i).stop();
+ } catch (Throwable t) {
+ LOG.error(getQualifiedName() + ": error stopping "
+ + aStarted.get(i).getQualifiedName());
+ }
+ }
+ }
+
+ private void checkAllRequiredServicesAlreadyProvided(
+ List<ProvidedInterface> aAllProvided, Component aComponent) {
+ // Check if all required services are already provided by
+ // earlier
+ // systems.
+
+ for (RequiredInterface descriptor : aComponent.getRequiredInterfaces()) {
+ ProvidedInterface[] filtered = filterProvidedServices(
+ descriptor, aAllProvided);
+ if ( filtered.length == 1 ) {
+ descriptor.setProvider(filtered[0]);
+ } else if ( filtered.length > 1 ) {
+ throw new SystemAssemblyException(
+ "Service '"
+ + descriptor
+ + "' required by system '"
+ + aComponent
+ + "' matches multiple services provided by other systems: "
+ + Arrays.asList(filtered));
+ } else {
+ // filtered.length == 0
+ if ( !descriptor.isOptional()) {
+ throw new SystemAssemblyException(
+ "Service '"
+ + descriptor
+ + "' required by system '"
+ + aComponent
+ + "' is not provided by systems that are started earlier");
+ }
+ }
+ }
+ }
+
@Override
protected void doStop() {
- for (int i = _systems.length - 1; i >= 0; i--) {
- _systems[i].stop();
+ for (int i = _components.length - 1; i >= 0; i--) {
+ _components[i].stop();
}
}
private List<Component> getClients(RequiredInterface aRequirement) {
List<Component> clients = new ArrayList<Component>();
- for (Component component: _systems) {
+ for (Component component: _components) {
for (RequiredInterface required: component.getRequiredInterfaces()) {
if ( required.equals(aRequirement) && required.isOptional() == aRequirement.isOptional()) {
clients.add(component);