? mutated
: new HashSet<BundleRequirement>();
for (int reqIdx = usedBlame.m_reqs.size() - 1; reqIdx >= 0; reqIdx--)
{
BundleRequirement req = usedBlame.m_reqs.get(reqIdx);
// If we've already permutated this requirement in another
// uses constraint, don't permutate it again just continue
// with the next uses constraint.
if (mutated.contains(req))
{
break;
}
// See if we can permutate the candidates for blamed
// requirement; there may be no candidates if the revision
// associated with the requirement is already resolved.
List<BundleCapability> candidates = permutation.getCandidates(req);
if ((candidates != null) && (candidates.size() > 1))
{
mutated.add(req);
// Remove the conflicting candidate.
candidates.remove(0);
// Continue with the next uses constraint.
break;
}
}
}
}
if (rethrow != null)
{
if (mutated.size() > 0)
{
m_usesPermutations.add(permutation);
}
m_logger.log(
Logger.LOG_DEBUG,
"Candidate permutation failed due to a conflict between "
+ "an export and import; will try another if possible.",
rethrow);
throw rethrow;
}
}
// Check if there are any uses conflicts with imported packages.
for (Entry<String, List<Blame>> entry : pkgs.m_importedPkgs.entrySet())
{
for (Blame importBlame : entry.getValue())
{
String pkgName = entry.getKey();
if (!pkgs.m_usedPkgs.containsKey(pkgName))
{
continue;
}
for (Blame usedBlame : pkgs.m_usedPkgs.get(pkgName))
{
if (!isCompatible(importBlame.m_cap, usedBlame.m_cap, revisionPkgMap))
{
// Create a candidate permutation that eliminates any candidates
// that conflict with existing selected candidates.
permutation = (permutation != null)
? permutation
: allCandidates.copy();
rethrow = (rethrow != null)
? rethrow
: new ResolveException(
"Uses constraint violation. Unable to resolve bundle revision "
+ revision.getSymbolicName()
+ " [" + revision
+ "] because it is exposed to package '"
+ pkgName
+ "' from bundle revisions "
+ importBlame.m_cap.getRevision().getSymbolicName()
+ " [" + importBlame.m_cap.getRevision()
+ "] and "
+ usedBlame.m_cap.getRevision().getSymbolicName()
+ " [" + usedBlame.m_cap.getRevision()
+ "] via two dependency chains.\n\nChain 1:\n"
+ toStringBlame(rc, allCandidates, importBlame)
+ "\n\nChain 2:\n"
+ toStringBlame(rc, allCandidates, usedBlame),
null,
null);
mutated = (mutated != null)
? mutated
: new HashSet();
for (int reqIdx = usedBlame.m_reqs.size() - 1; reqIdx >= 0; reqIdx--)
{
BundleRequirement req = usedBlame.m_reqs.get(reqIdx);
// If we've already permutated this requirement in another
// uses constraint, don't permutate it again just continue
// with the next uses constraint.
if (mutated.contains(req))
{
break;
}
// See if we can permutate the candidates for blamed
// requirement; there may be no candidates if the revision
// associated with the requirement is already resolved.
List<BundleCapability> candidates = permutation.getCandidates(req);
if ((candidates != null) && (candidates.size() > 1))
{
mutated.add(req);
// Remove the conflicting candidate.
candidates.remove(0);
// Continue with the next uses constraint.
break;
}
}
}
}
// If there was a uses conflict, then we should add a uses
// permutation if we were able to permutate any candidates.
// Additionally, we should try to push an import permutation
// for the original import to force a backtracking on the
// original candidate decision if no viable candidate is found
// for the conflicting uses constraint.
if (rethrow != null)
{
// Add uses permutation if we mutated any candidates.
if (mutated.size() > 0)
{
m_usesPermutations.add(permutation);
}
// Try to permutate the candidate for the original
// import requirement; only permutate it if we haven't
// done so already.
BundleRequirement req = importBlame.m_reqs.get(0);
if (!mutated.contains(req))
{
// Since there may be lots of uses constraint violations
// with existing import decisions, we may end up trying
// to permutate the same import a lot of times, so we should
// try to check if that the case and only permutate it once.
permutateIfNeeded(allCandidates, req, m_importPermutations);
}
m_logger.log(
Logger.LOG_DEBUG,
"Candidate permutation failed due to a conflict between "
+ "imports; will try another if possible.",
rethrow);
throw rethrow;
}
}
}
resultCache.put(revision, Boolean.TRUE);
// Now check the consistency of all revisions on which the
// current revision depends. Keep track of the current number
// of permutations so we know if the lower level check was
// able to create a permutation or not in the case of failure.
int permCount = m_usesPermutations.size() + m_importPermutations.size();
for (Entry<String, List<Blame>> entry : pkgs.m_importedPkgs.entrySet())
{
for (Blame importBlame : entry.getValue())
{
if (!revision.equals(importBlame.m_cap.getRevision()))
{
try
{
checkPackageSpaceConsistency(
rc, false, importBlame.m_cap.getRevision(),
allCandidates, revisionPkgMap, resultCache);
}
catch (ResolveException ex)
{
// If the lower level check didn't create any permutations,
// then we should create an import permutation for the
// requirement with the dependency on the failing revision
// to backtrack on our current candidate selection.
if (permCount == (m_usesPermutations.size() + m_importPermutations.size()))
{
BundleRequirement req = importBlame.m_reqs.get(0);
permutate(allCandidates, req, m_importPermutations);
}
throw ex;
}
}