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-2.0.0
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-osgi-mock.git

commit bf51720f966b0a801ccb5bb87cf9284a6ad47447
Author: Stefan Seifert <[email protected]>
AuthorDate: Tue Nov 24 00:36:18 2015 +0000

    SLING-5325 osgi-mock: Support target filtering on DS references
    
    git-svn-id: 
https://svn.apache.org/repos/asf/sling/trunk/testing/mocks/osgi-mock@1716001 
13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/testing/mock/osgi/MockBundleContext.java | 56 ++++++++++++----------
 .../sling/testing/mock/osgi/OsgiMetadataUtil.java  | 33 +++++++++++++
 .../sling/testing/mock/osgi/OsgiServiceUtil.java   | 43 ++++++++++-------
 ...ockBundleContextDynamicReferncesOsgiR6Test.java | 19 ++++++++
 .../testing/mock/osgi/OsgiServiceUtilTest.java     |  9 +++-
 ...sling.testing.mock.osgi.OsgiServiceUtilTest.xml |  1 +
 6 files changed, 115 insertions(+), 46 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 6a659cb..7ea264c 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
@@ -125,18 +125,20 @@ class MockBundleContext implements BundleContext {
         List<ReferenceInfo> affectedReferences = 
OsgiServiceUtil.getMatchingDynamicReferences(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, 
referenceInfo.getServiceRegistration().getService(),
-                        new ServiceInfo(registration));
-                break;
-            default:
-                throw new RuntimeException("Unepxected cardinality: " + 
reference.getCardinality());
+            if (reference.matchesTargetFilter(registration.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, 
referenceInfo.getServiceRegistration().getService(),
+                            new ServiceInfo(registration));
+                    break;
+                default:
+                    throw new RuntimeException("Unepxected cardinality: " + 
reference.getCardinality());
+                }
             }
         }
     }
