You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2022/11/22 21:03:54 UTC

[sling-org-apache-sling-testing-osgi-mock] branch feature/SLING-11698-serviceobjects created (now 381f3f6)

This is an automated email from the ASF dual-hosted git repository.

sseifert pushed a change to branch feature/SLING-11698-serviceobjects
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-osgi-mock.git


      at 381f3f6  SLING-11698 full support for ComponentServiceObjects

This branch includes the following new commits:

     new 381f3f6  SLING-11698 full support for ComponentServiceObjects

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-org-apache-sling-testing-osgi-mock] 01/01: SLING-11698 full support for ComponentServiceObjects

Posted by ss...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sseifert pushed a commit to branch feature/SLING-11698-serviceobjects
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-osgi-mock.git

commit 381f3f60e75b58dec92f56c8a6d194aa35cba4f7
Author: Stefan Seifert <st...@users.noreply.github.com>
AuthorDate: Tue Nov 22 22:03:36 2022 +0100

    SLING-11698 full support for ComponentServiceObjects
---
 .../sling/testing/mock/osgi/OsgiServiceUtil.java   |  77 +++++++----
 ...eferencesOsgiR6ComponentServiceObjectsTest.java |  34 +++++
 ...ckBundleContextDynamicReferencesOsgiR6Test.java |   7 +-
 ...ctionComponentServiceObjectsReferencesTest.java |  34 +++++
 ...icGreedyConstructorInjectionReferencesTest.java |   6 +-
 .../testing/mock/osgi/OsgiServiceUtilTest.java     |  12 +-
 .../osgi/testsvc/osgiserviceutil/DictionaryTo.java |  42 ++++++
 .../osgi/testsvc/osgiserviceutil/Service3.java     |  11 +-
 .../testsvc/osgiserviceutil/Service3OsgiR6.java    | 118 ++--------------
 ...Service3OsgiR6ComponentServiceObjectsImpl.java} |  69 +++++-----
 ...Service3OsgiR6.java => Service3OsgiR6Impl.java} |  13 +-
 ...ructorInjectionComponentServiceObjectsImpl.java | 148 +++++++++++++++++++++
 .../osgiserviceutil/Service3StaticGreedyImpl.java  |  11 +-
 13 files changed, 381 insertions(+), 201 deletions(-)

