FELIX-4352: Added support of circular dependency in the wtf command (work in progress)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1554191 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/shell/src/main/java/org/apache/felix/dm/shell/DMCommand.java b/dependencymanager/shell/src/main/java/org/apache/felix/dm/shell/DMCommand.java
index 36d3aab..02437e5 100644
--- a/dependencymanager/shell/src/main/java/org/apache/felix/dm/shell/DMCommand.java
+++ b/dependencymanager/shell/src/main/java/org/apache/felix/dm/shell/DMCommand.java
@@ -210,11 +210,11 @@
long numberOfDependencies = 0;
long lastBundleId = -1;
while (iterator.hasNext()) {
- DependencyManager manager = (DependencyManager) iterator.next();
+ DependencyManager manager = iterator.next();
List<Component> complist = manager.getComponents();
Iterator<Component> componentIterator = complist.iterator();
while (componentIterator.hasNext()) {
- Component component = (Component) componentIterator.next();
+ Component component = componentIterator.next();
ComponentDeclaration sc = (ComponentDeclaration) component;
String name = sc.getName();
// check if this component is enabled or disabled.
@@ -314,7 +314,7 @@
}
for (int i = 0; i < ids.size(); i ++) {
- String id = (String) ids.get(i);
+ String id = ids.get(i);
try {
Long longId = Long.valueOf(id);
if (longId == bundle.getBundleId()) {
@@ -512,7 +512,7 @@
private Set<ComponentId> getTheRootCouses(List<ComponentDeclaration> downComponents) {
Set<ComponentId> downComponentsRoot = new TreeSet<ComponentId>();
for (ComponentDeclaration c : downComponents) {
- ComponentId root = getRoot(downComponents, c);
+ ComponentId root = getRoot(downComponents, c, new ArrayList<ComponentId>());
if (root != null) {
downComponentsRoot.add(root);
}
@@ -622,7 +622,7 @@
return false;
}
- private ComponentId getRoot(List<ComponentDeclaration> downComponents, ComponentDeclaration c) {
+ private ComponentId getRoot(List<ComponentDeclaration> downComponents, ComponentDeclaration c, List<ComponentId> backTrace) {
ComponentDependencyDeclaration[] componentDependencies = c.getComponentDependencies();
int downDeps = 0;
for (ComponentDependencyDeclaration cdd : componentDependencies) {
@@ -636,7 +636,19 @@
}
return new ComponentId(cdd.getName(), cdd.getType(), contextName);
}
- return getRoot(downComponents, component);
+ // Detect circular dependency
+ ComponentId componentId = new ComponentId(cdd.getName(), cdd.getType(), null);
+ if (backTrace.contains(componentId)) {
+ // We already got this one so its a circular dependency
+ System.out.print("Circular dependency found:\n *");
+ for (ComponentId cid : backTrace) {
+ System.out.print(" -> " + cid.getName() + " ");
+ }
+ System.out.println(" -> " + componentId.getName());
+ return new ComponentId(c.getName(), SERVICE, c.getBundleContext().getBundle().getSymbolicName());
+ }
+ backTrace.add(componentId);
+ return getRoot(downComponents, component, backTrace);
}
}
if (downDeps > 0) {
diff --git a/dependencymanager/shell/src/test/java/org/apache/felix/dm/shell/DMCommandTest.java b/dependencymanager/shell/src/test/java/org/apache/felix/dm/shell/DMCommandTest.java
index 7293b58..c154a4c 100644
--- a/dependencymanager/shell/src/test/java/org/apache/felix/dm/shell/DMCommandTest.java
+++ b/dependencymanager/shell/src/test/java/org/apache/felix/dm/shell/DMCommandTest.java
@@ -28,6 +28,8 @@
import java.io.PrintStream;
import java.util.Properties;
+import javax.crypto.Cipher;
+
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.junit.After;
@@ -53,6 +55,8 @@
@Before
public void setUp() {
m_bundleContext = mock(BundleContext.class);
+ Bundle bundle = mock(Bundle.class);
+ when(m_bundleContext.getBundle()).thenReturn(bundle);
System.setOut(new PrintStream(outContent));
System.setErr(new PrintStream(errContent));
dm = new DependencyManager(m_bundleContext);
@@ -109,6 +113,35 @@
dm.remove(component);
}
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testComponentThatHaveCycliclyDependencyOnAOtheComponentShouldRegisterAsFailure() {
+ setupEmptyBundles();
+ DependencyManager dm = new DependencyManager(m_bundleContext);
+ DependencyManager.getDependencyManagers().add(dm);
+
+ Component component1 = dm.createComponent()
+ .setImplementation(Cipher.class)
+ .setInterface(Cipher.class.getName(), null)
+ .add(dm.createServiceDependency().setService(Math.class).setRequired(true));
+ dm.add(component1);
+
+ Component component2 = dm.createComponent()
+ .setImplementation(Math.class)
+ .setInterface(Math.class.getName(), null)
+ .add(dm.createServiceDependency().setService(Cipher.class).setRequired(true));
+ dm.add(component2);
+
+ dme.wtf();
+ String output = outContent.toString();
+ assertTrue(output.contains("Circular dependency found:"));
+ assertTrue(output.contains("-> java.lang.Math -> javax.crypto.Cipher -> java.lang.Math"));
+
+ // remove the mess
+ dm.remove(component1);
+ dm.remove(component2);
+ }
+
@Test
public void testCanFindRootFailure() {
setupEmptyBundles();