518488 ShutdownSorter does not take into account bundles with references to services provided by the same bundle
Signed-off-by: ootto <olaf@x100.de>
diff --git a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/shutdown/ShutdownSorter.java b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/shutdown/ShutdownSorter.java
index 4c406be..28394c6 100644
--- a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/shutdown/ShutdownSorter.java
+++ b/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/shutdown/ShutdownSorter.java
@@ -93,7 +93,11 @@
Bundle[] usingBundles = serviceReference.getUsingBundles();
if (!isEmpty(usingBundles)) {
- usingBundles = stream(usingBundles).filter(unsortedManagedBundles::contains).collect(toList()).toArray(new Bundle[]{});
+ usingBundles =
+ stream(usingBundles)
+ .filter(b -> unsortedManagedBundles.contains(b) && !b.equals(bundle))
+ .collect(toList())
+ .toArray(new Bundle[]{});
}
if (!isEmpty(usingBundles)) {
diff --git a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/BlueprintShutdownSorterTest.java b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/BlueprintShutdownSorterTest.java
index 0b5380a..1c6e254 100644
--- a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/BlueprintShutdownSorterTest.java
+++ b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/BlueprintShutdownSorterTest.java
@@ -7,7 +7,7 @@
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
- *
+ *
* Contributors:
* VMware Inc.
*****************************************************************************/
@@ -15,98 +15,140 @@
package org.eclipse.gemini.blueprint.extender.internal.dependencies;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
-
import junit.framework.TestCase;
-
import org.eclipse.gemini.blueprint.extender.internal.DependencyMockBundle;
import org.eclipse.gemini.blueprint.extender.internal.dependencies.shutdown.ShutdownSorter;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Costin Leau
*/
public class BlueprintShutdownSorterTest extends TestCase {
- // see tck-1.dot
- public void testCase1() throws Exception {
- DependencyMockBundle a = new DependencyMockBundle("A");
- DependencyMockBundle b = new DependencyMockBundle("B");
- DependencyMockBundle c = new DependencyMockBundle("C");
- DependencyMockBundle d = new DependencyMockBundle("D");
- DependencyMockBundle e = new DependencyMockBundle("E");
+ /**
+ * <pre>
+ * digraph G{
+ * A;
+ * B -> C;
+ * D -> E;
+ * E -> D;
+ * }
+ * </pre>
+ * Expected order is C, A, B, E, D
+ */
+ public void testCase1() throws Exception {
+ DependencyMockBundle a = new DependencyMockBundle("A");
+ DependencyMockBundle b = new DependencyMockBundle("B");
+ DependencyMockBundle c = new DependencyMockBundle("C");
+ DependencyMockBundle d = new DependencyMockBundle("D");
+ DependencyMockBundle e = new DependencyMockBundle("E");
- b.setDependentOn(c);
- d.setDependentOn(e);
- e.setDependentOn(d);
+ b.setDependentOn(c);
+ d.setDependentOn(e);
+ e.setDependentOn(d);
- List<Bundle> order = getOrder(a, b, c, d, e);
- System.out.println("Shutdown order is " + order);
- assertOrder(new Bundle[] { c, a, b, e, d }, order);
- }
+ List<Bundle> order = getOrder(a, b, c, d, e);
+ assertOrder(order, c, a, b, e, d);
+ }
- // similar to tck 2 but with D publishes a service with a lower ranking and
- // needs to be destroyed first
- public void testCase2() throws Exception {
- DependencyMockBundle a = new DependencyMockBundle("A");
- DependencyMockBundle b = new DependencyMockBundle("B");
- DependencyMockBundle c = new DependencyMockBundle("C");
- DependencyMockBundle d = new DependencyMockBundle("D");
- DependencyMockBundle e = new DependencyMockBundle("E");
+ /**
+ * similar to tck 2 but with D publishes a service with a lower ranking and
+ * needs to be destroyed first:
+ *
+ * <pre>
+ * digraph G{
+ * A;
+ * B -> C;
+ * D -> E; (lower rank)
+ * E -> D; (high rank)
+ * }
+ * </pre>
+ */
+ public void testCase2() throws Exception {
+ DependencyMockBundle a = new DependencyMockBundle("A");
+ DependencyMockBundle b = new DependencyMockBundle("B");
+ DependencyMockBundle c = new DependencyMockBundle("C");
+ DependencyMockBundle d = new DependencyMockBundle("D");
+ DependencyMockBundle e = new DependencyMockBundle("E");
- b.setDependentOn(c);
- d.setDependentOn(e, -13, 12);
- e.setDependentOn(d, 0, 14);
+ b.setDependentOn(c);
+ d.setDependentOn(e, -13, 12);
+ e.setDependentOn(d, 0, 14);
- List<Bundle> order = getOrder(a, b, c, d, e);
- System.out.println("Shutdown order is " + order);
- assertOrder(new Bundle[] { c, a, b, d, e }, order);
- }
+ List<Bundle> order = getOrder(a, b, c, d, e);
+ assertOrder(order, c, a, b, d, e);
+ }
- /**
- * If the service of a managed bundle are consumed by an unmanaged bundle,
- * that dependency should not affect the shutdown ordering as gemini blueprint is only responsible for
- * orderly shutting down the bundles it is managing.
- */
- public void testUnmanagedBundlesAreIgnoredForShutdownOrdering() throws Exception {
- DependencyMockBundle a = new DependencyMockBundle("A");
- DependencyMockBundle b = new DependencyMockBundle("B");
- DependencyMockBundle c = new DependencyMockBundle("C");
- DependencyMockBundle d = new DependencyMockBundle("D");
- DependencyMockBundle e = new DependencyMockBundle("E");
- DependencyMockBundle unmanaged = new DependencyMockBundle("F");
+ /**
+ * If the service of a managed bundle are consumed by an unmanaged bundle,
+ * that dependency should not affect the shutdown ordering as gemini blueprint is only responsible for
+ * orderly shutting down the bundles it is managing.
+ */
+ public void testUnmanagedBundlesAreIgnoredForShutdownOrdering() throws Exception {
+ DependencyMockBundle a = new DependencyMockBundle("A");
+ DependencyMockBundle b = new DependencyMockBundle("B");
+ DependencyMockBundle c = new DependencyMockBundle("C");
+ DependencyMockBundle d = new DependencyMockBundle("D");
+ DependencyMockBundle e = new DependencyMockBundle("E");
+ DependencyMockBundle unmanaged = new DependencyMockBundle("F");
- b.setDependentOn(c);
- d.setDependentOn(e, -13, 12);
- e.setDependentOn(d, 0, 14);
- a.setDependentOn(unmanaged);
+ b.setDependentOn(c);
+ d.setDependentOn(e, -13, 12);
+ e.setDependentOn(d, 0, 14);
+ a.setDependentOn(unmanaged);
- List<Bundle> order = getOrder(a, b, c, d, e);
- System.out.println("Shutdown order is " + order);
- assertOrder(new Bundle[] { c, a, b, d, e }, order);
- }
+ List<Bundle> order = getOrder(a, b, c, d, e);
+ assertOrder(order, c, a, b, d, e);
+ }
+
+ /**
+ * If the service of a managed bundle are consumed by an unmanaged bundle,
+ * that dependency should not affect the shutdown ordering as gemini blueprint is only responsible for
+ * orderly shutting down the bundles it is managing.
+ */
+ public void testReferencesToSelfProvidedServicesAreIgnoredForShutdownOrdering() throws Exception {
+ DependencyMockBundle a = new DependencyMockBundle("A");
+ DependencyMockBundle b = new DependencyMockBundle("B");
+ DependencyMockBundle c = new DependencyMockBundle("C");
+ DependencyMockBundle d = new DependencyMockBundle("D");
+ DependencyMockBundle e = new DependencyMockBundle("E");
+
+ e.setDependentOn(d);
+ d.setDependentOn(c);
+ c.setDependentOn(b);
+ b.setDependentOn(a);
+
+ a.setDependentOn(a);
+ b.setDependentOn(b);
+
+ List<Bundle> order = getOrder(a, b, c, d, e);
+ assertOrder(order, a, b, c, d, e);
+ }
- private void assertOrder(Bundle[] expected, List<Bundle> ordered) {
- assertTrue("shutdown order is incorrect", Arrays.equals(expected, ordered.toArray()));
- }
+ private void assertOrder(List<Bundle> ordered, Bundle... expected) {
+ assertThat(ordered)
+ .describedAs("The order %s does not match the expected order %s", ordered, expected)
+ .containsExactly(expected);
+ }
- private List<Bundle> getOrder(Bundle... bundles) {
- List<Bundle> list = new ArrayList<Bundle>(bundles.length);
- list.addAll(Arrays.asList(bundles));
- List<Bundle> result = new ArrayList<Bundle>();
+ private List<Bundle> getOrder(Bundle... bundles) throws BundleException {
+ List<Bundle> list = new ArrayList<>(bundles.length);
+ list.addAll(asList(bundles));
+ List<Bundle> result = new ArrayList<>();
- while (!list.isEmpty()) {
- result.addAll(ShutdownSorter.getBundles(list));
- for (Bundle bundle : result) {
- try {
- bundle.stop();
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
- }
- return result;
- }
+ while (!list.isEmpty()) {
+ result.addAll(ShutdownSorter.getBundles(list));
+ for (Bundle bundle : result) {
+ bundle.stop();
+ }
+ }
+ return result;
+ }
}
diff --git a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/blueprint-tck-1.dot b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/blueprint-tck-1.dot
deleted file mode 100644
index 4c337a3..0000000
--- a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/blueprint-tck-1.dot
+++ /dev/null
@@ -1,8 +0,0 @@
-digraph G{
- A;
- B -> C;
- D -> E;
- E -> D;
-}
-
-// order is C, A, B, E, D
\ No newline at end of file
diff --git a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/blueprint-tck-2.dot b/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/blueprint-tck-2.dot
deleted file mode 100644
index c47d862..0000000
--- a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/dependencies/blueprint-tck-2.dot
+++ /dev/null
@@ -1,6 +0,0 @@
-digraph G{
- A;
- B -> C;
- D -> E; (lower rank)
- E -> D; (high rank)
-}
\ No newline at end of file