felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pde...@apache.org
Subject svn commit: r1727869 [2/11] - in /felix/trunk/dependencymanager: org.apache.felix.dependencymanager.itest/ org.apache.felix.dependencymanager.lambda.itest/ org.apache.felix.dependencymanager.lambda.itest/.settings/ org.apache.felix.dependencymanager.la...
Date Sun, 31 Jan 2016 23:27:07 GMT
Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java?rev=1727869&view=auto
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java (added)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java Sun Jan 31 23:27:05 2016
@@ -0,0 +1,163 @@
+/*
+ * 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.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AdapterWithoutPropagationTest extends TestBase {
+    
+    public void testAdapterNoPropagate() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+
+        // The provider has a "foo=bar" property
+        ServiceProvider serviceProvider = new ServiceProvider(e);
+        Component provider = component(m).provides(OriginalService.class).properties(foo -> "bar").impl(serviceProvider).build();
+
+        // The Adapter will see the "foo=bar" property from the adaptee
+        Component adapter = adapter(m, OriginalService.class)
+            .propagate(false).cb("set", "change", null).provides(AdaptedService.class).impl(new ServiceAdapter(e)).build();
+
+        // The consumer depends on the AdaptedService, but won't see foo=bar property from the adaptee 
+        Component consumer = component(m) 
+            .impl(new ServiceConsumer(e)).withSrv(AdaptedService.class, b -> b.cb("set", "change", null)).build();
+        
+        // add the provider and the adapter
+        m.add(provider);
+        m.add(adapter);
+        // Checks if the adapter has been started and has seen the adaptee properties
+        e.waitForStep(1, 5000);
+        
+        // add a consumer that must not see the adaptee service properties
+        m.add(consumer);
+        e.waitForStep(2, 5000);
+        
+        // change the service properties of the provider, and check that the adapter callback instance is caled.
+        serviceProvider.changeServiceProperties();
+        e.waitForStep(3, 5000);
+        
+        // cleanup
+        m.clear();
+    }
+
+    public void testAdapterNoPropagateRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+
+        // The provider has a "foo=bar" property
+        ServiceProvider serviceProvider = new ServiceProvider(e);
+        Component provider = component(m).provides(OriginalService.class).properties(foo -> "bar").impl(serviceProvider).build();
+
+        // The Adapter will see the "foo=bar" property from the adaptee
+        ServiceAdapter saimpl = new ServiceAdapter(e);
+        Component adapter = adapter(m, OriginalService.class).propagate(false).impl(saimpl).provides(AdaptedService.class).cbi(saimpl::set, saimpl::change, null).build();           
+
+        // The consumer depends on the AdaptedService, but won't see foo=bar property from the adaptee 
+        ServiceConsumer scimpl = new ServiceConsumer(e);
+        Component consumer = component(m).impl(scimpl).withSrv(AdaptedService.class, s -> s.cbi(scimpl::set, scimpl::change, null)).build();
+        
+        // add the provider and the adapter
+        m.add(provider);
+        m.add(adapter);
+        // Checks if the adapter has been started and has seen the adaptee properties
+        e.waitForStep(1, 5000);
+        
+        // add a consumer that must not see the adaptee service properties
+        m.add(consumer);
+        e.waitForStep(2, 5000);
+        
+        // change the service properties of the provider, and check that the adapter callback instance is caled.
+        serviceProvider.changeServiceProperties();
+        e.waitForStep(3, 5000);
+        
+        // cleanup
+        m.clear();
+    }
+
+    static interface OriginalService {
+    }
+    
+    static interface AdaptedService {
+    }
+    
+    static class ServiceProvider implements OriginalService {
+        private volatile ServiceRegistration m_registration; // auto injected when started.
+        public ServiceProvider(Ensure e) {
+        }
+        public void changeServiceProperties() {
+            Hashtable<String, String> props = new Hashtable<>();
+            props.put("foo", "bar2");
+            m_registration.setProperties(props);
+        }
+    }
+    
+    public static class ServiceAdapter implements AdaptedService {
+        private final Ensure m_ensure;
+        
+        public ServiceAdapter(Ensure e) {
+            m_ensure = e;
+        }
+
+        public void set(OriginalService adaptee, Dictionary<String, Object> props) {
+            Assert.assertEquals("bar", props.get("foo"));
+            m_ensure.step(1);
+        }
+        
+        void change(OriginalService adapted, Dictionary<String, Object> props) {
+            Assert.assertEquals("bar2", props.get("foo"));
+            m_ensure.step(3);
+        }
+    }
+
+    static class ServiceConsumer {
+        @SuppressWarnings("unused")
+		private volatile AdaptedService m_service;
+        private final Ensure m_ensure;
+        
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        void set(AdaptedService adapted, Dictionary<String, Object> props) {
+            Assert.assertNull(props.get("foo"));
+            m_ensure.step(2);
+        }
+        
+        void change(AdaptedService adapted, Dictionary<String, Object> props) {
+            Assert.assertNull(props.get("foo"));
+            Assert.fail("Change callback should not be called");
+        }
+    }
+}
+
+

Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java?rev=1727869&view=auto
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java (added)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java Sun Jan 31 23:27:05 2016
@@ -0,0 +1,337 @@
+/*
+ * 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.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectBaseTest extends TestBase {    
+
+	public void testSingleAspect() {
+	    DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service provider and consumer
+        ServiceProvider p = new ServiceProvider(e, "a");
+        ServiceConsumer c = new ServiceConsumer(e);
+        
+        Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();
+        Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cb("add", "remove").autoConfig("m_service")).build();
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+            
+        m.add(sc);
+        m.add(sp);
+        // after the provider was added, the consumer's add should have been invoked once
+        e.waitForStep(1, 2000);
+        Assert.assertEquals("a", c.invoke());
+        m.add(sa);
+        // after the aspect was added, the consumer should get and add for the aspect and a remove
+        // for the original service
+        e.waitForStep(3, 2000);
+        Assert.assertEquals("aa", c.invoke());
+        m.remove(sa);
+        // removing the aspect again should give a remove and add
+        e.waitForStep(5, 2000);
+        Assert.assertEquals("a", c.invoke());
+        m.remove(sp);
+        // finally removing the original service should give a remove
+        e.waitForStep(6, 2000);
+        m.remove(sc);
+        e.step(7);
+        clearComponents();
+    }
+    
+    public void testSingleAspectRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service provider and consumer
+        ServiceProvider p = new ServiceProvider(e, "a");
+        ServiceConsumer c = new ServiceConsumer(e);
+        
+        Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();        
+        Component sc = component(m)
+            .impl(c).withSrv(ServiceInterface.class, srv -> srv.cbi(c::add, c::remove).autoConfig("m_service")).build();
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+        
+        m.add(sc);
+        m.add(sp);
+        // after the provider was added, the consumer's add should have been invoked once
+        e.waitForStep(1, 2000);
+        Assert.assertEquals("a", c.invoke());
+        m.add(sa);
+        // after the aspect was added, the consumer should get and add for the aspect and a remove
+        // for the original service
+        e.waitForStep(3, 2000);
+        Assert.assertEquals("aa", c.invoke());
+        m.remove(sa);
+        // removing the aspect again should give a remove and add
+        e.waitForStep(5, 2000);
+        Assert.assertEquals("a", c.invoke());
+        m.remove(sp);
+        // finally removing the original service should give a remove
+        e.waitForStep(6, 2000);
+        m.remove(sc);
+        e.step(7);
+        clearComponents();
+    }
+    
+    @SuppressWarnings("serial")
+    public void testSingleAspectThatAlreadyExisted() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service provider and consumer
+        ServiceProvider p = new ServiceProvider(e, "a");
+        ServiceConsumer c = new ServiceConsumer(e);
+        Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();            
+        Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cb("add", "remove").autoConfig("m_service")).build();
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+
+        // we first add the aspect
+        m.add(sa);
+        // then the service provider
+        m.add(sp);
+        // finally the consumer
+        m.add(sc);
+
+        Assert.assertEquals("aa", c.invoke());
+        
+        // now the consumer's added should be invoked once, as the aspect is already available and should
+        // directly hide the original service
+        e.waitForStep(1, 2000);
+        e.step(2);
+
+        m.remove(sa);
+        // after removing the aspect, the consumer should get the original service back, so
+        // remove and add will be invoked
+        e.waitForStep(4, 2000);
+        
+        Assert.assertEquals("a", c.invoke());
+        
+        m.remove(sp);
+        // after removing the original service, the consumer's remove should be called once
+        e.waitForStep(5, 2000);
+        
+        m.remove(sc);
+        e.step(6);
+    }
+
+    public void testSingleAspectThatAlreadyExistedRef() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create a service provider and consumer
+        ServiceProvider p = new ServiceProvider(e, "a");
+        ServiceConsumer c = new ServiceConsumer(e);
+        
+        Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();
+        Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cbi(c::add, c::remove).autoConfig("m_service")).build();
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+
+        // we first add the aspect
+        m.add(sa);
+        // then the service provider
+        m.add(sp);
+        // finally the consumer
+        m.add(sc);
+
+        Assert.assertEquals("aa", c.invoke());
+        
+        // now the consumer's added should be invoked once, as the aspect is already available and should
+        // directly hide the original service
+        e.waitForStep(1, 2000);
+        e.step(2);
+
+        m.remove(sa);
+        // after removing the aspect, the consumer should get the original service back, so
+        // remove and add will be invoked
+        e.waitForStep(4, 2000);
+        
+        Assert.assertEquals("a", c.invoke());
+        
+        m.remove(sp);
+        // after removing the original service, the consumer's remove should be called once
+        e.waitForStep(5, 2000);
+        
+        m.remove(sc);
+        e.step(6);
+    }
+
+    public void testMultipleAspects() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create service providers and consumers
+        ServiceConsumer c = new ServiceConsumer(e);
+        Component sp = component(m).impl(new ServiceProvider(e, "a")).provides(ServiceInterface.class).properties(name -> "a").build();
+        Component sp2 = component(m).impl(new ServiceProvider(e, "b")).provides(ServiceInterface.class).properties(name -> "b").build();
+        Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cb("add", "remove")).build();
+
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+        Component sa2 = aspect(m, ServiceInterface.class).rank(10).impl(ServiceAspect.class).build();
+
+        m.add(sp);
+        m.add(sp2);
+        m.add(sa);
+        m.add(sa2);
+        m.add(sc);
+        // the consumer will monitor progress, it should get it's add invoked twice, once for every
+        // (highest) aspect
+        e.waitForStep(2, 2000);
+        e.step(3);
+        
+        // now invoke all services the consumer collected
+        List<String> list = c.invokeAll();
+        // and make sure both of them are correctly invoked
+        Assert.assertTrue(list.size() == 2);
+        Assert.assertTrue(list.contains("aaa"));
+        Assert.assertTrue(list.contains("bbb"));
+        
+        m.remove(sc);
+        // removing the consumer now should get its removed method invoked twice
+        e.waitForStep(5, 2000);
+        e.step(6);
+        m.remove(sa2);
+        m.remove(sa);
+        m.remove(sp2);
+        m.remove(sp);
+        e.step(7);
+    }
+    
+    public void testMultipleAspectsRef() {
+        DependencyManager m = new DependencyManager(context);
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        
+        // create service providers and consumers
+        ServiceConsumer c = new ServiceConsumer(e);
+        Component sp = component(m).impl(new ServiceProvider(e, "a")).provides(ServiceInterface.class).properties(name -> "a").build();
+        Component sp2 = component(m).impl(new ServiceProvider(e, "b")).provides(ServiceInterface.class).properties(name -> "b").build();
+        Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cbi(c::add, c::remove)).build();
+
+        Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
+        Component sa2 = aspect(m, ServiceInterface.class).rank(10).impl(ServiceAspect.class).build();
+
+        m.add(sp);
+        m.add(sp2);
+        m.add(sa);
+        m.add(sa2);
+        m.add(sc);
+        // the consumer will monitor progress, it should get it's add invoked twice, once for every
+        // (highest) aspect
+        e.waitForStep(2, 2000);
+        e.step(3);
+        
+        // now invoke all services the consumer collected
+        List<String> list = c.invokeAll();
+        // and make sure both of them are correctly invoked
+        Assert.assertTrue(list.size() == 2);
+        Assert.assertTrue(list.contains("aaa"));
+        Assert.assertTrue(list.contains("bbb"));
+        
+        m.remove(sc);
+        // removing the consumer now should get its removed method invoked twice
+        e.waitForStep(5, 2000);
+        e.step(6);
+        m.remove(sa2);
+        m.remove(sa);
+        m.remove(sp2);
+        m.remove(sp);
+        e.step(7);
+    }
+    
+    public static interface ServiceInterface {
+        public String invoke(String input);
+    }
+    
+    public static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        private final String m_name;
+        public ServiceProvider(Ensure e, String name) {
+            m_ensure = e;
+            m_name = name;
+        }
+        public String invoke(String input) {
+            return input + m_name;
+        }
+    }
+    
+    public static class ServiceAspect implements ServiceInterface {
+        private volatile ServiceInterface m_originalService;
+        private volatile ServiceRegistration m_registration;
+        
+        public String invoke(String input) {
+            String result = m_originalService.invoke(input);
+            String property = (String) m_registration.getReference().getProperty("name");
+            return result + property;
+        }
+    }
+    
+    public static class ServiceConsumer {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_service;
+        private List<ServiceInterface> m_services = new ArrayList<ServiceInterface>();
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void add(ServiceReference<ServiceInterface> ref, ServiceInterface si) {
+            System.out.println("add: " + ServiceUtil.toString(ref));
+            m_services.add(si);
+            m_ensure.step();
+        }
+        
+        public void remove(ServiceReference<ServiceInterface> ref, ServiceInterface si) {
+            System.out.println("rem: " + ServiceUtil.toString(ref));
+            m_services.remove(si);
+            m_ensure.step();
+        }
+        
+        public String invoke() {
+            return m_service.invoke("");
+        }
+        
+        public List<String> invokeAll() {
+            List<String> results = new ArrayList<String>();
+            for (ServiceInterface si : m_services) {
+                results.add(si.invoke(""));
+            }
+            return results;
+        }
+    }
+}

Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java?rev=1727869&view=auto
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java (added)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java Sun Jan 31 23:27:05 2016
@@ -0,0 +1,113 @@
+/*
+ * 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.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectChainTest extends TestBase {
+
+	public void testBuildAspectChain() {
+	    DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class).build();
+        Component sa2 = aspect(m, ServiceInterface.class).rank(20).impl(new ServiceAspect(e, 3)).build();
+        Component sa3 = aspect(m, ServiceInterface.class).rank(30).impl(new ServiceAspect(e, 2)).build();
+        Component sa1 = aspect(m, ServiceInterface.class).rank(10).impl(new ServiceAspect(e, 4)).build();
+        m.add(sc);
+
+        m.add(sp);
+        m.add(sa2);
+        m.add(sa3);
+        m.add(sa1);
+        e.step();
+        e.waitForStep(5,  5000);
+        
+        m.remove(sa3);
+        m.remove(sa2);
+        m.remove(sa1);
+        m.remove(sp);
+        
+        m.remove(sc);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(Runnable run);
+    }
+    
+    static class ServiceProvider implements ServiceInterface {
+        @SuppressWarnings("unused")
+        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_parentService;
+        private final int m_step;
+        
+        public ServiceAspect(Ensure e, int step) {
+            m_ensure = e;
+            m_step = step;
+        }
+        public void start() {
+        }
+        
+        public void invoke(Runnable run) {
+            m_ensure.step(m_step);
+            m_parentService.invoke(run);
+        }
+        
+        public void stop() {
+        }
+    }
+
+    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.waitForStep(1, 2000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 5));
+        }
+    }
+}

Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java?rev=1727869&view=auto
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java (added)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java Sun Jan 31 23:27:05 2016
@@ -0,0 +1,252 @@
+/*
+ * 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.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectDynamicsTest extends TestBase {
+
+	public void testDynamicallyAddAndRemoveAspect() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        Ensure aspectStopEnsure = new Ensure();
+        // create a service provider and consumer
+        Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component provider2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class.getName()).build();
+        Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", null, null, "swap")).build();
+        Component aspect = aspect(m, ServiceInterface.class).autoAdd(false).rank(1).impl(new ServiceAspect(e, aspectStopEnsure)).build();
+        
+        m.add(consumer);
+        m.add(provider);
+        // the consumer should invoke the provider here, and when done, arrive at step 3
+        // finally wait for step 6 before continuing
+        e.waitForStep(3, 15000);
+        
+        m.add(aspect);
+        // after adding the aspect, we wait for its init to be invoked, arriving at
+        // step 4 after an instance bound dependency was added (on a service provided by
+        // provider 2)
+        e.waitForStep(4, 15000);
+        
+        m.add(provider2);
+        
+        // after adding provider 2, we should now see the client being swapped, so
+        // we wait for step 5 to happen
+        e.waitForStep(5, 15000);
+        
+        // now we continue with step 6, which will trigger the next part of the consumer's
+        // run method to be executed
+        e.step(6);
+        
+        // invoking step 7, 8 and 9 when invoking the aspect which in turn invokes the
+        // dependency and the original service, so we wait for that to finish here, which
+        // is after step 10 has been reached (the client will now wait for step 12)
+        e.waitForStep(10, 15000);
+        
+        m.remove(aspect);
+        aspectStopEnsure.waitForStep(1, 15000);
+        // removing the aspect should trigger step 11 (in the swap method of the consumer)
+        e.waitForStep(11, 15000);
+        
+        // step 12 triggers the client to continue
+        e.step(12);
+        
+        // wait for step 13, the final invocation of the provided service (without aspect)
+        e.waitForStep(13, 15000);
+        
+        // clean up
+        m.remove(provider2);
+        m.remove(provider);
+        m.remove(consumer);
+        e.waitForStep(16, 15000);
+        m.clear();
+    }
+    
+    public void testDynamicallyAddAndRemoveAspectRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        Ensure aspectStopEnsure = new Ensure();
+        // create a service provider and consumer
+        Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component provider2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class.getName()).build();
+        Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb(ServiceConsumer::add).sw(ServiceConsumer::swap)).build();
+        Component aspect = aspect(m, ServiceInterface.class).autoAdd(false).rank(1).impl(new ServiceAspect(e, aspectStopEnsure)).build();
+        
+        m.add(consumer);
+        m.add(provider);
+        // the consumer should invoke the provider here, and when done, arrive at step 3
+        // finally wait for step 6 before continuing
+        e.waitForStep(3, 15000);
+        
+        m.add(aspect);
+        // after adding the aspect, we wait for its init to be invoked, arriving at
+        // step 4 after an instance bound dependency was added (on a service provided by
+        // provider 2)
+        e.waitForStep(4, 15000);
+        
+        m.add(provider2);
+        
+        // after adding provider 2, we should now see the client being swapped, so
+        // we wait for step 5 to happen
+        e.waitForStep(5, 15000);
+        
+        // now we continue with step 6, which will trigger the next part of the consumer's
+        // run method to be executed
+        e.step(6);
+        
+        // invoking step 7, 8 and 9 when invoking the aspect which in turn invokes the
+        // dependency and the original service, so we wait for that to finish here, which
+        // is after step 10 has been reached (the client will now wait for step 12)
+        e.waitForStep(10, 15000);
+        
+        m.remove(aspect);
+        aspectStopEnsure.waitForStep(1, 15000);
+        // removing the aspect should trigger step 11 (in the swap method of the consumer)
+        e.waitForStep(11, 15000);
+        
+        // step 12 triggers the client to continue
+        e.step(12);
+        
+        // wait for step 13, the final invocation of the provided service (without aspect)
+        e.waitForStep(13, 15000);
+        
+        // clean up
+        m.remove(provider2);
+        m.remove(provider);
+        m.remove(consumer);
+        e.waitForStep(16, 15000);
+        m.clear();
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(Runnable run);
+    }
+    
+    static interface ServiceInterface2 {
+        public void invoke();
+    }
+    
+    static class ServiceProvider2 implements ServiceInterface2 {
+        private final Ensure m_ensure;
+
+        public ServiceProvider2(Ensure ensure) {
+            m_ensure = ensure;
+        }
+
+        public void invoke() {
+            m_ensure.step(9);
+        }
+        public void stop() {
+            m_ensure.step();
+        }
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(Runnable run) {
+            run.run();
+        }
+        public void stop() {
+            m_ensure.step();
+        }
+    }
+    
+    static class ServiceAspect implements ServiceInterface {
+        private final Ensure m_ensure;
+        private volatile ServiceInterface m_originalService;
+        private volatile ServiceInterface2 m_injectedService;
+        private volatile Component m_service;
+        private volatile DependencyManager m_manager;
+        private final Ensure m_stopEnsure;
+        
+        public ServiceAspect(Ensure e, Ensure stopEnsure) {
+            m_ensure = e;
+            m_stopEnsure = stopEnsure;
+        }
+        public void init() {
+            m_service.add(m_manager.createServiceDependency()
+                .setService(ServiceInterface2.class)
+                .setRequired(true)
+            );
+            m_ensure.step(4);
+        }
+
+        public void invoke(Runnable run) {
+            m_ensure.step(7);
+            m_originalService.invoke(run);
+            m_injectedService.invoke();
+        }
+        
+        public void stop() {
+            m_stopEnsure.step(1);
+        }
+    }
+
+    static class ServiceConsumer implements Runnable {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+        private final Ensure.Steps m_swapSteps = new Ensure.Steps(5, 11);
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        void add(ServiceInterface service) {
+            m_service = service;
+        }
+        
+        void swap(ServiceInterface oldService, ServiceInterface newService) {
+            System.out.println("swap: old=" + oldService + ", new=" + newService);
+            m_ensure.steps(m_swapSteps);
+            m_service = newService;
+        }
+        
+        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(6, 15000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 8));
+            m_ensure.step(10);
+            m_ensure.waitForStep(12, 15000);
+            m_service.invoke(Ensure.createRunnableStep(m_ensure, 13));
+        }
+        
+        public void stop() {
+            m_ensure.step();
+        }
+    }
+}

Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java?rev=1727869&view=auto
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java (added)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java Sun Jan 31 23:27:05 2016
@@ -0,0 +1,120 @@
+/*
+ * 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.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectServiceDependencyTest extends TestBase {
+    public void testServiceRegistrationAndConsumption() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", "remove")).build();
+        Component asp = aspect(m, ServiceInterface.class).rank(100).impl(ServiceProviderAspect.class).build();
+        		
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(8);
+    }
+    
+    static interface ServiceInterface {
+        public void invoke(String caller);
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(String caller) {
+        	if (caller.equals("consumer.init")) {
+        		m_ensure.step(3);
+        	} else if (caller.equals("aspect.consumer.add")) {
+        		m_ensure.step(5);
+        	}
+        }
+    }
+    
+    static class ServiceProviderAspect implements ServiceInterface {
+    	private volatile ServiceInterface m_service;
+    	
+    	public ServiceProviderAspect() {
+		}
+
+		@Override
+		public void invoke(String caller) {
+			m_service.invoke("aspect." + caller);
+		}
+    }
+
+    static class ServiceConsumer {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+        private int addCount = 0;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            m_ensure.step(2);
+            m_service.invoke("consumer.init");
+        }
+        
+        public void destroy() {
+            m_ensure.step(7);
+        }
+        
+        public void add(ServiceInterface service) {
+        	m_service = service;
+        	switch (addCount) {
+        		case 0: m_ensure.step(1);
+        				break;
+        		case 1: m_ensure.step(4);
+        				// aspect had been added
+        				m_service.invoke("consumer.add");
+        				break;
+        		case 2: m_ensure.step(6);
+        				break;
+        		default:
+        	}
+        	addCount ++;
+        }
+        public void remove(ServiceInterface service) {
+        	m_service = null;
+        }    
+    }
+
+}

Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java?rev=1727869&view=auto
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java (added)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java Sun Jan 31 23:27:05 2016
@@ -0,0 +1,141 @@
+/*
+ * 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.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectServiceDependencyWithSwapCallbackTest extends TestBase {
+    public void testServiceRegistrationAndConsumption() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", null, "remove", "swap")).build();
+        Component asp = aspect(m, ServiceInterface.class).rank(100).impl(ServiceProviderAspect.class).build();
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(7);
+    }
+    
+    public void testServiceRegistrationAndConsumptionRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        ServiceConsumer scimpl = new ServiceConsumer(e);
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sc = component(m).impl(scimpl).withSrv(ServiceInterface.class, s->s.cbi(scimpl::add, scimpl::remove).swi(scimpl::swap)).build();
+        Component asp = aspect(m, ServiceInterface.class).rank(100).impl(ServiceProviderAspect.class).build();
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(7);
+    }
+
+    static interface ServiceInterface {
+        public void invoke(String caller);
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(String caller) {
+        	if (caller.equals("consumer.init")) {
+        		m_ensure.step(3);
+        	} else if (caller.equals("aspect.consumer.add")) {
+        		m_ensure.step(5);
+        	}
+        }
+    }
+    
+    static class ServiceProviderAspect implements ServiceInterface {
+    	private volatile ServiceInterface m_service;
+    	
+    	public ServiceProviderAspect() {
+		}
+
+		@Override
+		public void invoke(String caller) {
+			m_service.invoke("aspect." + caller);
+		}
+    }
+
+    static class ServiceConsumer {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+        private int swapCount = 0;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            m_ensure.step(2);
+            m_service.invoke("consumer.init");
+        }
+        
+        public void destroy() {
+            m_ensure.step(6);
+        }
+        
+        public void add(ServiceInterface service) {
+        	m_service = service;
+        	m_ensure.step(1);
+        }
+        
+        public void remove(ServiceInterface service) {
+        	m_service = null;
+        }
+        
+        public void swap(ServiceInterface previous, ServiceInterface current) {
+        	switch (swapCount) {
+        		case 0: m_ensure.step(4);
+        				break;
+        		case 1: m_ensure.step(5);
+        				break;
+        		default:
+        	}
+        	m_service = current;
+        	swapCount ++;
+        }
+    }
+
+}

Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java?rev=1727869&view=auto
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java (added)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java Sun Jan 31 23:27:05 2016
@@ -0,0 +1,277 @@
+/*
+ * 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.dm.lambda.itest;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings({"rawtypes", "unchecked", "unused"})
+public class AspectWhiteboardTest extends TestBase {
+
+	public void testWhiteboardConsumer() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create service providers and consumer
+        Component sp1 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component sp2 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        ServiceConsumer sci = new ServiceConsumer(e);
+        Component sc = component(m).impl(sci).withSrv(ServiceInterface.class, srv->srv.required(false).cb("add", "remove")).build();
+        Component sa2 = aspect(m, ServiceInterface.class).rank(20).autoAdd(false).impl(new ServiceAspect(e, 3)).build();
+        Component sa1 = aspect(m, ServiceInterface.class).rank(10).autoAdd(false).impl(new ServiceAspect(e, 4)).build();
+        
+        // start with a service consumer
+        System.out.println("Adding consumer");
+        m.add(sc);
+        
+        // then add two providers, so the consumer will see two services
+        System.out.println("Adding 2 providers");
+        m.add(sp1);
+        m.add(sp2);
+        
+        // make sure consumer sees both services
+        Assert.assertEquals(2, sci.services());
+        
+        // add an aspect with ranking 20
+        System.out.println("Adding aspect with rank 20");
+        m.add(sa2);
+        
+        // make sure the consumer sees the two new aspects and no longer sees the two original services
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(20, sci.highestRanking());
+        Assert.assertEquals(20, sci.lowestRanking());
+        
+        // add an aspect with ranking 10
+        System.out.println("Adding aspect with rank 10");
+        m.add(sa1);
+        
+        // make sure the consumer still sees the two aspects with ranking 20
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(20, sci.highestRanking());
+        Assert.assertEquals(20, sci.lowestRanking());
+        
+        // remove the aspect with ranking 20
+        System.out.println("Removing aspect with rank 20");
+        m.remove(sa2);
+        
+        // make sure the consumer now sees the aspects with ranking 10
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(10, sci.highestRanking());
+        Assert.assertEquals(10, sci.lowestRanking());
+        
+        // remove one of the original services
+        System.out.println("Removing 1 service");
+        m.remove(sp1);
+        
+        // make sure the aspect of that service goes away
+        Assert.assertEquals(1, sci.services());
+        Assert.assertEquals(10, sci.highestRanking());
+        Assert.assertEquals(10, sci.lowestRanking());
+        
+        // remove the aspect with ranking 10
+        System.out.println("Removing aspect with rank 10");
+        m.remove(sa1);
+        
+        // make sure only the original service remains
+        Assert.assertEquals(1, sci.services());
+        Assert.assertEquals(0, sci.highestRanking());
+        Assert.assertEquals(0, sci.lowestRanking());
+
+        System.out.println("Done with test");
+
+        // end of test
+        m.remove(sa2);
+        m.remove(sp2);
+        m.remove(sc);
+    }
+    
+    public void testWhiteboardConsumerRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create service providers and consumer
+        Component sp1 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component sp2 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        ServiceConsumer sci = new ServiceConsumer(e);
+        Component sc = component(m).impl(sci).withSrv(ServiceInterface.class, srv->srv.required(false).cbi(sci::add, sci::remove)).build();
+        Component sa2 = aspect(m, ServiceInterface.class).rank(20).autoAdd(false).impl(new ServiceAspect(e, 3)).build();
+        Component sa1 = aspect(m, ServiceInterface.class).rank(10).autoAdd(false).impl(new ServiceAspect(e, 4)).build();
+        
+        // start with a service consumer
+        System.out.println("Adding consumer");
+        m.add(sc);
+        
+        // then add two providers, so the consumer will see two services
+        System.out.println("Adding 2 providers");
+        m.add(sp1);
+        m.add(sp2);
+        
+        // make sure consumer sees both services
+        Assert.assertEquals(2, sci.services());
+        
+        // add an aspect with ranking 20
+        System.out.println("Adding aspect with rank 20");
+        m.add(sa2);
+        
+        // make sure the consumer sees the two new aspects and no longer sees the two original services
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(20, sci.highestRanking());
+        Assert.assertEquals(20, sci.lowestRanking());
+        
+        // add an aspect with ranking 10
+        System.out.println("Adding aspect with rank 10");
+        m.add(sa1);
+        
+        // make sure the consumer still sees the two aspects with ranking 20
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(20, sci.highestRanking());
+        Assert.assertEquals(20, sci.lowestRanking());
+        
+        // remove the aspect with ranking 20
+        System.out.println("Removing aspect with rank 20");
+        m.remove(sa2);
+        
+        // make sure the consumer now sees the aspects with ranking 10
+        Assert.assertEquals(2, sci.services());
+        Assert.assertEquals(10, sci.highestRanking());
+        Assert.assertEquals(10, sci.lowestRanking());
+        
+        // remove one of the original services
+        System.out.println("Removing 1 service");
+        m.remove(sp1);
+        
+        // make sure the aspect of that service goes away
+        Assert.assertEquals(1, sci.services());
+        Assert.assertEquals(10, sci.highestRanking());
+        Assert.assertEquals(10, sci.lowestRanking());
+        
+        // remove the aspect with ranking 10
+        System.out.println("Removing aspect with rank 10");
+        m.remove(sa1);
+        
+        // make sure only the original service remains
+        Assert.assertEquals(1, sci.services());
+        Assert.assertEquals(0, sci.highestRanking());
+        Assert.assertEquals(0, sci.lowestRanking());
+
+        System.out.println("Done with test");
+
+        // end of test
+        m.remove(sa2);
+        m.remove(sp2);
+        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_parentService;
+        private final int m_step;
+        
+        public ServiceAspect(Ensure e, int step) {
+            m_ensure = e;
+            m_step = step;
+        }
+        public void start() {
+        }
+        
+        public void invoke(Runnable run) {
+            m_ensure.step(m_step);
+            m_parentService.invoke(run);
+        }
+        
+        public void stop() {
+        }
+    }
+
+    static class ServiceConsumer implements Runnable {
+        private List m_services = new ArrayList();
+        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() {
+        }
+        
+        public int services() {
+            return m_services.size();
+        }
+        
+        public int highestRanking() {
+            int ranking = Integer.MIN_VALUE;
+            for (int i = 0; i < m_services.size(); i++) {
+                ServiceReference ref = (ServiceReference) m_services.get(i);
+                Integer r = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
+                int rank = r == null ? 0 : r.intValue();
+                ranking = Math.max(ranking, rank);
+            }
+            return ranking;
+        }
+        public int lowestRanking() {
+            int ranking = Integer.MAX_VALUE;
+            for (int i = 0; i < m_services.size(); i++) {
+                ServiceReference ref = (ServiceReference) m_services.get(i);
+                Integer r = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
+                int rank = r == null ? 0 : r.intValue();
+                ranking = Math.min(ranking, rank);
+            }
+            return ranking;
+        }
+        
+        public void add(ServiceReference ref, ServiceInterface svc) {
+            System.out.println("Added: " + ServiceUtil.toString(ref));
+            m_services.add(ref);
+        }
+        public void remove(ServiceReference ref, ServiceInterface svc) {
+            System.out.println("Removed: " + ServiceUtil.toString(ref));
+            m_services.remove(ref);
+        }
+    }
+}

Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java?rev=1727869&view=auto
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java (added)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java Sun Jan 31 23:27:05 2016
@@ -0,0 +1,198 @@
+/*
+ * 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.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectWithCallbacksServiceDependencyTest extends TestBase {
+    public void testServiceRegistrationAndConsumption() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", "remove")).build();
+        Component asp = aspect(m, ServiceInterface.class).rank(100).cb("add", null, "remove", "swap").impl(ServiceProviderAspect.class).build();
+            
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(8);
+    }
+    
+    public void testServiceRegistrationAndConsumptionRef() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb(ServiceConsumer::add, ServiceConsumer::remove)).build();            
+        Component asp = aspect(m, ServiceInterface.class)
+            .impl(ServiceProviderAspect.class).rank(100)
+            .cb(ServiceProviderAspect::add, ServiceProviderAspect::remove).sw(ServiceProviderAspect::swap)
+            .build();
+                
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(8);
+    }
+    
+    public void testServiceRegistrationAndConsumptionWithAspectCallbackInstance() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // create a service provider and consumer
+        Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
+        Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", "remove")).build();
+                
+        ServiceProviderAspect providerAspect = new ServiceProviderAspect();
+        ServiceProviderAspectCallbackInstance aspectCb = new ServiceProviderAspectCallbackInstance(providerAspect);
+        Component asp = aspect(m, ServiceInterface.class).rank(100).impl(providerAspect).cbi(aspectCb::add, aspectCb::remove).swi(aspectCb::swap).build();
+            
+        m.add(sp);
+        m.add(sc);
+        m.add(asp);
+        m.remove(asp); 
+        m.remove(sc);
+        m.remove(sp);
+        
+        // ensure we executed all steps inside the component instance
+        e.step(8);
+    }
+    
+   static interface ServiceInterface {
+        public void invoke(String caller);
+    }
+
+    static class ServiceProvider implements ServiceInterface {
+        private final Ensure m_ensure;
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke(String caller) {
+        	if (caller.equals("consumer.init")) {
+        		m_ensure.step(3);
+        	} else if (caller.equals("aspect.consumer.add")) {
+        		m_ensure.step(5);
+        	}
+        }
+    }
+    
+    public static class ServiceProviderAspectCallbackInstance {
+        private final ServiceProviderAspect m_aspect;
+        
+        ServiceProviderAspectCallbackInstance(ServiceProviderAspect aspect) {
+            m_aspect = aspect;
+        }
+        
+        public void add(ServiceInterface service) {
+            m_aspect.add(service);
+        }
+        
+        public void remove(ServiceInterface service) {
+            m_aspect.remove(service);
+        }
+        
+        public void swap(ServiceInterface previous, ServiceInterface current) {
+            m_aspect.swap(previous, current);
+        }
+    }
+
+    static class ServiceProviderAspect implements ServiceInterface {
+    	private volatile ServiceInterface m_service;
+    	
+    	public ServiceProviderAspect() {
+		}
+
+		@Override
+		public void invoke(String caller) {
+			m_service.invoke("aspect." + caller);
+		}
+		
+		public void add(ServiceInterface service) {
+			m_service = service;
+		}
+		
+		public void remove(ServiceInterface service) {
+			m_service = null;
+		}
+		
+		public void swap(ServiceInterface previous, ServiceInterface current) {
+			m_service = current;
+		}
+    }
+
+    static class ServiceConsumer {
+        private volatile ServiceInterface m_service;
+        private final Ensure m_ensure;
+        private int addCount = 0;
+
+        public ServiceConsumer(Ensure e) {
+            m_ensure = e;
+        }
+        
+        public void init() {
+            m_ensure.step(2);
+            m_service.invoke("consumer.init");
+        }
+        
+        public void destroy() {
+            m_ensure.step(7);
+        }
+        
+        public void add(ServiceInterface service) {
+        	m_service = service;
+        	switch (addCount) {
+        		case 0: m_ensure.step(1);
+        				break;
+        		case 1: m_ensure.step(4);
+        				// aspect had been added
+        				m_service.invoke("consumer.add");
+        				break;
+        		case 2: m_ensure.step(6);
+        				break;
+        		default:
+        	}
+        	addCount ++;
+        }
+        public void remove(ServiceInterface service) {
+        	m_service = null;
+        }    
+    }
+
+}



Mime
View raw message