@@ -156,20 +158,22 @@ class MockBundleContext implements BundleContext {
         List<ReferenceInfo> affectedReferences = 
OsgiServiceUtil.getMatchingDynamicReferences(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, 
referenceInfo.getServiceRegistration().getService(),
-                        new ServiceInfo(registration));
-                break;
-            default:
-                throw new RuntimeException("Unepxected cardinality: " + 
reference.getCardinality());
+            if (reference.matchesTargetFilter(registration.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, 
referenceInfo.getServiceRegistration().getService(),
+                            new ServiceInfo(registration));
+                    break;
+                default:
+                    throw new RuntimeException("Unepxected cardinality: " + 
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 85db326..c3ad237 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
@@ -41,6 +41,10 @@ import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.felix.framework.FilterImpl;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -391,6 +395,8 @@ final class OsgiMetadataUtil {
         private final String unbind;
         private final String field;
         private final FieldCollectionType fieldCollectionType;
+        private final String target;
+        private final Filter targetFilter;
 
         private Reference(Class<?> clazz, Node node) {
             this.clazz = clazz;
@@ -403,6 +409,17 @@ final class OsgiMetadataUtil {
             this.unbind = getAttributeValue(node, "unbind");
             this.field = getAttributeValue(node, "field");
             this.fieldCollectionType = 
toFieldCollectionType(getAttributeValue(node, "field-collection-type"));
+            this.target = getAttributeValue(node, "target");
+            if (StringUtils.isNotEmpty(this.target)) {
+                try {
+                    this.targetFilter = new FilterImpl(this.target);
+                } catch (InvalidSyntaxException ex) {
+                    throw new RuntimeException("Invalid target filet in 
reference '" + this.name + "' of class " + clazz.getName(), ex);
+                }
+            }
+            else {
+                this.targetFilter = null;
+            }
         }
 
         public Class<?> getServiceClass() {
@@ -434,6 +451,11 @@ final class OsgiMetadataUtil {
                     || this.cardinality == 
ReferenceCardinality.MANDATORY_MULTIPLE;
         }
 
+        public boolean isCardinalityOptional() {
+            return this.cardinality == ReferenceCardinality.OPTIONAL_UNARY
+                    || this.cardinality == 
ReferenceCardinality.OPTIONAL_MULTIPLE;
+        }
+
         public ReferencePolicy getPolicy() {
             return policy;
         }
@@ -454,6 +476,17 @@ final class OsgiMetadataUtil {
             return this.field;
         }
         
+        public String getTarget() {
+            return this.target;
+        }
+        
+        public boolean matchesTargetFilter(ServiceReference<?> 
serviceReference) {
+            if (targetFilter == null) {
+                return true;
+            }
+            return targetFilter.match(serviceReference);
+        }
+        
         public FieldCollectionType getFieldCollectionType() {
             return this.fieldCollectionType;
         }
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 1f8eaa0..ea304d5 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
@@ -34,7 +34,6 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.FieldCollectionType;
 import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.OsgiMetadata;
 import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.Reference;
-import 
org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.ReferenceCardinality;
 import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.ReferencePolicy;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
@@ -343,20 +342,21 @@ final class OsgiServiceUtil {
         Class<?> type = reference.getInterfaceTypeAsClass();
 
         // get matching service references
-        List<ServiceInfo> matchingServices = getMatchingServices(type, 
bundleContext);
+        List<ServiceInfo> matchingServices = getMatchingServices(type, 
bundleContext, reference.getTarget());
 
         // no references found? check if reference was optional
         if (matchingServices.isEmpty()) {
-            boolean isOptional = (reference.getCardinality() == 
ReferenceCardinality.OPTIONAL_UNARY || reference
-                    .getCardinality() == 
ReferenceCardinality.OPTIONAL_MULTIPLE);
-            if (!isOptional) {
+            if (!reference.isCardinalityOptional()) {
                 throw new ReferenceViolationException("Unable to inject 
mandatory reference '" + reference.getName() + "' for class " + 
targetClass.getName() + " : no matching services were found.");
             }
+            if (reference.isCardinalityMultiple()) {
+                // make sure at least empty array is set  
+                invokeBindUnbindMethod(reference, target, null, true);
+            }
         }
 
         // multiple references found? check if reference is not multiple
-        if (matchingServices.size() > 1
-                && (reference.getCardinality() == 
ReferenceCardinality.MANDATORY_UNARY || reference.getCardinality() == 
ReferenceCardinality.OPTIONAL_UNARY)) {
+        if (matchingServices.size() > 1 && !reference.isCardinalityMultiple()) 
{
             throw new ReferenceViolationException("Multiple matches found for 
unary reference '" + reference.getName() + "' for class "+ 
targetClass.getName());
         }
 
@@ -378,7 +378,7 @@ final class OsgiServiceUtil {
                     + "for reference '" + reference.getName() + "' for class " 
+  targetClass.getName());
         }
 
-        if (StringUtils.isNotEmpty(methodName)) {
+        if (StringUtils.isNotEmpty(methodName) && serviceInfo != null) {
             
             // 1. ServiceReference
             Method method = getMethod(targetClass, methodName, new Class<?>[] 
{ ServiceReference.class });
@@ -414,9 +414,12 @@ final class OsgiServiceUtil {
                 switch (reference.getFieldCollectionType()) {
                     case SERVICE:
                     case REFERENCE:
-                        Object item = serviceInfo.getServiceInstance();
-                        if (reference.getFieldCollectionType() == 
FieldCollectionType.REFERENCE) {
-                            item = serviceInfo.getServiceReference();
+                        Object item = null;
+                        if (serviceInfo != null) {
+                            item = serviceInfo.getServiceInstance();
+                            if (reference.getFieldCollectionType() == 
FieldCollectionType.REFERENCE) {
+                                item = serviceInfo.getServiceReference();
+                            }
                         }
                         // 1. collection
                         Field field = getFieldWithAssignableType(targetClass, 
fieldName, Collection.class);
@@ -454,14 +457,14 @@ final class OsgiServiceUtil {
                 Class<?> interfaceType = reference.getInterfaceTypeAsClass();
                 Field field = getFieldWithAssignableType(targetClass, 
fieldName, interfaceType);
                 if (field != null) {
-                    setField(target, field, bind ? 
serviceInfo.getServiceInstance() : null);
+                    setField(target, field, bind && serviceInfo != null ? 
serviceInfo.getServiceInstance() : null);
                     return;
                 }
                 
                 // 2. ServiceReference
                 field = getField(targetClass, fieldName, 
ServiceReference.class);
                 if (field != null) {
-                    setField(target, field, bind ? 
serviceInfo.getServiceReference() : null);
+                    setField(target, field, bind && serviceInfo != null ? 
serviceInfo.getServiceReference() : null);
                     return;
                 }
             }
@@ -477,7 +480,9 @@ final class OsgiServiceUtil {
             if (collection == null) {
                 collection = new ArrayList<>();
             }
-            collection.add(item);
+            if (item != null) {
+                collection.add(item);
+            }
             field.set(target, collection);
             
         } catch (IllegalAccessException ex) {
@@ -495,9 +500,11 @@ final class OsgiServiceUtil {
             field.setAccessible(true);
             Collection<Object> collection = 
(Collection<Object>)field.get(target);
             if (collection == null) {
-                return;
+                collection = new ArrayList<>();
+            }
+            if (item != null) {
+                collection.remove(item);
             }
-            collection.remove(item);
             field.set(target, collection);
             
         } catch (IllegalAccessException ex) {
@@ -529,10 +536,10 @@ final class OsgiServiceUtil {
         invokeBindUnbindMethod(reference,  target, serviceInfo, false);
     }
     
-    private static List<ServiceInfo> getMatchingServices(Class<?> type, 
BundleContext bundleContext) {
+    private static List<ServiceInfo> getMatchingServices(Class<?> type, 
BundleContext bundleContext, String filter) {
         List<ServiceInfo> matchingServices = new ArrayList<ServiceInfo>();
         try {
-            ServiceReference[] references = 
bundleContext.getServiceReferences(type.getName(), null);
+            ServiceReference[] references = 
bundleContext.getServiceReferences(type.getName(), filter);
             if (references != null) {
                 for (ServiceReference<?> serviceReference : references) {
                     Object serviceInstance = 
bundleContext.getService(serviceReference);
diff --git 
a/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferncesOsgiR6Test.java
 
b/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferncesOsgiR6Test.java
index 0af80e9..b73bf5f 100644
--- 
a/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferncesOsgiR6Test.java
+++ 
b/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferncesOsgiR6Test.java
@@ -36,6 +36,7 @@ import org.mockito.runners.MockitoJUnitRunner;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
 @RunWith(MockitoJUnitRunner.class)
@@ -138,6 +139,19 @@ public class MockBundleContextDynamicReferncesOsgiR6Test {
         assertDependencies2();
     }
     
+    @Test
+    public void testReferenceWithTargetFilter() {
+        assertDependencies3Filtered();
+        
+        bundleContext.registerService(ServiceInterface3.class.getName(), 
dependency3a, 
+                MapUtil.toDictionary(ImmutableMap.<String, Object>of("prop1", 
"abc")));
+
+        bundleContext.registerService(ServiceInterface3.class.getName(), 
dependency3b, 
+                MapUtil.toDictionary(ImmutableMap.<String, Object>of("prop1", 
"def")));
+        
+        assertDependencies3Filtered(dependency3a);
+    }
+    
     private void assertDependency1(ServiceInterface1 instance) {
         if (instance == null) {
             assertNull(service.getReference1());
@@ -166,4 +180,9 @@ public class MockBundleContextDynamicReferncesOsgiR6Test {
                 
ImmutableSet.<ServiceSuperInterface3>copyOf(service.getReferences3()));
     }
     
+    private void assertDependencies3Filtered(ServiceSuperInterface3... 
instances) {
+        assertEquals(ImmutableSet.<ServiceSuperInterface3>copyOf(instances), 
+                
ImmutableSet.<ServiceSuperInterface3>copyOf(service.getReferences3Filtered()));
+    }
+    
 }
diff --git 
a/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java 
b/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java
index 9135bcf..8d086ad 100644
--- a/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java
+++ b/src/test/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtilTest.java
@@ -339,8 +339,9 @@ public class OsgiServiceUtilTest {
 
         private ServiceInterface1 reference1;
         private ServiceInterface1Optional reference1Optional;
-        private List<ServiceReference> references2 = new 
ArrayList<ServiceReference>();
-        private List<ServiceSuperInterface3> references3 = new 
ArrayList<ServiceSuperInterface3>();
+        private List<ServiceReference> references2;
+        private List<ServiceSuperInterface3> references3;
+        private List<ServiceSuperInterface3> references3Filtered;
 
         private ComponentContext componentContext;
         private Map<String, Object> config;
@@ -381,6 +382,10 @@ public class OsgiServiceUtilTest {
             return this.references3;
         }
 
+        public List<ServiceSuperInterface3> getReferences3Filtered() {
+            return this.references3Filtered;
+        }
+
         public ComponentContext getComponentContext() {
             return this.componentContext;
         }
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 94602cc..d8d0095 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
@@ -50,6 +50,7 @@
     <reference name="reference1Optional" 
interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface1Optional"
 cardinality="0..1" policy="dynamic" field="reference1Optional"/>
     <reference name="reference2" 
interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface2"
 cardinality="1..n" policy="dynamic" field="references2" 
field-collection-type="reference"/>
     <reference name="reference3" 
interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface3"
 cardinality="0..n" policy="dynamic" field="references3" 
field-collection-type="service"/>
+    <reference name="references3Filtered" 
interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface3"
 cardinality="0..n" policy="dynamic" field="references3Filtered" 
field-collection-type="service" target="(prop1=abc)"/>
   </scr:component>
   <scr:component 
name="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$Service4_other_name">
     <implementation 
class="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$Service4"/>

-- 
To stop receiving notification emails like this one, please contact
"[email protected]" <[email protected]>.

Reply via email to