Merge branch 'dynamic-reference-properties'
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 0340a55..07b80d2 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
@@ -37,6 +37,7 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.framework.FilterImpl;
+import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.DynamicReference;
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;
@@ -55,6 +56,7 @@
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.component.ComponentConstants;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
@@ -142,6 +144,11 @@
List<ReferenceInfo> affectedDynamicReferences = OsgiServiceUtil.getMatchingDynamicReferences(registeredServices, registration);
for (ReferenceInfo referenceInfo : affectedDynamicReferences) {
Reference reference = referenceInfo.getReference();
+ // Look for a target override
+ Object o = referenceInfo.getServiceRegistration().getProperties().get(reference.getName() + ComponentConstants.REFERENCE_TARGET_SUFFIX);
+ if (o != null && o instanceof String) {
+ reference = new DynamicReference(reference,(String)o);
+ }
if (reference.matchesTargetFilter(registration.getReference())) {
switch (reference.getCardinality()) {
case MANDATORY_UNARY:
diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/MockOsgi.java b/src/main/java/org/apache/sling/testing/mock/osgi/MockOsgi.java
index 7c07578..4d22717 100644
--- a/src/main/java/org/apache/sling/testing/mock/osgi/MockOsgi.java
+++ b/src/main/java/org/apache/sling/testing/mock/osgi/MockOsgi.java
@@ -145,7 +145,20 @@
* @return true if all dependencies could be injected, false if the service has no dependencies.
*/
public static boolean injectServices(Object target, BundleContext bundleContext) {
- return OsgiServiceUtil.injectServices(target, bundleContext);
+ return MockOsgi.injectServices(target, bundleContext, (Map<String, Object>)null);
+ }
+
+ /**
+ * Simulate OSGi service dependency injection. Injects direct references and
+ * multiple references. If a some references could not be injected no error
+ * is thrown.
+ * @param target Service instance
+ * @param bundleContext Bundle context from which services are fetched to inject.
+ * @param properties Service properties (used to resolve dynamic reference properties)
+ * @return true if all dependencies could be injected, false if the service has no dependencies.
+ */
+ public static boolean injectServices(Object target, BundleContext bundleContext, Map<String, Object> properties) {
+ return OsgiServiceUtil.injectServices(target, bundleContext, properties);
}
/**
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 1fca7a5..1e0b8d3 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
@@ -470,20 +470,20 @@
static class Reference {
- private final Class<?> clazz;
- private final String name;
- private final String interfaceType;
- private final ReferenceCardinality cardinality;
- private final ReferencePolicy policy;
- private final ReferencePolicyOption policyOption;
- private final String bind;
- private final String unbind;
- private final String field;
- private final FieldCollectionType fieldCollectionType;
- private final String target;
- private final Filter targetFilter;
+ protected final Class<?> clazz;
+ protected final String name;
+ protected final String interfaceType;
+ protected final ReferenceCardinality cardinality;
+ protected final ReferencePolicy policy;
+ protected final ReferencePolicyOption policyOption;
+ protected final String bind;
+ protected final String unbind;
+ protected final String field;
+ protected final FieldCollectionType fieldCollectionType;
+ protected String target;
+ protected Filter targetFilter;
- private Reference(Class<?> clazz, Node node) {
+ protected Reference(Class<?> clazz, Node node) {
this.clazz = clazz;
this.name = getAttributeValue(node, "name");
this.interfaceType = getAttributeValue(node, "interface");
@@ -507,6 +507,21 @@
}
}
+ protected Reference(Reference reference) {
+ this.clazz = reference.clazz;
+ this.name = reference.name;
+ this.interfaceType = reference.interfaceType;
+ this.cardinality = reference.cardinality;
+ this.policy = reference.policy;
+ this.policyOption = reference.policyOption;
+ this.bind = reference.bind;
+ this.unbind = reference.unbind;
+ this.field = reference.field;
+ this.fieldCollectionType = reference.fieldCollectionType;
+ this.target = reference.target;
+ this.targetFilter = reference.targetFilter;
+ }
+
public Class<?> getServiceClass() {
return clazz;
}
@@ -614,6 +629,22 @@
}
+ static class DynamicReference extends Reference {
+ public DynamicReference(Reference reference, String target) {
+ super(reference);
+ this.target = target;
+ if (StringUtils.isNotEmpty(this.target)) {
+ try {
+ this.targetFilter = new FilterImpl(this.target);
+ } catch (InvalidSyntaxException ex) {
+ throw new RuntimeException("Invalid target filter in reference '" + this.name + "' of class " + clazz.getName(), ex);
+ }
+ }
+ else {
+ this.targetFilter = null;
+ }
+ }
+ }
/**
* Options for {@link Reference#cardinality()} property.
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 b3fd20c..488b4fe 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
@@ -31,6 +31,7 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.impl.inject.Annotations;
+import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.DynamicReference;
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;
@@ -369,9 +370,10 @@
* multiple references.
* @param target Service instance
* @param bundleContext Bundle context from which services are fetched to inject.
+ * @param properties Services properties (used to resolve dynamic reference properties)
* @return true if all dependencies could be injected, false if the service has no dependencies.
*/
- public static boolean injectServices(Object target, BundleContext bundleContext) {
+ public static boolean injectServices(Object target, BundleContext bundleContext, Map<String, Object> properties) {
// collect all declared reference annotations on class and field level
Class<?> targetClass = target.getClass();
@@ -387,6 +389,13 @@
// try to inject services
for (Reference reference : references) {
+ if (properties != null) {
+ // Look for a target override
+ Object o = properties.get(reference.getName() + ".target");
+ if (o != null && o instanceof String) {
+ reference = new DynamicReference(reference,(String)o);
+ }
+ }
injectServiceReference(reference, target, bundleContext);
}
return true;
diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/context/OsgiContextImpl.java b/src/main/java/org/apache/sling/testing/mock/osgi/context/OsgiContextImpl.java
index acb96e7..ae9d0b2 100644
--- a/src/main/java/org/apache/sling/testing/mock/osgi/context/OsgiContextImpl.java
+++ b/src/main/java/org/apache/sling/testing/mock/osgi/context/OsgiContextImpl.java
@@ -150,7 +150,7 @@
* @return Registered service instance
*/
public final <T> T registerInjectActivateService(final T service, final Map<String, Object> properties) {
- MockOsgi.injectServices(service, bundleContext());
+ MockOsgi.injectServices(service, bundleContext(), properties);
MockOsgi.activate(service, bundleContext(), properties);
registerService(null, service, properties);
return service;
diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java b/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java
index d1f57fc..db6c8d4 100644
--- a/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java
+++ b/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java
@@ -19,5 +19,5 @@
/**
* Mock implementation of selected OSGi APIs.
*/
-@org.osgi.annotation.versioning.Version("3.3")
+@org.osgi.annotation.versioning.Version("3.4")
package org.apache.sling.testing.mock.osgi;
diff --git a/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6Test.java b/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6Test.java
index b7d022c..fa8a8c4 100644
--- a/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6Test.java
+++ b/src/test/java/org/apache/sling/testing/mock/osgi/MockBundleContextDynamicReferencesOsgiR6Test.java
@@ -63,6 +63,8 @@
private ServiceSuperInterface3 dependency3a;
@Mock
private ServiceSuperInterface3 dependency3b;
+ @Mock
+ private ServiceSuperInterface3 dependency3c;
@Before
public void setUp() {
@@ -75,7 +77,7 @@
service = new Service3OsgiR6();
MockOsgi.injectServices(service, bundleContext);
MockOsgi.activate(service, bundleContext);
- bundleContext.registerService(Service3OsgiR6.class.getName(), service, null);
+ bundleContext.registerService(Service3OsgiR6.class.getName(), service, MapUtil.toDictionary(ImmutableMap.<String,Object>of("reference3DynamicFiltered.target","(prop1=def)")));
assertDependency1(dependency1a);
assertDependency1Optional(null);
@@ -152,6 +154,22 @@
assertDependencies3Filtered(dependency3a);
}
+ @Test
+ public void testReferenceWithDynamicTargetFilter() {
+ assertDependencies3DynamicFiltered(null);
+
+ 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")));
+
+ bundleContext.registerService(ServiceInterface3.class.getName(), dependency3c,
+ MapUtil.toDictionary(ImmutableMap.<String, Object>of("prop1", "hij")));
+
+ assertDependencies3DynamicFiltered(dependency3b);
+ }
+
private void assertDependency1(ServiceInterface1 instance) {
if (instance == null) {
assertNull(service.getReference1());
@@ -184,5 +202,9 @@
assertEquals(ImmutableSet.<ServiceSuperInterface3>copyOf(instances),
ImmutableSet.<ServiceSuperInterface3>copyOf(service.getReferences3Filtered()));
}
-
+
+ private void assertDependencies3DynamicFiltered(ServiceSuperInterface3 instance) {
+ assertEquals(instance,service.getReference3DynamicFiltered());
+ }
+
}
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 1f92fa7..6ae014a 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
@@ -341,6 +341,7 @@
private List<ServiceReference> references2;
private List<ServiceSuperInterface3> references3;
private List<ServiceSuperInterface3> references3Filtered;
+ private ServiceSuperInterface3 reference3DynamicFiltered;
private ComponentContext componentContext;
private Map<String, Object> config;
@@ -385,6 +386,11 @@
return this.references3Filtered;
}
+
+ public ServiceSuperInterface3 getReference3DynamicFiltered() {
+ return this.reference3DynamicFiltered;
+ }
+
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 0229572..7698b9e 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
@@ -51,6 +51,7 @@
<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)"/>
+ <reference name="reference3DynamicFiltered" interface="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$ServiceInterface3" cardinality="0..1" policy="dynamic" field="reference3DynamicFiltered" field-collection-type="service"/>
</scr:component>
<scr:component name="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$Service3StaticGreedy" activate="activate" deactivate="deactivate" modified="modified">
<implementation class="org.apache.sling.testing.mock.osgi.OsgiServiceUtilTest$Service3StaticGreedy"/>