Removed DOCUMENT ME comments that were generated and applied source code
[utils] / system / spring / src / main / java / org / wamblee / system / spring / SpringComponent.java
index b9a2648c7ca706838795538637e0c0d584aa3271..8b8bed94b5b1a401dee1618e9dc119ba08841722 100644 (file)
+/*
+ * 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 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.AbstractComponent;
-import org.wamblee.system.ProvidedInterface;
-import org.wamblee.system.RequiredInterface;
-import org.wamblee.system.Service;
-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;
+
+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. 
- *
+ * 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 {
-
-       /**
-        * Singleton access to the service registry. Required while starting up.
-        */
-       static ThreadLocal<ServiceRegistry> REGISTRY = new ThreadLocal<ServiceRegistry>();
-
-       private Properties _properties; 
-       private String[] _configFiles;
-       private Map<String, ProvidedInterface> _provided;
-       private Map<RequiredInterface, String> _required;
-       /**
-        * Parent application context containing required services.
-        */
-       private GenericApplicationContext _parentContext;
-
-       /**
-        * Application context containing parsed objects.
-        */
-       private AbstractApplicationContext _context;
-
-       /**
-        * 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, ServiceRegistry aRegistry, String[] aConfigFiles,
-                       Map<String, ProvidedInterface> aProvided,
-                       Map<RequiredInterface, String> aRequired) {
-               super(aName, aRegistry, 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. 
-        */
-       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));
-               }
-       }
-
-       @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);
-                       }
-               } finally {
-                       REGISTRY.set(oldRegistry);
-               }
-       }
-
-       private void exposeProvidedServices(String aContext) {
-               // Call addService for each provided service.
-
-               for (String name : _provided.keySet()) {
-                       Object svc = _context.getBean(name);
-                       if (svc == null) {
-                               throw new IllegalArgumentException(aContext + ": service '"
-                                               + name + "' is null");
-                       }
-                       addService(aContext, _provided.get(name), svc);
-               }
-       }
-
-       private void parseConfigFiles() {
-               // Parse spring config files
-
-               _context = new ClassPathXmlApplicationContext((String[]) _configFiles,
-                               _parentContext);
-       }
-
-       private void registerRequiredServices(Service[] aRequiredServices) {
-               // Register required services in a parent context
-
-               for (Service svc: aRequiredServices) { 
-                       String id = svc.getId();
-                       ProvidedInterface descriptor = svc.getDescriptor();
-                       RequiredInterface[] requiredServices = SystemAssembler.filterRequiredServices(descriptor,
-                                       _required.keySet()); 
-                       for (RequiredInterface 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);
-                       }
-               }
-       }
-
-       @Override
-       protected void doStop() {
-           _context.close();
-       }
+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();
+
+            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)));
+
+            BeanDefinition definition = new RootBeanDefinition(
+                ConfiguredProperties.class, cargs, new MutablePropertyValues());
+            aParentContext.registerBeanDefinition(beanName, definition);
+        }
+    }
+
+    @Override
+    protected void doStop(Scope aRuntime) {
+        AbstractApplicationContext context = (AbstractApplicationContext) aRuntime
+            .get(CONTEXT_KEY);
+        context.close();
+    }
 }