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

[sling-org-apache-sling-testing-osgi-mock] 04/10: SLING-4439 add support for unregistering services and prepare dynamic service reference handling

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 dc9866e557685680ee107ead6b7cb8b5665247e8
Author: Stefan Seifert <ss...@apache.org>
AuthorDate: Thu Feb 19 15:28:14 2015 +0000

    SLING-4439 add support for unregistering services and prepare dynamic service reference handling
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/testing/mocks/osgi-mock@1660911 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/testing/mock/osgi/MockBundleContext.java | 32 ++++++++++--
 .../testing/mock/osgi/MockServiceRegistration.java | 34 +++++++++++--
 .../sling/testing/mock/osgi/OsgiMetadataUtil.java  | 19 ++++++--
 .../sling/testing/mock/osgi/OsgiServiceUtil.java   |  6 +--
 .../mock/osgi/ReferenceViolationException.java     | 31 ++++++++++++
 .../testing/mock/osgi/MockBundleContextTest.java   | 57 ++++++++++++++--------
 6 files changed, 146 insertions(+), 33 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 cbaa13d..37e6fd6 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
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.Dictionary;
 import java.util.List;
 import java.util.Set;
+import java.util.SortedSet;
 import java.util.TreeSet;
 
 import org.apache.commons.lang3.StringUtils;
