You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 10:18:53 UTC

[sling-org-apache-sling-testing-osgi-mock] 07/10: SLING-4439 implement dynamic service registration

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 <ss...@apache.org>
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
"commits@sling.apache.org" <co...@sling.apache.org>.