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:49 UTC

[sling-org-apache-sling-testing-osgi-mock] 03/10: SLING-4435 OSGi Mock: Cache reading of OSGi SCR Metadata files

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 68de5d4e00c22c66636341be4f80dd14159d7b78
Author: Stefan Seifert <ss...@apache.org>
AuthorDate: Thu Feb 19 11:00:05 2015 +0000

    SLING-4435 OSGi Mock: Cache reading of OSGi SCR Metadata files
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/testing/mocks/osgi-mock@1660841 13f79535-47bb-0310-9956-ffa450edef68
---
 .../testing/mock/osgi/MockServiceRegistration.java |  10 +-
 .../sling/testing/mock/osgi/OsgiMetadataUtil.java  | 121 +++++++++++++++++----
 .../sling/testing/mock/osgi/OsgiServiceUtil.java   |  22 ++--
 .../sling/testing/mock/osgi/package-info.java      |   2 +-
 .../testing/mock/osgi/OsgiMetadataUtilTest.java    |  23 ++--
 5 files changed, 128 insertions(+), 50 deletions(-)

diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/MockServiceRegistration.java b/src/main/java/org/apache/sling/testing/mock/osgi/MockServiceRegistration.java
index 1dc564b..f212b49 100644
--- a/src/main/java/org/apache/sling/testing/mock/osgi/MockServiceRegistration.java
+++ b/src/main/java/org/apache/sling/testing/mock/osgi/MockServiceRegistration.java
@@ -24,11 +24,11 @@ import java.util.Hashtable;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.OsgiMetadata;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.w3c.dom.Document;
 
 import com.google.common.collect.ImmutableList;
 