@@ -44,7 +45,7 @@ import org.osgi.framework.ServiceRegistration;
 class MockBundleContext implements BundleContext {
 
     private final MockBundle bundle;
-    private final List<MockServiceRegistration> registeredServices = new ArrayList<MockServiceRegistration>();
+    private final SortedSet<MockServiceRegistration> registeredServices = new TreeSet<MockServiceRegistration>();
     private final List<ServiceListener> serviceListeners = new ArrayList<ServiceListener>();
     private final List<BundleListener> bundleListeners = new ArrayList<BundleListener>();
 
@@ -77,12 +78,37 @@ class MockBundleContext implements BundleContext {
     @SuppressWarnings("unchecked")
     @Override
     public ServiceRegistration registerService(final String[] clazzes, final Object service, final Dictionary properties) {
-        MockServiceRegistration registration = new MockServiceRegistration(this.bundle, clazzes, service, properties);
+        MockServiceRegistration registration = new MockServiceRegistration(this.bundle, clazzes, service, properties, this);
+        handleRefsUpdateOnRegister(registration);
         this.registeredServices.add(registration);
         notifyServiceListeners(ServiceEvent.REGISTERED, registration.getReference());
         return registration;
     }
-
+    
+    /**
+     * Check for already registered services that may be affected by the service registration - either
+     * adding by additional optional references, or creating a conflict in the dependencies.
+     * @param registration
+     */
+    private void handleRefsUpdateOnRegister(MockServiceRegistration registration) {
+        // TODO: implement handling
+    }
+    
+    void unregisterService(MockServiceRegistration registration) {
+        this.registeredServices.remove(registration);
+        handleRefsUpdateOnUnregister(registration);
+        notifyServiceListeners(ServiceEvent.UNREGISTERING, registration.getReference());
+    }
+
+    /**
+     * Check for already registered services that may be affected by the service unregistration - either
+     * adding by removing optional references, or creating a conflict in the dependencies.
+     * @param registration
+     */
+    private void handleRefsUpdateOnUnregister(MockServiceRegistration registration) {
+        // TODO: implement handling
+    }
+    
     @Override
     public ServiceReference getServiceReference(final String clazz) {
         ServiceReference[] serviceRefs = getServiceReferences(clazz, null);
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 f212b49..c9c13dd 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
@@ -35,22 +35,26 @@ import com.google.common.collect.ImmutableList;
 /**
  * Mock {@link ServiceRegistration} implementation.
  */
-class MockServiceRegistration implements ServiceRegistration {
+class MockServiceRegistration implements ServiceRegistration, Comparable<MockServiceRegistration> {
 
     private static volatile long serviceCounter;
 
+    private final Long serviceId;
     private final Set<String> clazzes;
     private final Object service;
     private Dictionary<String, Object> properties;
     private final ServiceReference serviceReference;
+    private final MockBundleContext bundleContext;
 
     public MockServiceRegistration(final Bundle bundle, final String[] clazzes, final Object service,
-            final Dictionary<String, Object> properties) {
+            final Dictionary<String, Object> properties, MockBundleContext bundleContext) {
+        this.serviceId = ++serviceCounter;
         this.clazzes = new HashSet<String>(ImmutableList.copyOf(clazzes));
         this.service = service;
         this.properties = properties != null ? properties : new Hashtable<String,Object>();
-        this.properties.put(Constants.SERVICE_ID, ++serviceCounter);
+        this.properties.put(Constants.SERVICE_ID, this.serviceId);
         this.serviceReference = new MockServiceReference(bundle, this);
+        this.bundleContext = bundleContext;
         readOsgiMetadata();
     }
 
@@ -67,7 +71,7 @@ class MockServiceRegistration implements ServiceRegistration {
 
     @Override
     public void unregister() {
-        // do nothing for now
+        bundleContext.unregisterService(this);
     }
 
     Dictionary<String, Object> getProperties() {
@@ -78,10 +82,32 @@ class MockServiceRegistration implements ServiceRegistration {
         // ignore filter for now
         return this.clazzes.contains(clazz);
     }
+    
+    Set<String> getClasses() {
+        return clazzes;
+    }
 
     Object getService() {
         return this.service;
     }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof MockServiceRegistration)) {
+            return false;
+        }
+        return serviceId.equals(((MockServiceRegistration)obj).serviceId);
+    }
+
+    @Override
+    public int hashCode() {
+        return serviceId.hashCode();
+    }
+
+    @Override
+    public int compareTo(MockServiceRegistration obj) {
+        return serviceId.compareTo(obj.serviceId);
+    }
 
     /**
      * Try to read OSGI-metadata from /OSGI-INF and read all implemented
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 7cf7cfb..b64cd39 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
@@ -207,7 +207,7 @@ final class OsgiMetadataUtil {
         if (nodes != null) {
             for (int i = 0; i < nodes.getLength(); i++) {
                 Node node = nodes.item(i);
-                references.add(new Reference(node));
+                references.add(new Reference(clazz, node));
             }
         }
         return references;
@@ -253,6 +253,7 @@ final class OsgiMetadataUtil {
 
     static class OsgiMetadata {
         
+        private final Class<?> clazz;
         private final Set<String> serviceInterfaces;
         private final Map<String, Object> properties;
         private final List<Reference> references;
@@ -260,7 +261,8 @@ final class OsgiMetadataUtil {
         private final String deactivateMethodName;
         private final String modifiedMethodName;
         
-        private OsgiMetadata(Class clazz, Document metadataDocument) {
+        private OsgiMetadata(Class<?> clazz, Document metadataDocument) {
+            this.clazz = clazz;
             this.serviceInterfaces = OsgiMetadataUtil.getServiceInterfaces(clazz, metadataDocument);
             this.properties = OsgiMetadataUtil.getProperties(clazz, metadataDocument);
             this.references = OsgiMetadataUtil.getReferences(clazz, metadataDocument);
@@ -270,6 +272,7 @@ final class OsgiMetadataUtil {
         }
 
         private OsgiMetadata() {
+            this.clazz = null;
             this.serviceInterfaces = null;
             this.properties = null;
             this.references = null;
@@ -278,6 +281,10 @@ final class OsgiMetadataUtil {
             this.modifiedMethodName = null;
         }
         
+        public Class<?> getServiceClass() {
+            return clazz;
+        }
+
         public Set<String> getServiceInterfaces() {
             return serviceInterfaces;
         }
@@ -306,13 +313,15 @@ final class OsgiMetadataUtil {
 
     static class Reference {
 
+        private final Class<?> clazz;
         private final String name;
         private final String interfaceType;
         private final ReferenceCardinality cardinality;
         private final String bind;
         private final String unbind;
 
-        private Reference(Node node) {
+        private Reference(Class<?> clazz, Node node) {
+            this.clazz = clazz;
             this.name = getAttributeValue(node, "name");
             this.interfaceType = getAttributeValue(node, "interface");
             this.cardinality = toCardinality(getAttributeValue(node, "cardinality"));
@@ -320,6 +329,10 @@ final class OsgiMetadataUtil {
             this.unbind = getAttributeValue(node, "unbind");
         }
 
+        public Class<?> getServiceClass() {
+            return clazz;
+        }
+
         private ReferenceCardinality toCardinality(String value) {
             for (ReferenceCardinality item : ReferenceCardinality.values()) {
                 if (StringUtils.equals(item.getCardinalityString(), value)) {
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 b340b29..306a967 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
@@ -299,14 +299,14 @@ final class OsgiServiceUtil {
             boolean isOptional = (reference.getCardinality() == ReferenceCardinality.OPTIONAL_UNARY || reference
                     .getCardinality() == ReferenceCardinality.OPTIONAL_MULTIPLE);
             if (!isOptional) {
-                throw new RuntimeException("Unable to inject mandatory reference '" + reference.getName() + "' for class " + targetClass.getName());
+                throw new ReferenceViolationException("Unable to inject mandatory reference '" + reference.getName() + "' for class " + targetClass.getName());
             }
         }
 
         // multiple references found? check if reference is not multiple
         if (matchingServices.size() > 1
                 && (reference.getCardinality() == ReferenceCardinality.MANDATORY_UNARY || reference.getCardinality() == ReferenceCardinality.OPTIONAL_UNARY)) {
-            throw new RuntimeException("Multiple matches found for unary reference '" + reference.getName() + "' for class "+ targetClass.getName());
+            throw new ReferenceViolationException("Multiple matches found for unary reference '" + reference.getName() + "' for class "+ targetClass.getName());
         }
 
         // try to invoke bind method
@@ -350,7 +350,7 @@ final class OsgiServiceUtil {
         throw new RuntimeException("Bind method with name " + bindMethodName + " not found "
                 + "for reference '" + reference.getName() + "' for class {}" +  targetClass.getName());
     }
-
+    
     private static List<ServiceInfo> getMatchingServices(Class<?> type, BundleContext bundleContext) {
         List<ServiceInfo> matchingServices = new ArrayList<ServiceInfo>();
         try {
diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/ReferenceViolationException.java b/src/main/java/org/apache/sling/testing/mock/osgi/ReferenceViolationException.java
new file mode 100644
index 0000000..4bfa0f2
--- /dev/null
+++ b/src/main/java/org/apache/sling/testing/mock/osgi/ReferenceViolationException.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.testing.mock.osgi;
+
+/**
+ * Is thrown when a OSGi reference injection fails due to violated constraints.
+ */
+public final class ReferenceViolationException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    public ReferenceViolationException(String message) {
+        super(message);
+    }
+
+}
diff --git a/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextTest.java b/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextTest.java
index 6eef138..a6a6258 100644
--- a/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextTest.java
+++ b/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextTest.java
@@ -21,6 +21,7 @@ package org.apache.sling.testing.mock.osgi;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
@@ -50,12 +51,12 @@ public class MockBundleContextTest {
 
     @Before
     public void setUp() {
-        this.bundleContext = MockOsgi.newBundleContext();
+        bundleContext = MockOsgi.newBundleContext();
     }
 
     @Test
     public void testBundle() {
-        assertNotNull(this.bundleContext.getBundle());
+        assertNotNull(bundleContext.getBundle());
     }
 
     @Test
@@ -64,48 +65,64 @@ public class MockBundleContextTest {
         String clazz1 = String.class.getName();
         Object service1 = new Object();
         Dictionary properties1 = getServiceProperties(null);
-        ServiceRegistration reg1 = this.bundleContext.registerService(clazz1, service1, properties1);
+        ServiceRegistration reg1 = bundleContext.registerService(clazz1, service1, properties1);
 
         String[] clazzes2 = new String[] { String.class.getName(), Integer.class.getName() };
         Object service2 = new Object();
         Dictionary properties2 = getServiceProperties(null);
-        ServiceRegistration reg2 = this.bundleContext.registerService(clazzes2, service2, properties2);
+        ServiceRegistration reg2 = bundleContext.registerService(clazzes2, service2, properties2);
 
         String clazz3 = Integer.class.getName();
         Object service3 = new Object();
         Dictionary properties3 = getServiceProperties(100L);
-        ServiceRegistration reg3 = this.bundleContext.registerService(clazz3, service3, properties3);
+        ServiceRegistration reg3 = bundleContext.registerService(clazz3, service3, properties3);
 
         // test get service references
-        ServiceReference refString = this.bundleContext.getServiceReference(String.class.getName());
+        ServiceReference refString = bundleContext.getServiceReference(String.class.getName());
         assertSame(reg1.getReference(), refString);
 
-        ServiceReference refInteger = this.bundleContext.getServiceReference(Integer.class.getName());
+        ServiceReference refInteger = bundleContext.getServiceReference(Integer.class.getName());
         assertSame(reg3.getReference(), refInteger);
 
-        ServiceReference[] refsString = this.bundleContext.getServiceReferences(String.class.getName(), null);
+        ServiceReference[] refsString = bundleContext.getServiceReferences(String.class.getName(), null);
         assertEquals(2, refsString.length);
         assertSame(reg1.getReference(), refsString[0]);
         assertSame(reg2.getReference(), refsString[1]);
 
-        ServiceReference[] refsInteger = this.bundleContext.getServiceReferences(Integer.class.getName(), null);
+        ServiceReference[] refsInteger = bundleContext.getServiceReferences(Integer.class.getName(), null);
         assertEquals(2, refsInteger.length);
         assertSame(reg3.getReference(), refsInteger[0]);
         assertSame(reg2.getReference(), refsInteger[1]);
 
-        ServiceReference[] allRefsString = this.bundleContext.getAllServiceReferences(String.class.getName(), null);
+        ServiceReference[] allRefsString = bundleContext.getAllServiceReferences(String.class.getName(), null);
         assertArrayEquals(refsString, allRefsString);
 
         // test get services
-        assertSame(service1, this.bundleContext.getService(refsString[0]));
-        assertSame(service2, this.bundleContext.getService(refsString[1]));
-        assertSame(service3, this.bundleContext.getService(refInteger));
+        assertSame(service1, bundleContext.getService(refsString[0]));
+        assertSame(service2, bundleContext.getService(refsString[1]));
+        assertSame(service3, bundleContext.getService(refInteger));
 
         // unget does nothing
-        this.bundleContext.ungetService(refsString[0]);
-        this.bundleContext.ungetService(refsString[1]);
-        this.bundleContext.ungetService(refInteger);
+        bundleContext.ungetService(refsString[0]);
+        bundleContext.ungetService(refsString[1]);
+        bundleContext.ungetService(refInteger);
     }
+    
+    @Test
+    public void testServiceUnregistration() {
+        // prepare test services
+        String clazz1 = String.class.getName();
+        Object service1 = new Object();
+        Dictionary properties1 = getServiceProperties(null);
+        ServiceRegistration reg1 = bundleContext.registerService(clazz1, service1, properties1);
+        
+        assertNotNull(bundleContext.getServiceReference(clazz1));
+
+        reg1.unregister();
+
+        assertNull(bundleContext.getServiceReference(clazz1));
+    }
+    
 
     private Dictionary getServiceProperties(final Long serviceRanking) {
         Dictionary<String, Object> props = new Hashtable<String, Object>();
@@ -117,7 +134,7 @@ public class MockBundleContextTest {
 
     @Test
     public void testGetBundles() throws Exception {
-        assertEquals(0, this.bundleContext.getBundles().length);
+        assertEquals(0, bundleContext.getBundles().length);
     }
 
     @Test
@@ -128,7 +145,7 @@ public class MockBundleContextTest {
         // prepare test services
         String clazz1 = String.class.getName();
         Object service1 = new Object();
-        this.bundleContext.registerService(clazz1, service1, null);
+        bundleContext.registerService(clazz1, service1, null);
 
         verify(serviceListener).serviceChanged(any(ServiceEvent.class));
 
@@ -152,8 +169,8 @@ public class MockBundleContextTest {
     public void testFrameworkListener() throws Exception {
         // ensure that listeners can be called (although they are not expected
         // to to anything)
-        this.bundleContext.addFrameworkListener(null);
-        this.bundleContext.removeFrameworkListener(null);
+        bundleContext.addFrameworkListener(null);
+        bundleContext.removeFrameworkListener(null);
     }
 
 }

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