[FELIX-4942] Compute all package sources for a given resource at the same time.
[FELIX-4942]
[FELIX-4942] This is interesting when resources export the same package multiple times. It also avoids maintaining cycles.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1690712 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java b/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
index f388457..c98182e 100644
--- a/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
+++ b/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
@@ -1592,82 +1592,77 @@
private static Set<Capability> getPackageSources(
ResolveSession session, Capability cap, Map<Resource, Packages> resourcePkgMap)
{
- Map<Capability, Set<Capability>> packageSourcesCache = resourcePkgMap.get(cap.getResource()).m_sources;
- // If it is a package, then calculate sources for it.
- if (cap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ Set<Capability> sources = resourcePkgMap.get(cap.getResource()).m_sources.get(cap);
+ if (sources == null)
{
- Set<Capability> sources = packageSourcesCache.get(cap);
- if (sources == null)
- {
- sources = getPackageSourcesInternal(
- session.getContext(), cap, resourcePkgMap,
- new HashSet<Capability>(64), new HashSet<Capability>(64));
- packageSourcesCache.put(cap, sources);
- }
- return sources;
+ getPackageSourcesInternal(session, resourcePkgMap, cap.getResource());
+ sources = resourcePkgMap.get(cap.getResource()).m_sources.get(cap);
}
-
- // Otherwise, need to return generic capabilies that have
- // uses constraints so they are included for consistency
- // checking.
- String uses = cap.getDirectives().get(Namespace.CAPABILITY_USES_DIRECTIVE);
- if ((uses != null) && (uses.length() > 0))
- {
- return Collections.singleton(cap);
- }
-
- return Collections.emptySet();
+ return sources;
}
- private static Set<Capability> getPackageSourcesInternal(
- ResolveContext rc, Capability cap, Map<Resource, Packages> resourcePkgMap,
- Set<Capability> sources, Set<Capability> cycleMap)
+ private static void getPackageSourcesInternal(
+ ResolveSession session, Map<Resource, Packages> resourcePkgMap, Resource resource)
{
- if (cap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
- {
- if (!cycleMap.add(cap))
- {
- return sources;
- }
-
- // Get the package name associated with the capability.
- String pkgName = cap.getAttributes()
- .get(PackageNamespace.PACKAGE_NAMESPACE).toString();
-
- // Since a resource can export the same package more than once, get
- // all package capabilities for the specified package name.
- Wiring wiring = rc.getWirings().get(cap.getResource());
- List<Capability> caps = (wiring != null)
+ Wiring wiring = session.getContext().getWirings().get(resource);
+ List<Capability> caps = (wiring != null)
? wiring.getResourceCapabilities(null)
- : cap.getResource().getCapabilities(null);
- for (Capability sourceCap : caps)
- {
- if (sourceCap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE)
- && sourceCap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE).equals(pkgName))
- {
- // Since capabilities may come from fragments, we need to check
- // for that case and wrap them.
- if (!cap.getResource().equals(sourceCap.getResource()))
- {
- sourceCap = new WrappedCapability(cap.getResource(), sourceCap);
- }
- sources.add(sourceCap);
- }
+ : resource.getCapabilities(null);
+ OpenHashMap<String, Set<Capability>> pkgs = new OpenHashMap<String, Set<Capability>>(caps.size()) {
+ public Set<Capability> compute(String pkgName) {
+ return new HashSet<Capability>();
}
-
- // Then get any addition sources for the package from required bundles.
- Packages pkgs = resourcePkgMap.get(cap.getResource());
- List<Blame> required = pkgs.m_requiredPkgs.get(pkgName);
- if (required != null)
+ };
+ Map<Capability, Set<Capability>> sources = resourcePkgMap.get(resource).m_sources;
+ for (Capability sourceCap : caps)
+ {
+ if (sourceCap.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
{
- for (Blame blame : required)
+ String pkgName = (String) sourceCap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+ Set<Capability> pkgCaps = pkgs.getOrCompute(pkgName);
+ sources.put(sourceCap, pkgCaps);
+ // Since capabilities may come from fragments, we need to check
+ // for that case and wrap them.
+ if (!resource.equals(sourceCap.getResource()))
{
- getPackageSourcesInternal(rc, blame.m_cap, resourcePkgMap, sources, cycleMap);
+ sourceCap = new WrappedCapability(resource, sourceCap);
+ }
+ pkgCaps.add(sourceCap);
+ }
+ else
+ {
+ // Otherwise, need to return generic capabilities that have
+ // uses constraints so they are included for consistency
+ // checking.
+ String uses = sourceCap.getDirectives().get(Namespace.CAPABILITY_USES_DIRECTIVE);
+ if ((uses != null) && !uses.isEmpty())
+ {
+ sources.put(sourceCap, Collections.singleton(sourceCap));
+ }
+ else
+ {
+ sources.put(sourceCap, Collections.<Capability>emptySet());
}
}
}
-
- return sources;
+ for (Map.Entry<String, Set<Capability>> pkg : pkgs.fast())
+ {
+ String pkgName = pkg.getKey();
+ List<Blame> required = resourcePkgMap.get(resource).m_requiredPkgs.get(pkgName);
+ if (required != null)
+ {
+ Set<Capability> srcs = pkg.getValue();
+ for (Blame blame : required)
+ {
+ Capability bcap = blame.m_cap;
+ if (srcs.add(bcap))
+ {
+ Set<Capability> additional = getPackageSources(session, bcap, resourcePkgMap);
+ srcs.addAll(additional);
+ }
+ }
+ }
+ }
}
private static Resource getDeclaredResource(Resource resource)