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
32 private ThreadLocal<List<ProvidedInterface>> remaining;
34 private String context;
38 private List<ProvidedInterface> provided;
40 private List<RequiredInterface> required;
43 * Constructs the subsystem.
52 protected AbstractComponent(String aName,
53 List<ProvidedInterface> aProvided, List<RequiredInterface> aRequired) {
54 remaining = new ThreadLocal<List<ProvidedInterface>>();
57 provided = new ArrayList<ProvidedInterface>(aProvided);
58 required = new ArrayList<RequiredInterface>(aRequired);
62 * Constructs the subsystem.
71 protected AbstractComponent(String aName, ProvidedInterface[] aProvided,
72 RequiredInterface[] aRequired) {
73 this(aName, Arrays.asList(aProvided), Arrays.asList(aRequired));
77 * Creates a new AbstractComponent object.
80 protected AbstractComponent(String aName) {
81 this(aName, new ProvidedInterface[0], new RequiredInterface[0]);
84 public AbstractComponent<Type> addProvidedInterface(
85 ProvidedInterface aProvided) {
86 provided.add(aProvided);
91 public AbstractComponent<Type> addRequiredInterface(
92 RequiredInterface aRequired) {
93 required.add(aRequired);
99 public final String getName() {
104 public void addContext(String aContext) {
105 if (context == null) {
108 context = aContext + "." + context;
113 public String getContext() {
118 public String getQualifiedName() {
119 if (context == null) {
123 return context + "." + getName();
127 public final List<ProvidedInterface> getProvidedInterfaces() {
128 return Collections.unmodifiableList(provided);
132 public final List<RequiredInterface> getRequiredInterfaces() {
133 return Collections.unmodifiableList(required);
137 public final Type start(Scope aScope) {
138 LOG.info("Initialization starting '" + getQualifiedName() + "'");
140 List<ProvidedInterface> oldRemaining = remaining.get();
142 .set(new ArrayList<ProvidedInterface>(getProvidedInterfaces()));
145 Type runtime = doStart(aScope);
146 checkNotStartedInterfaces();
147 LOG.info("Initialization finished '" + getQualifiedName() + "'");
151 remaining.set(oldRemaining);
155 private void checkNotStartedInterfaces() {
156 if (remaining.get().size() > 0) {
157 StringBuffer notProvided = new StringBuffer();
159 for (ProvidedInterface providedIntf : remaining.get()) {
160 notProvided.append("\nComponent " + getQualifiedName() +
161 " did not start interface " + providedIntf);
164 throw new SystemAssemblyException(notProvided.toString());
169 * Must be implemented for initializing the subsystem. The implementation
170 * must call {@link #addInterface(ProvidedInterface, Object, Scope)} for
171 * each service that is started.
174 * @return Returns the runtime of the component.
176 protected abstract Type doStart(Scope aScope);
179 * Implementations must call this method to indicate that a new service has
183 * Provided interface.
185 * Implementation of the interface.
187 * scope in which to publish the implementation.
190 protected final void addInterface(ProvidedInterface aDescriptor,
191 Object aService, Scope aScope) {
192 LOG.info("Interface '" + getQualifiedName() + "." +
193 aDescriptor.getName() + "' started.");
195 if (!remaining.get().remove(aDescriptor)) {
196 throw new SystemAssemblyException("Component '" +
197 getQualifiedName() + "' started an unexpected interface '" +
199 "' that was not registerd as a provided interface before");
202 aScope.publishInterface(aDescriptor, aService);
206 public void stop(Type aRuntime) {
207 LOG.info("Stopping initiated '" + getQualifiedName() + "'");
209 LOG.info("Stopping completed '" + getQualifiedName() + "'");
212 protected abstract void doStop(Type aRuntime);
215 public String toString() {
216 return getQualifiedName();
219 public ProvidedInterface findProvidedInterface(String aName) {
220 for (ProvidedInterface providedIntf : getProvidedInterfaces()) {
221 if (providedIntf.getName().equals(aName)) {
229 public RequiredInterface findRequiredInterface(String aName) {
230 for (RequiredInterface requiredIntf : getRequiredInterfaces()) {
231 if (requiredIntf.getName().equals(aName)) {