+/*
+ * Copyright 2007 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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.spring;
import java.util.Map;
import java.util.Properties;
-import java.util.Set;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
-import org.wamblee.system.AbstractComponent;
-import org.wamblee.system.Container;
-import org.wamblee.system.ProvidedInterfaceDescriptor;
-import org.wamblee.system.RequiredInterfaceDescriptor;
-import org.wamblee.system.Service;
-import org.wamblee.system.InterfaceDescriptor;
-import org.wamblee.system.ServiceRegistry;
-import org.wamblee.system.SystemAssembler;
-import org.wamblee.system.SystemAssemblyException;
+import org.wamblee.system.core.AbstractComponent;
+import org.wamblee.system.core.DefaultScope;
+import org.wamblee.system.core.ProvidedInterface;
+import org.wamblee.system.core.RequiredInterface;
+import org.wamblee.system.core.Scope;
+import org.wamblee.system.core.SystemAssemblyException;
/**
- * Represents a system configured based on spring.
- * The spring config files that are configured should not contain any PropertyPlaceholderConfigurer
- * objects.
- *
+ * Represents a system configured based on spring. The spring config files that
+ * are configured should not contain any PropertyPlaceholderConfigurer objects.
+ *
* @author Erik Brakkee
*/
-public class SpringComponent extends AbstractComponent {
+public class SpringComponent extends AbstractComponent<Scope> {
- /**
- * Singleton access to the service registry. Required while starting up.
- */
- static ThreadLocal<ServiceRegistry> REGISTRY = new ThreadLocal<ServiceRegistry>();
+ private static final String CONTEXT_KEY = "context";
- private Properties _properties;
- private String[] _configFiles;
- private Map<String, ProvidedInterfaceDescriptor> _provided;
- private Map<RequiredInterfaceDescriptor, String> _required;
- /**
- * Parent application context containing required services.
- */
- private GenericApplicationContext _parentContext;
+ static final ThreadLocal<SpringComponent> THIS = new ThreadLocal<SpringComponent>();
+ static final ThreadLocal<Scope> SCOPE = new ThreadLocal<Scope>();
- /**
- * Application context containing parsed objects.
- */
- private AbstractApplicationContext _context;
+ private Properties _properties;
+ private String[] _configFiles;
+ private Map<String, ProvidedInterface> _provided;
+ private Map<RequiredInterface, String> _required;
/**
* Constructs a spring system.
* names that the spring config files use for each required
* service.
*/
- public SpringComponent(String aName, ServiceRegistry aRegistry, String[] aConfigFiles,
- Map<String, ProvidedInterfaceDescriptor> aProvided,
- Map<RequiredInterfaceDescriptor, String> aRequired) {
- super(aName, aRegistry, aProvided.values().toArray(new ProvidedInterfaceDescriptor[0]),
- aRequired.keySet().toArray(new RequiredInterfaceDescriptor[0]));
- _properties = new Properties();
+ public SpringComponent(String aName, String[] aConfigFiles,
+ Map<String, ProvidedInterface> aProvided,
+ Map<RequiredInterface, String> aRequired) {
+ super(aName, aProvided.values().toArray(new ProvidedInterface[0]),
+ aRequired.keySet().toArray(new RequiredInterface[0]));
+ _properties = new Properties();
_configFiles = aConfigFiles;
_provided = aProvided;
_required = aRequired;
}
-
+
/**
- * Must be called to make a property available in the application context.
- * @param aKey Property key.
- * @param aValue Property value.
+ * Must be called to make a property available in the application context.
+ *
+ * @param aKey
+ * Property key.
+ * @param aValue
+ * Property value.
*/
- public void setProperty(String aKey, String aValue) {
+ public void setProperty(String aKey, String aValue) {
_properties.put(aKey, aValue);
}
-
- public void addProperties(Properties aProperties) {
- for (Object key: aProperties.keySet()) {
- setProperty((String)key, aProperties.getProperty((String)key));
+
+ public void addProperties(Properties aProperties) {
+ for (Object key : aProperties.keySet()) {
+ setProperty((String) key, aProperties.getProperty((String) key));
}
}
+
+ public Scope start() {
+ return super.start(new DefaultScope(new ProvidedInterface[0]));
+ }
@Override
- protected void doStart(String aContext,
- Service[] aRequiredServices) {
- ServiceRegistry oldRegistry = REGISTRY.get();
- try {
- REGISTRY.set(getRegistry());
- try {
- _parentContext = new GenericApplicationContext();
-
- registerRequiredServices(aRequiredServices);
-
- _parentContext.refresh();
-
- parseConfigFiles();
-
- _context.addBeanFactoryPostProcessor(new PropertySetter(_properties));
- _context.refresh();
-
- exposeProvidedServices(aContext);
- } catch (Exception e) {
- throw new SystemAssemblyException(
- "Failed to assemble spring system", e);
- }
+ protected Scope doStart(Scope aExternalScope) {
+
+ SpringComponent old = THIS.get();
+ Scope oldScope = SCOPE.get();
+ THIS.set(this);
+ Scope scope = new DefaultScope(getProvidedInterfaces(), aExternalScope);
+ SCOPE.set(scope);
+ try {
+ GenericApplicationContext parentContext = new GenericApplicationContext();
+
+ registerRequiredServices(parentContext);
+
+ parentContext.refresh();
+
+ AbstractApplicationContext context = parseConfigFiles(parentContext);
+
+ context
+ .addBeanFactoryPostProcessor(new PropertySetter(_properties));
+ context.refresh();
+
+ exposeProvidedServices(context, scope);
+
+ scope.put(CONTEXT_KEY, context);
+ return scope;
+ } catch (Exception e) {
+ throw new SystemAssemblyException(
+ "Failed to assemble spring system", e);
} finally {
- REGISTRY.set(oldRegistry);
+ THIS.set(old);
+ SCOPE.set(oldScope);
}
}
- private void exposeProvidedServices(String aContext) {
+ private void exposeProvidedServices(AbstractApplicationContext aContext, Scope aScope) {
// Call addService for each provided service.
for (String name : _provided.keySet()) {
- Object svc = _context.getBean(name);
+ Object svc = aContext.getBean(name);
if (svc == null) {
- throw new IllegalArgumentException(aContext + ": service '"
+ throw new IllegalArgumentException(getQualifiedName() + ": service '"
+ name + "' is null");
}
- addService(aContext, _provided.get(name), svc);
+ addInterface(_provided.get(name), svc, aScope);
+ System.out.println("addService " + _provided.get(name) + " " + svc);
+ aScope.publishInterface(_provided.get(name), svc);
}
}
- private void parseConfigFiles() {
+ private AbstractApplicationContext parseConfigFiles(GenericApplicationContext aParentContext) {
// Parse spring config files
- _context = new ClassPathXmlApplicationContext((String[]) _configFiles,
- _parentContext);
+ return new ClassPathXmlApplicationContext((String[]) _configFiles,
+ aParentContext);
}
- private void registerRequiredServices(Service[] aRequiredServices) {
+ private void registerRequiredServices(GenericApplicationContext aParentContext) {
// Register required services in a parent context
-
- for (Service svc: aRequiredServices) {
- String id = svc.getId();
- ProvidedInterfaceDescriptor descriptor = svc.getDescriptor();
- RequiredInterfaceDescriptor[] requiredServices = SystemAssembler.filterRequiredServices(descriptor,
- _required.keySet());
- for (RequiredInterfaceDescriptor required: requiredServices) {
- String beanName = _required.get(required);
- ConstructorArgumentValues cargs = new ConstructorArgumentValues();
- cargs.addGenericArgumentValue(id);
- BeanDefinition definition = new RootBeanDefinition(RequiredServiceBean.class, cargs,
- new MutablePropertyValues());
- _parentContext.registerBeanDefinition(beanName, definition);
- }
+ for (RequiredInterface required: getRequiredInterfaces()) {
+ String beanName = _required.get(required);
+ ConstructorArgumentValues cargs = new ConstructorArgumentValues();
+ cargs.addGenericArgumentValue(required.getName());
+ BeanDefinition definition = new RootBeanDefinition(
+ RequiredServiceBean.class, cargs,
+ new MutablePropertyValues());
+ aParentContext.registerBeanDefinition(beanName, definition);
}
}
@Override
- protected void doStop() {
- _context.close();
+ protected void doStop(Scope aRuntime) {
+ AbstractApplicationContext context = (AbstractApplicationContext)aRuntime.get(CONTEXT_KEY);
+ context.close();
}
}