added spring subsystem implementation.
authorerik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Mon, 24 Mar 2008 15:19:19 +0000 (15:19 +0000)
committererik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Mon, 24 Mar 2008 15:19:19 +0000 (15:19 +0000)
19 files changed:
.classpath
pom.xml
support/src/test/java/org/wamblee/test/SpringTestCase.java
system/general/src/main/java/org/wamblee/system/AbstractSubSystem.java
system/general/src/main/java/org/wamblee/system/CompositeSystem.java
system/general/src/main/java/org/wamblee/system/DefaultServiceRegistry.java
system/general/src/main/java/org/wamblee/system/SubSystem.java
system/general/src/main/java/org/wamblee/system/SystemAssembler.java
system/general/src/test/java/org/wamblee/system/Application.java
system/general/src/test/java/org/wamblee/system/Environment.java
system/general/src/test/java/org/wamblee/system/SystemAssemblerTest.java
system/spring/pom.xml
system/spring/src/main/java/org/wamblee/system/spring/ProvidedServiceBean.java [new file with mode: 0644]
system/spring/src/main/java/org/wamblee/system/spring/SpringSystem.java [new file with mode: 0644]
system/spring/src/test/java/org/wamblee/system/spring/BlaService.java [new file with mode: 0644]
system/spring/src/test/java/org/wamblee/system/spring/HelloService.java [new file with mode: 0644]
system/spring/src/test/java/org/wamblee/system/spring/SpringSystemTest.java [new file with mode: 0644]
system/spring/src/test/resources/test.org.wamblee.system.spring.xml [new file with mode: 0644]
system/spring/src/test/resources/test.org.wamblee.system.springWithRequirements.xml [new file with mode: 0644]

index 216ffd34a8ab58e26e50d5a0961ffbd392c99f95..709e35be5180abeba4e7f11e59cc383f466190bc 100644 (file)
@@ -4,8 +4,11 @@
        <classpathentry kind="src" path="support/src/test/java"/>
        <classpathentry excluding="**" kind="src" output="support/src/main/resources" path="support/src/main/resources"/>
        <classpathentry excluding="**" kind="src" output="support/src/test/resources" path="support/src/test/resources"/>
-       <classpathentry kind="src" path="system/src/main/java"/>
-       <classpathentry kind="src" path="system/src/test/java"/>
+       <classpathentry kind="src" path="system/general/src/main/java"/>
+       <classpathentry kind="src" path="system/general/src/test/java"/>
+       <classpathentry kind="src" path="system/spring/src/main/java"/>
+       <classpathentry kind="src" path="system/spring/src/test/java"/>
+       <classpathentry excluding="**" kind="src" output="system/spring/src/test/resources" path="system/spring/src/test/resources"/>
        <classpathentry kind="src" path="security/src/main/java"/>
        <classpathentry kind="src" path="security/src/test/java"/>
        <classpathentry excluding="**" kind="src" output="security/src/test/resources" path="security/src/test/resources"/>
diff --git a/pom.xml b/pom.xml
index dd95286d0b60a5859e0b777350d4c59701f63261..092ca43ee75a94e49695fc75eccba13984e48449 100644 (file)
--- a/pom.xml
+++ b/pom.xml
                     </execution>
                 </executions>
             </plugin>
+            
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>cobertura-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>clean</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            
 
         </plugins>
-
+        
     </build>
 
     <reporting>
index 29334e003e78cea974ae913e64e919dfe6a841f6..556bac2af0f1140f541c978b68d8ae1e633b5172 100644 (file)
@@ -140,7 +140,6 @@ public class SpringTestCase extends MockObjectTestCase {
         if (_context == null) {
             _context = new ClassPathXmlApplicationContext(
                     (String[]) _configLocations, _parentContext);
-            assertNotNull(_context);
         }
         return _context;
     }
