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.2.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-osgi-mock.git
commit a9804736b3437fb5cff74fee9ad2f909a0ac85e3 Author: Stefan Seifert <[email protected]> AuthorDate: Thu Feb 19 22:54:45 2015 +0000 SLING-4439 implement dynamic service registration git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/testing/mocks/osgi-mock@1661030 13f79535-47bb-0310-9956-ffa450edef68 --- .../sling/testing/mock/osgi/MockBundleContext.java | 4 +- .../sling/testing/mock/osgi/OsgiMetadataUtil.java | 108 ++++++++++++++++----- .../sling/testing/mock/osgi/OsgiServiceUtil.java | 22 ++++- .../testing/mock/osgi/OsgiMetadataUtilTest.java | 8 +- ...sling.testing.mock.osgi.OsgiServiceUtilTest.xml | 8 +- ...iMetadataUtilTest.xml => serviceComponents.xml} | 1 + 6 files changed, 108 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java b/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java index fddb3c2..075df65 100644 --- a/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java +++ b/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java @@ -94,7 +94,7 @@ class MockBundleContext implements BundleContext { * @param registration */ private void handleRefsUpdateOnRegister(MockServiceRegistration registration) { - List<ReferenceInfo> affectedReferences = OsgiServiceUtil.getMatchingReferences(registeredServices, registration); + List<ReferenceInfo> affectedReferences = OsgiServiceUtil.getMatchingDynamicReferences(registeredServices, registration); for (ReferenceInfo referenceInfo : affectedReferences) { Reference reference = referenceInfo.getReference(); switch (reference.getCardinality()) { @@ -125,7 +125,7 @@ class MockBundleContext implements BundleContext { * @param registration */ private void handleRefsUpdateOnUnregister(MockServiceRegistration registration) { - List<ReferenceInfo> affectedReferences = OsgiServiceUtil.getMatchingReferences(registeredServices, registration); + List<ReferenceInfo> affectedReferences = OsgiServiceUtil.getMatchingDynamicReferences(registeredServices, registration); for (ReferenceInfo referenceInfo : affectedReferences) { Reference reference = referenceInfo.getReference(); switch (reference.getCardinality()) { diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java b/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java index b64cd39..359ac5b 100644 --- a/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java +++ b/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java @@ -20,7 +20,9 @@ package org.apache.sling.testing.mock.osgi; import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.util.ArrayList; +import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -40,6 +42,7 @@ import javax.xml.xpath.XPathFactory; import org.apache.commons.lang3.StringUtils; import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.ReferencePolicy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -52,6 +55,7 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableList; /** * Helper methods to parse OSGi metadata. @@ -82,13 +86,15 @@ final class OsgiMetadataUtil { private static final LoadingCache<Class, OsgiMetadata> METADATA_CACHE = CacheBuilder.newBuilder().build(new CacheLoader<Class, OsgiMetadata>() { @Override public OsgiMetadata load(Class clazz) throws Exception { - Document metadataDocument = OsgiMetadataUtil.getMetadataDocument(clazz); - if (metadataDocument == null) { - return NULL_METADATA; - } - else { - return new OsgiMetadata(clazz, metadataDocument); + List<Document> metadataDocuments = OsgiMetadataUtil.getMetadataDocument(clazz); + if (metadataDocuments != null) { + for (Document metadataDocument : metadataDocuments) { + if (matchesService(clazz, metadataDocument)) { + return new OsgiMetadata(clazz, metadataDocument); + } + } } + return NULL_METADATA; } }); @@ -114,7 +120,11 @@ final class OsgiMetadataUtil { }; public static String getMetadataPath(Class clazz) { - return "/OSGI-INF/" + StringUtils.substringBefore(clazz.getName(), "$") + ".xml"; + return "OSGI-INF/" + StringUtils.substringBefore(clazz.getName(), "$") + ".xml"; + } + + public static String getOldMetadataMultiPath() { + return "OSGI-INF/serviceComponents.xml"; } /** @@ -138,32 +148,63 @@ final class OsgiMetadataUtil { } } - private static Document getMetadataDocument(Class clazz) { + private static List<Document> getMetadataDocument(Class clazz) { String metadataPath = getMetadataPath(clazz); - InputStream metadataStream = clazz.getResourceAsStream(metadataPath); - if (metadataStream == null) { - log.debug("No OSGi metadata found at {}", metadataPath); - return null; + InputStream metadataStream = OsgiMetadataUtil.class.getClassLoader().getResourceAsStream(metadataPath); + if (metadataStream == null) { + String oldMetadataPath = getOldMetadataMultiPath(); + log.debug("No OSGi metadata found at {}, try to fallback to {}", metadataPath, oldMetadataPath); + + try { + Enumeration<URL> metadataUrls = OsgiMetadataUtil.class.getClassLoader().getResources(oldMetadataPath); + List<Document> docs = new ArrayList<Document>(); + while (metadataUrls.hasMoreElements()) { + URL metadataUrl = metadataUrls.nextElement(); + metadataStream = metadataUrl.openStream(); + docs.add(toXmlDocument(metadataStream, oldMetadataPath)); + } + if (docs.size() == 0) { + return null; + } + else { + return docs; + } + } + catch (IOException ex) { + throw new RuntimeException("Unable to read classpath resource: " + oldMetadataPath, ex); + } + } + else { + return ImmutableList.of(toXmlDocument(metadataStream, metadataPath)); } + } + + private static Document toXmlDocument(InputStream inputStream, String path) { try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); - return documentBuilder.parse(metadataStream); + return documentBuilder.parse(inputStream); } catch (ParserConfigurationException ex) { - throw new RuntimeException("Unable to read classpath resource: " + metadataPath, ex); + throw new RuntimeException("Unable to read classpath resource: " + path, ex); } catch (SAXException ex) { - throw new RuntimeException("Unable to read classpath resource: " + metadataPath, ex); + throw new RuntimeException("Unable to read classpath resource: " + path, ex); } catch (IOException ex) { - throw new RuntimeException("Unable to read classpath resource: " + metadataPath, ex); + throw new RuntimeException("Unable to read classpath resource: " + path, ex); } finally { try { - metadataStream.close(); + inputStream.close(); } catch (IOException ex) { // ignore } } } + private static boolean matchesService(Class clazz, Document metadata) { + String query = "/components/component[@name='" + clazz.getName() + "']"; + NodeList nodes = queryNodes(metadata, query); + return nodes != null && nodes.getLength() > 0; + } + private static Set<String> getServiceInterfaces(Class clazz, Document metadata) { Set<String> serviceInterfaces = new HashSet<String>(); String query = "/components/component[@name='" + clazz.getName() + "']/service/provide[@interface!='']"; @@ -317,6 +358,7 @@ final class OsgiMetadataUtil { private final String name; private final String interfaceType; private final ReferenceCardinality cardinality; + private final ReferencePolicy policy; private final String bind; private final String unbind; @@ -325,6 +367,7 @@ final class OsgiMetadataUtil { this.name = getAttributeValue(node, "name"); this.interfaceType = getAttributeValue(node, "interface"); this.cardinality = toCardinality(getAttributeValue(node, "cardinality")); + this.policy = toPolicy(getAttributeValue(node, "policy")); this.bind = getAttributeValue(node, "bind"); this.unbind = getAttributeValue(node, "unbind"); } @@ -333,15 +376,6 @@ final class OsgiMetadataUtil { return clazz; } - private ReferenceCardinality toCardinality(String value) { - for (ReferenceCardinality item : ReferenceCardinality.values()) { - if (StringUtils.equals(item.getCardinalityString(), value)) { - return item; - } - } - return ReferenceCardinality.MANDATORY_UNARY; - } - public String getName() { return this.name; } @@ -353,6 +387,10 @@ final class OsgiMetadataUtil { public ReferenceCardinality getCardinality() { return this.cardinality; } + + public ReferencePolicy getPolicy() { + return policy; + } public String getBind() { return this.bind; @@ -362,6 +400,24 @@ final class OsgiMetadataUtil { return this.unbind; } + private static ReferenceCardinality toCardinality(String value) { + for (ReferenceCardinality item : ReferenceCardinality.values()) { + if (StringUtils.equals(item.getCardinalityString(), value)) { + return item; + } + } + return ReferenceCardinality.MANDATORY_UNARY; + } + + private static ReferencePolicy toPolicy(String value) { + for (ReferencePolicy item : ReferencePolicy.values()) { + if (StringUtils.equalsIgnoreCase(item.name(), value)) { + return item; + } + } + return ReferencePolicy.STATIC; + } + } } diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtil.java b/src/main/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtil.java index 1960d0d..82c722c 100644 --- a/src/main/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtil.java +++ b/src/main/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtil.java @@ -30,6 +30,7 @@ import java.util.SortedSet; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.ReferencePolicy; import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.OsgiMetadata; import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.Reference; import org.osgi.framework.BundleContext; @@ -67,8 +68,14 @@ final class OsgiServiceUtil { } else { methodName = metadata.getDeactivateMethodName(); } + boolean fallbackDefaultName = false; if (StringUtils.isEmpty(methodName)) { - return false; + fallbackDefaultName = true; + if (activate) { + methodName = "activate"; + } else { + methodName = "deactivate"; + } } // try to find matching activate/deactivate method and execute it @@ -143,6 +150,9 @@ final class OsgiServiceUtil { return true; } + if (fallbackDefaultName) { + return false; + } throw new RuntimeException("No matching " + (activate ? "activation" : "deactivation") + " method with name '" + methodName + "' " + " found in class " + targetClass.getName()); } @@ -402,16 +412,18 @@ final class OsgiServiceUtil { * @param registration Service registration * @return List of references */ - public static List<ReferenceInfo> getMatchingReferences(SortedSet<MockServiceRegistration> registeredServices, + public static List<ReferenceInfo> getMatchingDynamicReferences(SortedSet<MockServiceRegistration> registeredServices, MockServiceRegistration registration) { List<ReferenceInfo> references = new ArrayList<ReferenceInfo>(); for (MockServiceRegistration existingRegistration : registeredServices) { OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(existingRegistration.getService().getClass()); if (metadata != null) { for (Reference reference : metadata.getReferences()) { - for (String serviceInterface : registration.getClasses()) { - if (StringUtils.equals(serviceInterface, reference.getInterfaceType())) { - references.add(new ReferenceInfo(existingRegistration, reference)); + if (reference.getPolicy() == ReferencePolicy.DYNAMIC) { + for (String serviceInterface : registration.getClasses()) { + if (StringUtils.equals(serviceInterface, reference.getInterfaceType())) { + references.add(new ReferenceInfo(existingRegistration, reference)); + } } } } diff --git a/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java b/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java index 4611d25..ebd671e 100644 --- a/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java +++ b/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java @@ -19,6 +19,7 @@ package org.apache.sling.testing.mock.osgi; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.List; @@ -53,12 +54,7 @@ public class OsgiMetadataUtilTest { @Test public void testNoMetadata() { OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(ServiceWithoutMetadata.class); - - Set<String> serviceInterfaces = metadata.getServiceInterfaces(); - assertEquals(0, serviceInterfaces.size()); - - Map<String, Object> props = metadata.getProperties(); - assertEquals(0, props.size()); + assertNull(metadata); } @Test diff --git a/src/test/resources/OSGI-INF/org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest.xml b/src/test/resources/OSGI-INF/org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest.xml index ab82616..a1cd7a4 100644 --- a/src/test/resources/OSGI-INF/org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest.xml +++ b/src/test/resources/OSGI-INF/org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest.xml @@ -20,10 +20,10 @@ <scr:component name="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$Service3" activate="activate" deactivate="deactivate" modified="modified"> <implementation class="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$Service3"/> <property name="service.pid" value="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$Service3"/> - <reference name="reference1" interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface1" cardinality="1..1" policy="static" bind="bindReference1" unbind="unbindReference1"/> - <reference name="reference1Optional" interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface1Optional" cardinality="0..1" policy="static" bind="bindReference1Optional" unbind="unbindReference1Optional"/> - <reference name="reference2" interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface2" cardinality="1..n" policy="static" bind="bindReference2" unbind="unbindReference2"/> - <reference name="reference3" interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface3" cardinality="0..n" policy="static" bind="bindReference3" unbind="unbindReference3"/> + <reference name="reference1" interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface1" cardinality="1..1" policy="dynamic" bind="bindReference1" unbind="unbindReference1"/> + <reference name="reference1Optional" interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface1Optional" cardinality="0..1" policy="dynamic" bind="bindReference1Optional" unbind="unbindReference1Optional"/> + <reference name="reference2" interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface2" cardinality="1..n" policy="dynamic" bind="bindReference2" unbind="unbindReference2"/> + <reference name="reference3" interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface3" cardinality="0..n" policy="dynamic" bind="bindReference3" unbind="unbindReference3"/> </scr:component> <scr:component name="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$Service4"> <implementation class="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$Service4"/> diff --git a/src/test/resources/OSGI-INF/org.apache.sling.testing.mock.osgi.OsgiMetadataUtilTest.xml b/src/test/resources/OSGI-INF/serviceComponents.xml similarity index 90% rename from src/test/resources/OSGI-INF/org.apache.sling.testing.mock.osgi.OsgiMetadataUtilTest.xml rename to src/test/resources/OSGI-INF/serviceComponents.xml index 95ac503..064f0fc 100644 --- a/src/test/resources/OSGI-INF/org.apache.sling.testing.mock.osgi.OsgiMetadataUtilTest.xml +++ b/src/test/resources/OSGI-INF/serviceComponents.xml @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- This file follows the old SCR convention using a fixed name "serviceComponents.xml" --> <components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"> <scr:component name="org.apache.sling.testing.mock.osgi.OsgiMetadataUtilTest$ServiceWithMetadata" activate="activate"> <implementation class="org.apache.sling.testing.mock.osgi.OsgiMetadataUtilTest$ServiceWithMetadata"/> -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
