Huge refactoring.
[utils] / system / spring / src / main / java / org / wamblee / system / spring / SpringComponent.java
index 633050cbfecacee89b2cd5a723762ec8d520b970..aea9b15aa1a548eacfe9e7c1a39667f684606003 100644 (file)
@@ -1,54 +1,54 @@
+/*
+ * 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.CompositeComponent;
-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.
@@ -66,101 +66,111 @@ public class SpringComponent extends AbstractComponent {
         *            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 InterfaceDescriptor[0]),
-                               aRequired.keySet().toArray(new InterfaceDescriptor[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();
        }
 }