index 7a6724f32ea8af702df9d9f45527f1dc53b09c98..6ae6f3cc566fc7f29cf01ca1fd74a3b7476a9b8b 100644 (file)
@@ -17,6 +17,7 @@ public abstract class AbstractSubSystem implements SubSystem {
        private static final Log LOG = LogFactory.getLog(AbstractSubSystem.class);
 
        private String _name;
+       private ServiceRegistry _registry; 
        private List<ServiceDescriptor> _provided;
        private List<ServiceDescriptor> _required;
        private Map<ServiceDescriptor, Service> _running;
@@ -33,9 +34,10 @@ public abstract class AbstractSubSystem implements SubSystem {
         * @param aRequired
         *            Required services.
         */
-       protected AbstractSubSystem(String aName, ServiceDescriptor[] aProvided,
+       protected AbstractSubSystem(String aName, ServiceRegistry aRegistry, ServiceDescriptor[] aProvided,
                        ServiceDescriptor[] aRequired) {
                _name = aName;
+               _registry = aRegistry; 
                _provided = new ArrayList<ServiceDescriptor>();
                _provided.addAll(Arrays.asList(aProvided));
                _required = new ArrayList<ServiceDescriptor>();
@@ -47,6 +49,10 @@ public abstract class AbstractSubSystem implements SubSystem {
        public final String getName() {
                return _name;
        }
+       
+       public ServiceRegistry getRegistry() {
+               return _registry;
+       }
 
        @Override
        public final ServiceDescriptor[] getProvidedServices() {
@@ -59,25 +65,23 @@ public abstract class AbstractSubSystem implements SubSystem {
        }
 
        @Override
-       public final Service[] start(String aContext, ServiceRegistry aRegistry,
+       public final Service[] start(String aContext,
                        Service[] aRequiredServices) {
                LOG.info("Initializing '" + aContext + "." + _name + "' with "
                                + Arrays.asList(aRequiredServices));
-               doStart(aContext + "." + getName(), aRegistry, aRequiredServices);
+               doStart(aContext + "." + getName(), aRequiredServices);
                return _running.values().toArray(new Service[0]);
        }
 
        /**
         * Must be implemented for initializing the subsystem. The implementation
         * must call {@link #addService(Service)} for each service that is started.
-        * 
-        * @param aRegistry Service registry. 
+        *  
         * @param aRequiredServices
         *            Services that are already running from other subsystems that
         *            may be used.
         */
        protected abstract void doStart(String aContext,
-                       ServiceRegistry aRegistry,
                        Service[] aRequiredServices);
 
        /**
@@ -88,10 +92,9 @@ public abstract class AbstractSubSystem implements SubSystem {
         *            Service.
         */
        protected final void addService(String aContext,
-                       ServiceRegistry aRegistry, 
                        ServiceDescriptor aDescriptor, Object aService) {
                LOG.info(aContext + ": service '" + aService + "' started.");
-               Service svc = aRegistry.register(aDescriptor, aService);
+               Service svc = getRegistry().register(aDescriptor, aService);
                _running.put(svc.getDescriptor(), svc);
        }
 
@@ -101,14 +104,14 @@ public abstract class AbstractSubSystem implements SubSystem {
        }
        
        @Override
-       public void stop(String aContext, ServiceRegistry aRegistry) {
-               doStop(aContext);       
+       public void stop() {
+               doStop();       
                for (Service svc: _running.values()) { 
-                       aRegistry.remove(svc);
+                       getRegistry().remove(svc);
                }
        }
        
-       protected abstract void doStop(String aContext); 
+       protected abstract void doStop(); 
 
        @Override
        public String toString() {
index 3255149810e8f6bfe0e21b4c3f081543eaa9e2f1..155d56030f15e119b61ea04dbe0857976f575b7f 100644 (file)
@@ -21,13 +21,14 @@ public class CompositeSystem extends AbstractSubSystem {
        /**
         * Construcst the composite system. 
         * @param aName Name of the system. 
+        * @param aRegistry Service registry.
         * @param aSystems Subsystems. 
         * @param aProvided Provided services of the system. 
         * @param aRequired Required services by the system. 
         */
-       public CompositeSystem(String aName, SubSystem[] aSystems,
+       public CompositeSystem(String aName, ServiceRegistry aRegistry, SubSystem[] aSystems,
                        ServiceDescriptor[] aProvided, ServiceDescriptor[] aRequired) {
-               super(aName, aProvided, aRequired);
+               super(aName, aRegistry, aProvided, aRequired);
                _systems = aSystems;
                validate();
        }
@@ -78,18 +79,18 @@ public class CompositeSystem extends AbstractSubSystem {
        }
 
        @Override
-       protected void doStart(String aContext, ServiceRegistry aRegistry, Service[] aRequiredServices) {
+       protected void doStart(String aContext, Service[] aRequiredServices) {
                List<ServiceDescriptor> descriptors = new ArrayList<ServiceDescriptor>();
                for (Service service : aRequiredServices) {
                        descriptors.add(service.getDescriptor());
                }
                SystemAssembler assembler = new SystemAssembler(aContext + "." + getName(), _systems,
                                descriptors.toArray(new ServiceDescriptor[0]));
-               assembler.start(aRegistry, aRequiredServices);
+               assembler.start(getRegistry(), aRequiredServices);
        }
        
        @Override
-       protected void doStop(String aContext) {
+       protected void doStop() {
                // Empty.       
        }
 
index 4d8bd465d0feffeef64bc8ff6b72aced868d1173..59515fec04229161dedead759fe1c75d51d86878 100644 (file)
@@ -33,9 +33,8 @@ public class DefaultServiceRegistry implements ServiceRegistry {
        }
 
        @Override
-       public synchronized Service find(String id) {
-               // TODO Auto-generated method stub
-               return null;
+       public synchronized Service find(String aId) {
+               return _services.get(aId);
        }
 
        @Override
index 16b37aab0936ca61d486c086a9c5bca7b57fd4fb..e25766d655eb43c4ca56cc4272449af683037ee8 100644 (file)
@@ -29,20 +29,16 @@ public interface SubSystem {
         * Initialises the subsytem by starting all the services that
         * it described as provided. 
         * @param aContext Unique name for the subsystem. 
-        * @param aRegistry Registry of service to which the subsystem must register the services it
-        *   creates. 
         * @param aRequiredServices Running services from other 
         * subsystems that are required by this subsystem. 
         * @return Services that are running in the subsystem. 
         */
-       Service[] start(String aContext, ServiceRegistry aRegistry, Service[] aRequiredServices);
+       Service[] start(String aContext, Service[] aRequiredServices);
        
        /**
-        * Stops a service. 
-        * @param aContext Context
-        * @param aRegistry Registry from which services must be removed. 
+        * Stops a subsystem. 
         */
-       void stop(String aContext, ServiceRegistry aRegistry); 
+       void stop(); 
        
        /**
         * Gets the list of running services in the subsystem. 
index 5b2c0e143f0080f3a6df43a9c27eb592e5a9a9c8..9e38a3e1a0a332cf5c47c9433f53ac018b058873 100644 (file)
@@ -102,7 +102,7 @@ public class SystemAssembler {
                                }
                                services.add(required);
                        }
-                       Service[] provided = system.start(_context, aRegistry, services
+                       Service[] provided = system.start(_context, services
                                        .toArray(new Service[0]));
                        for (Service service : provided) {
                                allProvided.put(service.getDescriptor(), service);
index 3587917b93e98653d2bd95294e770c505477896d..d5a3590db2775b0479a4ac857323e3492e7a66d0 100644 (file)
@@ -9,17 +9,17 @@ public class Application extends AbstractSubSystem {
                        new DefaultServiceDescriptor(Integer.class)
        };
        
-       public Application() {
-               super("application", new ServiceDescriptor[0], REQUIRED); 
+       public Application(ServiceRegistry aRegistry) {
+               super("application", aRegistry, new ServiceDescriptor[0], REQUIRED); 
        }
 
        @Override
-       protected void doStart(String aContext, ServiceRegistry aRegistry, Service[] aRequiredServices) {
+       protected void doStart(String aContext, Service[] aRequiredServices) {
                // Empty, no services provided externally. 
        }
        
        @Override
-       protected void doStop(String aContext) {
+       protected void doStop() {
                // Empty.       
        }
 }
index 901c67d75bf60c0c3ddb0c0b10bc8f31142d786a..a82310686aeb7c372da52ec0cb2002af9c870964 100644 (file)
@@ -11,18 +11,18 @@ public class Environment extends AbstractSubSystem {
                        new DefaultServiceDescriptor(Integer.class)
        };
        
-       public Environment() { 
-               super("environment", PROVIDED, new ServiceDescriptor[0]);
+       public Environment(ServiceRegistry aRegistry) { 
+               super("environment", aRegistry, PROVIDED, new ServiceDescriptor[0]);
        }
        
        @Override
-       protected void doStart(String aContext, ServiceRegistry aRegistry, Service[] aRequiredServices) {
-           addService(aContext, aRegistry, PROVIDED[0], new Integer(1));
-           addService(aContext, aRegistry, PROVIDED[1], new Integer(2));
+       protected void doStart(String aContext, Service[] aRequiredServices) {
+           addService(aContext, PROVIDED[0], new Integer(1));
+           addService(aContext, PROVIDED[1], new Integer(2));
        }
        
        @Override
-       protected void doStop(String aContext) {
+       protected void doStop() {
                // Empty.       
        }
 }
index 70558250b547d1b4bfdc92b7c56c0e61cbdbada2..1bd89ca5fb212765a7f5e78a016ed443c4f6a37f 100644 (file)
@@ -13,8 +13,8 @@ public class SystemAssemblerTest extends TestCase {
        }
 
        public void testEnvironmentApplication() {
-               SubSystem environment = new Environment();
-               SubSystem application = new Application();
+               SubSystem environment = new Environment(_registry);
+               SubSystem application = new Application(_registry);
                SystemAssembler assembler = new SystemAssembler(new SubSystem[] {
                                environment, application }, new ServiceDescriptor[0]);
                assembler.start(_registry, new Service[0]);
@@ -24,17 +24,17 @@ public class SystemAssemblerTest extends TestCase {
                assertEquals(2, appServices.length);
                assertEquals(2, _registry.listAllServices().length);
                
-               environment.stop("", _registry);
+               environment.stop();
                assertEquals(0, _registry.listAllServices().length);
                
-               application.stop("", _registry); 
+               application.stop(); 
                assertEquals(0, _registry.listAllServices().length);
        }
 
        public void testApplicationEnvironment() {
                try {
-                       SubSystem environment = new Environment();
-                       SubSystem application = new Application();
+                       SubSystem environment = new Environment(_registry);
+                       SubSystem application = new Application(_registry);
                        SystemAssembler assembler = new SystemAssembler(new SubSystem[] {
                                        application, environment }, new ServiceDescriptor[0]);
                        assembler.start(_registry, new Service[0]);
@@ -46,12 +46,12 @@ public class SystemAssemblerTest extends TestCase {
        }
 
        public void testComposite() {
-               SubSystem environment = new Environment();
-               SubSystem application = new Application();
-               CompositeSystem system = new CompositeSystem("all", new SubSystem[] {
+               SubSystem environment = new Environment(_registry);
+               SubSystem application = new Application(_registry);
+               CompositeSystem system = new CompositeSystem("all", _registry, new SubSystem[] {
                                environment, application }, new ServiceDescriptor[0],
                                new ServiceDescriptor[0]);
-               system.start("root", _registry, new Service[0]);
+               system.start("root", new Service[0]);
                ServiceDescriptor[] required = system.getRequiredServices();
                assertEquals(0, required.length);
                ServiceDescriptor[] provided = system.getProvidedServices();
@@ -60,9 +60,9 @@ public class SystemAssemblerTest extends TestCase {
 
        public void testCompositeWithWrongProvidedInfo() {
                try {
-                       SubSystem environment = new Environment();
-                       SubSystem application = new Application();
-                       CompositeSystem system = new CompositeSystem("all",
+                       SubSystem environment = new Environment(_registry);
+                       SubSystem application = new Application(_registry);
+                       CompositeSystem system = new CompositeSystem("all", _registry,
                                        new SubSystem[] { environment, application },
                                        new ServiceDescriptor[] { new DefaultServiceDescriptor(
                                                        String.class) }, new ServiceDescriptor[0]);
@@ -73,13 +73,13 @@ public class SystemAssemblerTest extends TestCase {
        }
 
        public void testCompositeWithSuperfluousRequiredInfo() {
-               SubSystem environment = new Environment();
-               SubSystem application = new Application();
-               CompositeSystem system = new CompositeSystem("all", new SubSystem[] {
+               SubSystem environment = new Environment(_registry);
+               SubSystem application = new Application(_registry);
+               CompositeSystem system = new CompositeSystem("all", _registry,new SubSystem[] {
                                environment, application }, new ServiceDescriptor[0],
                                new ServiceDescriptor[] { new DefaultServiceDescriptor(
                                                String.class) });
-               system.start("root", _registry, new Service[0]);
+               system.start("root", new Service[0]);
                ServiceDescriptor[] required = system.getRequiredServices();
                assertEquals(1, required.length);
                ServiceDescriptor[] provided = system.getProvidedServices();
@@ -88,12 +88,12 @@ public class SystemAssemblerTest extends TestCase {
 
        public void testCompositeWithExternalDependencesNotProvided() {
                try {
-                       SubSystem environment = new Environment();
-                       SubSystem application = new Application();
-                       CompositeSystem system = new CompositeSystem("all",
+                       SubSystem environment = new Environment(_registry);
+                       SubSystem application = new Application(_registry);
+                       CompositeSystem system = new CompositeSystem("all", _registry,
                                        new SubSystem[] { application }, new ServiceDescriptor[0],
                                        application.getRequiredServices());
-                       system.start("root", _registry, new Service[0]);
+                       system.start("root", new Service[0]);
                } catch (SystemAssemblyException e) {
                        return;
                }
@@ -103,13 +103,13 @@ public class SystemAssemblerTest extends TestCase {
 
        public void testCompositeWithExternalDependencesProvided() {
 
-               SubSystem environment = new Environment();
-               SubSystem application = new Application();
-               CompositeSystem system = new CompositeSystem("all",
+               SubSystem environment = new Environment(_registry);
+               SubSystem application = new Application(_registry);
+               CompositeSystem system = new CompositeSystem("all", _registry,
                                new SubSystem[] { application }, new ServiceDescriptor[0],
                                application.getRequiredServices());
-               Service[] envServices = environment.start("env", _registry,new Service[0]);
-               system.start("root", _registry, envServices);
+               Service[] envServices = environment.start("env", new Service[0]);
+               system.start("root", envServices);
                ServiceDescriptor[] required = system.getRequiredServices();
                assertEquals(2, required.length);
                ServiceDescriptor[] provided = system.getProvidedServices();
index bc1737e9c360b6e27e886ebd1215907863f4a62d..0ee69c1d6b0a7f1dbe5a16dfaad40aad1165e389 100644 (file)
@@ -1,24 +1,39 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
-  <parent>
+    <parent>
+        <groupId>org.wamblee</groupId>
+        <artifactId>wamblee-utils</artifactId>
+        <version>0.2-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
     <groupId>org.wamblee</groupId>
-    <artifactId>wamblee-utils</artifactId>
+    <artifactId>wamblee-system-spring</artifactId>
+    <packaging>jar</packaging>
     <version>0.2-SNAPSHOT</version>
-  </parent>
+    <name>wamblee.org system spring</name>
+    <url>http://wamblee.org</url>
+    <dependencies>
+        <dependency>
+            <groupId>org.wamblee</groupId>
+            <artifactId>wamblee-system-general</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
 
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>org.wamblee</groupId>
-  <artifactId>wamblee-system-spring</artifactId>
-  <packaging>jar</packaging>
-  <name>wamblee.org system general</name>
-  <url>http://wamblee.org</url>
-  <dependencies>
-    <dependency>
-      <groupId>commons-logging</groupId>
-      <artifactId>commons-logging</artifactId>
-    </dependency>
-  </dependencies>
+    </dependencies>
 
 </project>
diff --git a/system/spring/src/main/java/org/wamblee/system/spring/ProvidedServiceBean.java b/system/spring/src/main/java/org/wamblee/system/spring/ProvidedServiceBean.java
new file mode 100644 (file)
index 0000000..31dd576
--- /dev/null
@@ -0,0 +1,28 @@
+package org.wamblee.system.spring;
+
+import org.springframework.beans.factory.FactoryBean;
+
+public class ProvidedServiceBean implements FactoryBean {
+       
+       private String _id;
+       
+       public ProvidedServiceBean(String aId) { 
+               _id = aId; 
+       }
+
+       @Override
+       public Object getObject() throws Exception {
+               return SpringSystem.REGISTRY.get().find(_id).reference(Object.class);
+       }
+
+       @Override
+       public Class getObjectType() {
+               return null;
+       }
+
+       @Override
+       public boolean isSingleton() {
+               return true; 
+       }
+
+}
diff --git a/system/spring/src/main/java/org/wamblee/system/spring/SpringSystem.java b/system/spring/src/main/java/org/wamblee/system/spring/SpringSystem.java
new file mode 100644 (file)
index 0000000..5de2a94
--- /dev/null
@@ -0,0 +1,134 @@
+package org.wamblee.system.spring;
+
+import java.util.Map;
+
+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.AbstractSubSystem;
+import org.wamblee.system.CompositeSystem;
+import org.wamblee.system.Service;
+import org.wamblee.system.ServiceDescriptor;
+import org.wamblee.system.ServiceRegistry;
+import org.wamblee.system.SystemAssemblyException;
+
+/**
+ * Represents a system configured based on spring.
+ */
+public class SpringSystem extends AbstractSubSystem {
+
+       /**
+        * Singleton access to the service registry. Required while starting up.
+        */
+       static ThreadLocal<ServiceRegistry> REGISTRY = new ThreadLocal<ServiceRegistry>();
+
+       private String[] _configFiles;
+       private Map<String, ServiceDescriptor> _provided;
+       private Map<ServiceDescriptor, String> _required;
+       /**
+        * Parent application context containing required services.
+        */
+       private GenericApplicationContext _parentContext;
+
+       /**
+        * Application context containing parsed objects.
+        */
+       private AbstractApplicationContext _context;
+
+       /**
+        * Construcst a spring system.
+        * 
+        * @param aName
+        *            Name of the system.
+        * @param aConfigFiles
+        *            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 SpringSystem(String aName, ServiceRegistry aRegistry, String[] aConfigFiles,
+                       Map<String, ServiceDescriptor> aProvided,
+                       Map<ServiceDescriptor, String> aRequired) {
+               super(aName, aRegistry, aProvided.values().toArray(new ServiceDescriptor[0]),
+                               aRequired.keySet().toArray(new ServiceDescriptor[0]));
+               _configFiles = aConfigFiles;
+               _provided = aProvided;
+               _required = aRequired;
+       }
+
+       @Override
+       protected void doStart(String aContext, 
+                       Service[] aRequiredServices) {
+               ServiceRegistry old = REGISTRY.get(); 
+               try {   
+                       REGISTRY.set(getRegistry()); 
+                       try {
+
+                               registerRequiredServices(aRequiredServices);
+
+                               parseConfigFiles();
+
+                               exposeProvidedServices(aContext);
+                       } catch (Exception e) {
+                               throw new SystemAssemblyException(
+                                               "Failed to assemble spring system", e);
+                       }
+               } finally {
+                       REGISTRY.set(old);
+               }
+       }
+
+       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
+
+               // Register the Hibernate mapping files as a bean.
+               _parentContext = new GenericApplicationContext();
+               
+               for (Service svc: aRequiredServices) { 
+                       String id = svc.getId();
+                       ServiceDescriptor descriptor = svc.getDescriptor();
+                       String beanName = _required.get(descriptor);
+                       ConstructorArgumentValues cargs = new ConstructorArgumentValues();
+                       cargs.addGenericArgumentValue(id); 
+                       BeanDefinition definition = new RootBeanDefinition(ProvidedServiceBean.class, cargs,
+                                       new MutablePropertyValues());
+                       _parentContext.registerBeanDefinition(beanName, definition);
+               }
+               _parentContext.refresh();
+       }
+
+       @Override
+       protected void doStop() {
+           _context.close();
+       }
+}
diff --git a/system/spring/src/test/java/org/wamblee/system/spring/BlaService.java b/system/spring/src/test/java/org/wamblee/system/spring/BlaService.java
new file mode 100644 (file)
index 0000000..9b103b8
--- /dev/null
@@ -0,0 +1,20 @@
+package org.wamblee.system.spring;
+
+public class BlaService {
+       private HelloService _hello; 
+       
+       public BlaService(HelloService aService) {
+               if ( aService == null ) { 
+                       throw new IllegalArgumentException("helloService is null"); 
+               }
+               _hello = aService; 
+       }
+       
+       public String execute() { 
+               return _hello.say(); 
+       }
+       
+       public void stop() { 
+               System.out.println("Blaservice stopping");
+       }
+}
diff --git a/system/spring/src/test/java/org/wamblee/system/spring/HelloService.java b/system/spring/src/test/java/org/wamblee/system/spring/HelloService.java
new file mode 100644 (file)
index 0000000..fe9b2d5
--- /dev/null
@@ -0,0 +1,14 @@
+package org.wamblee.system.spring;
+
+public class HelloService {
+       
+       private String _msg; 
+       
+       public HelloService(String aMsg) { 
+               _msg = aMsg; 
+       }
+       
+       public String say() { 
+               return _msg; 
+       }
+}
diff --git a/system/spring/src/test/java/org/wamblee/system/spring/SpringSystemTest.java b/system/spring/src/test/java/org/wamblee/system/spring/SpringSystemTest.java
new file mode 100644 (file)
index 0000000..092a5bc
--- /dev/null
@@ -0,0 +1,108 @@
+package org.wamblee.system.spring;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.wamblee.system.DefaultServiceDescriptor;
+import org.wamblee.system.DefaultServiceRegistry;
+import org.wamblee.system.Service;
+import org.wamblee.system.ServiceDescriptor;
+import org.wamblee.system.ServiceRegistry;
+import org.wamblee.system.SystemAssemblyException;
+
+public class SpringSystemTest extends TestCase {
+
+       private static final String HELLO_SERVICE_SPRING_XML = "test.org.wamblee.system.spring.xml";
+       private static final String HELLO_SERVICE_SPRING_WITH_REQS_XML = "test.org.wamblee.system.springWithRequirements.xml";
+
+       private ServiceRegistry _registry;
+
+       @Override
+       protected void setUp() throws Exception {
+               super.setUp();
+               _registry = new DefaultServiceRegistry();
+       }
+
+       public void testBlackboxSystem() {
+               SpringSystem system = new SpringSystem("system", _registry,
+                               new String[] { HELLO_SERVICE_SPRING_XML },
+                               new HashMap<String, ServiceDescriptor>(),
+                               new HashMap<ServiceDescriptor, String>());
+               system.start("Hello", new Service[0]);
+               Service[] services = system.getRunningServices();
+               assertEquals(0, services.length);
+               
+               system.stop();
+       }
+
+       public void testOneProvidedService() {
+               Map<String, ServiceDescriptor> provided = new HashMap<String, ServiceDescriptor>();
+               provided.put("helloService", new DefaultServiceDescriptor(
+                               HelloService.class));
+
+               SpringSystem system = new SpringSystem("system", _registry,
+                               new String[] { HELLO_SERVICE_SPRING_XML }, provided,
+                               new HashMap<ServiceDescriptor, String>());
+               system.start("Hello", new Service[0]);
+               Service[] services = system.getRunningServices();
+               assertEquals(1, services.length);
+               assertTrue(services[0].reference(HelloService.class) instanceof HelloService);
+               assertEquals("Hello world!", services[0].reference(HelloService.class)
+                               .say());
+               system.stop();
+       }
+
+       public void testWithMissingRequiremnt() {
+               try {
+                       SpringSystem system = new SpringSystem("system", _registry,
+                                       new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML },
+                                       new HashMap<String, ServiceDescriptor>(),
+                                       new HashMap<ServiceDescriptor, String>());
+                       system.start("Bla", new Service[0]);
+               } catch (SystemAssemblyException e) {
+                       //e.printStackTrace();
+                       return;
+               }
+               fail();
+       }
+
+       public void testWithRequirement() {
+               Map<ServiceDescriptor, String> required = new HashMap<ServiceDescriptor, String>();
+               required.put(new DefaultServiceDescriptor(HelloService.class),
+                               "helloService");
+               SpringSystem system = new SpringSystem("system", _registry,
+                               new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML },
+                               new HashMap<String, ServiceDescriptor>(), required);
+               
+               HelloService helloObject = new HelloService("ladida"); 
+               Service helloService = _registry.register(new DefaultServiceDescriptor(HelloService.class), helloObject);
+               system.start("Bla", new Service[] { helloService } );
+               system.stop();
+       }
+       
+       public void testWithRequirementAndProvidedService() {
+               Map<ServiceDescriptor, String> required = new HashMap<ServiceDescriptor, String>();
+               required.put(new DefaultServiceDescriptor(HelloService.class),
+                               "helloService");
+               Map<String,ServiceDescriptor> provided = new HashMap<String, ServiceDescriptor>();
+               provided.put("blaService", new DefaultServiceDescriptor(
+                               BlaService.class));
+
+               SpringSystem system = new SpringSystem("system", _registry,
+                               new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML },
+                               provided, required);
+               
+               HelloService helloObject = new HelloService("ladida"); 
+               Service helloService = _registry.register(new DefaultServiceDescriptor(HelloService.class), helloObject);
+               Service[] services = system.start("Bla", new Service[] { helloService } );
+               assertEquals(1, services.length);
+               
+               assertTrue(services[0].reference(BlaService.class) instanceof BlaService);
+               assertEquals("ladida", services[0].reference(BlaService.class)
+                               .execute());
+               system.stop();
+       }
+
+}
diff --git a/system/spring/src/test/resources/test.org.wamblee.system.spring.xml b/system/spring/src/test/resources/test.org.wamblee.system.spring.xml
new file mode 100644 (file)
index 0000000..238054b
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans
+    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+    <bean id="helloService" class="org.wamblee.system.spring.HelloService">
+        <constructor-arg>
+            <value>Hello world!</value>
+        </constructor-arg>
+    </bean>
+
+</beans>
diff --git a/system/spring/src/test/resources/test.org.wamblee.system.springWithRequirements.xml b/system/spring/src/test/resources/test.org.wamblee.system.springWithRequirements.xml
new file mode 100644 (file)
index 0000000..a2f60d8
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans
+    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+    <bean id="blaService" class="org.wamblee.system.spring.BlaService" destroy-method="stop">
+        <constructor-arg>
+            <ref bean="helloService"/>
+        </constructor-arg>
+    </bean>
+
+</beans>