Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AdapterWithoutPropagationTest.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.dm.lambda.itest; + +import static org.apache.felix.dm.lambda.DependencyManagerActivator.adapter; +import static org.apache.felix.dm.lambda.DependencyManagerActivator.component; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.junit.Assert; +import org.osgi.framework.ServiceRegistration; + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class AdapterWithoutPropagationTest extends TestBase { + + public void testAdapterNoPropagate() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + + // The provider has a "foo=bar" property + ServiceProvider serviceProvider = new ServiceProvider(e); + Component provider = component(m).provides(OriginalService.class).properties(foo -> "bar").impl(serviceProvider).build(); + + // The Adapter will see the "foo=bar" property from the adaptee + Component adapter = adapter(m, OriginalService.class) + .propagate(false).cb("set", "change", null).provides(AdaptedService.class).impl(new ServiceAdapter(e)).build(); + + // The consumer depends on the AdaptedService, but won't see foo=bar property from the adaptee + Component consumer = component(m) + .impl(new ServiceConsumer(e)).withSrv(AdaptedService.class, b -> b.cb("set", "change", null)).build(); + + // add the provider and the adapter + m.add(provider); + m.add(adapter); + // Checks if the adapter has been started and has seen the adaptee properties + e.waitForStep(1, 5000); + + // add a consumer that must not see the adaptee service properties + m.add(consumer); + e.waitForStep(2, 5000); + + // change the service properties of the provider, and check that the adapter callback instance is caled. + serviceProvider.changeServiceProperties(); + e.waitForStep(3, 5000); + + // cleanup + m.clear(); + } + + public void testAdapterNoPropagateRef() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + + // The provider has a "foo=bar" property + ServiceProvider serviceProvider = new ServiceProvider(e); + Component provider = component(m).provides(OriginalService.class).properties(foo -> "bar").impl(serviceProvider).build(); + + // The Adapter will see the "foo=bar" property from the adaptee + ServiceAdapter saimpl = new ServiceAdapter(e); + Component adapter = adapter(m, OriginalService.class).propagate(false).impl(saimpl).provides(AdaptedService.class).cbi(saimpl::set, saimpl::change, null).build(); + + // The consumer depends on the AdaptedService, but won't see foo=bar property from the adaptee + ServiceConsumer scimpl = new ServiceConsumer(e); + Component consumer = component(m).impl(scimpl).withSrv(AdaptedService.class, s -> s.cbi(scimpl::set, scimpl::change, null)).build(); + + // add the provider and the adapter + m.add(provider); + m.add(adapter); + // Checks if the adapter has been started and has seen the adaptee properties + e.waitForStep(1, 5000); + + // add a consumer that must not see the adaptee service properties + m.add(consumer); + e.waitForStep(2, 5000); + + // change the service properties of the provider, and check that the adapter callback instance is caled. + serviceProvider.changeServiceProperties(); + e.waitForStep(3, 5000); + + // cleanup + m.clear(); + } + + static interface OriginalService { + } + + static interface AdaptedService { + } + + static class ServiceProvider implements OriginalService { + private volatile ServiceRegistration m_registration; // auto injected when started. + public ServiceProvider(Ensure e) { + } + public void changeServiceProperties() { + Hashtable<String, String> props = new Hashtable<>(); + props.put("foo", "bar2"); + m_registration.setProperties(props); + } + } + + public static class ServiceAdapter implements AdaptedService { + private final Ensure m_ensure; + + public ServiceAdapter(Ensure e) { + m_ensure = e; + } + + public void set(OriginalService adaptee, Dictionary<String, Object> props) { + Assert.assertEquals("bar", props.get("foo")); + m_ensure.step(1); + } + + void change(OriginalService adapted, Dictionary<String, Object> props) { + Assert.assertEquals("bar2", props.get("foo")); + m_ensure.step(3); + } + } + + static class ServiceConsumer { + @SuppressWarnings("unused") + private volatile AdaptedService m_service; + private final Ensure m_ensure; + + public ServiceConsumer(Ensure e) { + m_ensure = e; + } + + void set(AdaptedService adapted, Dictionary<String, Object> props) { + Assert.assertNull(props.get("foo")); + m_ensure.step(2); + } + + void change(AdaptedService adapted, Dictionary<String, Object> props) { + Assert.assertNull(props.get("foo")); + Assert.fail("Change callback should not be called"); + } + } +} + +
Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectBaseTest.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,337 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.dm.lambda.itest; + +import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect; +import static org.apache.felix.dm.lambda.DependencyManagerActivator.component; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.junit.Assert; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class AspectBaseTest extends TestBase { + + public void testSingleAspect() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + + // create a service provider and consumer + ServiceProvider p = new ServiceProvider(e, "a"); + ServiceConsumer c = new ServiceConsumer(e); + + Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build(); + Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cb("add", "remove").autoConfig("m_service")).build(); + Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build(); + + m.add(sc); + m.add(sp); + // after the provider was added, the consumer's add should have been invoked once + e.waitForStep(1, 2000); + Assert.assertEquals("a", c.invoke()); + m.add(sa); + // after the aspect was added, the consumer should get and add for the aspect and a remove + // for the original service + e.waitForStep(3, 2000); + Assert.assertEquals("aa", c.invoke()); + m.remove(sa); + // removing the aspect again should give a remove and add + e.waitForStep(5, 2000); + Assert.assertEquals("a", c.invoke()); + m.remove(sp); + // finally removing the original service should give a remove + e.waitForStep(6, 2000); + m.remove(sc); + e.step(7); + clearComponents(); + } + + public void testSingleAspectRef() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + + // create a service provider and consumer + ServiceProvider p = new ServiceProvider(e, "a"); + ServiceConsumer c = new ServiceConsumer(e); + + Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build(); + Component sc = component(m) + .impl(c).withSrv(ServiceInterface.class, srv -> srv.cbi(c::add, c::remove).autoConfig("m_service")).build(); + Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build(); + + m.add(sc); + m.add(sp); + // after the provider was added, the consumer's add should have been invoked once + e.waitForStep(1, 2000); + Assert.assertEquals("a", c.invoke()); + m.add(sa); + // after the aspect was added, the consumer should get and add for the aspect and a remove + // for the original service + e.waitForStep(3, 2000); + Assert.assertEquals("aa", c.invoke()); + m.remove(sa); + // removing the aspect again should give a remove and add + e.waitForStep(5, 2000); + Assert.assertEquals("a", c.invoke()); + m.remove(sp); + // finally removing the original service should give a remove + e.waitForStep(6, 2000); + m.remove(sc); + e.step(7); + clearComponents(); + } + + @SuppressWarnings("serial") + public void testSingleAspectThatAlreadyExisted() { + DependencyManager m = new DependencyManager(context); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + + // create a service provider and consumer + ServiceProvider p = new ServiceProvider(e, "a"); + ServiceConsumer c = new ServiceConsumer(e); + Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build(); + Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cb("add", "remove").autoConfig("m_service")).build(); + Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build(); + + // we first add the aspect + m.add(sa); + // then the service provider + m.add(sp); + // finally the consumer + m.add(sc); + + Assert.assertEquals("aa", c.invoke()); + + // now the consumer's added should be invoked once, as the aspect is already available and should + // directly hide the original service + e.waitForStep(1, 2000); + e.step(2); + + m.remove(sa); + // after removing the aspect, the consumer should get the original service back, so + // remove and add will be invoked + e.waitForStep(4, 2000); + + Assert.assertEquals("a", c.invoke()); + + m.remove(sp); + // after removing the original service, the consumer's remove should be called once + e.waitForStep(5, 2000); + + m.remove(sc); + e.step(6); + } + + public void testSingleAspectThatAlreadyExistedRef() { + DependencyManager m = new DependencyManager(context); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + + // create a service provider and consumer + ServiceProvider p = new ServiceProvider(e, "a"); + ServiceConsumer c = new ServiceConsumer(e); + + Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build(); + Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cbi(c::add, c::remove).autoConfig("m_service")).build(); + Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build(); + + // we first add the aspect + m.add(sa); + // then the service provider + m.add(sp); + // finally the consumer + m.add(sc); + + Assert.assertEquals("aa", c.invoke()); + + // now the consumer's added should be invoked once, as the aspect is already available and should + // directly hide the original service + e.waitForStep(1, 2000); + e.step(2); + + m.remove(sa); + // after removing the aspect, the consumer should get the original service back, so + // remove and add will be invoked + e.waitForStep(4, 2000); + + Assert.assertEquals("a", c.invoke()); + + m.remove(sp); + // after removing the original service, the consumer's remove should be called once + e.waitForStep(5, 2000); + + m.remove(sc); + e.step(6); + } + + public void testMultipleAspects() { + DependencyManager m = new DependencyManager(context); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + + // create service providers and consumers + ServiceConsumer c = new ServiceConsumer(e); + Component sp = component(m).impl(new ServiceProvider(e, "a")).provides(ServiceInterface.class).properties(name -> "a").build(); + Component sp2 = component(m).impl(new ServiceProvider(e, "b")).provides(ServiceInterface.class).properties(name -> "b").build(); + Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cb("add", "remove")).build(); + + Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build(); + Component sa2 = aspect(m, ServiceInterface.class).rank(10).impl(ServiceAspect.class).build(); + + m.add(sp); + m.add(sp2); + m.add(sa); + m.add(sa2); + m.add(sc); + // the consumer will monitor progress, it should get it's add invoked twice, once for every + // (highest) aspect + e.waitForStep(2, 2000); + e.step(3); + + // now invoke all services the consumer collected + List<String> list = c.invokeAll(); + // and make sure both of them are correctly invoked + Assert.assertTrue(list.size() == 2); + Assert.assertTrue(list.contains("aaa")); + Assert.assertTrue(list.contains("bbb")); + + m.remove(sc); + // removing the consumer now should get its removed method invoked twice + e.waitForStep(5, 2000); + e.step(6); + m.remove(sa2); + m.remove(sa); + m.remove(sp2); + m.remove(sp); + e.step(7); + } + + public void testMultipleAspectsRef() { + DependencyManager m = new DependencyManager(context); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + + // create service providers and consumers + ServiceConsumer c = new ServiceConsumer(e); + Component sp = component(m).impl(new ServiceProvider(e, "a")).provides(ServiceInterface.class).properties(name -> "a").build(); + Component sp2 = component(m).impl(new ServiceProvider(e, "b")).provides(ServiceInterface.class).properties(name -> "b").build(); + Component sc = component(m).impl(c).withSrv(ServiceInterface.class, srv -> srv.cbi(c::add, c::remove)).build(); + + Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build(); + Component sa2 = aspect(m, ServiceInterface.class).rank(10).impl(ServiceAspect.class).build(); + + m.add(sp); + m.add(sp2); + m.add(sa); + m.add(sa2); + m.add(sc); + // the consumer will monitor progress, it should get it's add invoked twice, once for every + // (highest) aspect + e.waitForStep(2, 2000); + e.step(3); + + // now invoke all services the consumer collected + List<String> list = c.invokeAll(); + // and make sure both of them are correctly invoked + Assert.assertTrue(list.size() == 2); + Assert.assertTrue(list.contains("aaa")); + Assert.assertTrue(list.contains("bbb")); + + m.remove(sc); + // removing the consumer now should get its removed method invoked twice + e.waitForStep(5, 2000); + e.step(6); + m.remove(sa2); + m.remove(sa); + m.remove(sp2); + m.remove(sp); + e.step(7); + } + + public static interface ServiceInterface { + public String invoke(String input); + } + + public static class ServiceProvider implements ServiceInterface { + private final Ensure m_ensure; + private final String m_name; + public ServiceProvider(Ensure e, String name) { + m_ensure = e; + m_name = name; + } + public String invoke(String input) { + return input + m_name; + } + } + + public static class ServiceAspect implements ServiceInterface { + private volatile ServiceInterface m_originalService; + private volatile ServiceRegistration m_registration; + + public String invoke(String input) { + String result = m_originalService.invoke(input); + String property = (String) m_registration.getReference().getProperty("name"); + return result + property; + } + } + + public static class ServiceConsumer { + private final Ensure m_ensure; + private volatile ServiceInterface m_service; + private List<ServiceInterface> m_services = new ArrayList<ServiceInterface>(); + + public ServiceConsumer(Ensure e) { + m_ensure = e; + } + + public void add(ServiceReference<ServiceInterface> ref, ServiceInterface si) { + System.out.println("add: " + ServiceUtil.toString(ref)); + m_services.add(si); + m_ensure.step(); + } + + public void remove(ServiceReference<ServiceInterface> ref, ServiceInterface si) { + System.out.println("rem: " + ServiceUtil.toString(ref)); + m_services.remove(si); + m_ensure.step(); + } + + public String invoke() { + return m_service.invoke(""); + } + + public List<String> invokeAll() { + List<String> results = new ArrayList<String>(); + for (ServiceInterface si : m_services) { + results.add(si.invoke("")); + } + return results; + } + } +} Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectChainTest.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.dm.lambda.itest; + +import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect; +import static org.apache.felix.dm.lambda.DependencyManagerActivator.component; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class AspectChainTest extends TestBase { + + public void testBuildAspectChain() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + // create a service provider and consumer + Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build(); + Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class).build(); + Component sa2 = aspect(m, ServiceInterface.class).rank(20).impl(new ServiceAspect(e, 3)).build(); + Component sa3 = aspect(m, ServiceInterface.class).rank(30).impl(new ServiceAspect(e, 2)).build(); + Component sa1 = aspect(m, ServiceInterface.class).rank(10).impl(new ServiceAspect(e, 4)).build(); + m.add(sc); + + m.add(sp); + m.add(sa2); + m.add(sa3); + m.add(sa1); + e.step(); + e.waitForStep(5, 5000); + + m.remove(sa3); + m.remove(sa2); + m.remove(sa1); + m.remove(sp); + + m.remove(sc); + } + + static interface ServiceInterface { + public void invoke(Runnable run); + } + + static class ServiceProvider implements ServiceInterface { + @SuppressWarnings("unused") + private final Ensure m_ensure; + public ServiceProvider(Ensure e) { + m_ensure = e; + } + public void invoke(Runnable run) { + run.run(); + } + } + + static class ServiceAspect implements ServiceInterface { + private final Ensure m_ensure; + private volatile ServiceInterface m_parentService; + private final int m_step; + + public ServiceAspect(Ensure e, int step) { + m_ensure = e; + m_step = step; + } + public void start() { + } + + public void invoke(Runnable run) { + m_ensure.step(m_step); + m_parentService.invoke(run); + } + + public void stop() { + } + } + + static class ServiceConsumer implements Runnable { + private volatile ServiceInterface m_service; + private final Ensure m_ensure; + + public ServiceConsumer(Ensure e) { + m_ensure = e; + } + + public void init() { + Thread t = new Thread(this); + t.start(); + } + + public void run() { + m_ensure.waitForStep(1, 2000); + m_service.invoke(Ensure.createRunnableStep(m_ensure, 5)); + } + } +} Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectDynamicsTest.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,252 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.dm.lambda.itest; + +import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect; +import static org.apache.felix.dm.lambda.DependencyManagerActivator.component; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class AspectDynamicsTest extends TestBase { + + public void testDynamicallyAddAndRemoveAspect() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + Ensure aspectStopEnsure = new Ensure(); + // create a service provider and consumer + Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build(); + Component provider2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class.getName()).build(); + Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", null, null, "swap")).build(); + Component aspect = aspect(m, ServiceInterface.class).autoAdd(false).rank(1).impl(new ServiceAspect(e, aspectStopEnsure)).build(); + + m.add(consumer); + m.add(provider); + // the consumer should invoke the provider here, and when done, arrive at step 3 + // finally wait for step 6 before continuing + e.waitForStep(3, 15000); + + m.add(aspect); + // after adding the aspect, we wait for its init to be invoked, arriving at + // step 4 after an instance bound dependency was added (on a service provided by + // provider 2) + e.waitForStep(4, 15000); + + m.add(provider2); + + // after adding provider 2, we should now see the client being swapped, so + // we wait for step 5 to happen + e.waitForStep(5, 15000); + + // now we continue with step 6, which will trigger the next part of the consumer's + // run method to be executed + e.step(6); + + // invoking step 7, 8 and 9 when invoking the aspect which in turn invokes the + // dependency and the original service, so we wait for that to finish here, which + // is after step 10 has been reached (the client will now wait for step 12) + e.waitForStep(10, 15000); + + m.remove(aspect); + aspectStopEnsure.waitForStep(1, 15000); + // removing the aspect should trigger step 11 (in the swap method of the consumer) + e.waitForStep(11, 15000); + + // step 12 triggers the client to continue + e.step(12); + + // wait for step 13, the final invocation of the provided service (without aspect) + e.waitForStep(13, 15000); + + // clean up + m.remove(provider2); + m.remove(provider); + m.remove(consumer); + e.waitForStep(16, 15000); + m.clear(); + } + + public void testDynamicallyAddAndRemoveAspectRef() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + Ensure aspectStopEnsure = new Ensure(); + // create a service provider and consumer + Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build(); + Component provider2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class.getName()).build(); + Component consumer = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb(ServiceConsumer::add).sw(ServiceConsumer::swap)).build(); + Component aspect = aspect(m, ServiceInterface.class).autoAdd(false).rank(1).impl(new ServiceAspect(e, aspectStopEnsure)).build(); + + m.add(consumer); + m.add(provider); + // the consumer should invoke the provider here, and when done, arrive at step 3 + // finally wait for step 6 before continuing + e.waitForStep(3, 15000); + + m.add(aspect); + // after adding the aspect, we wait for its init to be invoked, arriving at + // step 4 after an instance bound dependency was added (on a service provided by + // provider 2) + e.waitForStep(4, 15000); + + m.add(provider2); + + // after adding provider 2, we should now see the client being swapped, so + // we wait for step 5 to happen + e.waitForStep(5, 15000); + + // now we continue with step 6, which will trigger the next part of the consumer's + // run method to be executed + e.step(6); + + // invoking step 7, 8 and 9 when invoking the aspect which in turn invokes the + // dependency and the original service, so we wait for that to finish here, which + // is after step 10 has been reached (the client will now wait for step 12) + e.waitForStep(10, 15000); + + m.remove(aspect); + aspectStopEnsure.waitForStep(1, 15000); + // removing the aspect should trigger step 11 (in the swap method of the consumer) + e.waitForStep(11, 15000); + + // step 12 triggers the client to continue + e.step(12); + + // wait for step 13, the final invocation of the provided service (without aspect) + e.waitForStep(13, 15000); + + // clean up + m.remove(provider2); + m.remove(provider); + m.remove(consumer); + e.waitForStep(16, 15000); + m.clear(); + } + + static interface ServiceInterface { + public void invoke(Runnable run); + } + + static interface ServiceInterface2 { + public void invoke(); + } + + static class ServiceProvider2 implements ServiceInterface2 { + private final Ensure m_ensure; + + public ServiceProvider2(Ensure ensure) { + m_ensure = ensure; + } + + public void invoke() { + m_ensure.step(9); + } + public void stop() { + m_ensure.step(); + } + } + + static class ServiceProvider implements ServiceInterface { + private final Ensure m_ensure; + public ServiceProvider(Ensure e) { + m_ensure = e; + } + public void invoke(Runnable run) { + run.run(); + } + public void stop() { + m_ensure.step(); + } + } + + static class ServiceAspect implements ServiceInterface { + private final Ensure m_ensure; + private volatile ServiceInterface m_originalService; + private volatile ServiceInterface2 m_injectedService; + private volatile Component m_service; + private volatile DependencyManager m_manager; + private final Ensure m_stopEnsure; + + public ServiceAspect(Ensure e, Ensure stopEnsure) { + m_ensure = e; + m_stopEnsure = stopEnsure; + } + public void init() { + m_service.add(m_manager.createServiceDependency() + .setService(ServiceInterface2.class) + .setRequired(true) + ); + m_ensure.step(4); + } + + public void invoke(Runnable run) { + m_ensure.step(7); + m_originalService.invoke(run); + m_injectedService.invoke(); + } + + public void stop() { + m_stopEnsure.step(1); + } + } + + static class ServiceConsumer implements Runnable { + private volatile ServiceInterface m_service; + private final Ensure m_ensure; + private final Ensure.Steps m_swapSteps = new Ensure.Steps(5, 11); + + public ServiceConsumer(Ensure e) { + m_ensure = e; + } + + void add(ServiceInterface service) { + m_service = service; + } + + void swap(ServiceInterface oldService, ServiceInterface newService) { + System.out.println("swap: old=" + oldService + ", new=" + newService); + m_ensure.steps(m_swapSteps); + m_service = newService; + } + + public void init() { + Thread t = new Thread(this); + t.start(); + } + + public void run() { + m_ensure.step(1); + m_service.invoke(Ensure.createRunnableStep(m_ensure, 2)); + m_ensure.step(3); + m_ensure.waitForStep(6, 15000); + m_service.invoke(Ensure.createRunnableStep(m_ensure, 8)); + m_ensure.step(10); + m_ensure.waitForStep(12, 15000); + m_service.invoke(Ensure.createRunnableStep(m_ensure, 13)); + } + + public void stop() { + m_ensure.step(); + } + } +} Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyTest.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.dm.lambda.itest; + +import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect; +import static org.apache.felix.dm.lambda.DependencyManagerActivator.component; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; + + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class AspectServiceDependencyTest extends TestBase { + public void testServiceRegistrationAndConsumption() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + // create a service provider and consumer + Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build(); + Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", "remove")).build(); + Component asp = aspect(m, ServiceInterface.class).rank(100).impl(ServiceProviderAspect.class).build(); + + m.add(sp); + m.add(sc); + m.add(asp); + m.remove(asp); + m.remove(sc); + m.remove(sp); + + // ensure we executed all steps inside the component instance + e.step(8); + } + + static interface ServiceInterface { + public void invoke(String caller); + } + + static class ServiceProvider implements ServiceInterface { + private final Ensure m_ensure; + public ServiceProvider(Ensure e) { + m_ensure = e; + } + public void invoke(String caller) { + if (caller.equals("consumer.init")) { + m_ensure.step(3); + } else if (caller.equals("aspect.consumer.add")) { + m_ensure.step(5); + } + } + } + + static class ServiceProviderAspect implements ServiceInterface { + private volatile ServiceInterface m_service; + + public ServiceProviderAspect() { + } + + @Override + public void invoke(String caller) { + m_service.invoke("aspect." + caller); + } + } + + static class ServiceConsumer { + private volatile ServiceInterface m_service; + private final Ensure m_ensure; + private int addCount = 0; + + public ServiceConsumer(Ensure e) { + m_ensure = e; + } + + public void init() { + m_ensure.step(2); + m_service.invoke("consumer.init"); + } + + public void destroy() { + m_ensure.step(7); + } + + public void add(ServiceInterface service) { + m_service = service; + switch (addCount) { + case 0: m_ensure.step(1); + break; + case 1: m_ensure.step(4); + // aspect had been added + m_service.invoke("consumer.add"); + break; + case 2: m_ensure.step(6); + break; + default: + } + addCount ++; + } + public void remove(ServiceInterface service) { + m_service = null; + } + } + +} Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.dm.lambda.itest; + +import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect; +import static org.apache.felix.dm.lambda.DependencyManagerActivator.component; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; + + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class AspectServiceDependencyWithSwapCallbackTest extends TestBase { + public void testServiceRegistrationAndConsumption() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + // create a service provider and consumer + Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build(); + Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", null, "remove", "swap")).build(); + Component asp = aspect(m, ServiceInterface.class).rank(100).impl(ServiceProviderAspect.class).build(); + m.add(sp); + m.add(sc); + m.add(asp); + m.remove(asp); + m.remove(sc); + m.remove(sp); + + // ensure we executed all steps inside the component instance + e.step(7); + } + + public void testServiceRegistrationAndConsumptionRef() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + // create a service provider and consumer + ServiceConsumer scimpl = new ServiceConsumer(e); + Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build(); + Component sc = component(m).impl(scimpl).withSrv(ServiceInterface.class, s->s.cbi(scimpl::add, scimpl::remove).swi(scimpl::swap)).build(); + Component asp = aspect(m, ServiceInterface.class).rank(100).impl(ServiceProviderAspect.class).build(); + m.add(sp); + m.add(sc); + m.add(asp); + m.remove(asp); + m.remove(sc); + m.remove(sp); + + // ensure we executed all steps inside the component instance + e.step(7); + } + + static interface ServiceInterface { + public void invoke(String caller); + } + + static class ServiceProvider implements ServiceInterface { + private final Ensure m_ensure; + public ServiceProvider(Ensure e) { + m_ensure = e; + } + public void invoke(String caller) { + if (caller.equals("consumer.init")) { + m_ensure.step(3); + } else if (caller.equals("aspect.consumer.add")) { + m_ensure.step(5); + } + } + } + + static class ServiceProviderAspect implements ServiceInterface { + private volatile ServiceInterface m_service; + + public ServiceProviderAspect() { + } + + @Override + public void invoke(String caller) { + m_service.invoke("aspect." + caller); + } + } + + static class ServiceConsumer { + private volatile ServiceInterface m_service; + private final Ensure m_ensure; + private int swapCount = 0; + + public ServiceConsumer(Ensure e) { + m_ensure = e; + } + + public void init() { + m_ensure.step(2); + m_service.invoke("consumer.init"); + } + + public void destroy() { + m_ensure.step(6); + } + + public void add(ServiceInterface service) { + m_service = service; + m_ensure.step(1); + } + + public void remove(ServiceInterface service) { + m_service = null; + } + + public void swap(ServiceInterface previous, ServiceInterface current) { + switch (swapCount) { + case 0: m_ensure.step(4); + break; + case 1: m_ensure.step(5); + break; + default: + } + m_service = current; + swapCount ++; + } + } + +} Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWhiteboardTest.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,277 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.dm.lambda.itest; +import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect; +import static org.apache.felix.dm.lambda.DependencyManagerActivator.component; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.junit.Assert; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +@SuppressWarnings({"rawtypes", "unchecked", "unused"}) +public class AspectWhiteboardTest extends TestBase { + + public void testWhiteboardConsumer() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + // create service providers and consumer + Component sp1 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build(); + Component sp2 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build(); + ServiceConsumer sci = new ServiceConsumer(e); + Component sc = component(m).impl(sci).withSrv(ServiceInterface.class, srv->srv.required(false).cb("add", "remove")).build(); + Component sa2 = aspect(m, ServiceInterface.class).rank(20).autoAdd(false).impl(new ServiceAspect(e, 3)).build(); + Component sa1 = aspect(m, ServiceInterface.class).rank(10).autoAdd(false).impl(new ServiceAspect(e, 4)).build(); + + // start with a service consumer + System.out.println("Adding consumer"); + m.add(sc); + + // then add two providers, so the consumer will see two services + System.out.println("Adding 2 providers"); + m.add(sp1); + m.add(sp2); + + // make sure consumer sees both services + Assert.assertEquals(2, sci.services()); + + // add an aspect with ranking 20 + System.out.println("Adding aspect with rank 20"); + m.add(sa2); + + // make sure the consumer sees the two new aspects and no longer sees the two original services + Assert.assertEquals(2, sci.services()); + Assert.assertEquals(20, sci.highestRanking()); + Assert.assertEquals(20, sci.lowestRanking()); + + // add an aspect with ranking 10 + System.out.println("Adding aspect with rank 10"); + m.add(sa1); + + // make sure the consumer still sees the two aspects with ranking 20 + Assert.assertEquals(2, sci.services()); + Assert.assertEquals(20, sci.highestRanking()); + Assert.assertEquals(20, sci.lowestRanking()); + + // remove the aspect with ranking 20 + System.out.println("Removing aspect with rank 20"); + m.remove(sa2); + + // make sure the consumer now sees the aspects with ranking 10 + Assert.assertEquals(2, sci.services()); + Assert.assertEquals(10, sci.highestRanking()); + Assert.assertEquals(10, sci.lowestRanking()); + + // remove one of the original services + System.out.println("Removing 1 service"); + m.remove(sp1); + + // make sure the aspect of that service goes away + Assert.assertEquals(1, sci.services()); + Assert.assertEquals(10, sci.highestRanking()); + Assert.assertEquals(10, sci.lowestRanking()); + + // remove the aspect with ranking 10 + System.out.println("Removing aspect with rank 10"); + m.remove(sa1); + + // make sure only the original service remains + Assert.assertEquals(1, sci.services()); + Assert.assertEquals(0, sci.highestRanking()); + Assert.assertEquals(0, sci.lowestRanking()); + + System.out.println("Done with test"); + + // end of test + m.remove(sa2); + m.remove(sp2); + m.remove(sc); + } + + public void testWhiteboardConsumerRef() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + // create service providers and consumer + Component sp1 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build(); + Component sp2 = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build(); + ServiceConsumer sci = new ServiceConsumer(e); + Component sc = component(m).impl(sci).withSrv(ServiceInterface.class, srv->srv.required(false).cbi(sci::add, sci::remove)).build(); + Component sa2 = aspect(m, ServiceInterface.class).rank(20).autoAdd(false).impl(new ServiceAspect(e, 3)).build(); + Component sa1 = aspect(m, ServiceInterface.class).rank(10).autoAdd(false).impl(new ServiceAspect(e, 4)).build(); + + // start with a service consumer + System.out.println("Adding consumer"); + m.add(sc); + + // then add two providers, so the consumer will see two services + System.out.println("Adding 2 providers"); + m.add(sp1); + m.add(sp2); + + // make sure consumer sees both services + Assert.assertEquals(2, sci.services()); + + // add an aspect with ranking 20 + System.out.println("Adding aspect with rank 20"); + m.add(sa2); + + // make sure the consumer sees the two new aspects and no longer sees the two original services + Assert.assertEquals(2, sci.services()); + Assert.assertEquals(20, sci.highestRanking()); + Assert.assertEquals(20, sci.lowestRanking()); + + // add an aspect with ranking 10 + System.out.println("Adding aspect with rank 10"); + m.add(sa1); + + // make sure the consumer still sees the two aspects with ranking 20 + Assert.assertEquals(2, sci.services()); + Assert.assertEquals(20, sci.highestRanking()); + Assert.assertEquals(20, sci.lowestRanking()); + + // remove the aspect with ranking 20 + System.out.println("Removing aspect with rank 20"); + m.remove(sa2); + + // make sure the consumer now sees the aspects with ranking 10 + Assert.assertEquals(2, sci.services()); + Assert.assertEquals(10, sci.highestRanking()); + Assert.assertEquals(10, sci.lowestRanking()); + + // remove one of the original services + System.out.println("Removing 1 service"); + m.remove(sp1); + + // make sure the aspect of that service goes away + Assert.assertEquals(1, sci.services()); + Assert.assertEquals(10, sci.highestRanking()); + Assert.assertEquals(10, sci.lowestRanking()); + + // remove the aspect with ranking 10 + System.out.println("Removing aspect with rank 10"); + m.remove(sa1); + + // make sure only the original service remains + Assert.assertEquals(1, sci.services()); + Assert.assertEquals(0, sci.highestRanking()); + Assert.assertEquals(0, sci.lowestRanking()); + + System.out.println("Done with test"); + + // end of test + m.remove(sa2); + m.remove(sp2); + m.remove(sc); + } + + static interface ServiceInterface { + public void invoke(Runnable run); + } + + static class ServiceProvider implements ServiceInterface { + private final Ensure m_ensure; + public ServiceProvider(Ensure e) { + m_ensure = e; + } + public void invoke(Runnable run) { + run.run(); + } + } + + static class ServiceAspect implements ServiceInterface { + private final Ensure m_ensure; + private volatile ServiceInterface m_parentService; + private final int m_step; + + public ServiceAspect(Ensure e, int step) { + m_ensure = e; + m_step = step; + } + public void start() { + } + + public void invoke(Runnable run) { + m_ensure.step(m_step); + m_parentService.invoke(run); + } + + public void stop() { + } + } + + static class ServiceConsumer implements Runnable { + private List m_services = new ArrayList(); + private final Ensure m_ensure; + + public ServiceConsumer(Ensure e) { + m_ensure = e; + } + + public void init() { + Thread t = new Thread(this); + t.start(); + } + + public void run() { + } + + public int services() { + return m_services.size(); + } + + public int highestRanking() { + int ranking = Integer.MIN_VALUE; + for (int i = 0; i < m_services.size(); i++) { + ServiceReference ref = (ServiceReference) m_services.get(i); + Integer r = (Integer) ref.getProperty(Constants.SERVICE_RANKING); + int rank = r == null ? 0 : r.intValue(); + ranking = Math.max(ranking, rank); + } + return ranking; + } + public int lowestRanking() { + int ranking = Integer.MAX_VALUE; + for (int i = 0; i < m_services.size(); i++) { + ServiceReference ref = (ServiceReference) m_services.get(i); + Integer r = (Integer) ref.getProperty(Constants.SERVICE_RANKING); + int rank = r == null ? 0 : r.intValue(); + ranking = Math.min(ranking, rank); + } + return ranking; + } + + public void add(ServiceReference ref, ServiceInterface svc) { + System.out.println("Added: " + ServiceUtil.toString(ref)); + m_services.add(ref); + } + public void remove(ServiceReference ref, ServiceInterface svc) { + System.out.println("Removed: " + ServiceUtil.toString(ref)); + m_services.remove(ref); + } + } +} Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/AspectWithCallbacksServiceDependencyTest.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,198 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.dm.lambda.itest; + +import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect; +import static org.apache.felix.dm.lambda.DependencyManagerActivator.component; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; + + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class AspectWithCallbacksServiceDependencyTest extends TestBase { + public void testServiceRegistrationAndConsumption() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + // create a service provider and consumer + Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build(); + Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", "remove")).build(); + Component asp = aspect(m, ServiceInterface.class).rank(100).cb("add", null, "remove", "swap").impl(ServiceProviderAspect.class).build(); + + m.add(sp); + m.add(sc); + m.add(asp); + m.remove(asp); + m.remove(sc); + m.remove(sp); + + // ensure we executed all steps inside the component instance + e.step(8); + } + + public void testServiceRegistrationAndConsumptionRef() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + // create a service provider and consumer + Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build(); + Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb(ServiceConsumer::add, ServiceConsumer::remove)).build(); + Component asp = aspect(m, ServiceInterface.class) + .impl(ServiceProviderAspect.class).rank(100) + .cb(ServiceProviderAspect::add, ServiceProviderAspect::remove).sw(ServiceProviderAspect::swap) + .build(); + + m.add(sp); + m.add(sc); + m.add(asp); + m.remove(asp); + m.remove(sc); + m.remove(sp); + + // ensure we executed all steps inside the component instance + e.step(8); + } + + public void testServiceRegistrationAndConsumptionWithAspectCallbackInstance() { + DependencyManager m = getDM(); + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + // create a service provider and consumer + Component sp = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build(); + Component sc = component(m).impl(new ServiceConsumer(e)).withSrv(ServiceInterface.class, s->s.cb("add", "remove")).build(); + + ServiceProviderAspect providerAspect = new ServiceProviderAspect(); + ServiceProviderAspectCallbackInstance aspectCb = new ServiceProviderAspectCallbackInstance(providerAspect); + Component asp = aspect(m, ServiceInterface.class).rank(100).impl(providerAspect).cbi(aspectCb::add, aspectCb::remove).swi(aspectCb::swap).build(); + + m.add(sp); + m.add(sc); + m.add(asp); + m.remove(asp); + m.remove(sc); + m.remove(sp); + + // ensure we executed all steps inside the component instance + e.step(8); + } + + static interface ServiceInterface { + public void invoke(String caller); + } + + static class ServiceProvider implements ServiceInterface { + private final Ensure m_ensure; + public ServiceProvider(Ensure e) { + m_ensure = e; + } + public void invoke(String caller) { + if (caller.equals("consumer.init")) { + m_ensure.step(3); + } else if (caller.equals("aspect.consumer.add")) { + m_ensure.step(5); + } + } + } + + public static class ServiceProviderAspectCallbackInstance { + private final ServiceProviderAspect m_aspect; + + ServiceProviderAspectCallbackInstance(ServiceProviderAspect aspect) { + m_aspect = aspect; + } + + public void add(ServiceInterface service) { + m_aspect.add(service); + } + + public void remove(ServiceInterface service) { + m_aspect.remove(service); + } + + public void swap(ServiceInterface previous, ServiceInterface current) { + m_aspect.swap(previous, current); + } + } + + static class ServiceProviderAspect implements ServiceInterface { + private volatile ServiceInterface m_service; + + public ServiceProviderAspect() { + } + + @Override + public void invoke(String caller) { + m_service.invoke("aspect." + caller); + } + + public void add(ServiceInterface service) { + m_service = service; + } + + public void remove(ServiceInterface service) { + m_service = null; + } + + public void swap(ServiceInterface previous, ServiceInterface current) { + m_service = current; + } + } + + static class ServiceConsumer { + private volatile ServiceInterface m_service; + private final Ensure m_ensure; + private int addCount = 0; + + public ServiceConsumer(Ensure e) { + m_ensure = e; + } + + public void init() { + m_ensure.step(2); + m_service.invoke("consumer.init"); + } + + public void destroy() { + m_ensure.step(7); + } + + public void add(ServiceInterface service) { + m_service = service; + switch (addCount) { + case 0: m_ensure.step(1); + break; + case 1: m_ensure.step(4); + // aspect had been added + m_service.invoke("consumer.add"); + break; + case 2: m_ensure.step(6); + break; + default: + } + addCount ++; + } + public void remove(ServiceInterface service) { + m_service = null; + } + } + +}
