Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectBaseTest.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/AspectBaseTest.java?rev=1724333&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectBaseTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectBaseTest.java Tue Jan 12 22:45:36 2016 @@ -0,0 +1,362 @@ +/* + * 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.REM; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.aspect; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.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, comp -> comp + .autoAdd(false).impl(p).provides(ServiceInterface.class).properties(name -> "a")); + + Component sc = component(m, comp -> comp + .autoAdd(false).impl(c).withService(ServiceInterface.class, srv -> srv.cb("add", "remove").autoConfig("m_service"))); + + Component sa = aspect(m, ServiceInterface.class, asp -> asp.autoAdd(false).rank(20).impl(ServiceAspect.class)); + + 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, comp -> comp + .autoAdd(false).impl(p).provides(ServiceInterface.class).properties(name -> "a")); + + Component sc = component(m, comp -> comp + .autoAdd(false).impl(c).withService(ServiceInterface.class, srv -> srv.cbi(ADD, c::add).cbi(REM, c::remove).autoConfig("m_service"))); + + Component sa = aspect(m, ServiceInterface.class, asp -> asp.autoAdd(false).rank(20).impl(ServiceAspect.class)); + + 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, comp -> comp + .autoAdd(false).impl(p).provides(ServiceInterface.class).properties(name -> "a")); + + Component sc = component(m, comp -> comp + .autoAdd(false).impl(c).withService(ServiceInterface.class, srv -> srv.cb("add", "remove").autoConfig("m_service"))); + + Component sa = aspect(m, ServiceInterface.class, asp -> asp + .autoAdd(false).rank(20).impl(ServiceAspect.class)); + + // 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, comp -> comp + .autoAdd(false).impl(p).provides(ServiceInterface.class).properties(name -> "a")); + + Component sc = component(m, comp -> comp + .autoAdd(false).impl(c).withService(ServiceInterface.class, srv -> srv.cbi(ADD, c::add).cbi(REM, c::remove).autoConfig("m_service"))); + + Component sa = aspect(m, ServiceInterface.class, asp -> asp + .autoAdd(false).rank(20).impl(ServiceAspect.class)); + + // 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, comp -> comp + .autoAdd(false).impl(new ServiceProvider(e, "a")).provides(ServiceInterface.class).properties(name -> "a")); + Component sp2 = component(m, comp -> comp + .autoAdd(false).impl(new ServiceProvider(e, "b")).provides(ServiceInterface.class).properties(name -> "b")); + Component sc = component(m, comp -> comp + .autoAdd(false).impl(c).withService(ServiceInterface.class, srv -> srv.cb("add", "remove"))); + + Component sa = aspect(m, ServiceInterface.class, asp -> asp.rank(20).impl(ServiceAspect.class)); + Component sa2 = aspect(m, ServiceInterface.class, asp -> asp.rank(10).impl(ServiceAspect.class)); + + 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, comp -> comp + .autoAdd(false).impl(new ServiceProvider(e, "a")).provides(ServiceInterface.class).properties(name -> "a")); + Component sp2 = component(m, comp -> comp + .autoAdd(false).impl(new ServiceProvider(e, "b")).provides(ServiceInterface.class).properties(name -> "b")); + Component sc = component(m, comp -> comp + .autoAdd(false).impl(c).withService(ServiceInterface.class, srv -> srv.cbi(ADD, c::add).cbi(REM, c::remove))); + + Component sa = aspect(m, ServiceInterface.class, asp -> asp.rank(20).impl(ServiceAspect.class)); + Component sa2 = aspect(m, ServiceInterface.class, asp -> asp.rank(10).impl(ServiceAspect.class)); + + 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/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectChainTest.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/AspectChainTest.java?rev=1724333&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectChainTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectChainTest.java Tue Jan 12 22:45:36 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.builder.lambda.itest; + +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.aspect; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.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, c -> c.impl(new ServiceProvider(e)).provides(ServiceInterface.class)); + Component sc = component(m, c -> c.impl(new ServiceConsumer(e)).withService(ServiceInterface.class)); + Component sa2 = aspect(m, ServiceInterface.class, a -> a.rank(20).impl(new ServiceAspect(e, 3))); + Component sa3 = aspect(m, ServiceInterface.class, a -> a.rank(30).impl(new ServiceAspect(e, 2))); + Component sa1 = aspect(m, ServiceInterface.class, a -> a.rank(10).impl(new ServiceAspect(e, 4))); + 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/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectDynamicsTest.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/AspectDynamicsTest.java?rev=1724333&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectDynamicsTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectDynamicsTest.java Tue Jan 12 22:45:36 2016 @@ -0,0 +1,253 @@ +/* + * 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.DependencyActivatorBase.aspect; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.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, c->c.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName())); + Component provider2 = component(m, c->c.autoAdd(false).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class.getName())); + Component consumer = component(m, c->c.autoAdd(false).impl(new ServiceConsumer(e)).withService(ServiceInterface.class, s->s.cb("add", null, null, "swap"))); + Component aspect = aspect(m, ServiceInterface.class, a->a.autoAdd(false).rank(1).impl(new ServiceAspect(e, aspectStopEnsure))); + + 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, c->c.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName())); + Component provider2 = component(m, c->c.autoAdd(false).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class.getName())); + Component consumer = component(m, c->c.autoAdd(false).impl(new ServiceConsumer(e)).withService(ServiceInterface.class, s->s.cb(ADD, ServiceConsumer::add).sw(ServiceConsumer::swap))); + Component aspect = aspect(m, ServiceInterface.class, a->a.autoAdd(false).rank(1).impl(new ServiceAspect(e, aspectStopEnsure))); + + 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/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectServiceDependencyTest.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/AspectServiceDependencyTest.java?rev=1724333&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectServiceDependencyTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectServiceDependencyTest.java Tue Jan 12 22:45:36 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.builder.lambda.itest; + +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.aspect; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.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, c->c.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName())); + Component sc = component(m, c->c.autoAdd(false).impl(new ServiceConsumer(e)).withService(ServiceInterface.class, s->s.cb("add", "remove"))); + Component asp = aspect(m, ServiceInterface.class, a->a.autoAdd(false).rank(100).impl(ServiceProviderAspect.class)); + + 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/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.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/AspectServiceDependencyWithSwapCallbackTest.java?rev=1724333&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectServiceDependencyWithSwapCallbackTest.java Tue Jan 12 22:45:36 2016 @@ -0,0 +1,143 @@ +/* + * 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.REM; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.aspect; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.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, c->c.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class)); + Component sc = component(m, c->c.autoAdd(false).impl(new ServiceConsumer(e)).withService(ServiceInterface.class, s->s.cb("add", null, "remove", "swap"))); + Component asp = aspect(m, ServiceInterface.class, a->a.autoAdd(false).rank(100).impl(ServiceProviderAspect.class)); + 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, c->c.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class)); + Component sc = component(m, c->c.autoAdd(false).impl(scimpl).withService(ServiceInterface.class, s->s.cbi(ADD, scimpl::add).cbi(REM, scimpl::remove).swi(scimpl::swap))); + Component asp = aspect(m, ServiceInterface.class, a->a.autoAdd(false).rank(100).impl(ServiceProviderAspect.class)); + 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/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectWhiteboardTest.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/AspectWhiteboardTest.java?rev=1724333&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectWhiteboardTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectWhiteboardTest.java Tue Jan 12 22:45:36 2016 @@ -0,0 +1,279 @@ +/* + * 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.REM; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.aspect; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.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, s->s.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName())); + Component sp2 = component(m, s->s.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName())); + ServiceConsumer sci = new ServiceConsumer(e); + Component sc = component(m, s->s.autoAdd(false).impl(sci).withService(ServiceInterface.class, srv->srv.required(false).cb("add", "remove"))); + Component sa2 = aspect(m, ServiceInterface.class, a->a.rank(20).autoAdd(false).impl(new ServiceAspect(e, 3))); + Component sa1 = aspect(m, ServiceInterface.class, a->a.rank(10).autoAdd(false).impl(new ServiceAspect(e, 4))); + + // 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, s->s.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName())); + Component sp2 = component(m, s->s.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName())); + ServiceConsumer sci = new ServiceConsumer(e); + Component sc = component(m, s->s.autoAdd(false).impl(sci).withService(ServiceInterface.class, srv->srv.required(false).cbi(ADD, sci::add).cbi(REM, sci::remove))); + Component sa2 = aspect(m, ServiceInterface.class, a->a.rank(20).autoAdd(false).impl(new ServiceAspect(e, 3))); + Component sa1 = aspect(m, ServiceInterface.class, a->a.rank(10).autoAdd(false).impl(new ServiceAspect(e, 4))); + + // 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/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectWithCallbacksServiceDependencyTest.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/AspectWithCallbacksServiceDependencyTest.java?rev=1724333&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectWithCallbacksServiceDependencyTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/AspectWithCallbacksServiceDependencyTest.java Tue Jan 12 22:45:36 2016 @@ -0,0 +1,199 @@ +/* + * 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.REM; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.aspect; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.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, c->c.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName())); + Component sc = component(m, c->c.autoAdd(false).impl(new ServiceConsumer(e)).withService(ServiceInterface.class, s->s.cb("add", "remove"))); + Component asp = aspect(m, ServiceInterface.class, a->a.autoAdd(false).rank(100).cb("add", null, "remove", "swap").impl(ServiceProviderAspect.class)); + + 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, c->c.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName())); + Component sc = component(m, c->c.autoAdd(false).impl(new ServiceConsumer(e)) + .withService(ServiceInterface.class, s->s.cb(ADD, ServiceConsumer::add).cb(REM, ServiceConsumer::remove))); + Component asp = aspect(m, ServiceInterface.class, a->a.autoAdd(false).impl(ServiceProviderAspect.class).rank(100) + .cb(ADD, ServiceProviderAspect::add).cb(REM, ServiceProviderAspect::remove).sw(ServiceProviderAspect::swap)); + + 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, c->c.autoAdd(false).impl(new ServiceProvider(e)).provides(ServiceInterface.class)); + Component sc = component(m, c->c.autoAdd(false).impl(new ServiceConsumer(e)).withService(ServiceInterface.class, s->s.cb("add", "remove"))); + + ServiceProviderAspect providerAspect = new ServiceProviderAspect(); + ServiceProviderAspectCallbackInstance aspectCb = new ServiceProviderAspectCallbackInstance(providerAspect); + Component asp = aspect(m, ServiceInterface.class, a->a.autoAdd(false).rank(100).impl(providerAspect) + .cbi(ADD, aspectCb::add).cbi(REM,aspectCb::remove).swi(aspectCb::swap)); + 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; + } + } + +}