@@ -89,16 +89,16 @@ class MockServiceRegistration implements ServiceRegistration {
      */
     private void readOsgiMetadata() {
         Class<?> serviceClass = service.getClass();
-        Document doc = OsgiMetadataUtil.getMetadata(serviceClass);
-        if (doc == null) {
+        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(serviceClass);
+        if (metadata == null) {
             return;
         }
 
         // add service interfaces from OSGi metadata
-        clazzes.addAll(OsgiMetadataUtil.getServiceInterfaces(serviceClass, doc));
+        clazzes.addAll(metadata.getServiceInterfaces());
 
         // add properties from OSGi metadata
-        Map<String, Object> props = OsgiMetadataUtil.getProperties(serviceClass, doc);
+        Map<String, Object> props = metadata.getProperties();
         for (Map.Entry<String, Object> entry : props.entrySet()) {
             properties.put(entry.getKey(), entry.getValue());
         }
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 41fc4b5..7cf7cfb 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
@@ -27,6 +27,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ExecutionException;
 
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.parsers.DocumentBuilder;
@@ -46,6 +47,9 @@ import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
 
@@ -68,6 +72,25 @@ final class OsgiMetadataUtil {
     static {
         NAMESPACES.put("scr", "http://www.osgi.org/xmlns/scr/v1.1.0");
     }
+    
+    private static final OsgiMetadata NULL_METADATA = new OsgiMetadata();
+    
+    /*
+     * The OSGI metadata XML files do not change during the unit test runs because static part of classpath.
+     * So we can cache the parsing step if we need them multiple times.
+     */
+    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);
+            }
+        }
+    });
 
     private OsgiMetadataUtil() {
         // static methods only
@@ -95,12 +118,27 @@ final class OsgiMetadataUtil {
     }
 
     /**
-     * Try to read OSGI-metadata from /OSGI-INF and read all implemented
-     * interfaces and service properties
+     * Try to read OSGI-metadata from /OSGI-INF and read all implemented interfaces and service properties.
+     * The metadata is cached after initial read, so it's no problem to call this method multiple time for the same class.
      * @param clazz OSGi service implementation class
-     * @return Metadata document or null
+     * @return Metadata object or null if no metadata present in classpath
      */
-    public static Document getMetadata(Class clazz) {
+    public static OsgiMetadata getMetadata(Class clazz) {
+        try {
+            OsgiMetadata metadata = METADATA_CACHE.get(clazz);
+            if (metadata == NULL_METADATA) {
+                return null;
+            }
+            else {
+                return metadata;
+            }
+        }
+        catch (ExecutionException ex) {
+            throw new RuntimeException("Error loading OSGi metadata from loader cache.", ex);
+        }
+    }
+
+    private static Document getMetadataDocument(Class clazz) {
         String metadataPath = getMetadataPath(clazz);
         InputStream metadataStream = clazz.getResourceAsStream(metadataPath);
         if (metadataStream == null) {
@@ -126,7 +164,7 @@ final class OsgiMetadataUtil {
         }
     }
 
-    public static Set<String> getServiceInterfaces(Class clazz, Document metadata) {
+    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!='']";
         NodeList nodes = queryNodes(metadata, query);
@@ -142,7 +180,7 @@ final class OsgiMetadataUtil {
         return serviceInterfaces;
     }
 
-    public static Map<String, Object> getProperties(Class clazz, Document metadata) {
+    private static Map<String, Object> getProperties(Class clazz, Document metadata) {
         Map<String, Object> props = new HashMap<String, Object>();
         String query = "/components/component[@name='" + clazz.getName() + "']/property[@name!='' and @value!='']";
         NodeList nodes = queryNodes(metadata, query);
@@ -162,7 +200,7 @@ final class OsgiMetadataUtil {
         return props;
     }
 
-    public static List<Reference> getReferences(Class clazz, Document metadata) {
+    private static List<Reference> getReferences(Class clazz, Document metadata) {
         List<Reference> references = new ArrayList<Reference>();
         String query = "/components/component[@name='" + clazz.getName() + "']/reference[@name!='']";
         NodeList nodes = queryNodes(metadata, query);
@@ -175,18 +213,6 @@ final class OsgiMetadataUtil {
         return references;
     }
 
-    public static String getActivateMethodName(Class clazz, Document metadata) {
-        return getLifecycleMethodName(clazz, metadata, "activate");
-    }
-
-    public static String getDeactivateMethodName(Class clazz, Document metadata) {
-        return getLifecycleMethodName(clazz, metadata, "deactivate");
-    }
-
-    public static String getModifiedMethodName(Class clazz, Document metadata) {
-        return getLifecycleMethodName(clazz, metadata, "modified");
-    }
-
     private static String getLifecycleMethodName(Class clazz, Document metadata, String methodName) {
         String query = "/components/component[@name='" + clazz.getName() + "']";
         Node node = queryNode(metadata, query);
@@ -225,7 +251,60 @@ final class OsgiMetadataUtil {
         }
     }
 
-    public static class Reference {
+    static class OsgiMetadata {
+        
+        private final Set<String> serviceInterfaces;
+        private final Map<String, Object> properties;
+        private final List<Reference> references;
+        private final String activateMethodName;
+        private final String deactivateMethodName;
+        private final String modifiedMethodName;
+        
+        private OsgiMetadata(Class clazz, Document metadataDocument) {
+            this.serviceInterfaces = OsgiMetadataUtil.getServiceInterfaces(clazz, metadataDocument);
+            this.properties = OsgiMetadataUtil.getProperties(clazz, metadataDocument);
+            this.references = OsgiMetadataUtil.getReferences(clazz, metadataDocument);
+            this.activateMethodName = OsgiMetadataUtil.getLifecycleMethodName(clazz, metadataDocument, "activate");
+            this.deactivateMethodName = OsgiMetadataUtil.getLifecycleMethodName(clazz, metadataDocument, "deactivate");
+            this.modifiedMethodName = OsgiMetadataUtil.getLifecycleMethodName(clazz, metadataDocument, "modified");
+        }
+
+        private OsgiMetadata() {
+            this.serviceInterfaces = null;
+            this.properties = null;
+            this.references = null;
+            this.activateMethodName = null;
+            this.deactivateMethodName = null;
+            this.modifiedMethodName = null;
+        }
+        
+        public Set<String> getServiceInterfaces() {
+            return serviceInterfaces;
+        }
+
+        public Map<String, Object> getProperties() {
+            return properties;
+        }
+
+        public List<Reference> getReferences() {
+            return references;
+        }
+
+        public String getActivateMethodName() {
+            return activateMethodName;
+        }
+
+        public String getDeactivateMethodName() {
+            return deactivateMethodName;
+        }
+
+        public String getModifiedMethodName() {
+            return modifiedMethodName;
+        }
+        
+    }
+
+    static class Reference {
 
         private final String name;
         private final String interfaceType;
@@ -233,7 +312,7 @@ final class OsgiMetadataUtil {
         private final String bind;
         private final String unbind;
 
-        public Reference(Node node) {
+        private Reference(Node node) {
             this.name = getAttributeValue(node, "name");
             this.interfaceType = getAttributeValue(node, "interface");
             this.cardinality = toCardinality(getAttributeValue(node, "cardinality"));
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 7606d65..b340b29 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
@@ -29,12 +29,12 @@ 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.OsgiMetadata;
 import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.Reference;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentContext;
-import org.w3c.dom.Document;
 
 /**
  * Helper methods to inject dependencies and activate services.
@@ -56,15 +56,15 @@ final class OsgiServiceUtil {
         Class<?> targetClass = target.getClass();
 
         // get method name for activation/deactivation from osgi metadata
-        Document metadata = OsgiMetadataUtil.getMetadata(targetClass);
-        if (metadata==null) {
+        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(targetClass);
+        if (metadata == null) {
             throw new NoScrMetadataException(targetClass);
         }
         String methodName;
         if (activate) {
-            methodName = OsgiMetadataUtil.getActivateMethodName(targetClass, metadata);
+            methodName = metadata.getActivateMethodName();
         } else {
-            methodName = OsgiMetadataUtil.getDeactivateMethodName(targetClass, metadata);
+            methodName = metadata.getDeactivateMethodName();
         }
         if (StringUtils.isEmpty(methodName)) {
             return false;
@@ -156,11 +156,11 @@ final class OsgiServiceUtil {
         Class<?> targetClass = target.getClass();
 
         // get method name for activation/deactivation from osgi metadata
-        Document metadata = OsgiMetadataUtil.getMetadata(targetClass);
-        if (metadata==null) {
+        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(targetClass);
+        if (metadata == null) {
             throw new NoScrMetadataException(targetClass);
         }
-        String methodName = OsgiMetadataUtil.getModifiedMethodName(targetClass, metadata);
+        String methodName = metadata.getModifiedMethodName();
         if (StringUtils.isEmpty(methodName)) {
             return false;
         }
@@ -264,11 +264,11 @@ final class OsgiServiceUtil {
         // collect all declared reference annotations on class and field level
         Class<?> targetClass = target.getClass();
 
-        Document metadata = OsgiMetadataUtil.getMetadata(targetClass);
-        if (metadata==null) {
+        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(targetClass);
+        if (metadata == null) {
             throw new NoScrMetadataException(targetClass);
         }
-        List<Reference> references = OsgiMetadataUtil.getReferences(targetClass, metadata);
+        List<Reference> references = metadata.getReferences();
         if (references.isEmpty()) {
             return false;
         }
diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java b/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java
index 14b8744..6a6de3f 100644
--- a/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java
+++ b/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java
@@ -19,5 +19,5 @@
 /**
  * Mock implementation of selected OSGi APIs.
  */
-@aQute.bnd.annotation.Version("1.1")
+@aQute.bnd.annotation.Version("2.0")
 package org.apache.sling.testing.mock.osgi;
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 280f955..9db1197 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
@@ -26,24 +26,24 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.OsgiMetadata;
 import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.Reference;
 import org.junit.Test;
-import org.w3c.dom.Document;
 
 public class OsgiMetadataUtilTest {
 
     @Test
     public void testMetadata() {
-        Document doc = OsgiMetadataUtil.getMetadata(ServiceWithMetadata.class);
+        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(ServiceWithMetadata.class);
 
-        Set<String> serviceInterfaces = OsgiMetadataUtil.getServiceInterfaces(ServiceWithMetadata.class, doc);
+        Set<String> serviceInterfaces = metadata.getServiceInterfaces();
         assertEquals(3, serviceInterfaces.size());
         assertTrue(serviceInterfaces.contains("org.apache.sling.models.spi.Injector"));
         assertTrue(serviceInterfaces
                 .contains("org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessorFactory"));
         assertTrue(serviceInterfaces.contains("java.lang.Comparable"));
 
-        Map<String, Object> props = OsgiMetadataUtil.getProperties(ServiceWithMetadata.class, doc);
+        Map<String, Object> props = metadata.getProperties();
         assertEquals(3, props.size());
         assertEquals(5000, props.get("service.ranking"));
         assertEquals("The Apache Software Foundation", props.get("service.vendor"));
@@ -52,19 +52,19 @@ public class OsgiMetadataUtilTest {
 
     @Test
     public void testNoMetadata() {
-        Document doc = OsgiMetadataUtil.getMetadata(ServiceWithoutMetadata.class);
+        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(ServiceWithoutMetadata.class);
 
-        Set<String> serviceInterfaces = OsgiMetadataUtil.getServiceInterfaces(ServiceWithoutMetadata.class, doc);
+        Set<String> serviceInterfaces = metadata.getServiceInterfaces();
         assertEquals(0, serviceInterfaces.size());
 
-        Map<String, Object> props = OsgiMetadataUtil.getProperties(ServiceWithoutMetadata.class, doc);
+        Map<String, Object> props = metadata.getProperties();
         assertEquals(0, props.size());
     }
 
     @Test
     public void testReferences() {
-        Document doc = OsgiMetadataUtil.getMetadata(OsgiServiceUtilTest.Service3.class);
-        List<Reference> references = OsgiMetadataUtil.getReferences(OsgiServiceUtilTest.Service3.class, doc);
+        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(OsgiServiceUtilTest.Service3.class);
+        List<Reference> references = metadata.getReferences();
         assertEquals(3, references.size());
 
         Reference ref1 = references.get(0);
@@ -77,9 +77,8 @@ public class OsgiMetadataUtilTest {
 
     @Test
     public void testActivateMethodName() {
-        Document doc = OsgiMetadataUtil.getMetadata(OsgiServiceUtilTest.Service3.class);
-        String methodName = OsgiMetadataUtil.getActivateMethodName(OsgiServiceUtilTest.Service3.class, doc);
-        assertEquals("activate", methodName);
+        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(OsgiServiceUtilTest.Service3.class);
+        assertEquals("activate", metadata.getActivateMethodName());
     }
 
     static class ServiceWithMetadata {

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.