Improve resolver messages for constraint violations. (FELIX-2841)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1071050 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index aa2827a..bdd8a6e 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -3420,10 +3420,6 @@
catch (BundleException ex)
{
result = false;
- m_logger.log(targets[i],
- Logger.LOG_WARNING,
- "Unable to resolve bundle " + targets[i].getBundleId(),
- ex);
}
}
diff --git a/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java b/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
index ecfe761..53281f3 100644
--- a/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
@@ -34,8 +34,8 @@
import org.apache.felix.framework.capabilityset.CapabilitySet;
import org.apache.felix.framework.capabilityset.Directive;
import org.apache.felix.framework.capabilityset.Requirement;
+import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.RequirementImpl;
-import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
public class ResolverImpl implements Resolver
@@ -102,11 +102,6 @@
catch (ResolveException ex)
{
rethrow = ex;
- m_logger.log(
- module.getBundle(),
- Logger.LOG_DEBUG,
- "Current candidate permutation failed, will try another if possible.",
- ex);
}
}
while ((rethrow != null)
@@ -179,11 +174,6 @@
catch (ResolveException ex)
{
rethrow = ex;
- m_logger.log(
- module.getBundle(),
- Logger.LOG_DEBUG,
- "Current candidate permutation failed, will try another if possible.",
- ex);
}
}
while ((rethrow != null)
@@ -886,15 +876,27 @@
permutate(candidateMap, sourceBlame.m_reqs.get(0), m_importPermutations);
// Report conflict.
ResolveException ex = new ResolveException(
- "Constraint violation for package '"
- + entry.getKey() + "' when resolving module "
- + module + " between an import "
- + sourceBlame + " and a fragment import "
- + blame, module, blame.m_reqs.get(0));
+ "Unable to resolve module "
+ + module.getSymbolicName()
+ + " [" + module
+ + "] because it is exposed to package '"
+ + entry.getKey()
+ + "' from "
+ + sourceBlame.m_cap.getModule().getSymbolicName()
+ + " [" + sourceBlame.m_cap.getModule()
+ + "] and "
+ + blame.m_cap.getModule().getSymbolicName()
+ + " [" + blame.m_cap.getModule()
+ + "] via two dependency chains.\n\nChain 1:\n"
+ + toStringBlame(sourceBlame)
+ + "\n\nChain 2:\n"
+ + toStringBlame(blame),
+ null,
+ null);
m_logger.log(
- module.getBundle(),
Logger.LOG_DEBUG,
- "Conflicting fragment import",
+ "Candidate permutation failed due to a conflict with a "
+ + "fragment import; will try another if possible.",
ex);
throw ex;
}
@@ -922,11 +924,18 @@
rethrow = (rethrow != null)
? rethrow
: new ResolveException(
- "Constraint violation for package '"
- + pkgName + "' when resolving module "
- + module + " between existing export "
- + exportBlame + " and uses constraint "
- + usedBlame, null, null);
+ "Unable to resolve module "
+ + module.getSymbolicName()
+ + " [" + module
+ + "] because it exports package '"
+ + pkgName
+ + "' and is also exposed to it from "
+ + usedBlame.m_cap.getModule().getSymbolicName()
+ + " [" + usedBlame.m_cap.getModule()
+ + "] via the following dependency chain:\n\n"
+ + toStringBlame(usedBlame),
+ null,
+ null);
mutated = (mutated != null)
? mutated
@@ -967,12 +976,10 @@
{
m_usesPermutations.add(permutation);
}
- Bundle bundle =
- (rethrow.getModule() != null) ? rethrow.getModule().getBundle() : null;
m_logger.log(
- bundle,
Logger.LOG_DEBUG,
- "Conflict between an export and import",
+ "Candidate permutation failed due to a conflict between "
+ + "an export and import; will try another if possible.",
rethrow);
throw rethrow;
}
@@ -1000,11 +1007,23 @@
rethrow = (rethrow != null)
? rethrow
: new ResolveException(
- "Constraint violation for package '"
- + pkgName + "' when resolving module "
- + module + " between existing import "
- + importBlame + " and uses constraint "
- + usedBlame, null, null);
+ "Unable to resolve module "
+ + module.getSymbolicName()
+ + " [" + module
+ + "] because it is exposed to package '"
+ + pkgName
+ + "' from "
+ + importBlame.m_cap.getModule().getSymbolicName()
+ + " [" + importBlame.m_cap.getModule()
+ + "] and "
+ + usedBlame.m_cap.getModule().getSymbolicName()
+ + " [" + usedBlame.m_cap.getModule()
+ + "] via two dependency chains.\n\nChain 1:\n"
+ + toStringBlame(importBlame)
+ + "\n\nChain 2:\n"
+ + toStringBlame(usedBlame),
+ null,
+ null);
mutated = (mutated != null)
? mutated
@@ -1066,13 +1085,10 @@
permutateIfNeeded(candidateMap, req, m_importPermutations);
}
- Bundle bundle =
- (rethrow.getModule() != null)
- ? rethrow.getModule().getBundle() : null;
m_logger.log(
- bundle,
Logger.LOG_DEBUG,
- "Conflict between imports",
+ "Candidate permutation failed due to a conflict between "
+ + "imports; will try another if possible.",
rethrow);
throw rethrow;
}
@@ -1498,6 +1514,74 @@
}
}
+ private static String toStringBlame(Blame blame)
+ {
+ StringBuffer sb = new StringBuffer();
+ if ((blame.m_reqs != null) && !blame.m_reqs.isEmpty())
+ {
+ for (int i = 0; i < blame.m_reqs.size(); i++)
+ {
+ Requirement req = blame.m_reqs.get(i);
+ sb.append(" ");
+ sb.append(req.getModule().getSymbolicName());
+ sb.append(" [");
+ sb.append(req.getModule().toString());
+ sb.append("]\n import: ");
+ sb.append(req.getFilter().toString());
+ sb.append("\n |");
+ sb.append("\n export: ");
+ if ((i + 1) < blame.m_reqs.size())
+ {
+ Capability export = Util.getSatisfyingCapability(
+ blame.m_reqs.get(i + 1).getModule(),
+ blame.m_reqs.get(i));
+ sb.append(export.getAttribute(Capability.PACKAGE_ATTR).toString());
+ Capability usedCap;
+ if ((i + 2) < blame.m_reqs.size())
+ {
+ usedCap = Util.getSatisfyingCapability(
+ blame.m_reqs.get(i + 2).getModule(),
+ blame.m_reqs.get(i + 1));
+ }
+ else
+ {
+ usedCap = Util.getSatisfyingCapability(
+ blame.m_cap.getModule(),
+ blame.m_reqs.get(i + 1));
+ }
+ sb.append("; uses:=");
+ sb.append(usedCap.getAttribute(Capability.PACKAGE_ATTR).getValue());
+ sb.append("\n");
+ }
+ else
+ {
+ Capability export = Util.getSatisfyingCapability(
+ blame.m_cap.getModule(),
+ blame.m_reqs.get(i));
+ sb.append(export.getAttribute(Capability.PACKAGE_ATTR).toString());
+ if (!export.getAttribute(Capability.PACKAGE_ATTR).getValue()
+ .equals(blame.m_cap.getAttribute(Capability.PACKAGE_ATTR).getValue()))
+ {
+ sb.append("; uses:=");
+ sb.append(blame.m_cap.getAttribute(Capability.PACKAGE_ATTR).getValue());
+ sb.append("\n export: ");
+ sb.append(blame.m_cap.getAttribute(Capability.PACKAGE_ATTR).toString());
+ }
+ sb.append("\n ");
+ sb.append(blame.m_cap.getModule().getSymbolicName());
+ sb.append(" [");
+ sb.append(blame.m_cap.getModule().toString());
+ sb.append("]");
+ }
+ }
+ }
+ else
+ {
+ sb.append(blame.m_cap.getModule().toString());
+ }
+ return sb.toString();
+ }
+
private static class Packages
{
private final Module m_module;