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 java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.logging.Logger;
25 * Abstract subsystem class making it easy to implement new subsystems.
28 public abstract class AbstractComponent<Type> implements Component<Type> {
29 private static final Logger LOG = Logger.getLogger(AbstractComponent.class.getName());
31 private ThreadLocal<List<ProvidedInterface>> remaining;
33 private String context;
37 private List<ProvidedInterface> provided;
39 private List<RequiredInterface> required;
42 * Constructs the subsystem.
51 protected AbstractComponent(String aName,
52 List<ProvidedInterface> aProvided, List<RequiredInterface> aRequired) {
53 remaining = new ThreadLocal<List<ProvidedInterface>>();
56 provided = new ArrayList<ProvidedInterface>(aProvided);
57 required = new ArrayList<RequiredInterface>(aRequired);
61 * Constructs the subsystem.
70 protected AbstractComponent(String aName, ProvidedInterface[] aProvided,
71 RequiredInterface[] aRequired) {
72 this(aName, Arrays.asList(aProvided), Arrays.asList(aRequired));
76 * Creates a new AbstractComponent object.
79 protected AbstractComponent(String aName) {
80 this(aName, new ProvidedInterface[0], new RequiredInterface[0]);
83 public AbstractComponent<Type> addProvidedInterface(
84 ProvidedInterface aProvided) {
85 provided.add(aProvided);
90 public AbstractComponent<Type> addRequiredInterface(
91 RequiredInterface aRequired) {
92 required.add(aRequired);
98 public final String getName() {
103 public void addContext(String aContext) {
104 if (context == null) {
107 context = aContext + "." + context;
112 public String getContext() {
117 public String getQualifiedName() {
118 if (context == null) {
122 return context + "." + getName();
126 public final List<ProvidedInterface> getProvidedInterfaces() {
127 return Collections.unmodifiableList(provided);
131 public final List<RequiredInterface> getRequiredInterfaces() {
132 return Collections.unmodifiableList(required);
136 public final Type start(Scope aScope) {
137 LOG.info("Initialization starting '" + getQualifiedName() + "'");
139 List<ProvidedInterface> oldRemaining = remaining.get();
141 .set(new ArrayList<ProvidedInterface>(getProvidedInterfaces()));
144 Type runtime = doStart(aScope);
145 checkNotStartedInterfaces();
146 LOG.info("Initialization finished '" + getQualifiedName() + "'");
150 remaining.set(oldRemaining);
154 private void checkNotStartedInterfaces() {
155 if (remaining.get().size() > 0) {
156 StringBuffer notProvided = new StringBuffer();
158 for (ProvidedInterface providedIntf : remaining.get()) {
159 notProvided.append("\nComponent " + getQualifiedName() +
160 " did not start interface " + providedIntf);
163 throw new SystemAssemblyException(notProvided.toString());
168 * Must be implemented for initializing the subsystem. The implementation
169 * must call {@link #addInterface(ProvidedInterface, Object, Scope)} for
170 * each service that is started.
173 * @return Returns the runtime of the component.
175 protected abstract Type doStart(Scope aScope);
178 * Implementations must call this method to indicate that a new service has
182 * Provided interface.
184 * Implementation of the interface.
186 * scope in which to publish the implementation.
189 protected final void addInterface(ProvidedInterface aDescriptor,
190 Object aService, Scope aScope) {
191 LOG.info("Interface '" + getQualifiedName() + "." +
192 aDescriptor.getName() + "' started.");
194 if (!remaining.get().remove(aDescriptor)) {
195 throw new SystemAssemblyException("Component '" +
196 getQualifiedName() + "' started an unexpected interface '" +
198 "' that was not registerd as a provided interface before");
201 aScope.publishInterface(aDescriptor, aService);
205 public void stop(Type aRuntime) {
206 LOG.info("Stopping initiated '" + getQualifiedName() + "'");
208 LOG.info("Stopping completed '" + getQualifiedName() + "'");
211 protected abstract void doStop(Type aRuntime);
214 public String toString() {
215 return getQualifiedName();
218 public ProvidedInterface findProvidedInterface(String aName) {
219 for (ProvidedInterface providedIntf : getProvidedInterfaces()) {
220 if (providedIntf.getName().equals(aName)) {
228 public RequiredInterface findRequiredInterface(String aName) {
229 for (RequiredInterface requiredIntf : getRequiredInterfaces()) {
230 if (requiredIntf.getName().equals(aName)) {