// Wrap the requirement as a hosted requirement if it comes
// from a fragment, since we will need to know the host. We
// also need to wrap if the requirement is a dynamic import,
// since that requirement will be shared with any other
// matching dynamic imports.
Requirement r = wire.getRequirement();
if (!r.getResource().equals(wire.getRequirer())
|| ((r.getDirectives()
.get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE) != null)
&& r.getDirectives()
.get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE)
.equals(PackageNamespace.RESOLUTION_DYNAMIC)))
{
r = new WrappedRequirement(wire.getRequirer(), r);
}
// Wrap the capability as a hosted capability if it comes
// from a fragment, since we will need to know the host.
Capability c = wire.getCapability();
if (!c.getResource().equals(wire.getProvider()))
{
c = new WrappedCapability(wire.getProvider(), c);
}
reqs.add(r);
caps.add(c);
}
// Since the resource is resolved, it could be dynamically importing,
// so check to see if there are candidates for any of its dynamic
// imports.
//
// NOTE: If the resource is dynamically importing, the fact that
// the dynamic import is added here last to the parallel reqs/caps
// list is used later when checking to see if the package being
// dynamically imported shadows an existing provider.
for (Requirement req
: Util.getDynamicRequirements(wiring.getResourceRequirements(null)))
{
// Get the candidates for the current requirement.
List<Capability> candCaps = allCandidates.getCandidates(req);
// Optional requirements may not have any candidates.
if (candCaps == null)
{
continue;
}
// Grab first (i.e., highest priority) candidate.
Capability cap = candCaps.get(0);
reqs.add(req);
caps.add(cap);
isDynamicImporting = true;
// Can only dynamically import one at a time, so break
// out of the loop after the first.
break;
}
}
else
{
for (Requirement req : resource.getRequirements(null))
{
if (!Util.isDynamic(req))
{
// Get the candidates for the current requirement.
List<Capability> candCaps = allCandidates.getCandidates(req);
// Optional requirements may not have any candidates.
if (candCaps == null)
{
continue;
}
// For multiple cardinality requirements, we need to grab
// all candidates.
if (Util.isMultiple(req))
{
// Use the same requirement, but list each capability separately
for (Capability cap : candCaps)
{
reqs.add(req);
caps.add(cap);
}
}
// Grab first (i.e., highest priority) candidate
else
{
Capability cap = candCaps.get(0);
reqs.add(req);
caps.add(cap);
}
}
}
}
// First, add all exported packages to the target resource's package space.
calculateExportedPackages(session.getContext(), resource, allCandidates, resourcePkgMap);
resourcePkgs = resourcePkgMap.get(resource);
// Second, add all imported packages to the target resource's package space.
for (int i = 0; i < reqs.size(); i++)
{
Requirement req = reqs.get(i);
Capability cap = caps.get(i);
calculateExportedPackages(
session.getContext(), cap.getResource(), allCandidates, resourcePkgMap);
// If this resource is dynamically importing, then the last requirement
// is the dynamic import being resolved, since it is added last to the
// parallel lists above. For the dynamically imported package, make
// sure that the resource doesn't already have a provider for that
// package, which would be illegal and shouldn't be allowed.
if (isDynamicImporting && ((i + 1) == reqs.size()))
{
String pkgName = (String) cap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
if (resourcePkgs.m_exportedPkgs.containsKey(pkgName)
|| resourcePkgs.m_importedPkgs.containsKey(pkgName)
|| resourcePkgs.m_requiredPkgs.containsKey(pkgName))
{
throw new IllegalArgumentException(
"Resource "
+ resource
+ " cannot dynamically import package '"
+ pkgName
+ "' since it already has access to it.");
}
}
mergeCandidatePackages(
session.getContext(), resource, req, cap, resourcePkgMap, allCandidates,
new HashMap<Resource, List<Capability>>());
}
// Third, have all candidates to calculate their package spaces.
for (int i = 0; i < caps.size(); i++)
{
calculatePackageSpaces(
session, caps.get(i).getResource(), allCandidates, resourcePkgMap,
usesCycleMap, cycle);
}
// Fourth, if the target resource is unresolved or is dynamically importing,
// then add all the uses constraints implied by its imported and required
// packages to its package space.
// NOTE: We do not need to do this for resolved resources because their
// package space is consistent by definition and these uses constraints
// are only needed to verify the consistency of a resolving resource. The
// only exception is if a resolved resource is dynamically importing, then
// we need to calculate its uses constraints again to make sure the new
// import is consistent with the existing package space.
if ((wiring == null) || isDynamicImporting)
{
// Merge uses constraints from required capabilities.
for (int i = 0; i < reqs.size(); i++)
{
Requirement req = reqs.get(i);
Capability cap = caps.get(i);
// Ignore bundle/package requirements, since they are
// considered below.
if (!req.getNamespace().equals(BundleNamespace.BUNDLE_NAMESPACE)
&& !req.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
{
List<Requirement> blameReqs = new ArrayList<Requirement>();
blameReqs.add(req);
mergeUses(