You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2010/01/13 17:03:07 UTC
svn commit: r898817 -
/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java
Author: rickhall
Date: Wed Jan 13 16:03:07 2010
New Revision: 898817
URL: http://svn.apache.org/viewvc?rev=898817&view=rev
Log:
Calculate resolve module package spaces.
Modified:
felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java
Modified: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java?rev=898817&r1=898816&r2=898817&view=diff
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java (original)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java Wed Jan 13 16:03:07 2010
@@ -152,7 +152,7 @@
private static void dumpModulePkgs(Module module, Packages packages)
{
- System.out.println(module);
+ System.out.println(module + " (" + (module.isResolved() ? "RESOLVED)" : "UNRESOLVED)"));
System.out.println(" EXPORTED");
for (Entry<String, Blame> entry : packages.m_exportedPkgs.entrySet())
{
@@ -249,14 +249,8 @@
m_invokeCounts.put(methodName, count);
}
- // If the module is resolved, then it is consistent by definition,
- // so just return.
- if (module.isResolved())
- {
- return;
- }
// If the module is in the cycle map, then just return.
- else if (cycleMap.containsKey(module))
+ if (cycleMap.containsKey(module))
{
return;
}
@@ -265,52 +259,87 @@
//System.out.println("+++ RESOLVING " + module);
calculateExportedPackages(module, incomingReqs, modulePkgMap);
- List<Requirement> reqs = module.getRequirements();
- for (Requirement req : reqs)
+ if (module.isResolved())
{
- // Get the candidates for the current requirement.
- Set<Capability> candCaps = candidateMap.get(req);
- // Optional requirements may not have any candidates.
- if (candCaps == null)
- {
- continue;
- }
+// Packages pkgs = modulePkgMap.get(module);
+// calculateResolvedPackages(module, incomingReqs, pkgs);
+ for (Wire wire : module.getWires())
+ {
+ // Try to resolve the candidate.
+ findConsistentCandidates(
+ wire.getCapability().getModule(),
+ incomingReqs,
+ candidateMap,
+ modulePkgMap,
+ cycleMap);
- List<Requirement> outgoingReqs = new ArrayList<Requirement>(incomingReqs);
- outgoingReqs.add(req);
+ // If we are here, the candidate was consistent. Try to
+ // merge the candidate into the target module's packages.
+ mergeResolvedCandidatePackages(
+ module,
+ incomingReqs,
+ wire.getCapability(),
+ modulePkgMap);
- for (Iterator<Capability> it = candCaps.iterator(); it.hasNext(); )
+ // If we are here, we merged the candidate successfully,
+ // so we can continue with the next requirement
+ break;
+ }
+ }
+ else
+ {
+ List<Requirement> reqs = module.getRequirements();
+ for (Requirement req : reqs)
{
- Capability candCap = it.next();
-System.out.println("+++ TRYING CAND " + candCap + " FOR " + req);
- try
+ // Get the candidates for the current requirement.
+ Set<Capability> candCaps = candidateMap.get(req);
+ // Optional requirements may not have any candidates.
+ if (candCaps == null)
{
- // Try to resolve the candidate.
- findConsistentCandidates(
- candCap.getModule(),
- outgoingReqs,
- candidateMap,
- modulePkgMap,
- cycleMap);
-
- // If we are here, the candidate resolved. Try to merge
- // the candidate's into the target module's packages.
- mergeCandidatePackages(module, outgoingReqs, candCap, modulePkgMap, candidateMap);
-
- // If we are here, we merged the candidate successfully,
- // so we can continue with the next requirement
- break;
+ continue;
}
- catch (ResolveException ex)
+
+ List<Requirement> outgoingReqs = new ArrayList<Requirement>(incomingReqs);
+ outgoingReqs.add(req);
+
+ for (Iterator<Capability> it = candCaps.iterator(); it.hasNext(); )
{
+ Capability candCap = it.next();
+System.out.println("+++ TRYING CAND " + candCap + " FOR " + req);
+ try
+ {
+ // Try to resolve the candidate.
+ findConsistentCandidates(
+ candCap.getModule(),
+ outgoingReqs,
+ candidateMap,
+ modulePkgMap,
+ cycleMap);
+
+ // If we are here, the candidate was consistent. Try to
+ // merge the candidate into the target module's packages.
+ mergeCandidatePackages(
+ module,
+ outgoingReqs,
+ candCap,
+ modulePkgMap,
+ candidateMap);
+
+ // If we are here, we merged the candidate successfully,
+ // so we can continue with the next requirement
+ break;
+ }
+ catch (ResolveException ex)
+ {
System.out.println("RE: " + ex);
ex.printStackTrace();
-// it.remove();
- if (!it.hasNext() && !req.isOptional())
- {
-// candidateMap.remove(req);
- throw new ResolveException("Unresolved constraint "
- + req + " in " + module);
+// it.remove();
+ if (!it.hasNext() && !req.isOptional())
+ {
+// candidateMap.remove(req);
+ throw new ResolveException("Unresolved constraint "
+ + req + " in " + module);
+ }
}
}
}
@@ -431,7 +460,6 @@
System.out.println("+++ MERGING " + candBlame.m_cap + " INTO " + current);
String pkgName = (String)
candBlame.m_cap.getAttribute(Capability.PACKAGE_ATTR).getValue();
- Packages candPkgs = modulePkgMap.get(candBlame.m_cap.getModule());
// Since this capability represents a package, it will become
// a hard constraint on the module's package space, so we need
@@ -554,7 +582,7 @@
}
}
-// TODO: PROTO2 RESOLVER - We end up with duplicates in uses constraints,
+// TODO: PROTO3 RESOLVER - We end up with duplicates in uses constraints,
// see scenario 2 for an example.
private void verifyAndMergeUses(
Module current, Packages currentPkgs,
@@ -583,24 +611,24 @@
cycleMap.put(pkgName, list);
//System.out.println("+++ VERIFYING USES " + current + " FOR " + candBlame);
- for (Capability candCapSource : getPackageSources(candBlame.m_cap, modulePkgMap, new ArrayList<Capability>()))
+ for (Capability candSourceCap : getPackageSources(candBlame.m_cap, modulePkgMap, new ArrayList<Capability>()))
{
- for (String usedPkgName : candCapSource.getUses())
+ for (String usedPkgName : candSourceCap.getUses())
{
Blame currentExportedBlame = currentPkgs.m_exportedPkgs.get(usedPkgName);
Blame currentImportedBlame = currentPkgs.m_importedPkgs.get(usedPkgName);
// TODO: PROTO3 RESOLVER - What do we do with required packages?
List<Blame> currentRequiredBlames = currentPkgs.m_requiredPkgs.get(usedPkgName);
- Packages sourcePkgs = modulePkgMap.get(candCapSource.getModule());
-System.out.println("+++ candCapSource " + candCapSource);
-System.out.println("+++ candCapSource.getModule() " + candCapSource.getModule() + " (" + candCapSource.getModule().isResolved() + ")");
-System.out.println("+++ sourcePkgs " + sourcePkgs);
-System.out.println("+++ sourcePkgs.m_exportedPkgs " + sourcePkgs.m_exportedPkgs);
- Blame sourceBlame = sourcePkgs.m_exportedPkgs.get(usedPkgName);
- sourceBlame = (sourceBlame != null)
- ? sourceBlame
- : sourcePkgs.m_importedPkgs.get(usedPkgName);
+ Packages candSourcePkgs = modulePkgMap.get(candSourceCap.getModule());
+System.out.println("+++ candSourceCap " + candSourceCap);
+System.out.println("+++ candSourceCap.getModule() " + candSourceCap.getModule() + " (" + candSourceCap.getModule().isResolved() + ")");
+System.out.println("+++ candSourcePkgs " + candSourcePkgs);
+System.out.println("+++ candSourcePkgs.m_exportedPkgs " + candSourcePkgs.m_exportedPkgs);
+ Blame candSourceBlame = candSourcePkgs.m_exportedPkgs.get(usedPkgName);
+ candSourceBlame = (candSourceBlame != null)
+ ? candSourceBlame
+ : candSourcePkgs.m_importedPkgs.get(usedPkgName);
// sourceCap = (sourceCap != null)
// ? sourceCap
// : sourcePkgs.m_requiredPkgs.get(usedPkgName);
@@ -608,7 +636,7 @@
// If the candidate doesn't actually have a constraint for
// the used package, then just ignore it since this is likely
// an error in its metadata.
- if (sourceBlame == null)
+ if (candSourceBlame == null)
{
return;
}
@@ -625,23 +653,23 @@
usedCaps = new ArrayList<Blame>();
currentPkgs.m_usedPkgs.put(usedPkgName, usedCaps);
}
-//System.out.println("+++ MERGING CB " + candBlame + " SB " + sourceBlame);
+System.out.println("+++ MERGING CB " + candBlame + " SB " + candSourceBlame);
// usedCaps.add(new Blame(candBlame.m_reqs, sourceBlame.m_cap));
- usedCaps.add(sourceBlame);
+ usedCaps.add(candSourceBlame);
return;
}
else if ((currentExportedBlame != null)
- && !isCompatible(currentExportedBlame.m_cap, sourceBlame.m_cap, modulePkgMap))
+ && !isCompatible(currentExportedBlame.m_cap, candSourceBlame.m_cap, modulePkgMap))
{
throw new ResolveException("Constraint violation for package '" + usedPkgName
+ "' when resolving module " + current
+ " between existing constraint "
+ currentExportedBlame
+ " and candidate constraint "
- + sourceBlame);
+ + candSourceBlame);
}
else if ((currentImportedBlame != null)
- && !isCompatible(currentImportedBlame.m_cap, sourceBlame.m_cap, modulePkgMap))
+ && !isCompatible(currentImportedBlame.m_cap, candSourceBlame.m_cap, modulePkgMap))
{
//System.out.println("+++ CIB " + currentImportedBlame + " SB " + sourceBlame);
// Try to remove the previously selected candidate associated
@@ -671,7 +699,7 @@
+ " between existing constraint "
+ currentImportedBlame
+ " and candidate constraint "
- + sourceBlame);
+ + candSourceBlame);
}
// This does not need to be recursive, even though "uses" constraints
@@ -687,6 +715,192 @@
}
}
+ private void mergeResolvedCandidatePackages(
+ Module current, List<Requirement> outgoingReqs,
+ Capability candCap, Map<Module, Packages> modulePkgMap)
+ {
+ if (m_isInvokeCount)
+ {
+ String methodName = new Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+ Long count = m_invokeCounts.get(methodName);
+ count = (count == null) ? new Long(1) : new Long(count.longValue() + 1);
+ m_invokeCounts.put(methodName, count);
+ }
+
+ if (candCap.getNamespace().equals(Capability.PACKAGE_NAMESPACE))
+ {
+ mergeResolvedCandidatePackage(
+ current, false, new Blame(outgoingReqs, candCap), modulePkgMap);
+ }
+ else if (candCap.getNamespace().equals(Capability.MODULE_NAMESPACE))
+ {
+ // Get the candidate's package space to determine which packages
+ // will be visible to the current module.
+ Packages candPkgs = modulePkgMap.get(candCap.getModule());
+
+// TODO: PROTO3 RESOLVER - For now assume only exports, but eventually we also
+// have to support re-exported packages.
+ for (Entry<String, Blame> entry : candPkgs.m_exportedPkgs.entrySet())
+ {
+ mergeResolvedCandidatePackage(
+ current,
+ true,
+ new Blame(outgoingReqs, entry.getValue().m_cap),
+ modulePkgMap);
+ }
+ }
+ }
+
+ private void mergeResolvedCandidatePackage(
+ Module current, boolean requires,
+ Blame candBlame, Map<Module, Packages> modulePkgMap)
+ {
+ if (m_isInvokeCount)
+ {
+ String methodName = new Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+ Long count = m_invokeCounts.get(methodName);
+ count = (count == null) ? new Long(1) : new Long(count.longValue() + 1);
+ m_invokeCounts.put(methodName, count);
+ }
+
+// TODO: PROTO3 RESOLVER - Check for merging where module imports from itself,
+// then it should be listed as an export.
+ if (candBlame.m_cap.getNamespace().equals(Capability.PACKAGE_NAMESPACE))
+ {
+System.out.println("+++ MERGING " + candBlame.m_cap + " INTO " + current);
+ String pkgName = (String)
+ candBlame.m_cap.getAttribute(Capability.PACKAGE_ATTR).getValue();
+
+ // Since this capability represents a package, it will become
+ // a hard constraint on the module's package space, so we need
+ // to make sure it doesn't conflict with any other hard constraints
+ // or any other uses constraints.
+
+ //
+ // First, check to see if the capability conflicts with
+ // any existing hard constraints.
+ //
+
+ Packages currentPkgs = modulePkgMap.get(current);
+ Blame currentExportedBlame = currentPkgs.m_exportedPkgs.get(pkgName);
+ Blame currentImportedBlame = currentPkgs.m_importedPkgs.get(pkgName);
+ List<Blame> currentRequiredBlames = currentPkgs.m_requiredPkgs.get(pkgName);
+
+ if (!requires &&
+ (((currentExportedBlame != null) && !currentExportedBlame.m_cap.equals(candBlame.m_cap))
+ || ((currentImportedBlame != null) && !currentImportedBlame.m_cap.equals(candBlame.m_cap))
+ || ((currentRequiredBlames != null) && !currentRequiredBlames.contains(candBlame))))
+ {
+ throw new ResolveException("Constraint violation between "
+ + current + " and " + candBlame.m_cap.getModule()
+ + " for " + pkgName);
+ }
+
+ if (requires)
+ {
+ if (currentRequiredBlames == null)
+ {
+ currentRequiredBlames = new ArrayList<Blame>();
+ currentPkgs.m_requiredPkgs.put(pkgName, currentRequiredBlames);
+ }
+// TODO: PROTO2 RESOLVER - This is potentially modifying the original, we need to modify a copy.
+ currentRequiredBlames.add(candBlame);
+ }
+ else
+ {
+ currentPkgs.m_importedPkgs.put(pkgName, candBlame);
+ }
+
+ // Verify and merge the candidate's transitive uses constraints.
+ mergeResolvedUses(
+ current,
+ currentPkgs,
+ candBlame,
+ modulePkgMap,
+ new HashMap<String, List<Module>>());
+dumpModulePkgs(current, currentPkgs);
+ }
+ }
+
+// TODO: PROTO3 RESOLVER - We end up with duplicates in uses constraints,
+// see scenario 2 for an example.
+ private void mergeResolvedUses(
+ Module current, Packages currentPkgs,
+ Blame candBlame, Map<Module, Packages> modulePkgMap,
+ Map<String, List<Module>> cycleMap)
+ {
+ if (m_isInvokeCount)
+ {
+ String methodName = new Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+ Long count = m_invokeCounts.get(methodName);
+ count = (count == null) ? new Long(1) : new Long(count.longValue() + 1);
+ m_invokeCounts.put(methodName, count);
+ }
+
+ // Check for cycles.
+ String pkgName = (String)
+ candBlame.m_cap.getAttribute(Capability.PACKAGE_ATTR).getValue();
+ List<Module> list = cycleMap.get(pkgName);
+ if ((list != null) && list.contains(current))
+ {
+ return;
+ }
+ list = (list == null) ? new ArrayList<Module>() : list;
+ list.add(current);
+ cycleMap.put(pkgName, list);
+
+//System.out.println("+++ VERIFYING USES " + current + " FOR " + candBlame);
+ for (Capability candSourceCap : getPackageSources(candBlame.m_cap, modulePkgMap, new ArrayList<Capability>()))
+ {
+ for (String usedPkgName : candSourceCap.getUses())
+ {
+ Blame currentExportedBlame = currentPkgs.m_exportedPkgs.get(usedPkgName);
+ Blame currentImportedBlame = currentPkgs.m_importedPkgs.get(usedPkgName);
+// TODO: PROTO3 RESOLVER - What do we do with required packages?
+ List<Blame> currentRequiredBlames = currentPkgs.m_requiredPkgs.get(usedPkgName);
+
+ Packages candSourcePkgs = modulePkgMap.get(candSourceCap.getModule());
+System.out.println("+++ candSourceCap " + candSourceCap);
+System.out.println("+++ candSourceCap.getModule() " + candSourceCap.getModule() + " (" + candSourceCap.getModule().isResolved() + ")");
+System.out.println("+++ candSourcePkgs " + candSourcePkgs);
+System.out.println("+++ candSourcePkgs.m_exportedPkgs " + candSourcePkgs.m_exportedPkgs);
+ Blame candSourceBlame = candSourcePkgs.m_exportedPkgs.get(usedPkgName);
+ candSourceBlame = (candSourceBlame != null)
+ ? candSourceBlame
+ : candSourcePkgs.m_importedPkgs.get(usedPkgName);
+// sourceCap = (sourceCap != null)
+// ? sourceCap
+// : sourcePkgs.m_requiredPkgs.get(usedPkgName);
+
+ // If the candidate doesn't actually have a constraint for
+ // the used package, then just ignore it since this is likely
+ // an error in its metadata.
+ if (candSourceBlame == null)
+ {
+ return;
+ }
+
+ // If there is no current mapping for this package, then
+ // we can just return.
+ if ((currentExportedBlame == null)
+ && (currentImportedBlame == null)
+ && (currentRequiredBlames == null))
+ {
+ List<Blame> usedCaps = currentPkgs.m_usedPkgs.get(usedPkgName);
+ if (usedCaps == null)
+ {
+ usedCaps = new ArrayList<Blame>();
+ currentPkgs.m_usedPkgs.put(usedPkgName, usedCaps);
+ }
+System.out.println("+++ MERGING CB " + candBlame + " SB " + candSourceBlame);
+// usedCaps.add(new Blame(candBlame.m_reqs, sourceBlame.m_cap));
+ usedCaps.add(candSourceBlame);
+ return;
+ }
+ }
+ }
+ }
+
private static boolean isCompatible(
Capability currentCap, Capability candCap, Map<Module, Packages> modulePkgMap)
{
@@ -706,14 +920,6 @@
if (cap.getNamespace().equals(Capability.PACKAGE_NAMESPACE))
{
Packages pkgs = modulePkgMap.get(cap.getModule());
- if ((pkgs == null) && cap.getModule().isResolved())
- {
- pkgs = new Packages();
- calculateResolvedPackages(cap.getModule(), pkgs);
- modulePkgMap.put(cap.getModule(), pkgs);
-System.out.println("RESOLVED PACKAGES:");
-dumpModulePkgs(cap.getModule(), pkgs);
- }
sources.add(cap);
String pkgName = cap.getAttribute(Capability.PACKAGE_ATTR).getValue().toString();
List<Blame> required = pkgs.m_requiredPkgs.get(pkgName);
@@ -729,32 +935,16 @@
return sources;
}
- private static void calculateResolvedPackages(Module module, Packages pkgs)
+ private static void calculateResolvedPackages(
+ Module module, List<Requirement> incomingReqs, Packages pkgs)
{
- List<Capability> caps = module.getCapabilities();
- if (caps.size() > 0)
- {
- for (int i = 0; i < caps.size(); i++)
- {
-// TODO: PROTO3 RESOLVER - Assume if a module imports the same package it
-// exports that the import will overlap the export.
- if (caps.get(i).getNamespace().equals(Capability.PACKAGE_NAMESPACE)
- && !hasOverlappingImport(module, caps.get(i)))
- {
- pkgs.m_exportedPkgs.put(
- (String) caps.get(i).getAttribute(Capability.PACKAGE_ATTR).getValue(),
- new Blame(null, caps.get(i)));
- }
- }
- }
-
for (Wire wire : module.getWires())
{
if (wire.getCapability().getNamespace().equals(Capability.PACKAGE_NAMESPACE))
{
pkgs.m_importedPkgs.put(
(String) wire.getCapability().getAttribute(Capability.PACKAGE_ATTR).getValue(),
- new Blame(null, wire.getCapability()));
+ new Blame(incomingReqs, wire.getCapability()));
calculateResolvedUses(wire.getCapability(), pkgs.m_usedPkgs);
}
else if (wire.getCapability().getNamespace().equals(Capability.MODULE_NAMESPACE))
@@ -770,7 +960,7 @@
requiredBlames = new ArrayList<Blame>();
pkgs.m_requiredPkgs.put(pkgName, requiredBlames);
}
- requiredBlames.add(new Blame(null, cap));
+ requiredBlames.add(new Blame(incomingReqs, cap));
calculateResolvedUses(wire.getCapability(), pkgs.m_usedPkgs);
}
}