This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.testing.osgi-mock-1.1.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-osgi-mock.git
commit 59f74f698a3683ce4270f6c6effc275005325808 Author: Stefan Seifert <[email protected]> AuthorDate: Fri Nov 7 00:08:14 2014 +0000 SLING-4142 MockOsgi: Activate/Deactivate method does not support different signatures git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/testing/mocks/osgi-mock@1637273 13f79535-47bb-0310-9956-ffa450edef68 --- .../testing/mock/osgi/ReflectionServiceUtil.java | 112 +++++++- ...eflectionServiceUtilActivateDeactivateTest.java | 285 +++++++++++++++++++++ ...ReflectionServiceUtilActivateDeactivateTest.xml | 21 ++ 3 files changed, 405 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/ReflectionServiceUtil.java b/src/main/java/org/apache/sling/testing/mock/osgi/ReflectionServiceUtil.java index fe363ab..1ee8370 100644 --- a/src/main/java/org/apache/sling/testing/mock/osgi/ReflectionServiceUtil.java +++ b/src/main/java/org/apache/sling/testing/mock/osgi/ReflectionServiceUtil.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.Reference; @@ -70,24 +71,78 @@ final class ReflectionServiceUtil { return false; } - // if method is defined try to execute it + // try to find matchin activate/deactivate method and execute it + + // 1. componentContext Method method = getMethod(targetClass, methodName, new Class<?>[] { ComponentContext.class }, activate); if (method != null) { - try { - method.setAccessible(true); - method.invoke(target, componentContext); + invokeMethod(target, method, new Object[] { componentContext }); + return true; + } + + // 2. bundleContext + method = getMethod(targetClass, methodName, new Class<?>[] { BundleContext.class }, activate); + if (method != null) { + invokeMethod(target, method, new Object[] { componentContext.getBundleContext() }); + return true; + } + + // 3. map + method = getMethod(targetClass, methodName, new Class<?>[] { Map.class }, activate); + if (method != null) { + invokeMethod(target, method, new Object[] { componentContext.getProperties() }); + return true; + } + + // 4. int (deactivation only) + if (!activate) { + method = getMethod(targetClass, methodName, new Class<?>[] { int.class }, activate); + if (method != null) { + invokeMethod(target, method, new Object[] { 0 }); + return true; + } + } + + // 5. Integer (deactivation only) + if (!activate) { + method = getMethod(targetClass, methodName, new Class<?>[] { Integer.class }, activate); + if (method != null) { + invokeMethod(target, method, new Object[] { 0 }); return true; - } catch (IllegalAccessException ex) { - throw new RuntimeException("Unable to invoke activate/deactivate method for class " - + targetClass.getName(), ex); - } catch (IllegalArgumentException ex) { - throw new RuntimeException("Unable to invoke activate/deactivate method for class " - + targetClass.getName(), ex); - } catch (InvocationTargetException ex) { - throw new RuntimeException("Unable to invoke activate/deactivate method for class " - + targetClass.getName(), ex.getCause()); } } + + // 6. mixed arguments of componentContext, bundleContext and map + Class<?>[] mixedArgsAllowed = activate ? new Class<?>[] { ComponentContext.class, BundleContext.class, Map.class } + : new Class<?>[] { ComponentContext.class, BundleContext.class, Map.class, int.class, Integer.class }; + method = getMethodWithAnyCombinationArgs(targetClass, methodName, mixedArgsAllowed, activate); + if (method != null) { + Object[] args = new Object[method.getParameterTypes().length]; + for (int i=0; i<args.length; i++) { + if (method.getParameterTypes()[i] == ComponentContext.class) { + args[i] = componentContext; + } + else if (method.getParameterTypes()[i] == BundleContext.class) { + args[i] = componentContext.getBundleContext(); + } + else if (method.getParameterTypes()[i] == Map.class) { + args[i] = componentContext.getProperties(); + } + else if (method.getParameterTypes()[i] == int.class || method.getParameterTypes()[i] == Integer.class) { + args[i] = 0; + } + } + invokeMethod(target, method, args); + return true; + } + + // 7. noargs + method = getMethod(targetClass, methodName, new Class<?>[0], activate); + if (method != null) { + invokeMethod(target, method, new Object[0]); + return true; + } + log.warn("Method {}(ComponentContext) not found in class {}", methodName, targetClass.getName()); return false; } @@ -102,6 +157,37 @@ final class ReflectionServiceUtil { } return null; } + + private static Method getMethodWithAnyCombinationArgs(Class clazz, String methodName, Class<?>[] types, boolean activate) { + Method[] methods = clazz.getDeclaredMethods(); + for (Method method : methods) { + if (StringUtils.equals(method.getName(), methodName) && method.getParameterTypes().length > 1) { + for (Class<?> parameterType : method.getParameterTypes()) { + if (!ArrayUtils.contains(types, parameterType)) { + return null; + } + } + return method; + } + } + return null; + } + + private static void invokeMethod(Object target, Method method, Object[] args) { + try { + method.setAccessible(true); + method.invoke(target, args); + } catch (IllegalAccessException ex) { + throw new RuntimeException("Unable to invoke activate/deactivate method for class " + + target.getClass().getName(), ex); + } catch (IllegalArgumentException ex) { + throw new RuntimeException("Unable to invoke activate/deactivate method for class " + + target.getClass().getName(), ex); + } catch (InvocationTargetException ex) { + throw new RuntimeException("Unable to invoke activate/deactivate method for class " + + target.getClass().getName(), ex.getCause()); + } + } /** * Simulate OSGi service dependency injection. Injects direct references and diff --git a/src/test/java/org/apache/sling/testing/mock/osgi/ReflectionServiceUtilActivateDeactivateTest.java b/src/test/java/org/apache/sling/testing/mock/osgi/ReflectionServiceUtilActivateDeactivateTest.java new file mode 100644 index 0000000..36cf88e --- /dev/null +++ b/src/test/java/org/apache/sling/testing/mock/osgi/ReflectionServiceUtilActivateDeactivateTest.java @@ -0,0 +1,285 @@ +/* + * 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.sling.testing.mock.osgi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +import com.google.common.collect.ImmutableMap; + +/** + * Test different variants of activate/deactivate methods with varying signatures. + */ +public class ReflectionServiceUtilActivateDeactivateTest { + + private Map<String,Object> map = ImmutableMap.<String, Object>of("prop1", "value1"); + private BundleContext bundleContext = MockOsgi.newBundleContext(); + + @Test + public void testService1() { + Service1 service = new Service1(); + + assertTrue(MockOsgi.activate(service, bundleContext, map)); + assertTrue(service.isActivated()); + assertSame(bundleContext, service.getComponentContext().getBundleContext()); + + assertTrue(MockOsgi.deactivate(service, bundleContext, map)); + assertFalse(service.isActivated()); + } + + @Test + public void testService2() { + Service2 service = new Service2(); + + assertTrue(MockOsgi.activate(service, bundleContext, map)); + assertTrue(service.isActivated()); + assertSame(bundleContext, service.getBundleContext()); + + assertTrue(MockOsgi.deactivate(service, bundleContext, map)); + assertFalse(service.isActivated()); + } + + @Test + public void testService3() { + Service3 service = new Service3(); + + assertTrue(MockOsgi.activate(service, bundleContext, map)); + assertTrue(service.isActivated()); + assertEquals(map, ImmutableMap.copyOf(service.getMap())); + + assertTrue(MockOsgi.deactivate(service, bundleContext, map)); + assertFalse(service.isActivated()); + } + + @Test + public void testService4() { + Service4 service = new Service4(); + + assertTrue(MockOsgi.activate(service, bundleContext, map)); + assertTrue(service.isActivated()); + + assertTrue(MockOsgi.deactivate(service, bundleContext, map)); + assertFalse(service.isActivated()); + } + + @Test + public void testService5() { + Service5 service = new Service5(); + + assertTrue(MockOsgi.activate(service, bundleContext, map)); + assertTrue(service.isActivated()); + + assertTrue(MockOsgi.deactivate(service, bundleContext, map)); + assertFalse(service.isActivated()); + } + + @Test + public void testService6() { + Service6 service = new Service6(); + + assertTrue(MockOsgi.activate(service, bundleContext, map)); + assertTrue(service.isActivated()); + assertSame(bundleContext, service.getComponentContext().getBundleContext()); + assertSame(bundleContext, service.getBundleContext()); + assertEquals(map, ImmutableMap.copyOf(service.getMap())); + + assertTrue(MockOsgi.deactivate(service, bundleContext, map)); + assertFalse(service.isActivated()); + } + + @Component + public static class Service1 { + + private boolean activated; + private ComponentContext componentContext; + + @Activate + private void activate(ComponentContext ctx) { + this.activated = true; + this.componentContext = ctx; + } + + @Deactivate + private void deactivate(ComponentContext ctx) { + this.activated = false; + this.componentContext = null; + } + + public boolean isActivated() { + return activated; + } + + public ComponentContext getComponentContext() { + return componentContext; + } + + } + + @Component + public static class Service2 { + + private boolean activated; + private BundleContext bundleContext; + + @Activate + private void activate(BundleContext ctx) { + this.activated = true; + this.bundleContext = ctx; + } + + @Deactivate + private void deactivate(BundleContext ctx) { + this.activated = false; + this.bundleContext = null; + } + + public boolean isActivated() { + return activated; + } + + public BundleContext getBundleContext() { + return bundleContext; + } + + } + + @Component + public static class Service3 { + + private boolean activated; + private Map<String, Object> map; + + @Activate + private void activate(Map<String,Object> map) { + this.activated = true; + this.map = map; + } + + @Deactivate + private void deactivate(Map<String,Object> map) { + this.activated = false; + this.map = null; + } + + public boolean isActivated() { + return activated; + } + + public Map<String, Object> getMap() { + return map; + } + + } + + @Component + public static class Service4 { + + private boolean activated; + + @Activate + private void activate() { + this.activated = true; + } + + @Deactivate + private void deactivate(int value) { + this.activated = false; + } + + public boolean isActivated() { + return activated; + } + + } + + @Component + public static class Service5 { + + private boolean activated; + + @Activate + private void activate() { + this.activated = true; + } + + @Deactivate + private void deactivate(Integer value) { + this.activated = false; + } + + public boolean isActivated() { + return activated; + } + + } + + @Component + public static class Service6 { + + private boolean activated; + private ComponentContext componentContext; + private BundleContext bundleContext; + private Map<String,Object> map; + + @Activate + private void activate(ComponentContext componentContext, BundleContext bundleContext, Map<String,Object> map) { + this.activated = true; + this.componentContext = componentContext; + this.bundleContext = bundleContext; + this.map = map; + } + + @Deactivate + private void deactivate(Map<String,Object> map, BundleContext bundleContext, int value1, Integer value2) { + this.activated = false; + this.componentContext = null; + this.bundleContext = null; + this.map = null; + } + + public boolean isActivated() { + return activated; + } + + public ComponentContext getComponentContext() { + return componentContext; + } + + public BundleContext getBundleContext() { + return bundleContext; + } + + public Map<String, Object> getMap() { + return map; + } + + } + +} diff --git a/src/test/resources/OSGI-INF/org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest.xml b/src/test/resources/OSGI-INF/org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest.xml new file mode 100644 index 0000000..23c4585 --- /dev/null +++ b/src/test/resources/OSGI-INF/org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"> + <scr:component name="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service1" activate="activate" deactivate="deactivate"> + <implementation class="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service1"/> + </scr:component> + <scr:component name="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service2" activate="activate" deactivate="deactivate"> + <implementation class="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service2"/> + </scr:component> + <scr:component name="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service3" activate="activate" deactivate="deactivate"> + <implementation class="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service3"/> + </scr:component> + <scr:component name="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service4" activate="activate" deactivate="deactivate"> + <implementation class="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service4"/> + </scr:component> + <scr:component name="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service5" activate="activate" deactivate="deactivate"> + <implementation class="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service5"/> + </scr:component> + <scr:component name="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service6" activate="activate" deactivate="deactivate"> + <implementation class="org.apache.sling.testing.mock.osgi.ReflectionServiceUtilActivateDeactivateTest$Service6"/> + </scr:component> +</components> -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
