aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDirk Fauth2017-03-14 15:32:10 -0400
committerDirk Fauth2017-03-14 15:32:10 -0400
commitb6ec1fc74e3e998d1ba30ec281e1ff4f34c6860f (patch)
tree2636c1bf91d1ee51fb05b6aa40f9ffc141f026cb
parentbe314020004ae606df69649d3c023d0af337e973 (diff)
downloadeclipse.platform.runtime-b6ec1fc74e3e998d1ba30ec281e1ff4f34c6860f.tar.gz
eclipse.platform.runtime-b6ec1fc74e3e998d1ba30ec281e1ff4f34c6860f.tar.xz
eclipse.platform.runtime-b6ec1fc74e3e998d1ba30ec281e1ff4f34c6860f.zip
Bug 413287 - [e4] EclipseContextOSGi does not deal with OSGi-ServicesY20170316-0500I20170319-2000I20170318-2000I20170317-2000I20170316-2000I20170315-2000
appropriately Change-Id: Id5ae889ffc78f65d2c943e3941a3c488227838bf Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>
-rw-r--r--bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/osgi/EclipseContextOSGi.java50
-rw-r--r--tests/org.eclipse.e4.core.tests/META-INF/MANIFEST.MF5
-rw-r--r--tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceA.xml8
-rw-r--r--tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceB.xml9
-rw-r--r--tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceController.xml7
-rw-r--r--tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/ServiceContextTest.java113
-rw-r--r--tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestOtherService.java5
-rw-r--r--tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestService.java5
-rw-r--r--tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceA.java8
-rw-r--r--tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceB.java8
-rw-r--r--tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceController.java32
11 files changed, 224 insertions, 26 deletions
diff --git a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/osgi/EclipseContextOSGi.java b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/osgi/EclipseContextOSGi.java
index 1167d7c3c..149227101 100644
--- a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/osgi/EclipseContextOSGi.java
+++ b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/osgi/EclipseContextOSGi.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2015 IBM Corporation and others.
+ * Copyright (c) 2011, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -87,13 +87,6 @@ public class EclipseContextOSGi extends EclipseContext implements ServiceListene
return service;
}
- /**
- * Returns the service name for a service reference
- */
- private String serviceName(ServiceReference<?> reference) {
- return ((String[]) reference.getProperty(Constants.OBJECTCLASS))[0];
- }
-
@Override
public void dispose() {
for (ServiceReference<?> ref : refs.values()) {
@@ -109,21 +102,29 @@ public class EclipseContextOSGi extends EclipseContext implements ServiceListene
@Override
public void serviceChanged(ServiceEvent event) {
ServiceReference<?> ref = event.getServiceReference();
- String name = serviceName(ref);
- if (IContextFunction.SERVICE_NAME.equals(name)) // those keep associated names
- name = (String) ref.getProperty(IContextFunction.SERVICE_CONTEXT_KEY);
+ String[] names = ((String[]) ref.getProperty(Constants.OBJECTCLASS));
+ for (String name : names) {
+ if (IContextFunction.SERVICE_NAME.equals(name)) {
+ name = (String) ref.getProperty(IContextFunction.SERVICE_CONTEXT_KEY);
+ }
+
+ if (refs.containsKey(name)) {
+ // retrieve the highest ranked service of the same type
+ ref = bundleContext.getServiceReference(name);
- if (refs.containsKey(name)) {
- ServiceReference<?> oldRef = refs.get(name);
- if (oldRef != null)
- bundleContext.ungetService(oldRef);
- if (event.getType() == ServiceEvent.UNREGISTERING) {
- refs.put(name, null);
- remove(name);
- } else {
- Object service = bundleContext.getService(ref);
- refs.put(name, ref);
- set(name, service);
+ ServiceReference<?> oldRef = refs.get(name);
+ if (oldRef != null && oldRef != ref) {
+ bundleContext.ungetService(oldRef);
+ }
+
+ if (ref != null) {
+ Object service = bundleContext.getService(ref);
+ refs.put(name, ref);
+ set(name, service);
+ } else {
+ refs.put(name, null);
+ remove(name);
+ }
}
}
}
@@ -131,8 +132,9 @@ public class EclipseContextOSGi extends EclipseContext implements ServiceListene
@Override
public void bundleChanged(BundleEvent event) {
// In case OSGi context has not being properly disposed by the application,
- // OSGi framework shutdown will trigged uninjection of all consumed OSGi
- // service. To avoid this, we detect framework shutdown and release services.
+ // OSGi framework shutdown will triggered uninjection of all consumed
+ // OSGi service. To avoid this, we detect framework shutdown and release
+ // services.
if (event.getType() != BundleEvent.STOPPING)
return;
if (event.getBundle().getBundleId() == 0)
diff --git a/tests/org.eclipse.e4.core.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.e4.core.tests/META-INF/MANIFEST.MF
index 40f7fc430..3dafa7eb6 100644
--- a/tests/org.eclipse.e4.core.tests/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.e4.core.tests/META-INF/MANIFEST.MF
@@ -38,7 +38,10 @@ Service-Component: OSGI-INF/adder.xml,
OSGI-INF/org.eclipse.e4.core.internal.tests.di.extensions.SampleServiceB.xml,
OSGI-INF/org.eclipse.e4.core.internal.tests.di.extensions.ComponentEnabler.xml,
OSGI-INF/DisabledServiceA.xml,
- OSGI-INF/DisabledServiceB.xml
+ OSGI-INF/DisabledServiceB.xml,
+ OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceController.xml,
+ OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceA.xml,
+ OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceB.xml
Eclipse-BundleShape: dir
Require-Capability: osgi.extender;
filter:="(&(osgi.extender=osgi.component)(version>=1.3)(!(version>=2.0)))",
diff --git a/tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceA.xml b/tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceA.xml
new file mode 100644
index 000000000..7cf23f5e6
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceA.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" enabled="false" name="org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceA">
+ <service>
+ <provide interface="org.eclipse.e4.core.internal.tests.contexts.inject.TestService"/>
+ <provide interface="org.eclipse.e4.core.internal.tests.contexts.inject.TestOtherService"/>
+ </service>
+ <implementation class="org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceA"/>
+</scr:component> \ No newline at end of file
diff --git a/tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceB.xml b/tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceB.xml
new file mode 100644
index 000000000..bed59849e
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceB.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" enabled="false" name="org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceB">
+ <property name="service.ranking" type="Integer" value="5"/>
+ <service>
+ <provide interface="org.eclipse.e4.core.internal.tests.contexts.inject.TestService"/>
+ <provide interface="org.eclipse.e4.core.internal.tests.contexts.inject.TestOtherService"/>
+ </service>
+ <implementation class="org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceB"/>
+</scr:component> \ No newline at end of file
diff --git a/tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceController.xml b/tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceController.xml
new file mode 100644
index 000000000..f5a8db8ba
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests/OSGI-INF/org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceController.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" name="org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceController">
+ <service>
+ <provide interface="org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceController"/>
+ </service>
+ <implementation class="org.eclipse.e4.core.internal.tests.contexts.inject.TestServiceController"/>
+</scr:component> \ No newline at end of file
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/ServiceContextTest.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/ServiceContextTest.java
index 98f655efd..06e374041 100644
--- a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/ServiceContextTest.java
+++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/ServiceContextTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2015 IBM Corporation and others.
+ * Copyright (c) 2009, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@ package org.eclipse.e4.core.internal.tests.contexts.inject;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
@@ -34,6 +35,7 @@ import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
@@ -88,6 +90,16 @@ public class ServiceContextTest {
}
}
+ static class TestBean {
+ @Inject
+ @Optional
+ TestService testService;
+
+ @Inject
+ @Optional
+ TestOtherService testOtherService;
+ }
+
private IEclipseContext context;
private final List<ServiceRegistration<?>> registrations = new ArrayList<>();
@@ -277,4 +289,103 @@ public class ServiceContextTest {
crayon.draw();
}
+ @Test
+ public void testOptionalReferences() throws InterruptedException {
+ BundleContext context = FrameworkUtil.getBundle(getClass()).getBundleContext();
+ IEclipseContext serviceContext = EclipseContextFactory.getServiceContext(context);
+ TestBean bean = ContextInjectionFactory.make(TestBean.class, serviceContext);
+
+ assertNull(bean.testService);
+
+ ServiceReference<TestServiceController> ref = context.getServiceReference(TestServiceController.class);
+ TestServiceController controller = context.getService(ref);
+ try {
+ controller.enableTestServiceA();
+ // give the service registry and the injection some time
+ Thread.sleep(100);
+ assertNotNull(bean.testService);
+ assertSame(TestServiceA.class, bean.testService.getClass());
+ assertNotNull(bean.testOtherService);
+ assertSame(TestServiceA.class, bean.testOtherService.getClass());
+
+ controller.enableTestServiceB();
+ // give the service registry and the injection some time
+ Thread.sleep(100);
+ assertNotNull(bean.testService);
+ assertSame(TestServiceB.class, bean.testService.getClass());
+ assertNotNull(bean.testOtherService);
+ assertSame(TestServiceB.class, bean.testOtherService.getClass());
+
+ controller.disableTestServiceB();
+ // give the service registry and the injection some time
+ Thread.sleep(100);
+ assertNotNull(bean.testService);
+ assertSame(TestServiceA.class, bean.testService.getClass());
+ assertNotNull(bean.testOtherService);
+ assertSame(TestServiceA.class, bean.testOtherService.getClass());
+
+ controller.disableTestServiceA();
+ // give the service registry and the injection some time
+ Thread.sleep(100);
+ assertNull(bean.testService);
+ assertNull(bean.testOtherService);
+ } finally {
+ controller.disableTestServiceA();
+ controller.disableTestServiceB();
+ // give the service registry and the injection some time to ensure
+ // clear state after this test
+ Thread.sleep(100);
+ }
+ }
+
+ @Test
+ public void testServiceRanking() throws InterruptedException {
+ BundleContext context = FrameworkUtil.getBundle(getClass()).getBundleContext();
+ IEclipseContext serviceContext = EclipseContextFactory.getServiceContext(context);
+ TestBean bean = ContextInjectionFactory.make(TestBean.class, serviceContext);
+
+ assertNull(bean.testService);
+
+ ServiceReference<TestServiceController> ref = context.getServiceReference(TestServiceController.class);
+ TestServiceController controller = context.getService(ref);
+ try {
+ controller.enableTestServiceB();
+ // give the service registry and the injection some time
+ Thread.sleep(100);
+ assertNotNull(bean.testService);
+ assertSame(TestServiceB.class, bean.testService.getClass());
+ assertNotNull(bean.testOtherService);
+ assertSame(TestServiceB.class, bean.testOtherService.getClass());
+
+ // enable a service with a lower ranking
+ controller.enableTestServiceA();
+ // give the service registry and the injection some time
+ Thread.sleep(100);
+ assertNotNull(bean.testService);
+ // we expect that still the highest ranked service is injected
+ assertSame(TestServiceB.class, bean.testService.getClass());
+ assertNotNull(bean.testOtherService);
+ assertSame(TestServiceB.class, bean.testOtherService.getClass());
+
+ controller.disableTestServiceB();
+ // give the service registry and the injection some time
+ Thread.sleep(100);
+ assertNotNull(bean.testService);
+ assertSame(TestServiceA.class, bean.testService.getClass());
+ assertNotNull(bean.testOtherService);
+ assertSame(TestServiceA.class, bean.testOtherService.getClass());
+
+ controller.disableTestServiceA();
+ // give the service registry and the injection some time
+ Thread.sleep(100);
+ assertNull(bean.testService);
+ assertNull(bean.testOtherService);
+ } finally {
+ controller.disableTestServiceA();
+ controller.disableTestServiceB();
+ // give the service registry and the injection some time to ensure
+ // clear state after this test
+ Thread.sleep(100);
+ }
+ }
}
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestOtherService.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestOtherService.java
new file mode 100644
index 000000000..b983f3084
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestOtherService.java
@@ -0,0 +1,5 @@
+package org.eclipse.e4.core.internal.tests.contexts.inject;
+
+public interface TestOtherService {
+
+}
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestService.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestService.java
new file mode 100644
index 000000000..11f52fabd
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestService.java
@@ -0,0 +1,5 @@
+package org.eclipse.e4.core.internal.tests.contexts.inject;
+
+public interface TestService {
+
+}
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceA.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceA.java
new file mode 100644
index 000000000..aa1eac4f0
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceA.java
@@ -0,0 +1,8 @@
+package org.eclipse.e4.core.internal.tests.contexts.inject;
+
+import org.osgi.service.component.annotations.Component;
+
+@Component(enabled = false)
+public class TestServiceA implements TestService, TestOtherService {
+
+}
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceB.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceB.java
new file mode 100644
index 000000000..32df30315
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceB.java
@@ -0,0 +1,8 @@
+package org.eclipse.e4.core.internal.tests.contexts.inject;
+
+import org.osgi.service.component.annotations.Component;
+
+@Component(enabled = false, property = "service.ranking:Integer=5")
+public class TestServiceB implements TestService, TestOtherService {
+
+}
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceController.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceController.java
new file mode 100644
index 000000000..6873ed636
--- /dev/null
+++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/inject/TestServiceController.java
@@ -0,0 +1,32 @@
+package org.eclipse.e4.core.internal.tests.contexts.inject;
+
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+
+@Component(service = TestServiceController.class)
+public class TestServiceController {
+
+ ComponentContext context;
+
+ @Activate
+ void activate(ComponentContext context) {
+ this.context = context;
+ }
+
+ public void enableTestServiceA() {
+ this.context.enableComponent(TestServiceA.class.getName());
+ }
+
+ public void disableTestServiceA() {
+ this.context.disableComponent(TestServiceA.class.getName());
+ }
+
+ public void enableTestServiceB() {
+ this.context.enableComponent(TestServiceB.class.getName());
+ }
+
+ public void disableTestServiceB() {
+ this.context.disableComponent(TestServiceB.class.getName());
+ }
+}