FELIX-4352: committed the jan15.path attached in the felix issue (many thanks Jago !).
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1558409 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 95b008f..1b16279 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
@@ -25,6 +25,8 @@
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
+import java.util.Map.Entry;
+import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
@@ -512,10 +514,8 @@
private Set<ComponentId> getTheRootCouses(List<ComponentDeclaration> downComponents) {
Set<ComponentId> downComponentsRoot = new TreeSet<ComponentId>();
for (ComponentDeclaration c : downComponents) {
- ComponentId root = getRoot(downComponents, c, new ArrayList<ComponentId>());
- if (root != null) {
- downComponentsRoot.add(root);
- }
+ List<ComponentId> root = getRoot(downComponents, c, new ArrayList<ComponentId>());
+ downComponentsRoot.addAll(root);
}
return downComponentsRoot;
}
@@ -622,22 +622,25 @@
return false;
}
- private ComponentId getRoot(List<ComponentDeclaration> downComponents, ComponentDeclaration c, List<ComponentId> backTrace) {
+ private List<ComponentId> getRoot(List<ComponentDeclaration> downComponents, ComponentDeclaration c, List<ComponentId> backTrace) {
ComponentDependencyDeclaration[] componentDependencies = c.getComponentDependencies();
int downDeps = 0;
+ List<ComponentId> result = new ArrayList<ComponentId>();
for (ComponentDependencyDeclaration cdd : componentDependencies) {
if (cdd.getState() == ComponentDependencyDeclaration.STATE_UNAVAILABLE_REQUIRED) {
downDeps++;
// Detect missing configuration dependency
if (CONFIGURATION.equals(cdd.getType())) {
String bsn = c.getBundleContext().getBundle().getSymbolicName();
- return new ComponentId(cdd.getName(), cdd.getType(), bsn);
+ result.add(new ComponentId(cdd.getName(), cdd.getType(), bsn));
+ continue;
}
// Detect if the missing dependency is a root cause failure
ComponentDeclaration component = getComponentDeclaration(cdd.getName(), downComponents);
if (component == null) {
- return new ComponentId(cdd.getName(), cdd.getType(), null);
+ result.add(new ComponentId(cdd.getName(), cdd.getType(), null));
+ continue;
}
// Detect circular dependency
ComponentId componentId = new ComponentId(cdd.getName(), cdd.getType(), null);
@@ -648,30 +651,69 @@
System.out.print(" -> " + cid.getName() + " ");
}
System.out.println(" -> " + componentId.getName());
- return new ComponentId(c.getName(), SERVICE, c.getBundleContext().getBundle().getSymbolicName());
+ result.add(new ComponentId(c.getName(), SERVICE, c.getBundleContext().getBundle().getSymbolicName()));
+ continue;
}
backTrace.add(componentId);
return getRoot(downComponents, component, backTrace);
}
}
- if (downDeps > 0) {
- return new ComponentId(c.getName(), SERVICE, c.getBundleContext().getBundle().getSymbolicName());
+ if (downDeps > 0 && result.isEmpty()) {
+ result.add(new ComponentId(c.getName(), SERVICE, c.getBundleContext().getBundle().getSymbolicName()));
+ }
+ return result;
+ }
+
+ private ComponentDeclaration getComponentDeclaration(final String fullName, List<ComponentDeclaration> list) {
+ String simpleName = getSimpleName(fullName);
+ Properties props = parseProperties(fullName);
+ for (ComponentDeclaration c : list) {
+ String serviceNames = c.getName();
+ int cuttOff = serviceNames.indexOf("(");
+ if (cuttOff != -1) {
+ serviceNames = serviceNames.substring(0, cuttOff).trim();
+ }
+ for (String serviceName : serviceNames.split(",")) {
+ if (simpleName.equals(serviceName.trim()) && doPropertiesMatch(props, parseProperties(c.getName()))) {
+ return c;
+ }
+ }
}
return null;
}
- private ComponentDeclaration getComponentDeclaration(String name, List<ComponentDeclaration> list) {
- for (ComponentDeclaration c : list) {
- String serviceName = c.getName();
- int cuttOff = serviceName.indexOf("(");
- if (cuttOff != -1) {
- serviceName = serviceName.substring(0, cuttOff);
- }
- if (name.equals(serviceName)) {
- return c;
+ private boolean doPropertiesMatch(Properties need, Properties provide) {
+ for (Entry<Object, Object> entry : need.entrySet()) {
+ Object prop = provide.get(entry.getKey());
+ if (prop == null || !prop.equals(entry.getValue())) {
+ return false;
}
}
- return null;
+ return true;
+ }
+
+ private String getSimpleName(String name) {
+ int cuttOff = name.indexOf("(");
+ if (cuttOff != -1) {
+ return name.substring(0, cuttOff).trim();
+ }
+ return name.trim();
+ }
+
+ private Properties parseProperties(String name) {
+ Properties result = new Properties();
+ int cuttOff = name.indexOf("(");
+ if (cuttOff != -1) {
+ String propsText = name.substring(cuttOff + 1, name.indexOf(")"));
+ String[] split = propsText.split(",");
+ for (String prop : split) {
+ String[] kv = prop.split("=");
+ if (kv.length == 2) {
+ result.put(kv[0], kv[1]);
+ }
+ }
+ }
+ return result;
}
public static class DependencyManagerSorter implements Comparator<DependencyManager> {
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 c154a4c..3da016d 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
@@ -169,6 +169,62 @@
}
@Test
+ public void testCanFindRootFailureWithSecondair() {
+ setupEmptyBundles();
+
+ Component component1 = dm.createComponent()
+ .setImplementation(Object.class)
+ .setInterface(Object.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(Float.class).setRequired(true));
+ dm.add(component2);
+
+ Component component3 = dm.createComponent()
+ .setImplementation(Object.class)
+ .setInterface(new String[] {Object.class.getName(), Float.class.getName()}, null)
+ .add(dm.createServiceDependency().setService(String.class).setRequired(true));
+ dm.add(component3);
+
+ dme.wtf();
+ String output = outContent.toString();
+ assertTrue(output.contains("3 missing"));
+ assertTrue(output.contains("java.lang.String"));
+ assertFalse(output.contains("java.lang.Float"));
+
+ // remove the mess
+ dm.remove(component1);
+ dm.remove(component2);
+ dm.remove(component3);
+ }
+
+ @Test
+ public void testCanFindRootFailureWithTwoFailures() {
+ setupEmptyBundles();
+
+ Component component1 = dm.createComponent()
+ .setImplementation(Object.class)
+ .setInterface(Object.class.getName(), null)
+ .add(dm.createServiceDependency().setService(Math.class).setRequired(true))
+ .add(dm.createServiceDependency().setService(Long.class).setRequired(true));
+ dm.add(component1);
+
+
+ dme.wtf();
+ String output = outContent.toString();
+ assertTrue(output.contains("1 missing"));
+ assertTrue(output.contains("java.lang.Math"));
+ assertTrue(output.contains("java.lang.Long"));
+
+ // remove the mess
+ dm.remove(component1);
+ }
+
+ @Test
public void testInstalledBundleListing() {
Bundle bundle1 = mock(Bundle.class);
when(bundle1.getState()).thenReturn(Bundle.INSTALLED);