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:51 UTC
[sling-org-apache-sling-testing-osgi-mock] 05/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 e3e8bb10f076e1ea30cdd1e47570ab0bbfab2389
Author: Stefan Seifert <ss...@apache.org>
AuthorDate: Thu Feb 19 16:18:00 2015 +0000
SLING-4439 implement dynamic service registration
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/testing/mocks/osgi-mock@1660923 13f79535-47bb-0310-9956-ffa450edef68
---
.../sling/testing/mock/osgi/MockBundleContext.java | 41 +++++++-
.../sling/testing/mock/osgi/OsgiServiceUtil.java | 112 +++++++++++++++++----
2 files changed, 132 insertions(+), 21 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 37e6fd6..9ae85bc 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
@@ -28,6 +28,9 @@ import java.util.SortedSet;
import java.util.TreeSet;
import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.Reference;
+import org.apache.sling.testing.mock.osgi.OsgiServiceUtil.ReferenceInfo;
+import org.apache.sling.testing.mock.osgi.OsgiServiceUtil.ServiceInfo;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
@@ -91,7 +94,23 @@ class MockBundleContext implements BundleContext {
* @param registration
*/
private void handleRefsUpdateOnRegister(MockServiceRegistration registration) {
- // TODO: implement handling
+ List<ReferenceInfo> affectedReferences = OsgiServiceUtil.getMatchingReferences(registeredServices, registration);
+ for (ReferenceInfo referenceInfo : affectedReferences) {
+ Reference reference = referenceInfo.getReference();
+ switch (reference.getCardinality()) {
+ case MANDATORY_UNARY:
+ throw new ReferenceViolationException("Mandatory unary reference of type " + reference.getInterfaceType() + " already fulfilled "
+ + "for service " + reference.getServiceClass().getName() + ", registration of new service with this interface failed.");
+ case MANDATORY_MULTIPLE:
+ case OPTIONAL_MULTIPLE:
+ case OPTIONAL_UNARY:
+ OsgiServiceUtil.invokeBindMethod(reference, registration.getService(),
+ new ServiceInfo(referenceInfo.getServiceRegistration()));
+ break;
+ default:
+ throw new RuntimeException("Unepxected cardinality: " + reference.getCardinality());
+ }
+ }
}
void unregisterService(MockServiceRegistration registration) {
@@ -106,7 +125,25 @@ class MockBundleContext implements BundleContext {
* @param registration
*/
private void handleRefsUpdateOnUnregister(MockServiceRegistration registration) {
- // TODO: implement handling
+ List<ReferenceInfo> affectedReferences = OsgiServiceUtil.getMatchingReferences(registeredServices, registration);
+ for (ReferenceInfo referenceInfo : affectedReferences) {
+ Reference reference = referenceInfo.getReference();
+ switch (reference.getCardinality()) {
+ case MANDATORY_UNARY:
+ throw new ReferenceViolationException("Reference of type " + reference.getInterfaceType() + " "
+ + "for service " + reference.getServiceClass().getName() + " is mandatory unary, "
+ + "unregistration of service with this interface failed.");
+ case MANDATORY_MULTIPLE:
+ case OPTIONAL_MULTIPLE:
+ case OPTIONAL_UNARY:
+ // it is currently not checked if for a MANDATORY_MULTIPLE reference the last reference is removed
+ OsgiServiceUtil.invokeUnbindMethod(reference, registration.getService(),
+ new ServiceInfo(referenceInfo.getServiceRegistration()));
+ break;
+ default:
+ throw new RuntimeException("Unepxected cardinality: " + reference.getCardinality());
+ }
+ }
}
@Override
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 306a967..152379f 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
@@ -25,6 +25,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.SortedSet;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
@@ -310,15 +311,22 @@ final class OsgiServiceUtil {
}
// try to invoke bind method
- String bindMethodName = reference.getBind();
- if (StringUtils.isNotEmpty(bindMethodName)) {
+ for (ServiceInfo matchingService : matchingServices) {
+ invokeBindUnbindMethod(reference, target, matchingService, true);
+ }
+ }
+
+ private static void invokeBindUnbindMethod(Reference reference, Object target, ServiceInfo serviceInfo, boolean bind) {
+ Class<?> targetClass = target.getClass();
+
+ // try to invoke bind method
+ String methodName = bind ? reference.getBind() : reference.getUnbind();
+ if (StringUtils.isNotEmpty(methodName)) {
// 1. ServiceReference
- Method bindMethod = getMethod(targetClass, bindMethodName, new Class<?>[] { ServiceReference.class });
- if (bindMethod != null) {
- for (ServiceInfo matchingService : matchingServices) {
- invokeMethod(target, bindMethod, new Object[] { matchingService.getServiceReference() });
- }
+ Method method = getMethod(targetClass, methodName, new Class<?>[] { ServiceReference.class });
+ if (method != null) {
+ invokeMethod(target, method, new Object[] { serviceInfo.getServiceReference() });
return;
}
@@ -329,27 +337,43 @@ final class OsgiServiceUtil {
} catch (ClassNotFoundException e) {
throw new RuntimeException("Service reference type not found: " + reference.getInterfaceType());
}
- bindMethod = getMethodWithAssignableTypes(targetClass, bindMethodName, new Class<?>[] { interfaceType });
- if (bindMethod != null) {
- for (ServiceInfo matchingService : matchingServices) {
- invokeMethod(target, bindMethod, new Object[] { matchingService.getServiceInstance() });
- }
+ method = getMethodWithAssignableTypes(targetClass, methodName, new Class<?>[] { interfaceType });
+ if (method != null) {
+ invokeMethod(target, method, new Object[] { serviceInfo.getServiceInstance() });
return;
}
// 3. assignable from service instance plus map
- bindMethod = getMethodWithAssignableTypes(targetClass, bindMethodName, new Class<?>[] { interfaceType, Map.class });
- if (bindMethod != null) {
- for (ServiceInfo matchingService : matchingServices) {
- invokeMethod(target, bindMethod, new Object[] { matchingService.getServiceInstance(), matchingService.getServiceConfig() });
- }
+ method = getMethodWithAssignableTypes(targetClass, methodName, new Class<?>[] { interfaceType, Map.class });
+ if (method != null) {
+ invokeMethod(target, method, new Object[] { serviceInfo.getServiceInstance(), serviceInfo.getServiceConfig() });
return;
}
}
- throw new RuntimeException("Bind method with name " + bindMethodName + " not found "
+ throw new RuntimeException((bind ? "Bind" : "Unbind") + "method with name " + methodName + " not found "
+ "for reference '" + reference.getName() + "' for class {}" + targetClass.getName());
}
+
+ /**
+ * Directly invoke bind method on service for the given reference.
+ * @param reference Reference metadata
+ * @param target Target object for reference
+ * @param serviceInfo Service on which to invoke the method
+ */
+ public static void invokeBindMethod(Reference reference, Object target, ServiceInfo serviceInfo) {
+ invokeBindUnbindMethod(reference, target, serviceInfo, true);
+ }
+
+ /**
+ * Directly invoke unbind method on service for the given reference.
+ * @param reference Reference metadata
+ * @param target Target object for reference
+ * @param serviceInfo Service on which to invoke the method
+ */
+ public static void invokeUnbindMethod(Reference reference, Object target, ServiceInfo serviceInfo) {
+ invokeBindUnbindMethod(reference, target, serviceInfo, false);
+ }
private static List<ServiceInfo> getMatchingServices(Class<?> type, BundleContext bundleContext) {
List<ServiceInfo> matchingServices = new ArrayList<ServiceInfo>();
@@ -372,7 +396,31 @@ final class OsgiServiceUtil {
return matchingServices;
}
- private static class ServiceInfo {
+ /**
+ * Collects all references of any registered service that match with any of the exported interfaces of the given service registration.
+ * @param registeredServices Registered Services
+ * @param registration Service registration
+ * @return List of references
+ */
+ public static List<ReferenceInfo> getMatchingReferences(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));
+ }
+ }
+ }
+ }
+ }
+ return references;
+ }
+
+ static class ServiceInfo {
private final Object serviceInstance;
private final Map<String, Object> serviceConfig;
@@ -384,6 +432,12 @@ final class OsgiServiceUtil {
this.serviceReference = serviceReference;
}
+ public ServiceInfo(MockServiceRegistration registration) {
+ this.serviceInstance = registration.getService();
+ this.serviceConfig = MapUtil.toMap(registration.getProperties());
+ this.serviceReference = registration.getReference();
+ }
+
public Object getServiceInstance() {
return this.serviceInstance;
}
@@ -398,4 +452,24 @@ final class OsgiServiceUtil {
}
+ static class ReferenceInfo {
+
+ private final MockServiceRegistration serviceRegistration;
+ private final Reference reference;
+
+ public ReferenceInfo(MockServiceRegistration serviceRegistration, Reference reference) {
+ this.serviceRegistration = serviceRegistration;
+ this.reference = reference;
+ }
+
+ public MockServiceRegistration getServiceRegistration() {
+ return serviceRegistration;
+ }
+
+ public Reference getReference() {
+ return reference;
+ }
+
+ }
+
}
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.