/*
- * 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.
*/
package org.wamblee.system.spring;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
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.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
+
import org.wamblee.system.core.AbstractComponent;
import org.wamblee.system.core.DefaultScope;
import org.wamblee.system.core.ProvidedInterface;
import org.wamblee.system.core.Scope;
import org.wamblee.system.core.SystemAssemblyException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
/**
* 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<Scope> {
+ private static final String CONTEXT_KEY = "context";
+
+ static final ThreadLocal<SpringComponent> THIS = new ThreadLocal<SpringComponent>();
+
+ static final ThreadLocal<Scope> SCOPE = new ThreadLocal<Scope>();
+
+ private Properties properties;
+
+ private String[] configFiles;
+
+ private Map<String, ProvidedInterface> provided;
+
+ private Map<RequiredInterface, String> required;
+
+ private Map<String, Properties> propertyObjects;
+
+ /**
+ * Constructs a spring system.
+ *
+ * @param aName
+ * Name of the system.
+ * @param aConfigFil
+ * Spring config files to read.
+ * @param aProvided
+ * Map of bean name to service descriptor describing the bean
+ * names that the spring config files use for each required
+ * service.
+ * @param aRequired
+ * Map of bean name to service descriptor describing the bean
+ * names that the spring config files use for each required
+ * service.
+ */
+ 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;
+ propertyObjects = new HashMap<String, Properties>();
+ }
+
+ /**
+ * 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) {
+ properties.put(aKey, aValue);
+ }
+
+ public void addProperties(Properties aProperties) {
+ for (Object key : aProperties.keySet()) {
+ setProperty((String) key, aProperties.getProperty((String) key));
+ }
+ }
+
+ public void addProperties(String aBeanname, Properties aProperties) {
+ propertyObjects.put(aBeanname, aProperties);
+ }
+
+ public Properties getProperties(String aBeanname) {
+ return propertyObjects.get(aBeanname);
+ }
+
+ @Override
+ protected Scope doStart(Scope aExternalScope) {
+ SpringComponent old = THIS.get();
+ Scope oldScope = SCOPE.get();
+ THIS.set(this);
+
+ Scope scope = new DefaultScope(getProvidedInterfaces().toArray(
+ new ProvidedInterface[0]), aExternalScope);
+ SCOPE.set(scope);
+
+ try {
+ GenericApplicationContext parentContext = new GenericApplicationContext();
+
+ registerRequiredServices(parentContext);
+ registerPropertyObjects(parentContext);
+
+ parentContext.refresh();
- private static final String CONTEXT_KEY = "context";
-
- static final ThreadLocal<SpringComponent> THIS = new ThreadLocal<SpringComponent>();
- static final ThreadLocal<Scope> SCOPE = new ThreadLocal<Scope>();
-
- private Properties properties;
- private String[] configFiles;
- private Map<String, ProvidedInterface> provided;
- private Map<RequiredInterface, String> required;
- private Map<String, Properties> propertyObjects;
-
- /**
- * Constructs a spring system.
- *
- * @param aName
- * Name of the system.
- * @param aConfigFil
- * Spring config files to read.
- * @param aProvided
- * Map of bean name to service descriptor describing the bean
- * names that the spring config files use for each required
- * service.
- * @param aRequired
- * Map of bean name to service descriptor describing the bean
- * names that the spring config files use for each required
- * service.
- */
- 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;
- propertyObjects = new HashMap<String, Properties>();
-
- }
-
- /**
- * 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) {
- properties.put(aKey, aValue);
- }
-
- public void addProperties(Properties aProperties) {
- for (Object key : aProperties.keySet()) {
- setProperty((String) key, aProperties.getProperty((String) key));
- }
- }
-
- public void addProperties(String aBeanname, Properties aProperties) {
- propertyObjects.put(aBeanname, aProperties);
- }
-
- public Properties getProperties(String aBeanname) {
- return propertyObjects.get(aBeanname);
- }
-
- @Override
- protected Scope doStart(Scope aExternalScope) {
-
- SpringComponent old = THIS.get();
- Scope oldScope = SCOPE.get();
- THIS.set(this);
- Scope scope = new DefaultScope(getProvidedInterfaces().toArray(new ProvidedInterface[0]), aExternalScope);
- SCOPE.set(scope);
- try {
- GenericApplicationContext parentContext = new GenericApplicationContext();
-
- registerRequiredServices(parentContext);
- registerPropertyObjects(parentContext);
-
- parentContext.refresh();
-
- System.out.println("Parent context " + parentContext);
-
- AbstractApplicationContext context = parseConfigFiles(parentContext);
-
- context
- .addBeanFactoryPostProcessor(new PropertySetter(properties));
- context.refresh();
-
- exposeProvidedServices(context, aExternalScope);
-
- scope.put(CONTEXT_KEY, context);
- return scope;
- } catch (Exception e) {
- throw new SystemAssemblyException(
- "Failed to assemble spring system " + getName(), e);
- } finally {
- THIS.set(old);
- SCOPE.set(oldScope);
- }
- }
-
- private void exposeProvidedServices(AbstractApplicationContext aContext, Scope aScope) {
- // Call addService for each provided service.
-
- for (String name : provided.keySet()) {
- Object svc = aContext.getBean(name);
- if (svc == null) {
- throw new IllegalArgumentException(getQualifiedName() + ": service '"
- + name + "' is null");
- }
- addInterface(provided.get(name), svc, aScope);
- System.out.println("addService " + provided.get(name) + " " + svc);
- }
- }
-
- private AbstractApplicationContext parseConfigFiles(GenericApplicationContext aParentContext) {
- // Parse spring config files
-
- return new ClassPathXmlApplicationContext((String[]) configFiles,
- false, aParentContext);
- }
-
- private void registerRequiredServices(GenericApplicationContext aParentContext) {
- // Register required services in a parent context
- for (RequiredInterface requiredIntf: getRequiredInterfaces()) {
- String beanName = required.get(requiredIntf);
- if ( beanName != null && beanName.length() > 0) {
- ConstructorArgumentValues cargs = new ConstructorArgumentValues();
- cargs.addGenericArgumentValue(requiredIntf.getName());
- BeanDefinition definition = new RootBeanDefinition(
- RequiredServiceBean.class, cargs,
- new MutablePropertyValues());
- aParentContext.registerBeanDefinition(beanName, definition);
- } else {
- // The required interface is not required by the spring config but by the sub-class directly.
- }
- }
- }
-
- private void registerPropertyObjects(GenericApplicationContext aParentContext) {
- for (String beanName: propertyObjects.keySet()) {
+ System.out.println("Parent context " + parentContext);
+
+ AbstractApplicationContext context = parseConfigFiles(parentContext);
+
+ context.addBeanFactoryPostProcessor(new PropertySetter(properties));
+ context.refresh();
+
+ exposeProvidedServices(context, aExternalScope);
+
+ scope.put(CONTEXT_KEY, context);
+
+ return scope;
+ } catch (Exception e) {
+ throw new SystemAssemblyException(
+ "Failed to assemble spring system " + getName(), e);
+ } finally {
+ THIS.set(old);
+ SCOPE.set(oldScope);
+ }
+ }
+
+ private void exposeProvidedServices(AbstractApplicationContext aContext,
+ Scope aScope) {
+ // Call addService for each provided service.
+ for (String name : provided.keySet()) {
+ Object svc = aContext.getBean(name);
+
+ if (svc == null) {
+ throw new IllegalArgumentException(getQualifiedName() +
+ ": service '" + name + "' is null");
+ }
+
+ addInterface(provided.get(name), svc, aScope);
+ System.out.println("addService " + provided.get(name) + " " + svc);
+ }
+ }
+
+ private AbstractApplicationContext parseConfigFiles(
+ GenericApplicationContext aParentContext) {
+ // Parse spring config files
+ return new ClassPathXmlApplicationContext((String[]) configFiles,
+ false, aParentContext);
+ }
+
+ private void registerRequiredServices(
+ GenericApplicationContext aParentContext) {
+ // Register required services in a parent context
+ for (RequiredInterface requiredIntf : getRequiredInterfaces()) {
+ String beanName = required.get(requiredIntf);
+
+ if ((beanName != null) && (beanName.length() > 0)) {
+ ConstructorArgumentValues cargs = new ConstructorArgumentValues();
+ cargs.addGenericArgumentValue(requiredIntf.getName());
+
+ BeanDefinition definition = new RootBeanDefinition(
+ RequiredServiceBean.class, cargs,
+ new MutablePropertyValues());
+ aParentContext.registerBeanDefinition(beanName, definition);
+ } else {
+ // The required interface is not required by the spring config
+ // but by the sub-class directly.
+ }
+ }
+ }
+
+ private void registerPropertyObjects(
+ GenericApplicationContext aParentContext) {
+ for (String beanName : propertyObjects.keySet()) {
ConstructorArgumentValues cargs = new ConstructorArgumentValues();
- cargs.addGenericArgumentValue(PropertySetter.createPropertyFile(propertyObjects.get(beanName)));
+ cargs.addGenericArgumentValue(PropertySetter
+ .createPropertyFile(propertyObjects.get(beanName)));
+
BeanDefinition definition = new RootBeanDefinition(
- ConfiguredProperties.class, cargs,
- new MutablePropertyValues());
+ ConfiguredProperties.class, cargs, new MutablePropertyValues());
aParentContext.registerBeanDefinition(beanName, definition);
}
}
-
- @Override
- protected void doStop(Scope aRuntime) {
- AbstractApplicationContext context = (AbstractApplicationContext)aRuntime.get(CONTEXT_KEY);
- context.close();
- }
+ @Override
+ protected void doStop(Scope aRuntime) {
+ AbstractApplicationContext context = (AbstractApplicationContext) aRuntime
+ .get(CONTEXT_KEY);
+ context.close();
+ }
}