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>.