* 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;
/**
* Abstract subsystem class making it easy to implement new subsystems.
*/
-public abstract class AbstractComponent implements Component {
+public abstract class AbstractComponent<Type> implements Component<Type> {
private static final Log LOG = LogFactory.getLog(AbstractComponent.class);
- private Status _status;
- private String _context;
- private String _name;
+ private ThreadLocal<List<ProvidedInterface>> _remaining;
+
+ 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
* @param aRequired
* Required services.
*/
- protected AbstractComponent(String aName, ProvidedInterface[] aProvided,
- RequiredInterface[] aRequired) {
- _status = Status.NOT_STARTED;
- _context = null;
+ protected AbstractComponent(String aName, List<ProvidedInterface> aProvided,
+ List<RequiredInterface> aRequired) {
+ _remaining = new ThreadLocal<List<ProvidedInterface>>();
+ _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>();
+ _provided = new ArrayList<ProvidedInterface>(aProvided);
+ _required = new ArrayList<RequiredInterface>(aRequired);
}
- @Override
- public Status getStatus() {
- return _status;
+ /**
+ * 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));
+ }
+
+ 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 {
+ if (_context == null) {
+ _context = aContext;
+ } else {
_context = aContext + "." + _context;
}
}
+ @Override
+ public String getContext() {
+ return _context;
+ }
+
@Override
public String getQualifiedName() {
- if ( _context == null ) {
- return getName();
+ if (_context == null) {
+ return getName();
}
- return _context + "." + getName();
+ return _context + "." + getName();
}
@Override
- public final ProvidedInterface[] getProvidedServices() {
- return _provided.toArray(new ProvidedInterface[0]);
+ public final List<ProvidedInterface> getProvidedInterfaces() {
+ return Collections.unmodifiableList(_provided);
}
@Override
- public final RequiredInterface[] getRequiredServices() {
- return _required.toArray(new RequiredInterface[0]);
+ public final List<RequiredInterface> getRequiredInterfaces() {
+ return Collections.unmodifiableList(_required);
}
@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);
+ 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) {
+ String notProvided = "";
+ for (ProvidedInterface provided : _remaining.get()) {
+ notProvided += "\nComponent " + getQualifiedName()
+ + " did not start interface " + provided;
+ }
+ throw new SystemAssemblyException(notProvided);
}
}
/**
* Must be implemented for initializing the subsystem. The implementation
- * must call {@link #addService(Service)} for each service that is started.
+ * must call {@link #addInterface(ProvidedInterface, Object, Scope)} for each service that is started.
+ *
+ * @return Returns the runtime of the component.
*/
- protected abstract void doStart();
+ 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
- * Service.
+ * Implementation of the interface.
+ * @param aScope
+ * scope in which to publish the implementation.
*/
- protected final void addService(
- ProvidedInterface aDescriptor, Object aService) {
- LOG.info("Interface '" + getQualifiedName() + "." + aDescriptor.getName() + "' started.");
- _running.add(aDescriptor);
- aDescriptor.publish(aService);
+ 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 ProvidedInterface[] getRunningServices() {
- return _running.toArray(new ProvidedInterface[0]);
+ public void stop(Type aRuntime) {
+ LOG.info("Stopping initiated '" + getQualifiedName() + "'");
+ doStop(aRuntime);
+ LOG.info("Stopping completed '" + getQualifiedName() + "'");
}
-
- @Override
- public void stop() {
- doStop();
- _status = Status.STOPPED;
- }
-
- protected abstract void doStop();
+
+ protected abstract void doStop(Type aRuntime);
@Override
public String toString() {
- return _name;
+ return getQualifiedName();
+ }
+
+ public ProvidedInterface findProvidedInterface(String aName) {
+ for (ProvidedInterface provided: getProvidedInterfaces()) {
+ if ( provided.getName().equals(aName)) {
+ return provided;
+ }
+ }
+ return null;
+ }
+
+ public RequiredInterface findRequiredInterface(String aName) {
+ for (RequiredInterface required: getRequiredInterfaces()) {
+ if ( required.getName().equals(aName)) {
+ return required;
+ }
+ }
+ return null;
}
}