// Populate mandatory resources; since these are mandatory
// resources, failure throws a resolve exception.
for (Iterator<Resource> it = mandatoryResources.iterator();
it.hasNext();)
{
Resource resource = it.next();
if (Util.isFragment(resource) || (rc.getWirings().get(resource) == null))
{
allCandidates.populate(rc, resource, Candidates.MANDATORY);
}
else
{
it.remove();
}
}
// Populate optional resources; since these are optional
// resources, failure does not throw a resolve exception.
for (Resource resource : optionalResources)
{
boolean isFragment = Util.isFragment(resource);
if (isFragment || (rc.getWirings().get(resource) == null))
{
allCandidates.populate(rc, resource, Candidates.OPTIONAL);
}
}
// Populate ondemand fragments; since these are optional
// resources, failure does not throw a resolve exception.
for (Resource resource : ondemandFragments)
{
boolean isFragment = Util.isFragment(resource);
if (isFragment)
{
allCandidates.populate(rc, resource, Candidates.ON_DEMAND);
}
}
// Merge any fragments into hosts.
allCandidates.prepare(rc);
// Create a combined list of populated resources; for
// optional resources. We do not need to consider ondemand
// fragments, since they will only be pulled in if their
// host is already present.
Set<Resource> allResources =
new HashSet<Resource>(mandatoryResources);
for (Resource resource : optionalResources)
{
if (allCandidates.isPopulated(resource))
{
allResources.add(resource);
}
}
List<Candidates> usesPermutations = session.getUsesPermutations();
List<Candidates> importPermutations = session.getImportPermutations();
// Record the initial candidate permutation.
usesPermutations.add(allCandidates);
ResolutionException rethrow = null;
// If a populated resource is a fragment, then its host
// must ultimately be verified, so store its host requirement
// to use for package space calculation.
Map<Resource, List<Requirement>> hostReqs =
new HashMap<Resource, List<Requirement>>();
for (Resource resource : allResources)
{
if (Util.isFragment(resource))
{
hostReqs.put(
resource,
resource.getRequirements(HostNamespace.HOST_NAMESPACE));
}
}
do
{
rethrow = null;
resourcePkgMap.clear();
session.getPackageSourcesCache().clear();
// Null out each time a new permutation is attempted.
// We only use this to store a valid permutation which is a
// delta of the current permutation.
session.setMultipleCardCandidates(null);
allCandidates = (usesPermutations.size() > 0)
? usesPermutations.remove(0)
: importPermutations.remove(0);
//allCandidates.dump();
// Reuse a resultCache map for checking package consistency
// for all resources.
Map<Resource, Object> resultCache =
new HashMap<Resource, Object>(allResources.size());
// Check the package space consistency for all 'root' resources.
for (Resource resource : allResources)
{
Resource target = resource;
// If we are resolving a fragment, then get its
// host candidate and verify it instead.
List<Requirement> hostReq = hostReqs.get(resource);
if (hostReq != null)
{
target = allCandidates.getCandidates(hostReq.get(0))
.iterator().next().getResource();
}
calculatePackageSpaces(
session, allCandidates.getWrappedHost(target), allCandidates,
resourcePkgMap, new HashMap(), new HashSet());
//System.out.println("+++ PACKAGE SPACES START +++");
//dumpResourcePkgMap(resourcePkgMap);
//System.out.println("+++ PACKAGE SPACES END +++");
try
{
checkPackageSpaceConsistency(
session, allCandidates.getWrappedHost(target),
allCandidates, resourcePkgMap, resultCache);
}
catch (ResolutionException ex)
{
rethrow = ex;
}
}
}
while ((rethrow != null)
&& ((usesPermutations.size() > 0) || (importPermutations.size() > 0)));
// If there is a resolve exception, then determine if an
// optionally resolved resource is to blame (typically a fragment).
// If so, then remove the optionally resolved resolved and try
// again; otherwise, rethrow the resolve exception.
if (rethrow != null)
{
Collection<Requirement> exReqs = rethrow.getUnresolvedRequirements();
Requirement faultyReq = ((exReqs == null) || (exReqs.isEmpty()))
? null : exReqs.iterator().next();
Resource faultyResource = (faultyReq == null)
? null : getDeclaredResource(faultyReq.getResource());
// If the faulty requirement is wrapped, then it may
// be from a fragment, so consider the fragment faulty
// instead of the host.
if (faultyReq instanceof WrappedRequirement)
{
faultyResource =
((WrappedRequirement) faultyReq)
.getDeclaredRequirement().getResource();
}
// Try to ignore the faulty resource if it is not mandatory.
if (optionalResources.remove(faultyResource))
{
retry = true;
}
else if (ondemandFragments.remove(faultyResource))
{
retry = true;
}
else
{
throw rethrow;
}
}
// If there is no exception to rethrow, then this was a clean
// resolve, so populate the wire map.
else
{
if (session.getMultipleCardCandidates() != null)
{
// Candidates for multiple cardinality requirements were
// removed in order to provide a consistent class space.
// Use the consistent permutation
allCandidates = session.getMultipleCardCandidates();
}
for (Resource resource : allResources)
{
Resource target = resource;
// If we are resolving a fragment, then we
// actually want to populate its host's wires.
List<Requirement> hostReq = hostReqs.get(resource);
if (hostReq != null)