Author: sseifert Date: Fri Feb 20 00:17:52 2015 New Revision: 1661038 URL: http://svn.apache.org/r1661038 Log: SLING-4439 implement dynamic service registration - support string array properties in osgi metadata as well - merge properties from osgi metadata with those specified on activation/registration call - support "old-style" scr component metadata file as well (and test this case)
Modified: sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MapUtil.java sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MockOsgi.java sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java sling/trunk/testing/mocks/osgi-mock/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java sling/trunk/testing/mocks/osgi-mock/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java sling/trunk/testing/mocks/osgi-mock/src/test/resources/OSGI-INF/serviceComponents.xml Modified: sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MapUtil.java URL: http://svn.apache.org/viewvc/sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MapUtil.java?rev=1661038&r1=1661037&r2=1661038&view=diff ============================================================================== --- sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MapUtil.java (original) +++ sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MapUtil.java Fri Feb 20 00:17:52 2015 @@ -24,6 +24,8 @@ import java.util.HashMap; import java.util.Hashtable; import java.util.Map; +import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.OsgiMetadata; + /** * Map util methods. */ @@ -49,4 +51,40 @@ final class MapUtil { return map; } + public static Dictionary<String, Object> propertiesMergeWithOsgiMetadata(Object target, Dictionary<String, Object> properties) { + Dictionary<String, Object> mergedProperties = new Hashtable<String, Object>(); + + OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(target.getClass()); + if (metadata != null && metadata.getProperties() != null) { + for (Map.Entry<String, Object> entry : metadata.getProperties().entrySet()) { + mergedProperties.put(entry.getKey(), entry.getValue()); + } + } + + if (properties != null) { + Enumeration<String> keys = properties.keys(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); + mergedProperties.put(key, properties.get(key)); + } + } + + return mergedProperties; + } + + public static Map<String, Object> propertiesMergeWithOsgiMetadata(Object target, Map<String, Object> properties) { + Map<String, Object> mergedProperties = new HashMap<String, Object>(); + + OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(target.getClass()); + if (metadata != null && metadata.getProperties() != null) { + mergedProperties.putAll(metadata.getProperties()); + } + + if (properties != null) { + mergedProperties.putAll(properties); + } + + return mergedProperties; + } + } Modified: sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java URL: http://svn.apache.org/viewvc/sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java?rev=1661038&r1=1661037&r2=1661038&view=diff ============================================================================== --- sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java (original) +++ sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java Fri Feb 20 00:17:52 2015 @@ -81,7 +81,8 @@ class MockBundleContext implements Bundl @SuppressWarnings("unchecked") @Override public ServiceRegistration registerService(final String[] clazzes, final Object service, final Dictionary properties) { - MockServiceRegistration registration = new MockServiceRegistration(this.bundle, clazzes, service, properties, this); + Dictionary<String, Object> mergedPropertes = MapUtil.propertiesMergeWithOsgiMetadata(service, properties); + MockServiceRegistration registration = new MockServiceRegistration(this.bundle, clazzes, service, mergedPropertes, this); handleRefsUpdateOnRegister(registration); this.registeredServices.add(registration); notifyServiceListeners(ServiceEvent.REGISTERED, registration.getReference()); Modified: sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MockOsgi.java URL: http://svn.apache.org/viewvc/sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MockOsgi.java?rev=1661038&r1=1661037&r2=1661038&view=diff ============================================================================== --- sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MockOsgi.java (original) +++ sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/MockOsgi.java Fri Feb 20 00:17:52 2015 @@ -18,6 +18,10 @@ */ package org.apache.sling.testing.mock.osgi; +import static org.apache.sling.testing.mock.osgi.MapUtil.propertiesMergeWithOsgiMetadata; +import static org.apache.sling.testing.mock.osgi.MapUtil.toDictionary; +import static org.apache.sling.testing.mock.osgi.MapUtil.toMap; + import java.util.Dictionary; import java.util.Map; @@ -72,7 +76,7 @@ public final class MockOsgi { * @return Mocked {@link ComponentContext} instance */ public static ComponentContext newComponentContext(Map<String, Object> properties) { - return newComponentContext(MapUtil.toDictionary(properties)); + return newComponentContext(toDictionary(properties)); } /** @@ -91,7 +95,7 @@ public final class MockOsgi { * @return Mocked {@link ComponentContext} instance */ public static ComponentContext newComponentContext(BundleContext bundleContext, Map<String, Object> properties) { - return newComponentContext(bundleContext, MapUtil.toDictionary(properties)); + return newComponentContext(bundleContext, toDictionary(properties)); } /** @@ -120,8 +124,7 @@ public final class MockOsgi { * @return true if activation method was called. False if no activate method is defined. */ public static boolean activate(Object target) { - ComponentContext componentContext = newComponentContext(); - return OsgiServiceUtil.activateDeactivate(target, componentContext, true); + return MockOsgi.activate(target, (Dictionary<String, Object>)null); } /** @@ -131,7 +134,8 @@ public final class MockOsgi { * @return true if activation method was called. False if no activate method is defined. */ public static boolean activate(Object target, Dictionary<String, Object> properties) { - ComponentContext componentContext = newComponentContext(properties); + Dictionary<String, Object> mergedProperties = propertiesMergeWithOsgiMetadata(target, properties); + ComponentContext componentContext = newComponentContext(mergedProperties); return OsgiServiceUtil.activateDeactivate(target, componentContext, true); } @@ -142,7 +146,7 @@ public final class MockOsgi { * @return true if activation method was called. False if no activate method is defined. */ public static boolean activate(Object target, Map<String, Object> properties) { - return activate(target, MapUtil.toDictionary(properties)); + return activate(target, toDictionary(properties)); } /** @@ -153,7 +157,8 @@ public final class MockOsgi { * @return true if activation method was called. False if no activate method is defined. */ public static boolean activate(Object target, BundleContext bundleContext, Dictionary<String, Object> properties) { - ComponentContext componentContext = newComponentContext(bundleContext, properties); + Dictionary<String, Object> mergedProperties = propertiesMergeWithOsgiMetadata(target, properties); + ComponentContext componentContext = newComponentContext(bundleContext, mergedProperties); return OsgiServiceUtil.activateDeactivate(target, componentContext, true); } @@ -165,7 +170,7 @@ public final class MockOsgi { * @return true if activation method was called. False if no activate method is defined. */ public static boolean activate(Object target, BundleContext bundleContext, Map<String, Object> properties) { - return activate(target, bundleContext, MapUtil.toDictionary(properties)); + return activate(target, bundleContext, toDictionary(properties)); } /** @@ -174,8 +179,7 @@ public final class MockOsgi { * @return true if deactivation method was called. False if no deactivate method is defined. */ public static boolean deactivate(Object target) { - ComponentContext componentContext = newComponentContext(); - return OsgiServiceUtil.activateDeactivate(target, componentContext, false); + return MockOsgi.deactivate(target, (Dictionary<String, Object>)null); } /** @@ -185,7 +189,8 @@ public final class MockOsgi { * @return true if deactivation method was called. False if no deactivate method is defined. */ public static boolean deactivate(Object target, Dictionary<String, Object> properties) { - ComponentContext componentContext = newComponentContext(properties); + Dictionary<String, Object> mergedProperties = propertiesMergeWithOsgiMetadata(target, properties); + ComponentContext componentContext = newComponentContext(mergedProperties); return OsgiServiceUtil.activateDeactivate(target, componentContext, false); } @@ -196,7 +201,7 @@ public final class MockOsgi { * @return true if deactivation method was called. False if no deactivate method is defined. */ public static boolean deactivate(Object target, Map<String, Object> properties) { - return deactivate(target, MapUtil.toDictionary(properties)); + return deactivate(target, toDictionary(properties)); } /** @@ -207,7 +212,8 @@ public final class MockOsgi { * @return true if deactivation method was called. False if no deactivate method is defined. */ public static boolean deactivate(Object target, BundleContext bundleContext, Dictionary<String, Object> properties) { - ComponentContext componentContext = newComponentContext(bundleContext, properties); + Dictionary<String, Object> mergedProperties = propertiesMergeWithOsgiMetadata(target, properties); + ComponentContext componentContext = newComponentContext(bundleContext, mergedProperties); return OsgiServiceUtil.activateDeactivate(target, componentContext, false); } @@ -219,7 +225,7 @@ public final class MockOsgi { * @return true if deactivation method was called. False if no deactivate method is defined. */ public static boolean deactivate(Object target, BundleContext bundleContext, Map<String, Object> properties) { - return deactivate(target, bundleContext, MapUtil.toDictionary(properties)); + return deactivate(target, bundleContext, toDictionary(properties)); } /** @@ -230,7 +236,7 @@ public final class MockOsgi { * @return true if modified method was called. False if no modified method is defined. */ public static boolean modified(Object target, BundleContext bundleContext, Dictionary<String, Object> properties) { - return modified(target, bundleContext, MapUtil.toMap(properties)); + return modified(target, bundleContext, toMap(properties)); } /** @@ -241,7 +247,8 @@ public final class MockOsgi { * @return true if modified method was called. False if no modified method is defined. */ public static boolean modified(Object target, BundleContext bundleContext, Map<String, Object> properties) { - return OsgiServiceUtil.modified(target, bundleContext, properties); + Map<String, Object> mergedProperties = propertiesMergeWithOsgiMetadata(target, properties); + return OsgiServiceUtil.modified(target, bundleContext, mergedProperties); } } Modified: sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java URL: http://svn.apache.org/viewvc/sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java?rev=1661038&r1=1661037&r2=1661038&view=diff ============================================================================== --- sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java (original) +++ sling/trunk/testing/mocks/osgi-mock/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java Fri Feb 20 00:17:52 2015 @@ -238,6 +238,19 @@ final class OsgiMetadataUtil { } } } + query = "/components/component[@name='" + clazz.getName() + "']/property[@name!='' and text()!='']"; + nodes = queryNodes(metadata, query); + if (nodes != null) { + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + String name = getAttributeValue(node, "name"); + String[] value = StringUtils.split(StringUtils.trim(node.getTextContent()), "\n\r"); + for (int j = 0; j<value.length; j++) { + value[j] = StringUtils.trim(value[j]); + } + props.put(name, value); + } + } return props; } Modified: sling/trunk/testing/mocks/osgi-mock/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java URL: http://svn.apache.org/viewvc/sling/trunk/testing/mocks/osgi-mock/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java?rev=1661038&r1=1661037&r2=1661038&view=diff ============================================================================== --- sling/trunk/testing/mocks/osgi-mock/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java (original) +++ sling/trunk/testing/mocks/osgi-mock/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java Fri Feb 20 00:17:52 2015 @@ -18,6 +18,7 @@ */ package org.apache.sling.testing.mock.osgi; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -45,10 +46,12 @@ public class OsgiMetadataUtilTest { assertTrue(serviceInterfaces.contains("java.lang.Comparable")); Map<String, Object> props = metadata.getProperties(); - assertEquals(3, props.size()); + assertEquals(4, props.size()); assertEquals(5000, props.get("service.ranking")); assertEquals("The Apache Software Foundation", props.get("service.vendor")); assertEquals("org.apache.sling.models.impl.injectors.OSGiServiceInjector", props.get("service.pid")); + assertArrayEquals(new String[] { "org.apache.sling.api.resource.Resource", "org.apache.sling.api.resource.ResourceResolver" }, + (String[])props.get("adaptables")); } @Test Modified: sling/trunk/testing/mocks/osgi-mock/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java URL: http://svn.apache.org/viewvc/sling/trunk/testing/mocks/osgi-mock/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java?rev=1661038&r1=1661037&r2=1661038&view=diff ============================================================================== --- sling/trunk/testing/mocks/osgi-mock/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java (original) +++ sling/trunk/testing/mocks/osgi-mock/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java Fri Feb 20 00:17:52 2015 @@ -73,7 +73,7 @@ public class OsgiServiceUtilTest { assertTrue(MockOsgi.activate(service3, bundleContext, service3Config)); assertNotNull(service3.getComponentContext()); - assertEquals(service3Config, service3.getComponentContext().getProperties()); + assertEquals(service3Config.get("prop1"), service3.getComponentContext().getProperties().get("prop1")); assertSame(service1, service3.getReference1()); @@ -101,16 +101,16 @@ public class OsgiServiceUtilTest { Service3 service3 = new Service3(); MockOsgi.activate(service3, bundleContext, initialProperites); - assertEquals(initialProperites, service3.getConfig()); + assertEquals(initialProperites.get("prop1"), service3.getConfig().get("prop1")); Map<String,Object> newProperties = ImmutableMap.<String, Object>of("prop2", "value2"); MockOsgi.modified(service3, bundleContext, newProperties); - assertEquals(newProperties, service3.getConfig()); + assertEquals(newProperties.get("prop2"), service3.getConfig().get("prop2")); newProperties = ImmutableMap.<String, Object>of("prop3", "value3"); Dictionary<String,Object> newPropertiesDictonary = new Hashtable<String,Object>(newProperties); MockOsgi.modified(service3, bundleContext, newPropertiesDictonary); - assertEquals(newProperties, service3.getConfig()); + assertEquals(newProperties.get("prop3"), service3.getConfig().get("prop3")); } @Test Modified: sling/trunk/testing/mocks/osgi-mock/src/test/resources/OSGI-INF/serviceComponents.xml URL: http://svn.apache.org/viewvc/sling/trunk/testing/mocks/osgi-mock/src/test/resources/OSGI-INF/serviceComponents.xml?rev=1661038&r1=1661037&r2=1661038&view=diff ============================================================================== --- sling/trunk/testing/mocks/osgi-mock/src/test/resources/OSGI-INF/serviceComponents.xml (original) +++ sling/trunk/testing/mocks/osgi-mock/src/test/resources/OSGI-INF/serviceComponents.xml Fri Feb 20 00:17:52 2015 @@ -11,5 +11,9 @@ <property name="service.ranking" type="Integer" value="5000"/> <property name="service.vendor" value="The Apache Software Foundation"/> <property name="service.pid" value="org.apache.sling.models.impl.injectors.OSGiServiceInjector"/> + <property name="adaptables"> + org.apache.sling.api.resource.Resource + org.apache.sling.api.resource.ResourceResolver + </property> </scr:component> </components>