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