Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryConfigurationAdapterTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryConfigurationAdapterTest.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryConfigurationAdapterTest.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryConfigurationAdapterTest.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,227 @@
+/*
+ * 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.component;
+import static 
org.apache.felix.dm.lambda.DependencyManagerActivator.factoryPidAdapter;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class FactoryConfigurationAdapterTest extends TestBase
+{
+    private static Ensure m_ensure;
+    
+    public void testFactoryConfigurationAdapter() {
+       testFactoryConfigurationAdapter(Adapter.class, "updated");
+    }
+    
+    public void 
testFactoryConfigurationAdapterWithUpdatedCallbackThatTakesComponentAsParameter()
 {
+       
testFactoryConfigurationAdapter(AdapterWithUpdateMethodThatTakesComponentAsParameter.class,
 "updatedWithComponent");
+    }
+    
+    public void testFactoryConfigurationAdapter(Class<?> adapterImplClass, 
String adapterUpdate) {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        m_ensure = new Ensure();
+        
+        // Create a Configuration instance, which will create/update/remove a 
configuration for factoryPid "MyFactoryPid"
+        ConfigurationCreator configurator = new 
ConfigurationCreator("MyFactoryPid", "key", "value1");
+        Component s1 = 
component(m).impl(configurator).withSrv(ConfigurationAdmin.class).build();
+           
+        // Create an Adapter that will be instantiated, once the configuration 
is created.
+        // This Adapter provides an AdapterService, and depends on an 
AdapterExtraDependency service.
+        Component s2 = factoryPidAdapter(m)
+            
.factoryPid("MyFactoryPid").impl(adapterImplClass).cb(adapterUpdate).propagate().provides(AdapterService.class,
 "foo", "bar")            
+            .withSrv(AdapterExtraDependency.class)
+            .build();
+                    
+        // Create extra adapter service dependency upon which our adapter 
depends on.
+        Component s3 = component(m)
+            .impl(new 
AdapterExtraDependency()).provides(AdapterExtraDependency.class).build();
+        
+        // Create an AdapterService Consumer
+        Component s4 = component(m)
+            .impl(AdapterServiceConsumer.class).withSrv(AdapterService.class, 
srv -> srv.cb("bind", "change", "remove")).build();
+        
+        // Start services
+        m.add(s1);
+        m.add(s2);
+        m.add(s3);
+        m.add(s4);
+        
+        // Wait for step 8: the AdapterService consumer has been injected with 
the AdapterService, and has called the doService method.
+        m_ensure.waitForStep(8, 10000);
+        
+        // Modify configuration.
+        configurator.update("key", "value2");
+        
+        // Wait for step 13: the AdapterService has been updated, and the 
AdapterService consumer has seen the change
+        m_ensure.waitForStep(13, 10000);
+        
+        // Remove the configuration
+        m.remove(s1); // The stop method will remove the configuration
+        m_ensure.waitForStep(16, 10000);
+        m.clear();
+    }
+
+    public static class ConfigurationCreator {
+        private volatile ConfigurationAdmin m_ca;
+        private String m_key;
+        private String m_value;
+        private org.osgi.service.cm.Configuration m_conf;
+        private String m_factoryPid;
+        
+        public ConfigurationCreator(String factoryPid, String key, String 
value) {
+            m_factoryPid = factoryPid;
+            m_key = key;
+            m_value = value;
+        }
+
+        public void start() {
+            try {
+                m_ensure.step(1);
+                m_conf = m_ca.createFactoryConfiguration(m_factoryPid, null);
+                Hashtable props = new Hashtable();
+                props.put(m_key, m_value);
+                m_conf.update(props);
+            }
+            catch (IOException e) {
+                Assert.fail("Could not create configuration: " + 
e.getMessage());
+            }
+        }
+        
+        public void update(String key, String val) {
+            Hashtable props = new Hashtable();
+            props.put(key, val);
+            try {
+                m_conf.update(props);
+            }
+            catch (IOException e) {
+                Assert.fail("Could not update configuration: " + 
e.getMessage());
+            }
+        }
+        
+        public void stop() {
+            try
+            {
+                m_conf.delete();
+            }
+            catch (IOException e)
+            {
+                Assert.fail("Could not remove configuration: " + e.toString());
+            }
+        }
+    }
+    
+    public interface AdapterService {
+        public void doService();
+    }
+    
+    public static class AdapterExtraDependency {
+    }
+
+    public static class Adapter implements AdapterService {
+        volatile AdapterExtraDependency m_extraDependency; // extra dependency.
+        private int updateCount;
+        
+        void updated(Dictionary settings) {
+            updateCount ++;
+            if (updateCount == 1) {
+                m_ensure.step(2);
+                Assert.assertEquals(true, 
"value1".equals(settings.get("key")));
+                m_ensure.step(3);
+            } else if (updateCount == 2) {
+                m_ensure.step(9);
+                Assert.assertEquals(true, 
"value2".equals(settings.get("key")));
+                m_ensure.step(10);
+            } else {
+                Assert.fail("wrong call to updated method: count=" + 
updateCount);
+            }
+        }
+
+        public void doService() {   
+            m_ensure.step(8);
+        }
+        
+        public void start() {
+            m_ensure.step(4);
+            Assert.assertNotNull(m_extraDependency);
+            m_ensure.step(5);
+        }
+        
+        public void stop() {
+            m_ensure.step(16);
+        }
+    }
+    
+    public static class AdapterWithUpdateMethodThatTakesComponentAsParameter 
extends Adapter {
+        void updatedWithComponent(Component component, Dictionary settings) {
+               Assert.assertNotNull(component);
+               Assert.assertEquals(this, component.getInstance());
+               super.updated(settings);
+        }
+    }
+
+    public static class AdapterServiceConsumer {
+        private AdapterService m_adapterService;
+        private Map m_adapterServiceProperties;
+        
+        void bind(Map serviceProperties, AdapterService adapterService) {
+            m_ensure.step(6);
+            m_adapterService = adapterService;
+            m_adapterServiceProperties = serviceProperties;
+        }
+        
+        void change(Map serviceProperties, AdapterService adapterService) {
+            m_ensure.step(11);
+            Assert.assertEquals(true, 
"value2".equals(m_adapterServiceProperties.get("key")));
+            m_ensure.step(12);
+            Assert.assertEquals(true, 
"bar".equals(m_adapterServiceProperties.get("foo")));
+            m_ensure.step(13);
+        }
+        
+        public void start() {
+            m_ensure.step(7);
+            Assert.assertNotNull(m_adapterService);
+            Assert.assertEquals(true, 
"value1".equals(m_adapterServiceProperties.get("key")));
+            Assert.assertEquals(true, 
"bar".equals(m_adapterServiceProperties.get("foo")));
+            m_adapterService.doService();
+        }
+        
+        public void stop() {
+            m_ensure.step(14);
+        }
+        
+        void remove(AdapterService adapterService) {
+            m_ensure.step(15);
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java
 Sun Jan 31 23:27:05 2016
@@ -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.dm.lambda.itest;
+
+import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
+
+import java.io.IOException;
+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.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+
+/**
+ * Use case: one component is instantiated using another factory object, and 
the 
+ * factory object needs the configuration before the factory.create method is 
called.
+ * 
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+public class FactoryInjectedWithConfigurationBeforeTheCreateMethod extends 
TestBase {
+    Ensure m_e;
+    
+    public void testServiceInjection() {
+        DependencyManager m = getDM();
+        m_e = new Ensure();
+        
+        // Create the component that creates a configuration.
+        Component configurator = component(m).impl(new 
Configurator("foobar")).withSrv(ConfigurationAdmin.class).build();
+        
+        // Create the object that has to be injected with the configuration 
before its create method is called.
+        MyFactory factory = new MyFactory();
+        
+        // Create the Component for the MyComponent class that is created 
using the factory above.
+        Component myComponent = component(m).factory(factory, 
"create").withCnf(b->b.pid("foobar").cbi(factory, "updated")).build();
+        
+        // provide the configuration
+        m.add(configurator);
+        
+        m.add(myComponent);
+        m_e.waitForStep(4, 10000);
+        m.remove(myComponent);
+        m.remove(configurator);
+    }
+    
+    public void testServiceInjectionRef() {
+        DependencyManager m = getDM();
+        m_e = new Ensure();
+        
+        // Create the component that creates a configuration.
+        Component configurator = component(m).impl(new 
Configurator("foobar")).withSrv(ConfigurationAdmin.class).build();
+        
+        // Create the object that has to be injected with the configuration 
before its create method is called.
+        MyFactory factory = new MyFactory();
+        
+        // Create the Component for the MyComponent class that is created 
using the factory above.
+        Component myComponent = component(m).factory(factory, 
"create").withCnf(b->b.pid("foobar").cbi(factory::updated)).build();
+        
+        // provide the configuration
+        m.add(configurator);
+        
+        m.add(myComponent);
+        m_e.waitForStep(4, 10000);
+        m.remove(myComponent);
+        m.remove(configurator);
+    }
+
+    class Configurator {
+        private volatile ConfigurationAdmin m_ca;
+        Configuration m_conf;
+        final String m_pid;
+        
+        public Configurator(String pid) {
+            m_pid = pid;
+        }
+
+        public void init() {
+            try {
+                Assert.assertNotNull(m_ca);
+                m_e.step(1);
+                m_conf = m_ca.getConfiguration(m_pid, null);
+                Hashtable<String, Object> props = new Hashtable<>();
+                props.put("testkey", "testvalue");
+                m_conf.update(props);
+            }
+            catch (IOException e) {
+                Assert.fail("Could not create configuration: " + 
e.getMessage());
+            }
+        }
+        
+        public void destroy() throws IOException {
+            m_conf.delete();  
+        }
+    }
+
+    public class MyFactory {
+        public void updated(Dictionary<String, Object> conf) {
+            Assert.assertNotNull("configuration is null", conf);
+            m_e.step(2);
+        }
+        
+        public MyComponent create() {
+            m_e.step(3);
+            return new MyComponent();
+        }
+    }
+    
+    public class MyComponent {
+        void start() {
+            m_e.step(4);
+        }        
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/InstanceBoundDependencyTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/InstanceBoundDependencyTest.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/InstanceBoundDependencyTest.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/InstanceBoundDependencyTest.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,157 @@
+/*
+ * 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.component;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+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;
+
+/**
+ * This test does some injection tests on components being in 
INSTANTIATED_AND_WAITING_FOR_REQUIRED state.
+ * 
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class InstanceBoundDependencyTest extends TestBase {
+    Ensure m_e;
+    
+    public void testServiceInjection() {
+        DependencyManager m = getDM();
+        m_e = new Ensure();
+        
+        // Create a "C" component: it depends on some S1 services, and on some 
S2 instance-bound services (declared from C.init() method)        
+        C cimpl = new C();
+        Component c = component(m).impl(cimpl)
+            .withSrv(S1.class, sb->sb.cb("addS1", "changeS1", 
"removeS1").autoConfig(true)).build();
+        m.add(c);
+        
+        // Add S1 (s1_1): C.add(S1 s1) is called, then init() is called where 
a dependency is declared on S2
+        Hashtable s1_1_props = new Hashtable();
+        s1_1_props.put("name", "s1_1");
+        s1_1_props.put(Constants.SERVICE_RANKING, new Integer(10));
+        S1Impl s1_1_impl = new S1Impl();
+        Component s1_1 = 
component(m).impl(s1_1_impl).provides(S1.class.getName(), s1_1_props).build();
+        m.add(s1_1);
+        m_e.waitForStep(1, 5000); // wait until C.init called
+        ServiceReference ref = cimpl.getS1("s1_1");
+        Assert.assertNotNull(ref);
+        Assert.assertNotNull(cimpl.getS1());
+        Assert.assertEquals(s1_1_impl, cimpl.getS1());
+        
+        // At this point, MyComponent is in 
INSTANTIATED_AND_WAITING_FOR_REQUIRED state. 
+        // add now add another higher ranked S1 (s1_2) instance. C.add(s1_2) 
method should be called (the S1 dependency 
+        // is not instance bound), and m_s1 autoconfig field should be updated.
+        Hashtable s1_2_props = new Hashtable();
+        s1_2_props.put(Constants.SERVICE_RANKING, new Integer(20));
+        s1_2_props.put("name", "s1_2");
+        S1Impl s1_2_impl = new S1Impl();
+        Component s1_2 = 
component(m).impl(s1_2_impl).provides(S1.class.getName(), s1_2_props).build();
+        m.add(s1_2);
+        ref = cimpl.getS1("s1_2");
+        Assert.assertNotNull(ref);
+        Assert.assertNotNull(cimpl.getS1()); 
+        Assert.assertEquals(s1_2_impl, cimpl.getS1()); // must return s1_2 
with ranking = 20
+
+        // Now, change the s1_1 service properties: C.changed(s1_1) should be 
called, and C.m_s1AutoConfig should be updated
+        s1_1_props.put(Constants.SERVICE_RANKING, new Integer(30));
+        s1_1.setServiceProperties(s1_1_props);
+        ref = cimpl.getS1("s1_1");
+        Assert.assertNotNull(ref);
+        Assert.assertEquals(new Integer(30), 
ref.getProperty(Constants.SERVICE_RANKING));
+        Assert.assertNotNull(cimpl.getS1());
+        Assert.assertEquals(s1_1_impl, cimpl.getS1());
+        
+        // Now, remove the s1_1: C.remove(s1_1) should be called, and 
C.m_s1AutoConfig should be updated
+        m.remove(s1_1);
+        ref = cimpl.getS1("s1_1");
+        Assert.assertNull(cimpl.getS1("s1_1"));
+        Assert.assertNotNull(cimpl.getS1());
+        Assert.assertEquals(s1_2_impl, cimpl.getS1());
+        m.clear();
+    }
+    
+    // C component depends on some S1 required services
+    public interface S1 {
+    }
+    
+    public class S1Impl implements S1 {
+    }
+    
+    public interface S2 {        
+    }
+    
+    public class S2Impl implements S2 {        
+    }
+    
+    // Our "C" component: it depends on S1 (required) and S2 
(required/instance bound)
+    class C {        
+        final Map<String, ServiceReference> m_s1Map = new HashMap();
+        final Map<String, ServiceReference> m_s2Map = new HashMap();
+        volatile S1 m_s1; // auto configured
+        
+        S1 getS1() {
+            return m_s1;
+        }
+
+        void addS1(ServiceReference s1) {
+            m_s1Map.put((String) s1.getProperty("name"), s1);
+        }
+        
+        void changeS1(ServiceReference s1) {
+            m_s1Map.put((String) s1.getProperty("name"), s1);
+        }
+        
+        void removeS1(ServiceReference s1) {
+            m_s1Map.remove((String) s1.getProperty("name"));
+        }
+        
+        void addS2(ServiceReference s2) {
+            m_s2Map.put((String) s2.getProperty("name"), s2);
+        }
+        
+        void changeS2(ServiceReference s2) {
+            m_s2Map.put((String) s2.getProperty("name"), s2);
+        }
+        
+        void removeS2(ServiceReference s2) {
+            m_s2Map.remove((String) s2.getProperty("name"));
+        }
+        
+        ServiceReference getS1(String name) {
+            return m_s1Map.get(name);
+        }
+        
+        ServiceReference getS2(String name) {
+            return m_s2Map.get(name);
+        }
+        
+        void init(Component c) {
+            component(c, comp->comp.withSrv(S2.class, srv -> srv.cb(C::addS2, 
C::changeS2, C::removeS2)));
+            m_e.step(1);
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ModifiedBundleDependencyTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ModifiedBundleDependencyTest.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ModifiedBundleDependencyTest.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ModifiedBundleDependencyTest.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,168 @@
+/*
+ * 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.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+
+/**
+ * Test for FELIX-4334 issue.
+ * 
+ * Two components: A, B
+ * 
+ * - A provided.
+ * - B has a bundle dependency on the dependency manager shell bundle, which 
is currently stopped.
+ * - B has an instance bound dependency on A.
+ * - Now unregister A.
+ * - As a result of that, B becomes unavailable and is unbound from A. But B 
is not destroyed, because A dependency 
+ *   is "instance bound". So B is still bound to the bundle dependency.
+ * - Now, someone starts the dependency manager shell bundle: B then shall be 
called in its "changed" callback.
+ * 
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+public class ModifiedBundleDependencyTest extends TestBase {
+    public static interface A {
+    }
+    
+    static class AImpl implements A {
+    }
+        
+    public static interface B {
+    }
+    
+    static class BImpl implements B {
+        final Ensure m_e;
+        
+        BImpl(Ensure e) {
+            m_e = e;
+        }
+        
+        public void add(Bundle dmTest) {
+            m_e.step(1);
+        }
+
+        void init(Component c) {
+            m_e.step(2);
+            component(c, comp -> comp.withSrv(A.class, srv -> srv.cb("add", 
"remove")));
+        }
+        
+        public void add(A a) {
+            m_e.step(3);
+        }
+        
+        public void start() {
+            m_e.step(4);            
+        }
+        
+        public void stop() {
+            m_e.step(5);
+        }
+
+        public void remove(A a) {
+            m_e.step(6);
+        }
+
+        public void change(Bundle dmTest) { // called two times: one for 
STARTING, one for STARTED
+            m_e.step(); 
+        }
+        
+        public void destroy() {
+            m_e.step(9);
+        }
+
+        public void remove(Bundle dmTest) {   
+            m_e.step(10);
+        }                    
+    }
+    
+    public void testAdapterWithChangedInstanceBoundDependencyAndCallbacks() {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+
+        Component a = component(m).impl(new AImpl()).provides(A.class).build();
+        
+        String filter = "(Bundle-SymbolicName=org.apache.felix.metatype)";
+        int mask = 
Bundle.INSTALLED|Bundle.ACTIVE|Bundle.RESOLVED|Bundle.STARTING;
+        Component b = component(m)
+            .provides(B.class).impl(new BImpl(e)).withBundle(bd -> 
bd.filter(filter).mask(mask).cb("add", "change", "remove")).build();        
+                                                                           
+        Bundle dmtest = getBundle("org.apache.felix.metatype");
+        try {
+            dmtest.stop();
+        } catch (BundleException e1) {
+            Assert.fail("could not find metatype bundle");
+        }
+        
+        m.add(a);
+        m.add(b);
+        
+        e.waitForStep(4, 5000);        
+        m.remove(a); // B will loose A and will enter into "waiting for 
required (instantiated)" state.
+        System.out.println("Starting metatype bundle ...");        
+        try {
+            dmtest.start();
+        } catch (BundleException e1) {
+            Assert.fail("could not start metatype bundle");
+        }
+        e.waitForStep(7, 5000);     
+        m.remove(b);        
+        e.waitForStep(10, 5000);                
+    }
+
+    public void testAdapterWithChangedInstanceBoundDependencyRef() {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+
+        Component a = 
+               component(m, comp -> comp.impl(new 
AImpl()).provides(A.class).autoAdd(false));
+        
+        BImpl impl = new BImpl(e);
+        String filter = "(Bundle-SymbolicName=org.apache.felix.metatype)";
+        int mask = 
Bundle.INSTALLED|Bundle.ACTIVE|Bundle.RESOLVED|Bundle.STARTING;
+        Component b = component(m).provides(B.class).impl(impl)
+            .withBundle(bd -> bd.filter(filter).mask(mask).cbi(impl::add, 
impl::change, impl::remove)).build();                
+        
+        Bundle dmtest = getBundle("org.apache.felix.metatype");
+        try {
+            dmtest.stop();
+        } catch (BundleException e1) {
+            Assert.fail("could not find metatype bundle");
+        }
+        
+        m.add(a);
+        m.add(b);
+        
+        e.waitForStep(4, 5000);        
+        m.remove(a); // B will loose A and will enter into "waiting for 
required (instantiated)" state.
+        System.out.println("Starting metatype bundle ...");        
+        try {
+            dmtest.start();
+        } catch (BundleException e1) {
+            Assert.fail("could not start metatype bundle");
+        }
+        e.waitForStep(7, 5000);     
+        m.remove(b);        
+        e.waitForStep(10, 5000);                
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependenciesTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependenciesTest.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependenciesTest.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependenciesTest.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,154 @@
+/*
+ * 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.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+
+/**
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class MultipleExtraDependenciesTest extends TestBase {
+    /**
+     * Check that list of extra dependencies (defined from init method) are 
handled properly.
+     * The extra dependencies are added using a List object 
(Component.add(List)).
+     * A component c1 will define two extra dependencies over *available* 
c4/c5 services.
+     */
+     public void testWithTwoAvailableExtraDependency() {   
+         DependencyManager m = getDM();
+         // Helper class that ensures certain steps get executed in sequence
+         Ensure e = new Ensure();
+         Component c1 = component(m).provides(Service1.class).impl(new 
MyComponent1(e)).withSrv(Service2.class, 
srv->srv.autoConfig("m_service2")).build();
+         Component c2 = component(m).impl(new 
MyComponent2(e)).withSrv(Service1.class, 
srv->srv.required(false).autoConfig(false).cb("added")).build();
+         Component c3 = 
component(m).provides(Service2.class).impl(Service2Impl.class).build();
+         Component c4 = 
component(m).impl(Service3Impl1.class).provides(Service3.class, type -> 
"xx").build();
+         Component c5 = 
component(m).impl(Service3Impl2.class).provides(Service3.class, type -> 
"yy").build();
+
+         System.out.println("\n+++ Adding c2 / MyComponent2");
+         m.add(c2);
+         System.out.println("\n+++ Adding c3 / Service2");
+         m.add(c3);
+         System.out.println("\n+++ Adding c4 / Service3(xx)");
+         m.add(c4);
+         System.out.println("\n+++ Adding c5 / Service3(yy)");
+         m.add(c5);
+         System.out.println("\n+++ Adding c1 / MyComponent1");
+         // c1 have declared two extra dependency on Service3 (xx/yy).
+         // both extra dependencies are available, so the c1 component should 
be started immediately.
+         m.add(c1);
+         e.waitForStep(3, 3000);
+         m.clear();
+     }
+
+    /**
+     * Check that list of extra dependencies (defined from init method) are 
handled properly.
+     * The extra dependencies are added using a List object 
(Component.add(List)).
+     * A component c1 will define two extra dependencies over c4/c5. At the 
point c1.init()
+     * is adding the two extra dependencies from its init method, c4 is 
available, but not c5.
+     * So, c1 is not yet activated.
+     * Then c5 is added, and it triggers the c1 activation ...
+     */
+    public void testWithOneAvailableExtraDependency() {  
+        DependencyManager m = getDM();
+        // Helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        Component c1 = component(m).provides(Service1.class).impl(new 
MyComponent1(e)).withSrv(Service2.class, 
srv->srv.autoConfig("m_service2")).build();
+        Component c2 = component(m).impl(new 
MyComponent2(e)).withSrv(Service1.class, 
srv->srv.required(false).autoConfig(false).cb("added")).build();
+        Component c3 = 
component(m).provides(Service2.class).impl(Service2Impl.class).build();
+        Component c4 = 
component(m).impl(Service3Impl1.class).provides(Service3.class, type -> 
"xx").build();
+        Component c5 = 
component(m).impl(Service3Impl2.class).provides(Service3.class, type -> 
"yy").build();
+
+        System.out.println("\n+++ Adding c2 / MyComponent2");
+        m.add(c2);
+        System.out.println("\n+++ Adding c3 / Service2");
+        m.add(c3);
+        System.out.println("\n+++ Adding c4 / Service3(xx)");
+        m.add(c4);
+        System.out.println("\n+++ Adding c1 / MyComponent1");
+        m.add(c1);
+
+        // c1 have declared two extra dependency on Service3 (xx/yy).
+        // So, because we have not yet added c5 (yy), c1 should not be started 
currently.
+        // But, now, we'll add c5 (Service3/yy) and c1 should then be started 
...
+        System.out.println("\n+++ Adding c5 / Service3(yy)");
+        m.add(c5);
+        e.waitForStep(3, 3000);
+        m.clear();
+    }
+
+
+    public interface Service1 {}
+    public interface Service2 {}
+    public interface Service3 {}
+
+    public static class Service2Impl implements Service2 {}
+    public static class Service3Impl1 implements Service3 {}
+    public static class Service3Impl2 implements Service3 {}
+
+    public static class MyComponent1 implements Service1 {
+        Service2 m_service2;
+        Service3 m_service3_xx;
+        Service3 m_service3_yy;
+        Ensure m_ensure;
+        
+        public MyComponent1(Ensure e) {
+            m_ensure = e;
+        }
+
+        void init(Component c) {
+            m_ensure.step(1);
+            // Service3/xx currently available
+            // Service3/yy not yet available
+
+            component(c, comp -> comp
+                .withSrv(Service3.class, 
srv->srv.filter("(type=xx)").autoConfig("m_service3_xx"))
+                .withSrv(Service3.class, 
srv->srv.filter("(type=yy)").autoConfig("m_service3_yy")));
+        }
+        
+        void start() {
+            System.out.println("MyComponent1.start");
+            Assert.assertNotNull(m_service2);
+            Assert.assertNotNull(m_service3_xx);
+            Assert.assertNotNull(m_service3_yy);
+            m_ensure.step(2);
+        }
+    }
+    
+    public static class MyComponent2 {
+        Ensure m_ensure;
+        
+        public MyComponent2(Ensure e) {
+            m_ensure = e;
+        }
+
+        void added(Service1 s1) {
+            System.out.println("MyComponent2.bind(" + s1 + ")");
+            Assert.assertNotNull(s1);
+            m_ensure.step(3);
+        }
+        
+        void start() {
+            System.out.println("MyComponent2.start");
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,209 @@
+/*
+ * 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.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+
+/**
+ * Test which validates multi-dependencies combination.
+ * 
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes", "serial"})
+public class MultipleExtraDependencyTest extends TestBase {
+    public void testMultipleExtraDependencies()
+    {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+        
+        Component sp2 = component(m)
+              .impl(ServiceProvider2.class).provides(ServiceProvider2.class)
+              .withSrv(Runnable.class, 
srv->srv.filter("(foo=bar)").required(false).autoConfig("m_runnable"))
+              .withSrv(Sequencer.class, srv->srv.cb("bind"))
+              .composition("getComposition")
+              .build();
+
+        Component sp = component(m)
+              .impl(ServiceProvider.class)
+              .provides(ServiceInterface.class, foo -> "bar")
+              .start("start").stop("stop")
+              .withSrv(Sequencer.class, srv->srv.autoConfig("m_sequencer"))
+              .withSrv(ServiceProvider2.class, srv->srv.cb("bind", "unbind"))
+              .build();
+        
+        Component sc = component(m)
+              .impl(ServiceConsumer.class)
+              .start("start").stop("stop")
+              .withSrv(Sequencer.class, srv->srv.autoConfig("m_sequencer"))
+              .withSrv(ServiceInterface.class, 
srv->srv.filter("(foo=bar)").autoConfig("m_service"))
+              .build();
+        
+        Component sequencer = component(m)
+           .impl(new SequencerImpl(e))
+           .provides(Sequencer.class.getName())
+           .build();
+           
+        m.add(sp2);
+        m.add(sp);
+        m.add(sc);
+        m.add(sequencer);
+        
+        // Check if ServiceProvider component have been initialized orderly
+        e.waitForStep(7, 5000);
+        
+        // Stop the test.annotation bundle
+        m.remove(sequencer);
+        m.remove(sp);
+        m.remove(sp2);
+        m.remove(sc);
+        
+        // And check if ServiceProvider2 has been deactivated orderly
+        e.waitForStep(11, 5000);
+    }
+    
+    public interface Sequencer
+    {
+        void step();
+        void step(int step);
+        void waitForStep(int step, int timeout);
+    }
+    
+    public static class SequencerImpl implements Sequencer {
+        Ensure m_ensure;
+        
+        public SequencerImpl(Ensure e)
+        {
+            m_ensure = e;
+        }
+        
+        public void step()
+        {
+            m_ensure.step();
+        }
+
+        public void step(int step)
+        {
+            m_ensure.step(step);
+        }
+
+        public void waitForStep(int step, int timeout)
+        {
+            m_ensure.waitForStep(step, timeout);
+        }  
+    }
+    
+    public interface ServiceInterface
+    {
+        public void doService();
+    }
+    
+    public static class ServiceConsumer
+    {
+        volatile Sequencer m_sequencer;
+        volatile ServiceInterface m_service;
+
+        void start()
+        {
+            m_sequencer.step(6);
+            m_service.doService();
+        }
+
+        void stop()
+        {
+            m_sequencer.step(8);
+        }
+    }
+    
+    public static class ServiceProvider implements ServiceInterface
+    {
+        Sequencer m_sequencer;
+        ServiceProvider2 m_serviceProvider2;
+
+        void bind(ServiceProvider2 provider2)
+        {
+            m_serviceProvider2 = provider2;
+        }
+
+        void start()
+        {
+            m_serviceProvider2.step(4);
+            m_sequencer.step(5);
+        }
+
+        void stop()
+        {
+            m_sequencer.step(9);
+        }
+
+        void unbind(ServiceProvider2 provider2)
+        {
+            m_sequencer.step(10);
+        }
+
+        public void doService()
+        {
+            m_sequencer.step(7);
+        }
+    }
+
+    public static class ServiceProvider2
+    {
+        Composite m_composite = new Composite();
+        Sequencer m_sequencer;
+        Runnable m_runnable;
+
+        void bind(Sequencer seq)
+        {
+            m_sequencer = seq;
+            m_sequencer.step(1);
+        }
+
+        void start()
+        {
+            m_sequencer.step(3);
+            m_runnable.run(); // NullObject
+        }
+
+        public void step(int step) // called by ServiceProvider.start() method 
+        { 
+            m_sequencer.step(step);
+        }
+        
+        void stop()
+        {
+            m_sequencer.step(11);
+        }
+
+        Object[] getComposition()
+        {
+            return new Object[] { this, m_composite };
+        }
+    }
+    
+    public static class Composite
+    {
+        void bind(Sequencer seq)
+        {
+            seq.step(2);
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest2.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest2.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest2.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleExtraDependencyTest2.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,235 @@
+/*
+ * 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.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ServiceDependency;
+
+/**
+ * Tests for extra dependencies which are declared from service's init method.
+ * 
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+public class MultipleExtraDependencyTest2 extends TestBase {
+    public void testMultipleExtraDependencies() {
+        DependencyManager m = getDM();
+        Ensure e = new Ensure();
+        
+        Component sp2 = component(m)
+            .impl(ServiceProvider2.class)
+            .provides(ServiceProvider2.class)
+            .init("init").start("start").stop("stop")
+            .composition("getComposition").build();
+        
+        Component sp = component(m)
+            .impl(ServiceProvider.class)
+            .provides(ServiceInterface.class, "foo", "bar")                    
        
+            
.init(ServiceProvider::init).start(ServiceProvider::start).stop(ServiceProvider::stop)
+            .build();
+        
+        Component sc = component(m)
+            .impl(ServiceConsumer.class)
+            .init("init").start("start").stop("stop")
+            .build();
+        
+        // Provide the Sequencer service to the MultipleAnnotationsTest class.
+        Component sequencer =  component(m)
+            .impl(new SequencerImpl(e))
+            .provides(Sequencer.class)
+            .build();
+        
+        m.add(sp2);
+        m.add(sp);
+        m.add(sc);
+        m.add(sequencer);
+
+        // Check if the test.annotation components have been initialized 
orderly
+        e.waitForStep(7, 10000);
+        
+        // Stop the test.annotation bundle
+        m.remove(sequencer);
+        m.remove(sp);
+        m.remove(sp2);
+        m.remove(sc);
+        
+//        m.remove(sp2);
+//        m.remove(sc);
+//        m.remove(sp);
+//        m.remove(sequencer);
+        
+
+        
+        // And check if the test.annotation bundle has been deactivated orderly
+        e.waitForStep(11, 10000);
+        m.clear();
+    }
+    
+    public interface Sequencer
+    {
+        void step();
+        void step(int step);
+        void waitForStep(int step, int timeout);
+    }
+    
+    public static class SequencerImpl implements Sequencer {
+        final Ensure m_ensure;
+        
+        public SequencerImpl(Ensure e)
+        {
+            m_ensure = e;
+        }
+        
+        public void step()
+        {
+            m_ensure.step();
+        }
+
+        public void step(int step)
+        {
+            m_ensure.step(step);
+        }
+
+        public void waitForStep(int step, int timeout)
+        {
+            m_ensure.waitForStep(step, timeout);
+        }  
+    }
+    
+    public interface ServiceInterface
+    {
+        public void doService();
+    }
+    
+    public static class ServiceConsumer {
+        volatile Sequencer m_sequencer;
+        volatile ServiceInterface m_service;
+        volatile Dependency m_d1, m_d2;
+
+        public void init(Component s) {
+            component(s, comp->comp
+                .withSrv(Sequencer.class, srv->srv.autoConfig("m_sequencer"))
+                .withSrv(ServiceInterface.class, 
srv->srv.filter("(foo=bar)").autoConfig("m_service")));
+        }
+        
+        void start() {
+            m_sequencer.step(6);
+            m_service.doService();
+        }
+
+        void stop() {
+            m_sequencer.step(8);
+        }
+    }
+    
+    public static class ServiceProvider implements ServiceInterface
+    {
+        volatile Sequencer m_sequencer;
+        volatile ServiceProvider2 m_serviceProvider2;
+        volatile ServiceDependency m_d1, m_d2;
+
+        public void init(Component c)
+        {
+            component(c, comp->comp
+                .withSrv(Sequencer.class, srv->srv.autoConfig("m_sequencer"))
+                .withSrv(ServiceProvider2.class, srv->srv.cb("bind", 
"unbind")));
+        }
+        
+        void bind(ServiceProvider2 provider2)
+        {
+            m_serviceProvider2 = provider2;
+        }
+
+        void start()
+        {
+            m_serviceProvider2.step(4);
+            m_sequencer.step(5);
+        }
+
+        void stop()
+        {
+            m_sequencer.step(9);
+        }
+
+        void unbind(ServiceProvider2 provider2)
+        {
+            m_sequencer.step(10);
+        }
+
+        public void doService()
+        {
+            m_sequencer.step(7);
+        }
+    }
+
+    public static class ServiceProvider2
+    {
+        final Composite m_composite = new Composite();
+        volatile Sequencer m_sequencer;
+        volatile Runnable m_runnable;
+        volatile ServiceDependency m_d1, m_d2;
+
+        public void init(Component c)
+        {
+            component(c, comp->comp
+                     .withSrv(Runnable.class, 
srv->srv.optional().filter("(foo=bar)"))
+                     .withSrv(Sequencer.class, srv->srv.cb("bind")));
+        }
+        
+        void bind(Sequencer seq)
+        {
+            System.out.println("ServiceProvider2.bind(" + seq + ")");
+            m_sequencer = seq;
+            m_sequencer.step(1);
+        }
+
+        void start()
+        {
+            System.out.println("ServiceProvider2.start: m_runnable=" + 
m_runnable + ", m_sequencer = " + m_sequencer);
+            m_sequencer.step(3);
+            m_runnable.run(); // NullObject
+        }
+
+        public void step(int step) // called by ServiceProvider.start() method 
+        { 
+            m_sequencer.step(step);
+        }
+        
+        void stop()
+        {
+            m_sequencer.step(11);
+        }
+
+        Object[] getComposition()
+        {
+            return new Object[] { this, m_composite };
+        }
+    }
+    
+    public static class Composite
+    {
+        void bind(Sequencer seq)
+        {
+            seq.step(2);
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleServiceDependencyTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleServiceDependencyTest.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleServiceDependencyTest.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/MultipleServiceDependencyTest.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,144 @@
+/*
+ * 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.component;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Constants;
+
+/**
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes", "serial"})
+public class MultipleServiceDependencyTest extends TestBase {
+   public void testMultipleServiceRegistrationAndConsumption() {
+       DependencyManager m = getDM();
+       // helper class that ensures certain steps get executed in sequence
+       Ensure e = new Ensure();
+       // create a service provider and consumer
+       Component provider = component(m).impl(new 
ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
+       Component providerWithHighRank = component(m).impl(new 
ServiceProvider2(e)).provides(ServiceInterface.class.getName(), 
Constants.SERVICE_RANKING, Integer.valueOf(5)).build();
+       Component consumer = component(m).impl(new 
ServiceConsumer(e)).withSrv(ServiceInterface.class).build();
+       m.add(provider);
+       m.add(providerWithHighRank);
+       m.add(consumer);
+       e.waitForStep(3, 5000);
+       m.remove(providerWithHighRank);
+       e.step(4);
+       e.waitForStep(5, 5000);
+       m.remove(provider);
+       m.remove(consumer);
+       e.waitForStep(6, 5000);
+   }
+
+   public void testReplacementAutoConfig() {
+       DependencyManager m = getDM();
+       // helper class that ensures certain steps get executed in sequence
+       Ensure e = 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(ServiceInterface.class.getName()).build();
+       Component consumer = component(m).impl(new 
ServiceConsumer(e)).withSrv(ServiceInterface.class).build();
+       m.add(provider2);
+       m.add(consumer);
+       e.waitForStep(3, 5000);
+       m.add(provider);
+       m.remove(provider2);
+       e.step(4);
+       e.waitForStep(5, 5000);
+       m.remove(provider);
+       m.remove(consumer);
+       e.waitForStep(6, 5000);
+   }
+
+   public void testReplacementCallbacks() {
+       DependencyManager m = getDM();
+       // helper class that ensures certain steps get executed in sequence
+       Ensure e = 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(ServiceInterface.class.getName()).build();
+       Component consumer = component(m).impl(new 
ServiceConsumer(e)).withSrv(ServiceInterface.class, srv->srv.cb("add", 
"remove")).build();
+       m.add(provider2);
+       m.add(consumer);
+       e.waitForStep(3, 15000);
+       m.add(provider);
+       m.remove(provider2);
+       e.step(4);
+       e.waitForStep(5, 15000);
+       m.remove(provider);
+       m.remove(consumer);
+       e.waitForStep(6, 15000);
+   }
+
+   static interface ServiceInterface {
+       public void invoke();
+   }
+
+   static class ServiceProvider implements ServiceInterface {
+       private final Ensure m_ensure;
+       public ServiceProvider(Ensure e) {
+           m_ensure = e;
+       }
+       public void invoke() {
+           m_ensure.step(5);
+       }
+   }
+
+   static class ServiceProvider2 implements ServiceInterface {
+       private final Ensure m_ensure;
+       public ServiceProvider2(Ensure e) {
+           m_ensure = e;
+       }
+       public void invoke() {
+           m_ensure.step(2);
+       }
+   }
+
+   static class ServiceConsumer implements Runnable {
+       private volatile ServiceInterface m_service;
+       private final Ensure m_ensure;
+
+       @SuppressWarnings("unused")
+       private void add(ServiceInterface service) { m_service = service; }
+       
+       @SuppressWarnings("unused")
+       private void remove(ServiceInterface service) { if (m_service == 
service) { m_service = null; }}
+       public ServiceConsumer(Ensure e) { m_ensure = e; }
+
+       public void start() {
+           Thread t = new Thread(this);
+           t.start();
+       }
+
+       public void run() {
+           m_ensure.step(1);
+           m_service.invoke();
+           m_ensure.step(3);
+           m_ensure.waitForStep(4, 15000);
+           m_service.invoke();
+       }
+
+       public void stop() {
+           m_ensure.step(6);
+       }
+   }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/RemovedDependencyTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/RemovedDependencyTest.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/RemovedDependencyTest.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/RemovedDependencyTest.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,173 @@
+/*
+ * 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.component;
+import static 
org.apache.felix.dm.lambda.DependencyManagerActivator.serviceDependency;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * One consumer, Three providers. The Consumer has two required dependency on 
provider1, provider2, and one 
+ * instance-bound required dependency on provider3.
+ * When the three providers are there, the consumer is started.
+ * 
+ * This test asserts the following correct behaviors:
+ *   - when we remove the dependency on provider2, then the consumer is not 
stopped.
+ *   - when we remove the (instance-bound) dependency on provider3, then the 
consumer os not stopped.
+ * 
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes", "unused"})
+public class RemovedDependencyTest extends TestBase {
+    public void testRemoveDependencyAndConsumerMustRemainStarted() {
+        DependencyManager m = getDM();
+        // helper class that ensures certain steps get executed in sequence
+        Ensure e = new Ensure();
+        // Create two providers
+        Hashtable props = new Hashtable();
+        props.put("name", "provider1");
+        Component sp = component(m).impl(new 
ServiceProvider(e)).provides(ServiceInterface.class, props).build();
+        props = new Properties();
+        props.put("name", "provider2");
+        Component sp2 = component(m).impl(new 
ServiceProvider(e)).provides(ServiceInterface.class.getName(), props).build();
+        props = new Properties();
+        props.put("name", "provider3");
+        Component sp3 = component(m).impl(new 
ServiceProvider(e)).provides(ServiceInterface.class.getName(), props).build();
+
+        // Create the consumer, and start it
+        Dependency d3 = 
m.createServiceDependency().setService(ServiceInterface.class, 
"(name=provider3)").setRequired(true).setCallbacks("add", "remove");
+
+        ServiceConsumer consumer = new ServiceConsumer(e, d3);
+        Component sc = component(m).impl(consumer).build();
+        
+        Dependency d1 = serviceDependency(sc, 
ServiceInterface.class).filter("(name=provider1)").cb("add", "remove").build();
+        Dependency d2 = serviceDependency(sc, 
ServiceInterface.class).filter("(name=provider2)").cb("add", "remove").build();
+        
+        sc.add(d1, d2);
+            
+        // Add the first two providers and the consumer
+        m.add(sp);
+        m.add(sp2);
+        m.add(sp3);
+        m.add(sc);
+        
+        // Check if consumer has been bound to the three providers
+        e.waitForStep(3,  5000);
+        Assert.assertEquals(3, consumer.getProvidersCount());
+        Assert.assertNotNull(consumer.getProvider("provider1"));
+        Assert.assertNotNull(consumer.getProvider("provider2"));
+        Assert.assertNotNull(consumer.getProvider("provider3"));
+        
+        // Now remove the provider2, and check if the consumer is still alive
+        sc.remove(d2);
+        Assert.assertFalse(consumer.isStopped());
+        Assert.assertEquals(2, consumer.getProvidersCount());
+        Assert.assertNotNull(consumer.getProvider("provider1"));
+        Assert.assertNull(consumer.getProvider("provider2"));
+        Assert.assertNotNull(consumer.getProvider("provider3"));
+
+        // Now remove the provider3 (the consumer has an instance bound 
dependency on it), and check if the consumer is still alive
+        sc.remove(d3);
+        Assert.assertFalse(consumer.isStopped());
+        Assert.assertEquals(1, consumer.getProvidersCount());
+        Assert.assertNotNull(consumer.getProvider("provider1"));
+        Assert.assertNull(consumer.getProvider("provider2"));
+        Assert.assertNull(consumer.getProvider("provider3"));
+        
+        m.clear();
+    }
+    
+    static interface ServiceInterface {
+        public void invoke();
+    }
+
+    class ServiceProvider implements ServiceInterface {
+        final Ensure m_ensure;
+        
+        public ServiceProvider(Ensure e) {
+            m_ensure = e;
+        }
+        public void invoke() {
+            m_ensure.step();
+        }
+    }
+    
+    class ServiceConsumer {
+        private final Ensure m_ensure;
+        private final List<ServiceReference> m_providers = new ArrayList<>();
+        private BundleContext m_bc;
+        private boolean m_stopped;
+        private final Dependency m_dependency3;
+
+        public ServiceConsumer(Ensure e, Dependency dependency3) {
+            m_ensure = e;
+            m_dependency3 = dependency3;
+        }
+                
+        public void add(ServiceReference ref) {
+            debug("ServiceConsumer.add(%s)", ref);
+            m_providers.add(ref);
+            ServiceInterface s = (ServiceInterface) m_bc.getService(ref);
+            s.invoke();
+        }
+        
+        public void remove(ServiceReference ref) {
+            debug("ServiceConsumer.remove(%s)", ref);
+            m_providers.remove(ref);
+            debug("ServiceConsumer: current providers list=%s", m_providers);
+        }
+        
+        public void init(Component c) {
+            c.add(m_dependency3);
+        }
+        
+        public int getProvidersCount() {
+            return m_providers.size();
+        }
+        
+        public ServiceInterface getProvider(String name) {
+            for (ServiceReference ref : m_providers) {
+                Object n = ref.getProperty("name");
+                if (n.equals(name)) {
+                    return (ServiceInterface) m_bc.getService(ref);
+                }
+            }
+            return null;
+        }
+        
+        public void stop() {
+            m_stopped = true;
+        }
+        
+        public boolean isStopped() {
+            return m_stopped;
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ResourceProvider.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ResourceProvider.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ResourceProvider.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ResourceProvider.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,122 @@
+/*
+ * 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 java.net.URL;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.felix.dm.ResourceHandler;
+import org.apache.felix.dm.ResourceUtil;
+import org.junit.Assert;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+class ResourceProvider {
+       final URL[] m_resources;
+    final BundleContext m_context;
+    final Map<ResourceHandler, Filter> m_handlers = new HashMap<>();
+
+       ResourceProvider(BundleContext ctx, URL ... resources) {
+               m_context = ctx;
+               m_resources = resources;
+       }
+       
+    public void change() {
+        for (int i = 0; i < m_resources.length; i++) {
+               change(i);
+        }      
+    }
+    
+    @SuppressWarnings({ "deprecation", "unchecked" })
+       public void change(int resourceIndex) {
+        Map<ResourceHandler, Filter> handlers = new HashMap<>();
+        synchronized (m_handlers) {
+            handlers.putAll(m_handlers);
+        }
+        for (Map.Entry<ResourceHandler, Filter> e : handlers.entrySet()) {
+               ResourceHandler handler = e.getKey();
+               Filter filter = e.getValue();
+               if (filter == null || filter.match((Dictionary<String, ? 
>)ResourceUtil.createProperties(m_resources[resourceIndex]))) {
+                       handler.changed(m_resources[resourceIndex]);
+            }
+        }
+    }
+
+    @SuppressWarnings({ "deprecation", "unchecked" })
+       public void add(ServiceReference<ResourceHandler> ref, ResourceHandler 
handler) {
+        String filterString = (String) ref.getProperty("filter");
+        Filter filter = null;
+        if (filterString != null) {
+            try {
+                filter = m_context.createFilter(filterString);
+            }
+            catch (InvalidSyntaxException e) {
+                Assert.fail("Could not create filter for resource handler: " + 
e);
+                return;
+            }
+        }
+        for (int i = 0; i < m_resources.length; i++) {
+            if (filter == null || filter.match((Dictionary<String, ? >) 
ResourceUtil.createProperties(m_resources[i]))) {
+                synchronized (m_handlers) {
+                    m_handlers.put(handler, filter);
+                }
+                handler.added(m_resources[i]);
+            }
+        }
+    }
+
+    public void remove(ServiceReference<ResourceHandler> ref, ResourceHandler 
handler) {
+        Filter filter;
+        synchronized (m_handlers) {
+            filter = (Filter) m_handlers.remove(handler);
+        }
+        if (filter != null) {
+               removeResources(handler, filter);
+        }
+    }
+
+    @SuppressWarnings({ "deprecation", "unchecked" })
+       private void removeResources(ResourceHandler handler, Filter filter) {
+            for (int i = 0; i < m_resources.length; i++) {
+                if (filter == null || filter.match((Dictionary<String, ? 
>)ResourceUtil.createProperties(m_resources[i]))) {
+                    handler.removed(m_resources[i]);
+                }
+            }
+        }
+
+    public void destroy() {
+        Map<ResourceHandler, Filter> handlers = new HashMap<>();
+        synchronized (m_handlers) {
+            handlers.putAll(m_handlers);
+        }
+
+        for (Map.Entry<ResourceHandler, Filter> e : handlers.entrySet()) {
+            ResourceHandler handler = e.getKey();
+            Filter filter = e.getValue();
+            removeResources(handler, filter);
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyCallbackSignaturesTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyCallbackSignaturesTest.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyCallbackSignaturesTest.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/ServiceDependencyCallbackSignaturesTest.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,297 @@
+/*
+ * 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.component;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * @author <a href="mailto:[email protected]";>Felix Project Team</a>
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class ServiceDependencyCallbackSignaturesTest extends TestBase {
+    volatile Ensure m_ensure;
+    
+    /**
+     * Tests if all possible dependency callbacks signatures supported by 
ServiceDependency.
+     */
+    public void testDependencyCallbackSignatures() {
+        DependencyManager m = getDM();
+        m_ensure = new Ensure();    
+        Hashtable<String, String> props = new Hashtable<>();
+        props.put("foo", "bar");
+        Component provider = component(m)
+            .impl(new ProviderImpl()).provides(Provider.class.getName(), 
props).build();
+        
+        component(m, c->c.impl(new Consumer1()).withSrv(Provider.class, 
srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer2()).withSrv(Provider.class, 
srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer3()).withSrv(Provider.class, 
srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer4()).withSrv(Provider.class, 
srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer5()).withSrv(Provider.class, 
srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer6()).withSrv(Provider.class, 
srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer7()).withSrv(Provider.class, 
srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer8()).withSrv(Provider.class, 
srv->srv.cb("bind", "change", "remove")));
+        component(m, c->c.impl(new Consumer9()).withSrv(Provider.class, 
srv->srv.cb("bind", "change", "remove")));
+
+        m.add(provider);
+        m_ensure.waitForStep(9, 5000);
+        
+        props = new Hashtable<>();
+        props.put("foo", "zoo");
+        provider.setServiceProperties(props);
+        m_ensure.waitForStep(18, 5000);
+        
+        m.remove(provider);
+        m_ensure.waitForStep(26, 5000);
+    }
+    
+    /**
+     * Tests if all possible dependency callbacks signatures supported by 
ServiceDependency.
+     */
+    public void testDependencyCallbackSignaturesRef() {
+        DependencyManager m = getDM();
+        m_ensure = new Ensure();    
+        Hashtable<String, String> props = new Hashtable<>();
+        props.put("foo", "bar");
+        Component provider = component(m)
+            .impl(new ProviderImpl()).provides(Provider.class.getName(), 
props).build();
+        
+        component(m, c->c.impl(new Consumer1()).withSrv(Provider.class, 
srv->srv.cb(Consumer1::bind, Consumer1::change, Consumer1::remove)));
+        component(m, c->c.impl(new Consumer2()).withSrv(Provider.class, 
srv->srv.cb(Consumer2::bind, Consumer2::change, Consumer2::remove)));
+        component(m, c->c.impl(new Consumer3()).withSrv(Provider.class, 
srv->srv.cb(Consumer3::bind, Consumer3::change, Consumer3::remove)));
+        component(m, c->c.impl(new Consumer4()).withSrv(Provider.class, 
srv->srv.cb(Consumer4::bind, Consumer4::change, Consumer4::remove)));
+        component(m, c->c.impl(new Consumer5()).withSrv(Provider.class, 
srv->srv.cb(Consumer5::bind, Consumer5::change, Consumer5::remove)));
+        component(m, c->c.impl(new Consumer6()).withSrv(Provider.class, 
srv->srv.cb(Consumer6::bind, Consumer6::change, Consumer6::remove)));
+        component(m, c->c.impl(new Consumer7()).withSrv(Provider.class, 
srv->srv.cb(Consumer7::bind, Consumer7::change, Consumer7::remove)));
+        component(m, c->c.impl(new Consumer8()).withSrv(Provider.class, 
srv->srv.cb(Consumer8::bind, Consumer8::change, Consumer8::remove)));
+        component(m, c->c.impl(new Consumer9()).withSrv(Provider.class, 
srv->srv.cb(Consumer9::bind, Consumer9::change, Consumer9::remove)));
+
+        m.add(provider);
+        m_ensure.waitForStep(9, 5000);
+        
+        props = new Hashtable<>();
+        props.put("foo", "zoo");
+        provider.setServiceProperties(props);
+        m_ensure.waitForStep(18, 5000);
+        
+        m.remove(provider);
+        m_ensure.waitForStep(26, 5000);
+    }
+    
+    private void declareConsumer(DependencyManager m, Object consumerImpl) {
+        Component consumer = component(m)
+            .impl(consumerImpl)
+            .withSrv(Provider.class, srv->srv.cb("bind", "change", "change"))
+            .build();
+        m.add(consumer);
+    }
+
+    public static interface Provider {        
+    }
+    
+    public static class ProviderImpl implements Provider {        
+    }
+    
+    class Consumer1 {        
+        void bind(Provider provider) {
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+        void change(Provider provider) {
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+        
+        void remove(Provider provider) {
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+    }
+    
+    class Consumer2 {        
+        void bind(Provider provider, Map<String, Object> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("bar", props.get("foo"));
+            m_ensure.step();
+        }
+        void change(Provider provider, Map<String, Object> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", props.get("foo"));
+            m_ensure.step();
+        }
+        void remove(Provider provider, Map<String, Object> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", props.get("foo"));
+            m_ensure.step();
+        }
+    }
+    
+    class Consumer3 {        
+        void bind(Provider provider, Dictionary<?, ?> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("bar", props.get("foo"));
+            m_ensure.step();
+        }
+        void change(Provider provider, Dictionary<?, ?> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", props.get("foo"));
+            m_ensure.step();
+        }
+        void remove(Provider provider, Dictionary<?, ?> props) {
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", props.get("foo"));
+            m_ensure.step();
+        }
+    }
+
+    class Consumer4 {        
+        void bind(ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("bar", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+        void change(ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+        void remove(ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+    }
+        
+    class Consumer5 {        
+        void bind(ServiceReference ref) {
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("bar", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+        void change(ServiceReference ref) {
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+        void remove(ServiceReference ref) {
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            m_ensure.step();
+        }
+    }
+
+    class Consumer6 {        
+        void bind(Component c) {
+            Assert.assertNotNull(c);
+            m_ensure.step();
+        }
+        void change(Component c) {
+            Assert.assertNotNull(c);
+            m_ensure.step();
+        }
+        void remove(Component c) {
+            Assert.assertNotNull(c);
+            m_ensure.step();
+        }
+    }
+        
+    class Consumer7 {
+        void bind(Component c, ServiceReference ref) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("bar", ref.getProperty("foo"));
+            Assert.assertNotNull(context.getService(ref));
+            Assert.assertEquals(context.getService(ref).getClass(), 
ProviderImpl.class);
+            m_ensure.step();
+        }
+        void change(Component c, ServiceReference ref) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            Assert.assertNotNull(context.getService(ref));
+            Assert.assertEquals(context.getService(ref).getClass(), 
ProviderImpl.class);
+            m_ensure.step();
+        }
+        void remove(Component c, ServiceReference ref) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            Assert.assertNotNull(context.getService(ref));
+            Assert.assertEquals(context.getService(ref).getClass(), 
ProviderImpl.class);
+            m_ensure.step();
+        }
+    }
+        
+    class Consumer8 {
+        void bind(Component c, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+        void change(Component c, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+        void remove(Component c, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(provider);
+            m_ensure.step();
+        }
+    }
+    
+    class Consumer9 {
+        void bind(Component c, ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("bar", ref.getProperty("foo"));
+            Assert.assertEquals(context.getService(ref), provider);
+            m_ensure.step();
+        }
+        void change(Component c, ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            Assert.assertEquals(context.getService(ref), provider);
+            m_ensure.step();
+        }
+        void remove(Component c, ServiceReference ref, Provider provider) {
+            Assert.assertNotNull(c);
+            Assert.assertNotNull(ref);
+            Assert.assertNotNull(provider);
+            Assert.assertEquals("zoo", ref.getProperty("foo"));
+            Assert.assertEquals(context.getService(ref), provider);
+            m_ensure.step();
+        }
+    }
+        
+}


Reply via email to