/*
- * 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<Type> implements Component<Type> {
-
- private static final Log LOG = LogFactory.getLog(AbstractComponent.class);
-
- 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, ProvidedInterface[] aProvided,
- 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));
- }
-
- protected AbstractComponent(String aName) {
- this(aName, new ProvidedInterface[0], new RequiredInterface[0]);
- }
-
- public AbstractComponent addProvidedInterface(ProvidedInterface aProvided) {
- _provided.add(aProvided);
- return this;
- }
-
- public AbstractComponent 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 ProvidedInterface[] getProvidedInterfaces() {
- return _provided.toArray(new ProvidedInterface[0]);
- }
-
- @Override
- public final RequiredInterface[] getRequiredInterfaces() {
- return _required.toArray(new RequiredInterface[0]);
- }
-
- @Override
- public final Type start(Scope aScope) {
- LOG.info("Initializing '" + getQualifiedName() + "'");
- List<ProvidedInterface> oldRemaining = _remaining.get();
- _remaining.set(new ArrayList<ProvidedInterface>(Arrays.asList(getProvidedInterfaces())));
- try {
- Type runtime = doStart(aScope);
- checkNotStartedInterfaces();
- 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.
- *
- * @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.");
- _remaining.get().remove(aDescriptor);
- aScope.publishInterface(aDescriptor, aService);
- }
-
- @Override
- public void stop(Type aRuntime) {
- doStop(aRuntime);
- }
-
- protected abstract void doStop(Type aRuntime);
-
- @Override
- public String toString() {
- return getQualifiedName();
- }
-
+ 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;
+ }
}