Return-Path: X-Original-To: apmail-felix-commits-archive@www.apache.org Delivered-To: apmail-felix-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9975618CE5 for ; Sun, 17 Jan 2016 23:39:03 +0000 (UTC) Received: (qmail 51639 invoked by uid 500); 17 Jan 2016 23:39:03 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 51595 invoked by uid 500); 17 Jan 2016 23:39:03 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 51586 invoked by uid 99); 17 Jan 2016 23:39:03 -0000 Received: from Unknown (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 17 Jan 2016 23:39:03 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id D482BC2605 for ; Sun, 17 Jan 2016 23:39:02 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.799 X-Spam-Level: * X-Spam-Status: No, score=1.799 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RP_MATCHES_RCVD=-0.001] autolearn=disabled Received: from mx1-us-east.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id E_W4z49LLj6i for ; Sun, 17 Jan 2016 23:38:57 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-us-east.apache.org (ASF Mail Server at mx1-us-east.apache.org) with ESMTP id 57BF442BA7 for ; Sun, 17 Jan 2016 23:38:57 +0000 (UTC) Received: from svn01-us-west.apache.org (svn.apache.org [10.41.0.6]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id B73EAE0282 for ; Sun, 17 Jan 2016 23:38:56 +0000 (UTC) Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id A4F823A00E7 for ; Sun, 17 Jan 2016 23:38:56 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1725147 [1/2] - in /felix/sandbox/pderop/dependencymanager-lambda: ./ org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/ org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/depe... Date: Sun, 17 Jan 2016 23:38:56 -0000 To: commits@felix.apache.org From: pderop@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20160117233856.A4F823A00E7@svn01-us-west.apache.org> Author: pderop Date: Sun Jan 17 23:38:55 2016 New Revision: 1725147 URL: http://svn.apache.org/viewvc?rev=1725147&view=rev Log: Added more tests. Added needsInstance method in ConfigurationDependencyBuilder. Added optional method in ServiceDependencyBuilder. Added withService(Class service, String filter) method in ComponentBuilder. Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/InstanceBoundDependencyTest.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependenciesTest.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependencyTest.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependencyTest2.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleServiceDependencyTest.java Modified: felix/sandbox/pderop/dependencymanager-lambda/TODO felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AdapterWithModifiedInstanceBoundDependencyTest.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/DynamicProxyAspectTest.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/compositefactory/Activator.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/Activator.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/Activator.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDependencyBuilder.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ComponentBuilder.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ConfigurationDependencyBuilder.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/Functions.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/FutureDependencyBuilder.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ServiceCallbacksBuilder.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ServiceDependencyBuilder.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/AdapterBase.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/CompletableFutureDependencyImpl.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ComponentBuilderImpl.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ConfigurationDependencyBuilderImpl.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ServiceCallbacksBuilderImpl.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ServiceDependencyBuilderImpl.java Modified: felix/sandbox/pderop/dependencymanager-lambda/TODO URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/TODO?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/TODO (original) +++ felix/sandbox/pderop/dependencymanager-lambda/TODO Sun Jan 17 23:38:55 2016 @@ -1,13 +1,3 @@ -- add more signatures in ServiceDependencyBuilder (with Component type) - -- add factories methods in ComponentImpl that take object/string params (like in original DM API) - and update DynamicProxyAspectTest.java - -- when a component instance method ref is not found, log an error. - -- ConfigurationDependency: - * allow to set "needsInstance" flag - - Finish to adapt all DependencyManager integration tests - add BundeAdapter Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AdapterWithModifiedInstanceBoundDependencyTest.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AdapterWithModifiedInstanceBoundDependencyTest.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AdapterWithModifiedInstanceBoundDependencyTest.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AdapterWithModifiedInstanceBoundDependencyTest.java Sun Jan 17 23:38:55 2016 @@ -120,7 +120,7 @@ public class AdapterWithModifiedInstance Component a = component(m).impl(new AImpl(e)).provides(A.class).properties(foo -> "bar").build(); Component b = adapter(m, A.class).cb("addA", "changeA", "removeA").provides(B.class).impl(new BImpl(e)).build(); - Component c = component(m).impl(new CImpl()).provides(C.class).withService(A.class, s -> s.filter("(foo=bar)")).build(); + Component c = component(m).impl(new CImpl()).provides(C.class).withService(A.class, "(foo=bar)").build(); m.add(a); m.add(c); Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/DynamicProxyAspectTest.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/DynamicProxyAspectTest.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/DynamicProxyAspectTest.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/DynamicProxyAspectTest.java Sun Jan 17 23:38:55 2016 @@ -34,11 +34,72 @@ import org.junit.Assert; */ @SuppressWarnings({"rawtypes"}) public class DynamicProxyAspectTest extends TestBase { + public void testImplementGenericAspectWithDynamicProxyAndFactory() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + + DynamicProxyHandler.resetCounter(); + + // create two service providers, each providing a different service interface + Component sp1 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build(); + Component sp2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class).build(); + + // create a dynamic proxy based aspect and hook it up to both services + Component a1 = aspect(m, ServiceInterface.class) + .rank(10) + .autoConfig("m_service") + .factory(new Factory(e, ServiceInterface.class, "ServiceInterfaceProxy"), "create") + .build(); + + Component a2 = aspect(m, ServiceInterface2.class) + .rank(10) + .autoConfig("m_service") + .factory(new Factory(e, ServiceInterface2.class, "ServiceInterfaceProxy2"), "create") + .build(); + + // create a client that invokes a method on boths services, validate that it goes + // through the proxy twice + Component sc = component(m) + .impl(new ServiceConsumer(e)) + .withService(ServiceInterface.class, ServiceInterface2.class).build(); + + // register both producers, validate that both services are started + m.add(sp1); + e.waitForStep(1, 2000); + m.add(sp2); + e.waitForStep(2, 2000); + + // add both aspects, and validate that both instances have been created + m.add(a1); + m.add(a2); + e.waitForStep(4, 4000); + + // add the client, which will automatically invoke both services + m.add(sc); + + // wait until both services have been invoked + e.waitForStep(6, 4000); + + // make sure the proxy has been called twice + Assert.assertEquals("Proxy should have been invoked this many times.", 2, DynamicProxyHandler.getCounter()); + + m.remove(sc); + m.remove(a2); + m.remove(a1); + m.remove(sp2); + m.remove(sp1); + m.remove(a2); + m.remove(a1); + } + public void testImplementGenericAspectWithDynamicProxyAndFactoryRef() { DependencyManager m = getDM(); // helper class that ensures certain steps get executed in sequence Ensure e = new Ensure(); + DynamicProxyHandler.resetCounter(); + // create two service providers, each providing a different service interface Component sp1 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build(); Component sp2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class).build(); @@ -81,15 +142,7 @@ public class DynamicProxyAspectTest exte m.remove(sp2); m.remove(sp1); m.remove(a2); - m.remove(a1); - - try { - Thread.sleep(2000); - } - catch (InterruptedException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } + m.remove(a1); } static interface ServiceInterface { @@ -176,6 +229,10 @@ public class DynamicProxyAspectTest exte public static int getCounter() { return m_counter; } + + public static void resetCounter() { + m_counter = 0; + } } static class Factory { Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java?rev=1725147&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/FactoryInjectedWithConfigurationBeforeTheCreateMethod.java Sun Jan 17 23:38:55 2016 @@ -0,0 +1,133 @@ +/* + * 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.builder.lambda.itest; + +import java.io.IOException; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Properties; + +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; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.*; +import static org.apache.felix.dm.builder.lambda.Cb.*; + + +/** + * 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 Felix Project Team + */ +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")).withService(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").withConfiguration(b->b.pid("foobar").cb(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")).withService(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").withConfiguration(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 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 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/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/InstanceBoundDependencyTest.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/InstanceBoundDependencyTest.java?rev=1725147&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/InstanceBoundDependencyTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/InstanceBoundDependencyTest.java Sun Jan 17 23:38:55 2016 @@ -0,0 +1,160 @@ +/* + * 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.builder.lambda.itest; + +import static org.apache.felix.dm.builder.lambda.Cb.ADD; +import static org.apache.felix.dm.builder.lambda.Cb.CHG; +import static org.apache.felix.dm.builder.lambda.Cb.REM; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.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 Felix Project Team + */ +@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) + .withService(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 m_s1Map = new HashMap(); + final Map 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.withService(S2.class, srv -> srv.cb(ADD, C::addS2).cb(CHG, C::changeS2).cb(REM, C::removeS2))); + m_e.step(1); + } + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependenciesTest.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependenciesTest.java?rev=1725147&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependenciesTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependenciesTest.java Sun Jan 17 23:38:55 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.builder.lambda.itest; + +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.component; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.junit.Assert; + +/** + * @author Felix Project Team + */ +@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)).withService(Service2.class, srv->srv.autoConfig("m_service2")).build(); + Component c2 = component(m).impl(new MyComponent2(e)).withService(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)).withService(Service2.class, srv->srv.autoConfig("m_service2")).build(); + Component c2 = component(m).impl(new MyComponent2(e)).withService(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 + .withService(Service3.class, srv->srv.filter("(type=xx)").autoConfig("m_service3_xx")) + .withService(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/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependencyTest.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependencyTest.java?rev=1725147&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependencyTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependencyTest.java Sun Jan 17 23:38:55 2016 @@ -0,0 +1,213 @@ +/* + * 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.builder.lambda.itest; + +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.component; + +import java.util.Hashtable; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; + +/** + * Test which validates multi-dependencies combination. + * + * @author Felix Project Team + */ +@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) + .withService(Runnable.class, srv->srv.filter("(foo=bar)").required(false).autoConfig("m_runnable")) + .withService(Sequencer.class, srv->srv.cb("bind")) + .cb(null, "start", "stop", null) + .composition("getComposition") + .build(); + + Component sp = component(m) + .impl(ServiceProvider.class) + .provides(ServiceInterface.class.getName(), + new Hashtable() {{ put("foo", "bar"); }}) + .withService(Sequencer.class, srv->srv.autoConfig("m_sequencer")) + .withService(ServiceProvider2.class, srv->srv.cb("bind", "unbind")) + .cb(null, "start", "stop", null) + .build(); + + Component sc = component(m) + .impl(ServiceConsumer.class) + .withService(Sequencer.class, srv->srv.autoConfig("m_sequencer")) + .withService(ServiceInterface.class, srv->srv.filter("(foo=bar)").autoConfig("m_service")) + .cb(null, "start", "stop", null) + .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/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependencyTest2.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependencyTest2.java?rev=1725147&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependencyTest2.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleExtraDependencyTest2.java Sun Jan 17 23:38:55 2016 @@ -0,0 +1,237 @@ +/* + * 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.builder.lambda.itest; + +import java.util.Hashtable; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.Dependency; +import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.ServiceDependency; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.*; + +/** + * Tests for extra dependencies which are declared from service's init method. + * + * @author Felix Project Team + */ +@SuppressWarnings({"unchecked", "rawtypes", "serial"}) +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) + .cb("init", "start", "stop", null) + .composition("getComposition").build(); + + Component sp = component(m) + .impl(ServiceProvider.class) + .provides(ServiceInterface.class, "foo", "bar") + .cb("init", "start", "stop", null) + .build(); + + Component sc = component(m) + .impl(ServiceConsumer.class) + .cb("init", "start", "stop", null) + .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 + .withService(Sequencer.class, srv->srv.autoConfig("m_sequencer")) + .withService(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 + .withService(Sequencer.class, srv->srv.autoConfig("m_sequencer")) + .withService(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 + .withService(Runnable.class, srv->srv.optional().filter("(foo=bar)")) + .withService(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/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleServiceDependencyTest.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleServiceDependencyTest.java?rev=1725147&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleServiceDependencyTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/MultipleServiceDependencyTest.java Sun Jan 17 23:38:55 2016 @@ -0,0 +1,145 @@ +/* + * 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.builder.lambda.itest; + +import java.util.Hashtable; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.osgi.framework.Constants; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.*; + +/** + * @author Felix Project Team + */ +@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)).withService(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)).withService(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)).withService(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); + } + } +} Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/compositefactory/Activator.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/compositefactory/Activator.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/compositefactory/Activator.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/compositefactory/Activator.java Sun Jan 17 23:38:55 2016 @@ -19,7 +19,7 @@ package org.apache.felix.dependencymanager.lambda.samples.compositefactory; import static java.lang.System.out; -import static org.apache.felix.dm.builder.lambda.Cb.ADD; +import static org.apache.felix.dm.builder.lambda.Cb.*; import org.apache.felix.dm.builder.lambda.DependencyActivatorBase; import org.osgi.service.cm.ConfigurationAdmin; @@ -52,6 +52,7 @@ public class Activator extends Dependenc // before creating the composition of classes. component(comp -> comp .factory(factory::create, factory::getComposition) + .cb(START, ProviderImpl::start) // only call start on ProviderImpl .withService(LogService.class, srv -> srv.cb(ADD, ProviderImpl::bind).cb(ADD, ProviderComposite1::bind)) .withConfiguration(conf -> conf.pid(ProviderFactory.class).cbi(factory::updated))); Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/Activator.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/Activator.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/Activator.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/Activator.java Sun Jan 17 23:38:55 2016 @@ -53,7 +53,7 @@ public class Activator extends Dependenc component(comp -> comp .impl(SpellChecker.class) .provides(SpellChecker.class, COMMAND_SCOPE, "dictionary", COMMAND_FUNCTION, new String[] {"spellcheck"}) - .withService(DictionaryService.class, srv -> srv.required()) + .withService(DictionaryService.class) .withService(LogService.class, srv -> srv.required(false))); } } Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/Activator.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/Activator.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/Activator.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/Activator.java Sun Jan 17 23:38:55 2016 @@ -52,7 +52,7 @@ public class Activator extends Dependenc .provides(FelixLinks.class) .withService(LogService.class, srv -> srv.cb(ADD, FelixLinksImpl::bind)) .withFuture(futureLinks, future -> future.cb(FelixLinksImpl::setLinks))); - + // Define a component that just displays the links found from the Felix web site. // It depends on a log service and on the FelixLink service, which are both injected in class fields. component(comp -> comp Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDependencyBuilder.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDependencyBuilder.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDependencyBuilder.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDependencyBuilder.java Sun Jan 17 23:38:55 2016 @@ -27,7 +27,6 @@ public interface BundleDependencyBuilder BundleDependencyBuilder cb(Cb callbackType, CbTypeBundle callback); BundleDependencyBuilder cb(Cb callbackType, CbTypeComponentBundle callback); - BundleDependencyBuilder cbi(Cb callbackType, CbBundle callback); BundleDependencyBuilder cbi(Cb callbackType, CbComponentBundle callback); Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ComponentBuilder.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ComponentBuilder.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ComponentBuilder.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ComponentBuilder.java Sun Jan 17 23:38:55 2016 @@ -31,6 +31,23 @@ public interface ComponentBuilder B impl(Class implClass); /** + * TODO + * + * @param factory + * @param createMethod + * @return + */ + B factory(Object factory, String createMethod); + + /** + * TODO + * + * @param createMethod + * @return + */ + B factory(java.lang.String createMethod); + + /** * Configures a factory that can be used to create this component implementation. * Example: "factory(ComponentImpl::new)", or "factory(() -> new ComponentImpl())". * @@ -132,6 +149,13 @@ public interface ComponentBuilder service, String filter); + + /** + * Adds a required/autoconfig service dependency. * @param service the dependency that is required and that will be injected in any field with the same dependency type. * @return this builder */ @@ -166,6 +190,10 @@ public interface ComponentBuilder B withFuture(CompletableFuture future, Consumer> consumer); + + B cb(String init, String start, String stop, String destroy); + B cb(Object callbackInstance, String init, String start, String stop, String destroy); + B cb(Cb callbackType, CbConsumer callback); B cb(Cb callbackType, CbBiConsumer callback); B cbi(Cb callbackType, Runnable callback); Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ConfigurationDependencyBuilder.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ConfigurationDependencyBuilder.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ConfigurationDependencyBuilder.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ConfigurationDependencyBuilder.java Sun Jan 17 23:38:55 2016 @@ -27,6 +27,7 @@ public interface ConfigurationDependency ConfigurationDependencyBuilder pid(Class pidClass); ConfigurationDependencyBuilder propagate(); ConfigurationDependencyBuilder propagate(boolean propagate); + ConfigurationDependencyBuilder needsInstance(boolean needsInstance); ConfigurationDependencyBuilder cb(String updateMethod); ConfigurationDependencyBuilder cb(Object callbackInstance, String updateMethod); Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/Functions.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/Functions.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/Functions.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/Functions.java Sun Jan 17 23:38:55 2016 @@ -260,6 +260,16 @@ public class Functions { } @FunctionalInterface + public interface CbTypeComponentServiceService extends SerializableLambda { + void accept(T instance, Component c, S old, S replace); + + default CbTypeComponentServiceService andThen(CbTypeComponentServiceService after) { + Objects.requireNonNull(after); + return (T instance, Component c, S old, S replace) -> { accept(instance, c, old, replace); after.accept(instance, c, old, replace); }; + } + } + + @FunctionalInterface public interface CbTypeRefServiceRefService extends SerializableLambda { void accept(T instance, ServiceReference oldRef, S old, ServiceReference replaceRef, S replace); @@ -270,6 +280,16 @@ public class Functions { } @FunctionalInterface + public interface CbTypeComponentRefServiceRefService extends SerializableLambda { + void accept(T instance, Component c, ServiceReference oldRef, S old, ServiceReference replaceRef, S replace); + + default CbTypeComponentRefServiceRefService andThen(CbTypeComponentRefServiceRefService after) { + Objects.requireNonNull(after); + return (T instance, Component c, ServiceReference oldRef, S old, ServiceReference replaceRef, S replace) -> { accept(instance, c, oldRef, old, replaceRef, replace); after.accept(instance, c, oldRef, old, replaceRef, replace); }; + } + } + + @FunctionalInterface public interface CbTypeMapServiceMapService extends SerializableLambda { void accept(T instance, Map oldProps, S old, Map replaceProps, S replace); @@ -300,6 +320,16 @@ public class Functions { } @FunctionalInterface + public interface CbComponentServiceService extends SerializableLambda { + void accept(Component c, S old, S replace); + + default CbComponentServiceService andThen(CbComponentServiceService after) { + Objects.requireNonNull(after); + return (Component c, S old, S replace) -> { accept(c, old, replace); after.accept(c, old, replace); }; + } + } + + @FunctionalInterface public interface CbRefServiceRefService { void accept(ServiceReference oldRef, S old, ServiceReference replaceRef, S replace); @@ -310,6 +340,16 @@ public class Functions { } @FunctionalInterface + public interface CbComponentRefServiceRefService { + void accept(Component c, ServiceReference oldRef, S old, ServiceReference replaceRef, S replace); + + default CbComponentRefServiceRefService andThen(CbComponentRefServiceRefService after) { + Objects.requireNonNull(after); + return (Component c, ServiceReference oldRef, S old, ServiceReference replaceRef, S replace) -> { accept(c, oldRef, old, replaceRef, replace); after.accept(c, oldRef, old, replaceRef, replace); }; + } + } + + @FunctionalInterface public interface CbMapServiceMapService { void accept(Map oldProps, S old, Map replaceProps, S replace); @@ -320,6 +360,16 @@ public class Functions { } @FunctionalInterface + public interface CbComponentMapServiceMapService { + void accept(Component c, Map oldProps, S old, Map replaceProps, S replace); + + default CbComponentMapServiceMapService andThen(CbComponentMapServiceMapService after) { + Objects.requireNonNull(after); + return (Component c, Map oldProps, S old, Map replaceProps, S replace) -> { accept(c, oldProps, old, replaceProps, replace); after.accept(c, oldProps, old, replaceProps, replace); }; + } + } + + @FunctionalInterface public interface CbDictServiceDictService { void accept(Dictionary oldProps, S old, Dictionary replaceProps, S replace); @@ -329,6 +379,16 @@ public class Functions { } } + @FunctionalInterface + public interface CbComponentDictServiceDictService { + void accept(Component c, Dictionary oldProps, S old, Dictionary replaceProps, S replace); + + default CbComponentDictServiceDictService andThen(CbComponentDictServiceDictService after) { + Objects.requireNonNull(after); + return (Component c, Dictionary oldProps, S old, Dictionary replaceProps, S replace) -> { accept(c, oldProps, old, replaceProps, replace); after.accept(c, oldProps, old, replaceProps, replace); }; + } + } + @FunctionalInterface public interface CbComponent { void accept(Component component); Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/FutureDependencyBuilder.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/FutureDependencyBuilder.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/FutureDependencyBuilder.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/FutureDependencyBuilder.java Sun Jan 17 23:38:55 2016 @@ -39,7 +39,11 @@ import org.apache.felix.dm.builder.lambd * * @param the type of the CompletableFuture result. */ -public interface FutureDependencyBuilder extends DependencyBuilder { +public interface FutureDependencyBuilder extends DependencyBuilder { + + FutureDependencyBuilder cb(String callback); + FutureDependencyBuilder cbi(Object callbackInstance, String callback); + /** * Sets the action to perform when the future task has completed. The action is one of the Component instance method that accepts the * result of the completed future. Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ServiceCallbacksBuilder.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ServiceCallbacksBuilder.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ServiceCallbacksBuilder.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ServiceCallbacksBuilder.java Sun Jan 17 23:38:55 2016 @@ -1,11 +1,15 @@ package org.apache.felix.dm.builder.lambda; import org.apache.felix.dm.builder.lambda.Functions.CbComponent; +import org.apache.felix.dm.builder.lambda.Functions.CbComponentDictServiceDictService; +import org.apache.felix.dm.builder.lambda.Functions.CbComponentMapServiceMapService; import org.apache.felix.dm.builder.lambda.Functions.CbComponentRef; import org.apache.felix.dm.builder.lambda.Functions.CbComponentRefService; +import org.apache.felix.dm.builder.lambda.Functions.CbComponentRefServiceRefService; import org.apache.felix.dm.builder.lambda.Functions.CbComponentService; import org.apache.felix.dm.builder.lambda.Functions.CbComponentServiceDict; import org.apache.felix.dm.builder.lambda.Functions.CbComponentServiceMap; +import org.apache.felix.dm.builder.lambda.Functions.CbComponentServiceService; import org.apache.felix.dm.builder.lambda.Functions.CbDictServiceDictService; import org.apache.felix.dm.builder.lambda.Functions.CbMapServiceMapService; import org.apache.felix.dm.builder.lambda.Functions.CbRef; @@ -18,9 +22,11 @@ import org.apache.felix.dm.builder.lambd import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponent; import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponentRef; import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponentRefService; +import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponentRefServiceRefService; import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponentService; import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponentServiceDict; import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponentServiceMap; +import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponentServiceService; import org.apache.felix.dm.builder.lambda.Functions.CbTypeDictServiceDictService; import org.apache.felix.dm.builder.lambda.Functions.CbTypeMapServiceMapService; import org.apache.felix.dm.builder.lambda.Functions.CbTypeRef; @@ -95,12 +101,17 @@ public interface ServiceCallbacksBuilder B cbi(Cb callbackType, CbComponentRefService callback); B sw(CbTypeServiceService swap); + B sw(CbTypeComponentServiceService swap); B sw(CbTypeRefServiceRefService swap); + B sw(CbTypeComponentRefServiceRefService swap); B sw(CbTypeMapServiceMapService swap); B sw(CbTypeDictServiceDictService swap); B swi(CbServiceService swap); + B swi(CbComponentServiceService swap); B swi(CbRefServiceRefService swap); + B swi(CbComponentRefServiceRefService swap); B swi(CbMapServiceMapService swap); + B swi(CbComponentMapServiceMapService swap); B swi(CbDictServiceDictService swap); - // TODO add more swap signatures with Component param. + B swi(CbComponentDictServiceDictService swap); } Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ServiceDependencyBuilder.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ServiceDependencyBuilder.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ServiceDependencyBuilder.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ServiceDependencyBuilder.java Sun Jan 17 23:38:55 2016 @@ -28,6 +28,12 @@ public interface ServiceDependencyBuilde ServiceDependencyBuilder ref(ServiceReference ref); /** + * Configures this dependency as optional. By default, a dependency is required. + * @return this builder + */ + ServiceDependencyBuilder optional(); + + /** * Configures this dependency as required. By default, a dependency is required. * @return this builder */ Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/AdapterBase.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/AdapterBase.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/AdapterBase.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/AdapterBase.java Sun Jan 17 23:38:55 2016 @@ -38,6 +38,16 @@ public interface AdapterBase compBuilder.factory(factory, createMethod)); + return (B) this; + } + + default B factory(String createMethod) { + andThenBuild(compBuilder -> compBuilder.factory(createMethod)); + return (B) this; + } + default B factory(Supplier create) { andThenBuild(compBuilder -> compBuilder.factory(create)); return (B) this; @@ -153,6 +163,11 @@ public interface AdapterBase service, String filter) { + andThenBuild(compBuilder -> compBuilder.withService(service, filter)); + return (B) this; + } + default B withService(Class service, Class ... services) { andThenBuild(compBuilder -> compBuilder.withService(service, services)); return (B) this; @@ -178,6 +193,16 @@ public interface AdapterBase compBuilder.cb(init, start, stop, destroy)); + return (B) this; + } + + default B cb(Object callbackInstance, String init, String start, String stop, String destroy) { + andThenBuild(compBuilder -> compBuilder.cb(callbackInstance, init, start, stop, destroy)); + return (B) this; + } + default B cb(Cb callbackType, CbConsumer callback) { andThenBuild(compBuilder -> compBuilder.cb(callbackType, callback)); return (B) this; Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/CompletableFutureDependencyImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/CompletableFutureDependencyImpl.java?rev=1725147&r1=1725146&r2=1725147&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/CompletableFutureDependencyImpl.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/CompletableFutureDependencyImpl.java Sun Jan 17 23:38:55 2016 @@ -1,5 +1,7 @@ package org.apache.felix.dm.builder.lambda.impl; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.stream.Stream; @@ -49,6 +51,17 @@ public class CompletableFutureDependency } @Override + public FutureDependencyBuilder cb(String callback) { + return cbi(null, callback); + } + + @Override + public FutureDependencyBuilder cbi(Object callbackInstance, String callback) { + super.setCallbacks(callbackInstance, callback, null); + return this; + } + + @Override public FutureDependencyBuilder cb(CbTypeFuture consumer) { return cb(consumer, false); } @@ -148,6 +161,11 @@ public class CompletableFutureDependency try { switch (type) { case ADDED: + if (m_add != null) { + // Inject result by reflection on a method name + injectByReflection(events[0].getEvent()); + return; + } F result = events[0].getEvent(); if (m_accept2 != null) { if (m_accept2Type != null) { @@ -192,4 +210,32 @@ public class CompletableFutureDependency m_component.handleEvent(this, EventType.ADDED, new Event(result)); } } + + /** + * Injects the completed fiture result in a method by reflection. + * We try to find a method which has in its signature a parameter that is compatible with the future result + * (including any interfaces the result may implements). + * + * @param result the result of the completable future. + */ + private void injectByReflection(Object result) { + List> types = new ArrayList<>(); + Class currentClazz = result.getClass(); + + while (currentClazz != null && currentClazz != Object.class) { + types.add(currentClazz); + Stream.of(currentClazz.getInterfaces()).forEach(types::add); + currentClazz = currentClazz.getSuperclass(); + } + + Class[][] classes = new Class[types.size() + 1][1]; + Object[][] results = new Object[types.size() + 1][1]; + for (int i = 0; i < types.size(); i ++) { + classes[i] = new Class[] { types.get(i) }; + results[i] = new Object[] { result }; + } + classes[types.size()] = new Class[0]; + results[types.size()] = new Object[0]; + m_component.invokeCallbackMethod(getInstances(), m_add, classes, results); + } }