(no commit message)
[utils] / system / general / src / main / java / org / wamblee / system / core / AbstractComponent.java
index 5d89e4a46f839078c7adc5876bae684a3d2cdb8f..aea2bd6b5cebd7e5bbf804d7044cc0ca2904764e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 the original author or authors.
+ * Copyright 2005-2010 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.
  * 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;
 import java.util.Arrays;
-import java.util.HashSet;
+import java.util.Collections;
 import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import java.util.logging.Logger;
 
 /**
  * Abstract subsystem class making it easy to implement new subsystems.
+ * 
  */
-public abstract class AbstractComponent implements Component {
-
-       private static final Log LOG = LogFactory.getLog(AbstractComponent.class);
-
-       private Status _status;
-       private String _context; 
-       private String _name; 
-       private List<ProvidedInterface> _provided;
-       private List<RequiredInterface> _required;
-       private Set<ProvidedInterface> _running;
-       
-       /**
-        * Constructs the subsystem.
-        *
-        * @param aName
-        *            Name of the system.
-        * @param aProvided
-        *            Provided services.
-        * @param aRequired
-        *            Required services.
-        */
-       protected AbstractComponent(String aName, ProvidedInterface[] aProvided,
-                       RequiredInterface[] aRequired) {
-               _status = Status.NOT_STARTED;
-               _context = null; 
-               _name = aName;
-               _provided = new ArrayList<ProvidedInterface>();
-               _provided.addAll(Arrays.asList(aProvided));
-               _required = new ArrayList<RequiredInterface>();
-               _required.addAll(Arrays.asList(aRequired));
-               _running = new HashSet<ProvidedInterface>();
-       }
-       
-       @Override
-       public Status getStatus() {
-               return _status; 
-       }
-
-       @Override
-       public final String getName() {
-               return _name;
-       }
-       
-       @Override
-       public void addContext(String aContext) {
-               if (_context == null ) { 
-                       _context = aContext; 
-               }
-               else { 
-                       _context = aContext + "." + _context;
-               }
-       }
-       
-       @Override
-       public String getQualifiedName() {
-               if ( _context == null ) { 
-                       return getName(); 
-               }
-               return _context + "." + getName(); 
-       }
-
-       @Override
-       public final ProvidedInterface[] getProvidedServices() {
-               return _provided.toArray(new ProvidedInterface[0]);
-       }
-
-       @Override
-       public final RequiredInterface[] getRequiredServices() {
-               return _required.toArray(new RequiredInterface[0]);
-       }
-
-       @Override
-       public final void start() {
-               LOG.info("Initializing '" + getQualifiedName() + "'");
-               doStart();
-               _status = Status.RUNNING;
-               if ( _running.size() != _provided.size()) { 
-                       List<ProvidedInterface> remaining = 
-                               new ArrayList<ProvidedInterface>(_provided);
-                       remaining.removeAll(_running);
-                       throw new SystemAssemblyException(getQualifiedName() + ": not all services were started, missing " + remaining);
-               }
-       }
-
-       /**
-        * Must be implemented for initializing the subsystem. The implementation
-        * must call {@link #addService(Service)} for each service that is started.
-        */
-       protected abstract void doStart();
-
-       /**
-        * Implementations must call this method to indicate that a new service has
-        * been started.
-        * 
-        * @param aService
-        *            Service.
-        */
-       protected final void addService(
-                       ProvidedInterface aDescriptor, Object aService) {
-               LOG.info("Interface '" + getQualifiedName() + "." + aDescriptor.getName() + "' started.");
-               _running.add(aDescriptor);
-               aDescriptor.publish(aService);
-       }
-
-       @Override
-       public ProvidedInterface[] getRunningServices() {
-               return _running.toArray(new ProvidedInterface[0]);
-       }
-       
-       @Override
-       public void stop() {
-               doStop();       
-               _status = Status.STOPPED;
-       }
-       
-       protected abstract void doStop(); 
-
-       @Override
-       public String toString() {
-               return _name;
-       }
+public abstract class AbstractComponent<Type> implements Component<Type> {
+    private static final Logger LOG = Logger.getLogger(AbstractComponent.class
+        .getName());
+
+    private ThreadLocal<List<ProvidedInterface>> remaining;
+
+    private String context;
+
+    private String name;
+
+    private List<ProvidedInterface> provided;
+
+    private List<RequiredInterface> required;
+
+    /**
+     * Constructs the subsystem.
+     * 
+     * @param aName
+     *            Name of the system.
+     * @param aProvided
+     *            Provided services.
+     * @param aRequired
+     *            Required services.
+     */
+    protected AbstractComponent(String aName,
+        List<ProvidedInterface> aProvided, List<RequiredInterface> aRequired) {
+        remaining = new ThreadLocal<List<ProvidedInterface>>();
+        context = null;
+        name = aName;
+        provided = new ArrayList<ProvidedInterface>(aProvided);
+        required = new ArrayList<RequiredInterface>(aRequired);
+    }
+
+    /**
+     * Constructs the subsystem.
+     * 
+     * @param aName
+     *            Name of the system.
+     * @param aProvided
+     *            Provided services.
+     * @param aRequired
+     *            Required services.
+     */
+    protected AbstractComponent(String aName, ProvidedInterface[] aProvided,
+        RequiredInterface[] aRequired) {
+        this(aName, Arrays.asList(aProvided), Arrays.asList(aRequired));
+    }
+
+    /**
+     * Creates a new AbstractComponent object.
+     * 
+     */
+    protected AbstractComponent(String aName) {
+        this(aName, new ProvidedInterface[0], new RequiredInterface[0]);
+    }
+
+    public AbstractComponent<Type> addProvidedInterface(
+        ProvidedInterface aProvided) {
+        provided.add(aProvided);
+
+        return this;
+    }
+
+    public AbstractComponent<Type> addRequiredInterface(
+        RequiredInterface aRequired) {
+        required.add(aRequired);
+
+        return this;
+    }
+
+    @Override
+    public final String getName() {
+        return name;
+    }
+
+    @Override
+    public void addContext(String aContext) {
+        if (context == null) {
+            context = aContext;
+        } else {
+            context = aContext + "." + context;
+        }
+    }
+
+    @Override
+    public String getContext() {
+        return context;
+    }
+
+    @Override
+    public String getQualifiedName() {
+        if (context == null) {
+            return getName();
+        }
+
+        return context + "." + getName();
+    }
+
+    @Override
+    public final List<ProvidedInterface> getProvidedInterfaces() {
+        return Collections.unmodifiableList(provided);
+    }
+
+    @Override
+    public final List<RequiredInterface> getRequiredInterfaces() {
+        return Collections.unmodifiableList(required);
+    }
+
+    @Override
+    public final Type start(Scope aScope) {
+        LOG.info("Initialization starting '" + getQualifiedName() + "'");
+
+        List<ProvidedInterface> oldRemaining = remaining.get();
+        remaining
+            .set(new ArrayList<ProvidedInterface>(getProvidedInterfaces()));
+
+        try {
+            Type runtime = doStart(aScope);
+            checkNotStartedInterfaces();
+            LOG.info("Initialization finished '" + getQualifiedName() + "'");
+
+            return runtime;
+        } finally {
+            remaining.set(oldRemaining);
+        }
+    }
+
+    private void checkNotStartedInterfaces() {
+        if (remaining.get().size() > 0) {
+            StringBuffer notProvided = new StringBuffer();
+
+            for (ProvidedInterface providedIntf : remaining.get()) {
+                notProvided.append("\nComponent " + getQualifiedName() +
+                    " did not start interface " + providedIntf);
+            }
+
+            throw new SystemAssemblyException(notProvided.toString());
+        }
+    }
+
+    /**
+     * Must be implemented for initializing the subsystem. The implementation
+     * must call {@link #addInterface(ProvidedInterface, Object, Scope)} for
+     * each service that is started.
+     * 
+     * 
+     * @return Returns the runtime of the component.
+     */
+    protected abstract Type doStart(Scope aScope);
+
+    /**
+     * Implementations must call this method to indicate that a new service has
+     * been started.
+     * 
+     * @param aDescriptor
+     *            Provided interface.
+     * @param aService
+     *            Implementation of the interface.
+     * @param aScope
+     *            scope in which to publish the implementation.
+     * 
+     */
+    protected final void addInterface(ProvidedInterface aDescriptor,
+        Object aService, Scope aScope) {
+        LOG.info("Interface '" + getQualifiedName() + "." +
+            aDescriptor.getName() + "' started.");
+
+        if (!remaining.get().remove(aDescriptor)) {
+            throw new SystemAssemblyException("Component '" +
+                getQualifiedName() + "' started an unexpected interface '" +
+                aDescriptor +
+                "' that was not registerd as a provided interface before");
+        }
+
+        aScope.publishInterface(aDescriptor, aService);
+    }
+
+    @Override
+    public void stop(Type aRuntime) {
+        LOG.info("Stopping initiated '" + getQualifiedName() + "'");
+        doStop(aRuntime);
+        LOG.info("Stopping completed '" + getQualifiedName() + "'");
+    }
+
+    protected abstract void doStop(Type aRuntime);
+
+    @Override
+    public String toString() {
+        return getQualifiedName();
+    }
+
+    public ProvidedInterface findProvidedInterface(String aName) {
+        for (ProvidedInterface providedIntf : getProvidedInterfaces()) {
+            if (providedIntf.getName().equals(aName)) {
+                return providedIntf;
+            }
+        }
+
+        return null;
+    }
+
+    public RequiredInterface findRequiredInterface(String aName) {
+        for (RequiredInterface requiredIntf : getRequiredInterfaces()) {
+            if (requiredIntf.getName().equals(aName)) {
+                return requiredIntf;
+            }
+        }
 
+        return null;
+    }
 }