(no commit message)
[utils] / system / general / src / main / java / org / wamblee / system / core / Container.java
index ec45283e2d0fff00b1bc711658d80f5310414994..b7ee4e60c6ddcb61f0fed6c52b911cfb37fb7998 100644 (file)
@@ -12,7 +12,7 @@
  * 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.core;
 
 import java.util.ArrayList;
@@ -26,8 +26,8 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 /**
- * Composite system consisting of multiple subsystems. 
- *
+ * Composite system consisting of multiple subsystems.
+ * 
  * @author Erik Brakkee
  */
 public class Container extends AbstractComponent {
@@ -49,8 +49,7 @@ public class Container extends AbstractComponent {
        }
 
        public static ProvidedInterface[] filterProvidedServices(
-                       RequiredInterface aRequired,
-                       Collection<ProvidedInterface> aProvided) {
+                       RequiredInterface aRequired, Collection<ProvidedInterface> aProvided) {
                List<ProvidedInterface> provided = new ArrayList<ProvidedInterface>();
                for (ProvidedInterface descriptor : aProvided) {
                        if (aRequired.implementedBy(descriptor)) {
@@ -59,30 +58,36 @@ public class Container extends AbstractComponent {
                }
                return provided.toArray(new ProvidedInterface[0]);
        }
-       
+
        /**
-        * Construcst the composite system. 
-        * @param aName Name of the system. 
-        * @param aRegistry Service registry.
-        * @param aSystems Subsystems. 
-        * @param aProvided Provided services of the system. 
-        * @param aRequired Required services by the system. 
+        * Construcst the composite system.
+        * 
+        * @param aName
+        *            Name of the system.
+        * @param aRegistry
+        *            Service registry.
+        * @param aSystems
+        *            Subsystems.
+        * @param aProvided
+        *            Provided services of the system.
+        * @param aRequired
+        *            Required services by the system.
         */
        public Container(String aName, Component[] aSystems,
                        ProvidedInterface[] aProvided, RequiredInterface[] aRequired) {
                super(aName, aProvided, aRequired);
                _systems = aSystems;
-               for (Component component: aSystems) { 
+               for (Component component : aSystems) {
                        component.addContext(getQualifiedName());
                }
                validate(aRequired);
        }
 
        /**
-        * Validates the subsystems 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.  
+        * Validates the subsystems 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(RequiredInterface[] aRequired) {
                List<ProvidedInterface> provided = new ArrayList<ProvidedInterface>();
@@ -97,7 +102,8 @@ public class Container extends AbstractComponent {
 
                for (ProvidedInterface service : getProvidedInterfaces()) {
                        if (!(provided.contains(service))) {
-                               throw new SystemAssemblyException(getName() + ": Service '" + service
+                               throw new SystemAssemblyException(getName() + ": Service '"
+                                               + service
                                                + "' is not provided by any of the subsystems");
                        }
                }
@@ -114,42 +120,43 @@ public class Container extends AbstractComponent {
                                required);
                // Compute all required interfaces that are not provided
                for (ProvidedInterface service : provided) {
-                       List<RequiredInterface> fulfilled = 
-                               Arrays.asList(filterRequiredServices(service, 
-                                       reallyRequired));
-                       reallyRequired.removeAll(fulfilled); 
+                       List<RequiredInterface> fulfilled = Arrays
+                                       .asList(filterRequiredServices(service, reallyRequired));
+                       reallyRequired.removeAll(fulfilled);
                }
                // Now the remaining interfaces should be covered by the required
-               // list. 
+               // list.
                reallyRequired.removeAll(Arrays.asList(aRequired));
-               
+
                String missingRequired = "";
-               for (RequiredInterface service: reallyRequired) {
+               for (RequiredInterface service : reallyRequired) {
                        missingRequired += service + "\n";
                }
-               if ( missingRequired.length() > 0 ) { 
-                       throw new SystemAssemblyException(getName() + ": missing required services\n" + missingRequired);
+               if (missingRequired.length() > 0) {
+                       throw new SystemAssemblyException(getName()
+                                       + ": missing required services\n" + missingRequired);
                }
        }
 
        @Override
        protected void doStart() {
                List<ProvidedInterface> provided = new ArrayList<ProvidedInterface>();
-               
+
                // all interfaces from the required list of this container are
                // provided to the components inside it.
                RequiredInterface[] required = getRequiredInterfaces();
-               for (RequiredInterface intf: required) { 
-                   ProvidedInterface provider = intf.getProvider(); 
-                   if ( provider == null ) { 
-                       throw new SystemAssemblyException(getQualifiedName() + ": required interface '" + intf +"' is not provided");
-                   }
+               for (RequiredInterface intf : required) {
+                       ProvidedInterface provider = intf.getProvider();
+                       if (provider == null) {
+                               throw new SystemAssemblyException(getQualifiedName()
+                                               + ": required interface '" + intf + "' is not provided");
+                       }
                        provided.add(intf.getProvider());
                }
-               
+
                startImpl();
        }
-       
+
        /**
         * Starts the subsystems.
         * 
@@ -160,55 +167,77 @@ public class Container extends AbstractComponent {
        private void startImpl() {
                LOG.info("Starting '" + getQualifiedName() + "'");
                List<ProvidedInterface> allProvided = new ArrayList<ProvidedInterface>();
-               
-               // Add the provides of all externally required interfaces to the list of available
+
+               // Add the provides of all externally required interfaces to the list of
+               // available
                // interfaces
-               for (RequiredInterface required: getRequiredInterfaces()) { 
+               for (RequiredInterface required : getRequiredInterfaces()) {
                        allProvided.add(required.getProvider());
                }
-               
+
+               List<Component> started = new ArrayList<Component>();
                for (Component system : _systems) {
-                       // Check if all required services are already provided by earlier
-                       // systems.
-                       RequiredInterface[] required = system.getRequiredInterfaces();
-
-                       for (RequiredInterface descriptor : required) {
-                               ProvidedInterface[] filtered = filterProvidedServices(
-                                               descriptor, allProvided);
-
-                               if (filtered.length == 0) {
-                                       throw new SystemAssemblyException(
-                                                       "Service '"
-                                                                       + descriptor
-                                                                       + "' required by system '"
-                                                                       + system
-                                                                       + "' is not provided by systems that are started earlier");
+                       try {
+                               // Check if all required services are already provided by
+                               // earlier
+                               // systems.
+                               RequiredInterface[] required = system.getRequiredInterfaces();
+
+                               for (RequiredInterface descriptor : required) {
+                                       ProvidedInterface[] filtered = filterProvidedServices(
+                                                       descriptor, allProvided);
+
+                                       if (filtered.length == 0) {
+                                               throw new SystemAssemblyException(
+                                                               "Service '"
+                                                                               + descriptor
+                                                                               + "' required by system '"
+                                                                               + 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));
+                                       }
+                                       descriptor.setProvider(filtered[0]);
                                }
-                               if (filtered.length > 1) {
-                                       throw new SystemAssemblyException(
-                                                       "Service '"
-                                                                       + descriptor
-                                                                       + "' required by system '"
-                                                                       + system
-                                                                       + "' matches multiple services provided by other systems: " + 
-                                                                       Arrays.asList(filtered));
+
+                               // Start the service.
+                               system.start();
+                               started.add(system);
+
+                               // add all provided services
+                               ProvidedInterface[] provided = system.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());
+                                       }
                                }
-                               descriptor.setProvider(filtered[0]);
+                               throw e; 
                        }
-                       
-                       // Start the service. 
-                       system.start();
-
-                       // add all provided services
-                       ProvidedInterface[] provided = system.getProvidedInterfaces();
-                       allProvided.addAll(Arrays.asList(provided));
                }
+
        }
 
-       
        @Override
        protected void doStop() {
-               for (int i = _systems.length-1; i >= 0; i--) { 
+               for (int i = _systems.length - 1; i >= 0; i--) {
                        _systems[i].stop();
                }
        }