WIP: start implementing support for service scope, and proper implementation of factory service support
diff --git a/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java b/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java
index e094d10..216e022 100644
--- a/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java
+++ b/core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtil.java
@@ -22,6 +22,7 @@
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
@@ -47,10 +48,12 @@
import org.apache.commons.collections4.bidimap.TreeBidiMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.framework.FilterImpl;
+import org.jetbrains.annotations.NotNull;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.annotations.ServiceScope;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
import org.slf4j.Logger;
@@ -287,6 +290,22 @@
return serviceInterfaces;
}
+ @SuppressWarnings("null")
+ private static @NotNull ServiceScope getServiceScope(Class clazz, Document metadata) {
+ String query = getComponentXPathQuery(clazz) + "/service";
+ String scopeValue;
+ NodeList nodes = queryNodes(metadata, query);
+ if (nodes != null && nodes.getLength() > 0) {
+ scopeValue = getAttributeValue(nodes.item(0), "scope");
+ }
+ else {
+ scopeValue = null;
+ }
+ return Arrays.stream(ServiceScope.values())
+ .filter(serviceScope -> StringUtils.equals(scopeValue, serviceScope.toString()))
+ .findFirst().orElse(ServiceScope.DEFAULT);
+ }
+
private static Map<String, Object> getProperties(Class clazz, Document metadata) {
Map<String, Object> props = new HashMap<String, Object>();
String query = getComponentXPathQuery(clazz) + "/property[@name!='' and @value!='']";
@@ -384,6 +403,7 @@
private final String name;
private final String[] configurationPID;
private final Set<String> serviceInterfaces;
+ private final ServiceScope serviceScope;
private final Map<String, Object> properties;
private final List<Reference> references;
private final String activateMethodName;
@@ -395,6 +415,7 @@
this.name = OsgiMetadataUtil.getComponentName(clazz, metadataDocument);
this.configurationPID = OsgiMetadataUtil.getConfigurationPID(clazz, metadataDocument);
this.serviceInterfaces = OsgiMetadataUtil.getServiceInterfaces(clazz, metadataDocument);
+ this.serviceScope = OsgiMetadataUtil.getServiceScope(clazz, metadataDocument);
this.properties = OsgiMetadataUtil.getProperties(clazz, metadataDocument);
this.references = OsgiMetadataUtil.getReferences(clazz, metadataDocument);
this.activateMethodName = OsgiMetadataUtil.getLifecycleMethodName(clazz, metadataDocument, "activate");
@@ -407,6 +428,7 @@
this.name = null;
this.configurationPID = null;
this.serviceInterfaces = null;
+ this.serviceScope = ServiceScope.DEFAULT;
this.properties = null;
this.references = null;
this.activateMethodName = null;
@@ -438,6 +460,10 @@
return serviceInterfaces;
}
+ public @NotNull ServiceScope getServiceScope() {
+ return serviceScope;
+ }
+
public Map<String, Object> getProperties() {
return properties;
}
diff --git a/core/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java b/core/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java
index a1d64f7..913bf27 100644
--- a/core/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java
+++ b/core/src/test/java/org/apache/sling/testing/mock/osgi/OsgiMetadataUtilTest.java
@@ -30,10 +30,12 @@
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.testsvc.osgiserviceutil.ScopePrototypeService;
import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service3;
import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ServiceInterface2;
import org.junit.Test;
import org.osgi.framework.Constants;
+import org.osgi.service.component.annotations.ServiceScope;
public class OsgiMetadataUtilTest {
@@ -46,6 +48,7 @@
Set<String> serviceInterfaces = metadata.getServiceInterfaces();
assertEquals(1, serviceInterfaces.size());
assertTrue(serviceInterfaces.contains("java.lang.Comparable"));
+ assertEquals(ServiceScope.DEFAULT, metadata.getServiceScope());
Map<String, Object> props = metadata.getProperties();
assertEquals(3, props.size());
@@ -81,6 +84,12 @@
assertEquals("activate", metadata.getActivateMethodName());
}
+ @Test
+ public void testServiceScope() {
+ OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(ScopePrototypeService.class);
+ assertEquals(ServiceScope.PROTOTYPE, metadata.getServiceScope());
+ }
+
static class ServiceWithMetadata {
// empty class
}
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..01208f5 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
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -32,13 +33,15 @@
import java.util.Map;
import java.util.Set;
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ScopePrototypeService;
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ScopePrototypeServiceFactory;
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ScopePrototypeServiceFactory.ScopePrototpyeInstance;
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.Service4;
import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.Service5;
-import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ServiceFactory1;
import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ServiceInterface1;
import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ServiceInterface2;
import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ServiceInterface3;
@@ -48,10 +51,8 @@
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
-import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.ServiceReference;
import com.google.common.collect.ImmutableMap;
@@ -210,34 +211,38 @@
}
@Test
- public void testServiceFactoryViaScr() {
- ServiceFactory1 serviceFactory1 = new ServiceFactory1();
+ public void testScopePrototypeService() {
+ MockOsgi.registerInjectActivateService(ScopePrototypeService.class, bundleContext);
- MockOsgi.injectServices(serviceFactory1, bundleContext);
- MockOsgi.activate(serviceFactory1, bundleContext, (Dictionary<String, Object>) null);
- bundleContext.registerService(ServiceFactory1.class.getName(), serviceFactory1, null);
+ ServiceReference<ScopePrototypeService> ref = bundleContext.getServiceReference(ScopePrototypeService.class);
+ assertNotNull(ref);
- assertSame(serviceFactory1, bundleContext.getService(
- bundleContext.getServiceReference(ServiceFactory1.class.getName())));
+ ScopePrototypeService instance1 = bundleContext.getService(ref);
+ assertNotNull(instance1);
+
+ ScopePrototypeService instance2 = bundleContext.getService(ref);
+ assertNotNull(instance2);
+
+ assertNotSame(instance1, instance2);
+ assertTrue(instance2.getInstanceId() > instance1.getInstanceId());
}
@Test
- public void testServiceFactoryViaManualRegistration() {
- final ServiceFactory1 serviceFactory1 = new ServiceFactory1();
+ @SuppressWarnings("unchecked")
+ public void testScopePrototypeServiceFactory() {
+ MockOsgi.registerInjectActivateService(ScopePrototypeServiceFactory.class, bundleContext);
- bundleContext.registerService(ServiceFactory1.class.getName(), new ServiceFactory() {
- @Override
- public Object getService(Bundle bundle, ServiceRegistration registration) {
- return serviceFactory1;
- }
- @Override
- public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
- // nothing to do
- }
- }, null);
+ ServiceReference<ScopePrototpyeInstance> ref = (ServiceReference)bundleContext.getServiceReference(ScopePrototypeServiceFactory.class);
+ assertNotNull(ref);
- assertSame(serviceFactory1, bundleContext.getService(
- bundleContext.getServiceReference(ServiceFactory1.class.getName())));
+ ScopePrototpyeInstance instance1 = bundleContext.getService(ref);
+ assertNotNull(instance1);
+
+ ScopePrototpyeInstance instance2 = bundleContext.getService(ref);
+ assertNotNull(instance2);
+
+ assertNotSame(instance1, instance2);
+ assertTrue(instance2.getInstanceId() > instance1.getInstanceId());
}
}
diff --git a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/ServiceFactory1.java b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/ScopePrototypeService.java
similarity index 67%
rename from test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/ServiceFactory1.java
rename to test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/ScopePrototypeService.java
index 3fcbef7..199ed3a 100644
--- a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/ServiceFactory1.java
+++ b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/ScopePrototypeService.java
@@ -18,9 +18,20 @@
*/
package org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil;
-import org.osgi.service.component.annotations.Component;
+import java.util.concurrent.atomic.AtomicLong;
-@Component(service = ServiceFactory1.class, servicefactory = true)
-public class ServiceFactory1 {
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ServiceScope;
+
+@Component(service = ScopePrototypeService.class, scope = ServiceScope.PROTOTYPE)
+public class ScopePrototypeService {
+
+ private static final AtomicLong INSTANCE_COUNTER = new AtomicLong();
+
+ private final long instanceId = INSTANCE_COUNTER.incrementAndGet();
+
+ public long getInstanceId() {
+ return instanceId;
+ }
}
diff --git a/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/ScopePrototypeServiceFactory.java b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/ScopePrototypeServiceFactory.java
new file mode 100644
index 0000000..31744f1
--- /dev/null
+++ b/test-services/src/main/java/org/apache/sling/testing/mock/osgi/testsvc/osgiserviceutil/ScopePrototypeServiceFactory.java
@@ -0,0 +1,60 @@
+/*
+ * 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.concurrent.atomic.AtomicLong;
+
+import org.apache.sling.testing.mock.osgi.testsvc.osgiserviceutil.ScopePrototypeServiceFactory.ScopePrototpyeInstance;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ServiceScope;
+
+@Component(service = ScopePrototypeServiceFactory.class, scope = ServiceScope.PROTOTYPE)
+public class ScopePrototypeServiceFactory implements ServiceFactory<ScopePrototpyeInstance> {
+
+ private static final AtomicLong INSTANCE_COUNTER = new AtomicLong();
+
+ @Override
+ public ScopePrototpyeInstance getService(Bundle bundle, ServiceRegistration<ScopePrototpyeInstance> registration) {
+ return new ScopePrototpyeInstance(INSTANCE_COUNTER.incrementAndGet());
+ }
+
+ @Override
+ public void ungetService(Bundle bundle, ServiceRegistration<ScopePrototpyeInstance> registration,
+ ScopePrototpyeInstance service) {
+ // nothing to do
+ }
+
+ public static class ScopePrototpyeInstance {
+
+ private final long instanceId;
+
+ private ScopePrototpyeInstance(long instanceId) {
+ this.instanceId = instanceId;
+ }
+
+ public long getInstanceId() {
+ return instanceId;
+ }
+
+ }
+
+}