diff --git a/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtil.java b/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtil.java
index 6adc7b3..35460ce 100644
--- a/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtil.java
+++ b/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtil.java
@@ -50,7 +50,6 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceObjects;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.ComponentServiceObjects;
@@ -577,7 +576,7 @@ final class OsgiServiceUtil {
             switch (reference.getFieldCollectionType()) {
                 case SERVICE:
                     matchingServices.stream()
-                        .map(ServiceInfo::getServiceInstance)
+                        .map(ServiceInfo::getService)
                         .forEach(collection::add);
                     break;
                 case REFERENCE:
@@ -585,6 +584,9 @@ final class OsgiServiceUtil {
                         .map(ServiceInfo::getServiceReference)
                         .forEach(collection::add);
                     break;
+                case SERVICEOBJECTS:
+                    collection.addAll(matchingServices);
+                    break;
                 default:
                     throw new RuntimeException("Field collection type '" + reference.getFieldCollectionType() + "' not supported "
                             + "for reference '" + reference.getName()  + "' (" + type.getName() +  ") into constructor parameter " + parameterIndex + " for class " +  targetClass.getName());
@@ -598,13 +600,18 @@ final class OsgiServiceUtil {
 
             // 1. assignable from service instance
             if (parameterType.isAssignableFrom(reference.getInterfaceTypeAsClass())) {
-                return firstServiceInfo.map(ServiceInfo::getServiceInstance);
+                return firstServiceInfo.map(ServiceInfo::getService);
             }
 
             // 2. ServiceReference
             if (parameterType == ServiceReference.class) {
                 return firstServiceInfo.map(ServiceInfo::getServiceReference);
             }
+
+            // 3. ServiceReference
+            if (parameterType == ComponentServiceObjects.class) {
+                return firstServiceInfo;
+            }
         }
 
         // no match
@@ -669,7 +676,7 @@ final class OsgiServiceUtil {
             // 2. ComponentServiceObjects
             method = getMethod(targetClass, methodName, new Class<?>[] { ComponentServiceObjects.class });
             if (method != null) {
-                invokeMethod(target, method, new Object[] { toComponentServiceObjects(bundleContext.getServiceObjects(serviceInfo.getServiceReference())) });
+                invokeMethod(target, method, new Object[] { serviceInfo });
                 return;
             }
 
@@ -677,7 +684,7 @@ final class OsgiServiceUtil {
             Class<?> interfaceType = reference.getInterfaceTypeAsClass();
             method = getMethodWithAssignableTypes(targetClass, methodName, new Class<?>[] { interfaceType });
             if (method != null) {
-                invokeMethod(target, method, new Object[] { serviceInfo.getServiceInstance() });
+                invokeMethod(target, method, new Object[] { serviceInfo.getService() });
                 return;
             }
 
@@ -698,10 +705,10 @@ final class OsgiServiceUtil {
                         args[i] = serviceInfo.getServiceReference();
                     }
                     else if (method.getParameterTypes()[i] == ComponentServiceObjects.class) {
-                        args[i] = toComponentServiceObjects(bundleContext.getServiceObjects(serviceInfo.getServiceReference()));
+                        args[i] = serviceInfo;
                     }
                     else if (method.getParameterTypes()[i].isAssignableFrom(interfaceType)) {
-                        args[i] = serviceInfo.getServiceInstance();
+                        args[i] = serviceInfo.getService();
                     }
                     else if (method.getParameterTypes()[i] == Map.class) {
                         args[i] = serviceInfo.getServiceConfig();
@@ -723,12 +730,16 @@ final class OsgiServiceUtil {
                 switch (reference.getFieldCollectionType()) {
                     case SERVICE:
                     case REFERENCE:
+                    case SERVICEOBJECTS:
                         Object item = null;
                         if (serviceInfo != null) {
-                            item = serviceInfo.getServiceInstance();
+                            item = serviceInfo.getService();
                             if (reference.getFieldCollectionType() == FieldCollectionType.REFERENCE) {
                                 item = serviceInfo.getServiceReference();
                             }
+                            else if (reference.getFieldCollectionType() == FieldCollectionType.SERVICEOBJECTS) {
+                                item = serviceInfo;
+                            }
                         }
                         Field field = getCollectionField(targetClass, fieldName);
                         if (field != null) {
@@ -753,7 +764,7 @@ final class OsgiServiceUtil {
                 Class<?> interfaceType = reference.getInterfaceTypeAsClass();
                 Field field = getFieldWithAssignableType(targetClass, fieldName, interfaceType);
                 if (field != null) {
-                    setField(target, field, bind && serviceInfo != null ? serviceInfo.getServiceInstance() : null);
+                    setField(target, field, bind && serviceInfo != null ? serviceInfo.getService() : null);
                     return;
                 }
 
@@ -763,28 +774,18 @@ final class OsgiServiceUtil {
                     setField(target, field, bind && serviceInfo != null ? serviceInfo.getServiceReference() : null);
                     return;
                 }
+
+                // 3. ComponentServiceObjects
+                field = getField(targetClass, fieldName, ComponentServiceObjects.class);
+                if (field != null) {
+                    setField(target, field, bind && serviceInfo != null ? serviceInfo : null);
+                    return;
+                }
             }
         }
 
     }
 
-    private static <T> ComponentServiceObjects<T> toComponentServiceObjects(ServiceObjects<T> serviceObjects) {
-        return new ComponentServiceObjects<T>() {
-            @Override
-            public T getService() {
-                return serviceObjects.getService();
-            }
-            @Override
-            public void ungetService(T service) {
-                serviceObjects.ungetService(service);
-            }
-            @Override
-            public ServiceReference<T> getServiceReference() {
-                return serviceObjects.getServiceReference();
-            }
-        };
-    }
-
     @SuppressWarnings("unchecked")
     private static void addToCollection(Object target, Field field, Object item) {
         try {
@@ -942,7 +943,7 @@ final class OsgiServiceUtil {
         return references;
     }
 
-    static class ServiceInfo<T> {
+    static class ServiceInfo<T> implements ComponentServiceObjects<T> {
 
         private final T serviceInstance;
         private final Map<String, Object> serviceConfig;
@@ -960,7 +961,7 @@ final class OsgiServiceUtil {
             this.serviceReference = registration.getReference();
         }
 
-        public T getServiceInstance() {
+        public T getService() {
             return this.serviceInstance;
         }
 
@@ -972,6 +973,26 @@ final class OsgiServiceUtil {
             return serviceReference;
         }
 
+        @Override
+        public void ungetService(T service) {
+            // nothing to do
+        }
+
+        @Override
+        @SuppressWarnings("null")
+        public int hashCode() {
+            return serviceInstance.hashCode();
+        }
+
+        @Override
+        @SuppressWarnings("null")
+        public boolean equals(Object obj) {
+            if (obj instanceof ServiceInfo) {
+                return serviceInstance.equals(((ServiceInfo)obj).serviceInstance);
+            }
+            return false;
+        }
+
     }
 
     static class ReferenceInfo<T> {
diff --git a/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6ComponentServiceObjectsTest.java b/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6ComponentServiceObjectsTest.java
new file mode 100644
index 0000000..0b04165
--- /dev/null
+++ b/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6ComponentServiceObjectsTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3OsgiR6;
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3OsgiR6ComponentServiceObjectsImpl;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MockBundleContextDynamicReferencesOsgiR6ComponentServiceObjectsTest extends MockBundleContextDynamicReferencesOsgiR6Test {
+
+    @Override
+    protected Service3OsgiR6 newService3OsgiR6() {
+        return new Service3OsgiR6ComponentServiceObjectsImpl();
+    }
+
+}
diff --git a/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6Test.java b/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6Test.java
index 4bebcf4..db6d6d1 100644
--- a/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6Test.java
+++ b/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6Test.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 
 import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3OsgiR6;
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3OsgiR6Impl;
 import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ServiceInterface1;
 import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ServiceInterface1Optional;
 import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ServiceInterface2;
@@ -74,7 +75,7 @@ public class MockBundleContextDynamicReferencesOsgiR6Test {
         reg1a = bundleContext.registerService(ServiceInterface1.class.getName(), dependency1a, null);
         reg2a = bundleContext.registerService(ServiceInterface2.class.getName(), dependency2a, null);
 
-        service = new Service3OsgiR6();
+        service = newService3OsgiR6();
         MockOsgi.injectServices(service, bundleContext);
         MockOsgi.activate(service, bundleContext);
         bundleContext.registerService(Service3OsgiR6.class.getName(), service, MapUtil.toDictionary(ImmutableMap.<String,Object>of("reference3DynamicFiltered.target","(prop1=def)")));
@@ -85,6 +86,10 @@ public class MockBundleContextDynamicReferencesOsgiR6Test {
         assertDependencies3();
     }
 
+    protected Service3OsgiR6 newService3OsgiR6() {
+        return new Service3OsgiR6Impl();
+    }
+
     @Test
     public void testAddRemoveOptionalUnaryService() {
         ServiceRegistration reg1aOptional = bundleContext.registerService(ServiceInterface1Optional.class.getName(), dependency1aOptional, null);
diff --git a/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextStaticGreedyConstructorInjectionComponentServiceObjectsReferencesTest.java b/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextStaticGreedyConstructorInjectionComponentServiceObjectsReferencesTest.java
new file mode 100644
index 0000000..45abff3
--- /dev/null
+++ b/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextStaticGreedyConstructorInjectionComponentServiceObjectsReferencesTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3StaticGreedy;
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3StaticGreedyConstructorInjectionComponentServiceObjectsImpl;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MockBundleContextStaticGreedyConstructorInjectionComponentServiceObjectsReferencesTest  extends MockBundleContextStaticGreedyConstructorInjectionReferencesTest {
+
+    @Override
+    protected Class<? extends Service3StaticGreedy> getService3StaticGreedyClass() {
+        return Service3StaticGreedyConstructorInjectionComponentServiceObjectsImpl.class;
+    }
+
+}
diff --git a/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextStaticGreedyConstructorInjectionReferencesTest.java b/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextStaticGreedyConstructorInjectionReferencesTest.java
index 1673f93..ce0bebf 100644
--- a/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextStaticGreedyConstructorInjectionReferencesTest.java
+++ b/core/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextStaticGreedyConstructorInjectionReferencesTest.java
@@ -72,7 +72,7 @@ public class MockBundleContextStaticGreedyConstructorInjectionReferencesTest {
         reg1a = bundleContext.registerService(ServiceInterface1.class.getName(), dependency1a, null);
         reg2a = bundleContext.registerService(ServiceInterface2.class.getName(), dependency2a, null);
 
-        Service3StaticGreedy service = MockOsgi.activateInjectServices(Service3StaticGreedyConstructorInjectionImpl.class, bundleContext);
+        Service3StaticGreedy service = MockOsgi.activateInjectServices(getService3StaticGreedyClass(), bundleContext);
         bundleContext.registerService(Service3StaticGreedy.class.getName(), service, null);
 
         assertDependency1(dependency1a);
@@ -81,6 +81,10 @@ public class MockBundleContextStaticGreedyConstructorInjectionReferencesTest {
         assertDependencies3();
     }
 
+    protected Class<? extends Service3StaticGreedy> getService3StaticGreedyClass() {
+        return Service3StaticGreedyConstructorInjectionImpl.class;
+    }
+
     @Test
     public void testAddRemoveOptionalUnaryService() {
         ServiceRegistration reg1aOptional = bundleContext.registerService(ServiceInterface1Optional.class.getName(), dependency1aOptional, null);
diff --git a/core/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java b/core/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java
index 3e428ce..53eb85f 100644
--- a/core/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java
+++ b/core/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java
@@ -36,6 +36,8 @@ import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service1;
 import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service2;
 import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3;
 import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3OsgiR6;
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3OsgiR6ComponentServiceObjectsImpl;
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3OsgiR6Impl;
 import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service4;
 import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service5;
 import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ServiceFactory1;
@@ -110,7 +112,15 @@ public class OsgiServiceUtilTest {
 
     @Test
     public void testService3OsgiR6() {
-        Service3OsgiR6 service3 = new Service3OsgiR6();
+        testService3OsgiR6(new Service3OsgiR6Impl());
+    }
+
+    @Test
+    public void testService3OsgiR6ComponentServiceObjects() {
+        testService3OsgiR6(new Service3OsgiR6ComponentServiceObjectsImpl());
+    }
+
+    private void testService3OsgiR6(Service3OsgiR6 service3) {
         assertTrue(MockOsgi.injectServices(service3, bundleContext));
 
         Dictionary<String, Object> service3Config = new Hashtable<String, Object>();
diff --git a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/DictionaryTo.java b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/DictionaryTo.java
new file mode 100644
index 0000000..8b5f111
--- /dev/null
+++ b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/DictionaryTo.java
@@ -0,0 +1,42 @@
+/*
+ * 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.testsvc.osgiserviceutil;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+final class DictionaryTo {
+
+    private DictionaryTo() {
+        // static methods only
+    }
+
+    public static Map<String,Object> map(Dictionary<String,Object> dictionary) {
+        Map<String,Object> result = new HashMap<>();
+        Enumeration<String> keys = dictionary.keys();
+        while (keys.hasMoreElements()) {
+            String key = keys.nextElement();
+            result.put(key, dictionary.get(key));
+        }
+        return result;
+    }
+
+}
diff --git a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3.java b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3.java
index 6f0bd12..fb48824 100644
--- a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3.java
+++ b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3.java
@@ -19,8 +19,6 @@
 package org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil;
 
 import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -69,14 +67,7 @@ public class Service3 implements ServiceInterface2 {
     @Activate
     private void activate(ComponentContext ctx) {
         this.componentContext = ctx;
-
-        // copy properties dictionary to config map
-        this.config = new HashMap<>();
-        Enumeration<String> keys = ctx.getProperties().keys();
-        while (keys.hasMoreElements()) {
-            String key = keys.nextElement();
-            this.config.put(key, ctx.getProperties().get(key));
-        }
+        this.config = DictionaryTo.map(ctx.getProperties());
     }
 
     @Deactivate
diff --git a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6.java b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6.java
index 17ad401..b8745b8 100644
--- a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6.java
+++ b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6.java
@@ -18,129 +18,33 @@
  */
 package org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.FieldOption;
-import org.osgi.service.component.annotations.Modified;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.osgi.service.component.annotations.ReferencePolicy;
-import org.osgi.service.component.annotations.ReferencePolicyOption;
 
-@Component
-public class Service3OsgiR6 {
+public interface Service3OsgiR6 {
 
-    @Reference
-    private ServiceInterface1 reference1;
+    ServiceInterface1 getReference1();
 
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
-    private volatile ServiceInterface1Optional reference1Optional;
+    ServiceInterface1Optional getReference1Optional();
 
-    @Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE,
-            policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
-    private volatile List<ServiceReference<ServiceInterface2>> references2 = new ArrayList<>();
+    List<ServiceInterface2> getReferences2();
 
-    @Reference(service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE,
-            policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
-    private volatile List<ServiceSuperInterface3> references3;
+    List<ServiceSuperInterface3> getReferences3();
 
-    @Reference(service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE, target="(prop1=abc)",
-            policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
-    private volatile List<ServiceSuperInterface3> references3Filtered;
+    List<ServiceSuperInterface3> getReferences3Filtered();
 
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL,
-            policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY,
-            name = "reference3DynamicFiltered")
-    private volatile ServiceSuperInterface3 reference3DynamicFiltered;
+    ServiceSuperInterface3 getReference3DynamicFiltered();
 
-    @Reference(service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE,
-            policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY,
-            fieldOption = FieldOption.UPDATE)
-    private volatile Set<ServiceSuperInterface3> references3Set;
+    Set<ServiceSuperInterface3> getReferences3Set();
 
-    @Reference(service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE,
-            policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
-    private volatile Collection<ServiceSuperInterface3> references3Collection;
+    Collection<ServiceSuperInterface3> getReferences3Collection();
 
-    private ComponentContext componentContext;
-    private Map<String, Object> config;
+    ComponentContext getComponentContext();
 
-    @Activate
-    private void activate(ComponentContext ctx) {
-        this.componentContext = ctx;
-
-        // copy properties dictionary to config map
-        this.config = new HashMap<>();
-        Enumeration<String> keys = ctx.getProperties().keys();
-        while (keys.hasMoreElements()) {
-            String key = keys.nextElement();
-            this.config.put(key, ctx.getProperties().get(key));
-        }
-    }
-
-    @Deactivate
-    private void deactivate(ComponentContext ctx) {
-        this.componentContext = null;
-    }
-
-    @Modified
-    private void modified(Map<String,Object> newConfig) {
-        this.config = newConfig;
-    }
-
-    public ServiceInterface1 getReference1() {
-        return this.reference1;
-    }
-
-    public ServiceInterface1Optional getReference1Optional() {
-        return this.reference1Optional;
-    }
-
-    public List<ServiceInterface2> getReferences2() {
-        List<ServiceInterface2> services = new ArrayList<ServiceInterface2>();
-        for (ServiceReference<?> serviceReference : references2) {
-            services.add((ServiceInterface2)componentContext.getBundleContext().getService(serviceReference));
-        }
-        return services;
-    }
-
-    public List<ServiceSuperInterface3> getReferences3() {
-        return this.references3;
-    }
-
-    public List<ServiceSuperInterface3> getReferences3Filtered() {
-        return this.references3Filtered;
-    }
-
-    public ServiceSuperInterface3 getReference3DynamicFiltered() {
-        return this.reference3DynamicFiltered;
-    }
-
-    public Set<ServiceSuperInterface3> getReferences3Set() {
-        return this.references3Set;
-    }
-
-    public Collection<ServiceSuperInterface3> getReferences3Collection() {
-        return this.references3Collection;
-    }
-
-    public ComponentContext getComponentContext() {
-        return this.componentContext;
-    }
-
-    public Map<String, Object> getConfig() {
-        return config;
-    }
+    Map<String, Object> getConfig();
 
 }
diff --git a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6.java b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6ComponentServiceObjectsImpl.java
similarity index 64%
copy from test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6.java
copy to test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6ComponentServiceObjectsImpl.java
index 17ad401..969227c 100644
--- a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6.java
+++ b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6ComponentServiceObjectsImpl.java
@@ -20,14 +20,14 @@ package org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Collectors;
 
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.ComponentServiceObjects;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
@@ -39,39 +39,39 @@ import org.osgi.service.component.annotations.ReferencePolicy;
 import org.osgi.service.component.annotations.ReferencePolicyOption;
 
 @Component
-public class Service3OsgiR6 {
+public class Service3OsgiR6ComponentServiceObjectsImpl implements Service3OsgiR6 {
 
     @Reference
-    private ServiceInterface1 reference1;
+    private ComponentServiceObjects<ServiceInterface1> reference1;
 
     @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
-    private volatile ServiceInterface1Optional reference1Optional;
+    private volatile ComponentServiceObjects<ServiceInterface1Optional> reference1Optional;
 
     @Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE,
             policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
-    private volatile List<ServiceReference<ServiceInterface2>> references2 = new ArrayList<>();
+    private volatile List<ComponentServiceObjects<ServiceInterface2>> references2 = new ArrayList<>();
 
     @Reference(service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE,
             policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
-    private volatile List<ServiceSuperInterface3> references3;
+    private volatile List<ComponentServiceObjects<ServiceSuperInterface3>> references3;
 
     @Reference(service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE, target="(prop1=abc)",
             policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
-    private volatile List<ServiceSuperInterface3> references3Filtered;
+    private volatile List<ComponentServiceObjects<ServiceSuperInterface3>> references3Filtered;
 
     @Reference(cardinality = ReferenceCardinality.OPTIONAL,
             policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY,
             name = "reference3DynamicFiltered")
-    private volatile ServiceSuperInterface3 reference3DynamicFiltered;
+    private volatile ComponentServiceObjects<ServiceSuperInterface3> reference3DynamicFiltered;
 
     @Reference(service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE,
             policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY,
             fieldOption = FieldOption.UPDATE)
-    private volatile Set<ServiceSuperInterface3> references3Set;
+    private volatile Set<ComponentServiceObjects<ServiceSuperInterface3>> references3Set;
 
     @Reference(service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE,
             policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
-    private volatile Collection<ServiceSuperInterface3> references3Collection;
+    private volatile Collection<ComponentServiceObjects<ServiceSuperInterface3>> references3Collection;
 
     private ComponentContext componentContext;
     private Map<String, Object> config;
@@ -79,14 +79,7 @@ public class Service3OsgiR6 {
     @Activate
     private void activate(ComponentContext ctx) {
         this.componentContext = ctx;
-
-        // copy properties dictionary to config map
-        this.config = new HashMap<>();
-        Enumeration<String> keys = ctx.getProperties().keys();
-        while (keys.hasMoreElements()) {
-            String key = keys.nextElement();
-            this.config.put(key, ctx.getProperties().get(key));
-        }
+        this.config = DictionaryTo.map(ctx.getProperties());
     }
 
     @Deactivate
@@ -100,39 +93,51 @@ public class Service3OsgiR6 {
     }
 
     public ServiceInterface1 getReference1() {
-        return this.reference1;
+        return Optional.ofNullable(this.reference1)
+            .map(ComponentServiceObjects::getService)
+            .orElse(null);
     }
 
     public ServiceInterface1Optional getReference1Optional() {
-        return this.reference1Optional;
+        return Optional.ofNullable(this.reference1Optional)
+                .map(ComponentServiceObjects::getService)
+                .orElse(null);
     }
 
     public List<ServiceInterface2> getReferences2() {
-        List<ServiceInterface2> services = new ArrayList<ServiceInterface2>();
-        for (ServiceReference<?> serviceReference : references2) {
-            services.add((ServiceInterface2)componentContext.getBundleContext().getService(serviceReference));
-        }
-        return services;
+        return references2.stream()
+                .map(ComponentServiceObjects::getService)
+                .collect(Collectors.toList());
     }
 
     public List<ServiceSuperInterface3> getReferences3() {
-        return this.references3;
+        return this.references3.stream()
+                .map(ComponentServiceObjects::getService)
+                .collect(Collectors.toList());
     }
 
     public List<ServiceSuperInterface3> getReferences3Filtered() {
-        return this.references3Filtered;
+        return this.references3Filtered.stream()
+                .map(ComponentServiceObjects::getService)
+                .collect(Collectors.toList());
     }
 
     public ServiceSuperInterface3 getReference3DynamicFiltered() {
-        return this.reference3DynamicFiltered;
+        return Optional.ofNullable(this.reference3DynamicFiltered)
+                .map(ComponentServiceObjects::getService)
+                .orElse(null);
     }
 
     public Set<ServiceSuperInterface3> getReferences3Set() {
-        return this.references3Set;
+        return this.references3Set.stream()
+                .map(ComponentServiceObjects::getService)
+                .collect(Collectors.toSet());
     }
 
     public Collection<ServiceSuperInterface3> getReferences3Collection() {
-        return this.references3Collection;
+        return this.references3Collection.stream()
+                .map(ComponentServiceObjects::getService)
+                .collect(Collectors.toList());
     }
 
     public ComponentContext getComponentContext() {
diff --git a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6.java b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6Impl.java
similarity index 92%
copy from test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6.java
copy to test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6Impl.java
index 17ad401..5c2043a 100644
--- a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6.java
+++ b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3OsgiR6Impl.java
@@ -20,8 +20,6 @@ package org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -39,7 +37,7 @@ import org.osgi.service.component.annotations.ReferencePolicy;
 import org.osgi.service.component.annotations.ReferencePolicyOption;
 
 @Component
-public class Service3OsgiR6 {
+public class Service3OsgiR6Impl implements Service3OsgiR6 {
 
     @Reference
     private ServiceInterface1 reference1;
@@ -79,14 +77,7 @@ public class Service3OsgiR6 {
     @Activate
     private void activate(ComponentContext ctx) {
         this.componentContext = ctx;
-
-        // copy properties dictionary to config map
-        this.config = new HashMap<>();
-        Enumeration<String> keys = ctx.getProperties().keys();
-        while (keys.hasMoreElements()) {
-            String key = keys.nextElement();
-            this.config.put(key, ctx.getProperties().get(key));
-        }
+        this.config = DictionaryTo.map(ctx.getProperties());
     }
 
     @Deactivate
diff --git a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3StaticGreedyConstructorInjectionComponentServiceObjectsImpl.java b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3StaticGreedyConstructorInjectionComponentServiceObjectsImpl.java
new file mode 100644
index 0000000..af66ad9
--- /dev/null
+++ b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3StaticGreedyConstructorInjectionComponentServiceObjectsImpl.java
@@ -0,0 +1,148 @@
+/*
+ * 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.testsvc.osgiserviceutil;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.ComponentServiceObjects;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+@Component(service= Service3StaticGreedy.class)
+public class Service3StaticGreedyConstructorInjectionComponentServiceObjectsImpl implements Service3StaticGreedy {
+
+    private final ComponentServiceObjects<ServiceInterface1> reference1;
+    private final ComponentServiceObjects<ServiceInterface1Optional> reference1Optional;
+    private final List<ComponentServiceObjects<ServiceInterface2>> references2;
+    private final List<ComponentServiceObjects<ServiceSuperInterface3>> references3;
+
+    private final ComponentContext componentContext;
+    private final Map<String, Object> config;
+
+    // this constructor should be ignored as it contains additional parameters not valid for injection
+    public Service3StaticGreedyConstructorInjectionComponentServiceObjectsImpl(
+            ComponentServiceObjects<ServiceInterface1> reference1,
+            ComponentServiceObjects<ServiceInterface1Optional> reference1Optional,
+            List<ComponentServiceObjects<ServiceInterface2>> references2,
+            List<ComponentServiceObjects<ServiceSuperInterface3>> references3,
+            ComponentContext ctx,
+            Map<String, Object> config,
+            Object illegalParameter) {
+
+        this.componentContext = ctx;
+
+        this.reference1 = reference1;
+        this.reference1Optional = reference1Optional;
+        this.references2 = references2;
+        this.references3 = references3;
+
+        this.config = config;
+    }
+
+    @Activate
+    public Service3StaticGreedyConstructorInjectionComponentServiceObjectsImpl(
+
+            @Reference(policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY)
+            ComponentServiceObjects<ServiceInterface1> reference1,
+
+            @Reference(cardinality = ReferenceCardinality.OPTIONAL,
+                    policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY)
+            ComponentServiceObjects<ServiceInterface1Optional> reference1Optional,
+
+            @Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE,
+                    policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY)
+            List<ComponentServiceObjects<ServiceInterface2>> references2,
+
+            @Reference(name = "reference3", service = ServiceInterface3.class, cardinality = ReferenceCardinality.MULTIPLE,
+                    policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY)
+            List<ComponentServiceObjects<ServiceSuperInterface3>> references3,
+
+            ComponentContext ctx,
+            Map<String, Object> config) {
+
+        this.componentContext = ctx;
+
+        this.reference1 = reference1;
+        this.reference1Optional = reference1Optional;
+        this.references2 = references2;
+        this.references3 = references3;
+
+        this.config = config;
+    }
+
+    @Override
+    public ServiceInterface1 getReference1() {
+        return Optional.ofNullable(this.reference1)
+                .map(ComponentServiceObjects::getService)
+                .orElse(null);
+    }
+
+    @Override
+    public ServiceInterface1Optional getReference1Optional() {
+        return Optional.ofNullable(this.reference1Optional)
+                .map(ComponentServiceObjects::getService)
+                .orElse(null);
+    }
+
+    @Override
+    public List<ServiceInterface2> getReferences2() {
+        return references2.stream()
+                .map(ComponentServiceObjects::getService)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<ServiceSuperInterface3> getReferences3() {
+        return this.references3.stream()
+                .map(ComponentServiceObjects::getService)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<Map<String, Object>> getReference3Configs() {
+        return this.references3.stream()
+                .map(ComponentServiceObjects::getServiceReference)
+                .map(ServiceReference::getProperties)
+                .map(DictionaryTo::map)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<ServiceSuperInterface3> getReferences3Filtered() {
+        return null;
+    }
+
+    public ComponentContext getComponentContext() {
+        return this.componentContext;
+    }
+
+    public Map<String, Object> getConfig() {
+        return config;
+    }
+
+}
diff --git a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3StaticGreedyImpl.java b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3StaticGreedyImpl.java
index 6beb5d8..aadd261 100644
--- a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3StaticGreedyImpl.java
+++ b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/Service3StaticGreedyImpl.java
@@ -19,8 +19,6 @@
 package org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil;
 
 import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -67,14 +65,7 @@ public class Service3StaticGreedyImpl implements Service3StaticGreedy {
     @Activate
     private void activate(ComponentContext ctx) {
         this.componentContext = ctx;
-
-        // copy properties dictionary to config map
-        this.config = new HashMap<>();
-        Enumeration<String> keys = ctx.getProperties().keys();
-        while (keys.hasMoreElements()) {
-            String key = keys.nextElement();
-            this.config.put(key, ctx.getProperties().get(key));
-        }
+        this.config = DictionaryTo.map(ctx.getProperties());
     }
 
     @Deactivate