2 * Copyright 2005-2010 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.system.core;
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.List;
27 * Abstract subsystem class making it easy to implement new subsystems.
30 public abstract class AbstractComponent<Type> implements Component<Type> {
31 private static final Log LOG = LogFactory.getLog(AbstractComponent.class);
33 private ThreadLocal<List<ProvidedInterface>> remaining;
35 private String context;
39 private List<ProvidedInterface> provided;
41 private List<RequiredInterface> required;
44 * Constructs the subsystem.
53 protected AbstractComponent(String aName,
54 List<ProvidedInterface> aProvided, List<RequiredInterface> aRequired) {
55 remaining = new ThreadLocal<List<ProvidedInterface>>();
58 provided = new ArrayList<ProvidedInterface>(aProvided);
59 required = new ArrayList<RequiredInterface>(aRequired);
63 * Constructs the subsystem.
72 protected AbstractComponent(String aName, ProvidedInterface[] aProvided,
73 RequiredInterface[] aRequired) {
74 this(aName, Arrays.asList(aProvided), Arrays.asList(aRequired));
78 * Creates a new AbstractComponent object.
81 protected AbstractComponent(String aName) {
82 this(aName, new ProvidedInterface[0], new RequiredInterface[0]);
85 public AbstractComponent<Type> addProvidedInterface(
86 ProvidedInterface aProvided) {
87 provided.add(aProvided);
92 public AbstractComponent<Type> addRequiredInterface(
93 RequiredInterface aRequired) {
94 required.add(aRequired);
100 public final String getName() {
105 public void addContext(String aContext) {
106 if (context == null) {
109 context = aContext + "." + context;
114 public String getContext() {
119 public String getQualifiedName() {
120 if (context == null) {
124 return context + "." + getName();
128 public final List<ProvidedInterface> getProvidedInterfaces() {
129 return Collections.unmodifiableList(provided);
133 public final List<RequiredInterface> getRequiredInterfaces() {
134 return Collections.unmodifiableList(required);
138 public final Type start(Scope aScope) {
139 LOG.info("Initialization starting '" + getQualifiedName() + "'");
141 List<ProvidedInterface> oldRemaining = remaining.get();
143 .set(new ArrayList<ProvidedInterface>(getProvidedInterfaces()));
146 Type runtime = doStart(aScope);
147 checkNotStartedInterfaces();
148 LOG.info("Initialization finished '" + getQualifiedName() + "'");
152 remaining.set(oldRemaining);
156 private void checkNotStartedInterfaces() {
157 if (remaining.get().size() > 0) {
158 String notProvided = "";
160 for (ProvidedInterface provided : remaining.get()) {
161 notProvided += ("\nComponent " + getQualifiedName() +
162 " did not start interface " + provided);
165 throw new SystemAssemblyException(notProvided);
170 * Must be implemented for initializing the subsystem. The implementation
171 * must call {@link #addInterface(ProvidedInterface, Object, Scope)} for
172 * each service that is started.
175 * @return Returns the runtime of the component.
177 protected abstract Type doStart(Scope aScope);
180 * Implementations must call this method to indicate that a new service has
184 * Provided interface.
186 * Implementation of the interface.
188 * scope in which to publish the implementation.
191 protected final void addInterface(ProvidedInterface aDescriptor,
192 Object aService, Scope aScope) {
193 LOG.info("Interface '" + getQualifiedName() + "." +
194 aDescriptor.getName() + "' started.");
196 if (!remaining.get().remove(aDescriptor)) {
197 throw new SystemAssemblyException("Component '" +
198 getQualifiedName() + "' started an unexpected interface '" +
200 "' that was not registerd as a provided interface before");
203 aScope.publishInterface(aDescriptor, aService);
207 public void stop(Type aRuntime) {
208 LOG.info("Stopping initiated '" + getQualifiedName() + "'");
210 LOG.info("Stopping completed '" + getQualifiedName() + "'");
213 protected abstract void doStop(Type aRuntime);
216 public String toString() {
217 return getQualifiedName();
220 public ProvidedInterface findProvidedInterface(String aName) {
221 for (ProvidedInterface provided : getProvidedInterfaces()) {
222 if (provided.getName().equals(aName)) {
230 public RequiredInterface findRequiredInterface(String aName) {
231 for (RequiredInterface required : getRequiredInterfaces()) {
232 if (required.getName().equals(aName)) {