Author: marrs
Date: Tue Dec  1 22:12:26 2009
New Revision: 885969

URL: http://svn.apache.org/viewvc?rev=885969&view=rev
Log:
added support for adding dynamic aspects for services, plus a test that 
validates the basic behaviour

Added:
    
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/AspectImpl.java
    
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/AspectTest.java
Modified:
    
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
    
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
    
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Service.java
    
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java
    
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java

Modified: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java?rev=885969&r1=885968&r2=885969&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
 (original)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
 Tue Dec  1 22:12:26 2009
@@ -18,6 +18,7 @@
  */
 package org.apache.felix.dependencymanager;
 
+import java.util.Dictionary;
 import java.util.List;
 
 import org.apache.felix.dependencymanager.dependencies.BundleDependency;
@@ -141,6 +142,10 @@
         return m_manager.createBundleDependency();
     }
 
+    public Service createAspectService(Class serviceInterface, String 
serviceFilter, Object aspectImplementation, Dictionary properties) {
+        return m_manager.createAspectService(serviceInterface, serviceFilter, 
aspectImplementation, properties);
+    }
+
     /**
      * Cleans up all services and their dependencies.
      * 

Modified: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java?rev=885969&r1=885968&r2=885969&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
 (original)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
 Tue Dec  1 22:12:26 2009
@@ -20,12 +20,14 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Dictionary;
 import java.util.List;
 
 import org.apache.felix.dependencymanager.dependencies.BundleDependency;
 import org.apache.felix.dependencymanager.dependencies.ConfigurationDependency;
 import org.apache.felix.dependencymanager.dependencies.ServiceDependency;
 import 
org.apache.felix.dependencymanager.dependencies.TemporalServiceDependency;
+import org.apache.felix.dependencymanager.impl.AspectImpl;
 import org.apache.felix.dependencymanager.impl.Logger;
 import org.apache.felix.dependencymanager.impl.ServiceImpl;
 import org.osgi.framework.BundleContext;
@@ -108,7 +110,17 @@
     public BundleDependency createBundleDependency() {
         return new BundleDependency(m_context, m_logger);
     }
-    
+
+    public Service createAspectService(Class serviceInterface, String 
serviceFilter, Object aspectImplementation, Dictionary properties) {
+        return createService()
+            .setImplementation(new AspectImpl(serviceInterface, serviceFilter, 
aspectImplementation, properties))
+            .add(createServiceDependency()
+                .setService(serviceInterface, serviceFilter)
+                .setAutoConfig(false)
+                .setCallbacks("added", "removed")
+            );
+    }
+
     /**
      * Returns a list of services.
      * 
@@ -117,5 +129,4 @@
     public List getServices() {
         return Collections.unmodifiableList(m_services);
     }
-
 }

Modified: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Service.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Service.java?rev=885969&r1=885968&r2=885969&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Service.java
 (original)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Service.java
 Tue Dec  1 22:12:26 2009
@@ -36,6 +36,7 @@
      * @return this service
      */
     public Service add(Dependency dependency);
+    public Service add(List dependencies);
     
     /**
      * Removes a dependency from this service.

Added: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/AspectImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/AspectImpl.java?rev=885969&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/AspectImpl.java
 (added)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/AspectImpl.java
 Tue Dec  1 22:12:26 2009
@@ -0,0 +1,72 @@
+package org.apache.felix.dependencymanager.impl;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.apache.felix.dependencymanager.Service;
+import org.osgi.framework.ServiceReference;
+
+public class AspectImpl {
+       private volatile DependencyManager m_manager;
+       private volatile Service m_service;
+       private final Class m_serviceInterface;
+       private final String m_serviceFilter;
+       private final Object m_aspectImplementation;
+       private final Map m_services = new HashMap();
+    private final Dictionary m_aspectProperties;
+       
+       public AspectImpl(Class serviceInterface, String serviceFilter, Object 
aspectImplementation, Dictionary properties) {
+               m_serviceInterface = serviceInterface;
+               m_serviceFilter = serviceFilter;
+               m_aspectImplementation = aspectImplementation;
+               m_aspectProperties = properties;
+       }
+
+       public void added(ServiceReference ref, Object service) {
+               Properties props = new Properties();
+               String[] keys = ref.getPropertyKeys();
+               for (int i = 0; i < keys.length; i++) {
+                   props.put(keys[i], ref.getProperty(keys[i]));
+               }
+               Enumeration e = m_aspectProperties.keys();
+        while (e.hasMoreElements()) {
+            Object key = e.nextElement();
+            props.put(key, m_aspectProperties.get(key));
+        }
+
+               Service newService = m_manager.createService()
+                       .setInterface(m_serviceInterface.getName(), props)
+                       .setImplementation(m_aspectImplementation)
+                       .add(m_service.getDependencies())
+                       .add(m_manager.createServiceDependency()
+                               .setService(m_serviceInterface, ref)
+                               .setRequired(true)
+                               );
+               m_services.put(ref, newService);
+               m_manager.add(newService);
+       }
+
+       public void removed(ServiceReference ref, Object service) {
+               Service newService = (Service) m_services.remove(ref);
+               if (newService == null) {
+                       System.out.println("Service should not be null here, 
dumping stack.");
+                       Thread.dumpStack();
+               }
+               else {
+                       m_manager.remove(newService);
+               }
+       }
+       
+    public void stop() { 
+        Iterator i = m_services.values().iterator();
+        while (i.hasNext()) {
+            m_manager.remove((Service) i.next());
+        }
+        m_services.clear();
+    }
+}

Modified: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java?rev=885969&r1=885968&r2=885969&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java
 (original)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java
 Tue Dec  1 22:12:26 2009
@@ -904,23 +904,13 @@
                 }
                 catch (Exception e) {
                     m_logger.log(Logger.LOG_ERROR, "Could not obtain instances 
from the composition manager.", e);
-                    instances = new Object[] { m_serviceInstance };
+                    instances = m_serviceInstance == null ? new Object[] {} : 
new Object[] { m_serviceInstance };
                 }
             }
         }
         else {
-            instances = new Object[] { m_serviceInstance };
+            instances = m_serviceInstance == null ? new Object[] {} : new 
Object[] { m_serviceInstance };
         }
-        // TODO remove this test code; there are definitely cases where some 
instances in this array can be
-        // null, but it's not always harmful (in fact it's not possible to 
determine that here), this also happens
-        // when you start tracking required dependencies... it's probably safe 
not to include these null's in the
-        // array in the first place
-//        for (int i = 0; i < instances.length; i++) {
-//            if (instances[i] == null) {
-//                System.out.println("GetCompositionInstances had a null 
instance at index " + i + " dumping stack:");
-//                Thread.dumpStack();
-//            }
-//        }
         return instances;
     }
 

Added: 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/AspectTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/AspectTest.java?rev=885969&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/AspectTest.java
 (added)
+++ 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/AspectTest.java
 Tue Dec  1 22:12:26 2009
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.felix.dependencymanager.test;
+
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.provision;
+
+import java.util.Properties;
+
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.apache.felix.dependencymanager.Service;
+import org.apache.felix.dependencymanager.impl.Logger;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+...@runwith(JUnit4TestRunner.class)
+public class AspectTest {
+    @Configuration
+    public static Option[] configuration() {
+        return options(
+            provision(
+                
mavenBundle().groupId("org.osgi").artifactId("org.osgi.compendium").version("4.2.0"),
+                
mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.dependencymanager").versionAsInProject()
+            )
+        );
+    }    
+
+    @Test
+    public void testServiceRegistrationAndConsumption(BundleContext context) {
+        DependencyManager m = new DependencyManager(context, new 
Logger(context));
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Service sp = m.createService().setImplementation(new 
ServiceProvider(e)).setInterface(ServiceInterface.class.getName(), null);
+        Service sc = m.createService().setImplementation(new 
ServiceConsumer(e)).add(m.createServiceDependency().setService(ServiceInterface.class).setRequired(true));
+        Service sa = m.createAspectService(ServiceInterface.class, "(|(!(" + 
Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=0))", new 
ServiceAspect(e), new Properties() {{ put(Constants.SERVICE_RANKING, 
Integer.valueOf(1)); }} );
+        m.add(sc);
+        m.add(sp);
+        e.waitForStep(3, 2000);
+        m.add(sa);
+        e.waitForStep(4, 2000);
+        e.step(5);
+        e.waitForStep(8, 2000);
+        m.remove(sa);
+        e.waitForStep(9, 2000);
+        e.step(10);
+        e.waitForStep(11, 2000);
+        m.remove(sp);
+        m.remove(sc);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(Runnable run);
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(Runnable run) {
+            run.run();
+        }
+    }
+    
+    static class ServiceAspect implements ServiceInterface {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_originalService;
+        
+        public ServiceAspect(Ensure e) {
+            m_ensure = e;
+        }
+        public void start() {
+            m_ensure.step(4);
+        }
+        public void invoke(Runnable run) {
+            m_ensure.step(6);
+            m_originalService.invoke(run);
+        }
+        
+        public void stop() {
+            m_ensure.step(9);
+        }
+    }
+
+    static class ServiceConsumer implements Runnable {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            Thread t = new Thread(this);
+            t.start();
+        }
+        
+        public void run() {
+            m_ensure.step(1);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 2));
+            m_ensure.step(3);
+            m_ensure.waitForStep(5, 2000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 7));
+            m_ensure.step(8);
+            m_ensure.waitForStep(10, 2000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 11));
+        }
+    }
+}

Modified: 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java?rev=885969&r1=885968&r2=885969&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java
 (original)
+++ 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java
 Tue Dec  1 22:12:26 2009
@@ -79,4 +79,8 @@
             System.out.println("[Ensure " + INSTANCE + "] arrived at step " + 
nr);
         }
     }
+    
+    public static Runnable createRunnableStep(final Ensure ensure, final int 
nr) {
+        return new Runnable() { public void run() { ensure.step(nr); }};
+    }
 }


Reply via email to