Added experimental "implicit import" concept that allows exporters to push
additional imports to importers of their packages; this feature will likely
be removed in the future.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@546926 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
index 065ee3b..31f97c7 100755
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
@@ -1036,7 +1036,19 @@
// Get the package map for the target module, which is a
// map of all packages accessible to the module and their
// associated package sources.
- Map pkgMap = getModulePackages(moduleMap, targetModule, candidatesMap);
+ Map pkgMap = null;
+ try
+ {
+ pkgMap = getModulePackages(moduleMap, targetModule, candidatesMap);
+ }
+ catch (ResolveException ex)
+ {
+ m_logger.log(
+ Logger.LOG_DEBUG,
+ "Constraint violation for " + targetModule + " detected.",
+ ex);
+ return false;
+ }
// Loop through all of the target module's accessible packages and
// verify that all package sources are consistent.
@@ -1059,7 +1071,19 @@
// Now we need to calculate the "uses" constraints of every package
// accessible to the target module based on the current candidates.
- Map usesMap = calculateUsesConstraints(targetModule, moduleMap, candidatesMap);
+ Map usesMap = null;
+ try
+ {
+ usesMap = calculateUsesConstraints(targetModule, moduleMap, candidatesMap);
+ }
+ catch (ResolveException ex)
+ {
+ m_logger.log(
+ Logger.LOG_DEBUG,
+ "Constraint violation for " + targetModule + " detected.",
+ ex);
+ return false;
+ }
// Verify that none of the implied "uses" constraints in the uses map
// conflict with anything in the target module's package map.
@@ -1121,6 +1145,7 @@
private Map calculateUsesConstraints(
IModule targetModule, Map moduleMap, Map candidatesMap)
+ throws ResolveException
{
//System.out.println("calculateUsesConstraints("+targetModule+")");
// Map to store calculated uses constraints. This maps a
@@ -1158,6 +1183,7 @@
private Map calculateUsesConstraints(
PackageSource psTarget, Map moduleMap, Map usesMap,
Map cycleMap, Map candidatesMap)
+ throws ResolveException
{
//System.out.println("calculateUsesConstraints2("+psTarget.m_module+")");
// If we are in a cycle, then return for now.
@@ -1216,6 +1242,7 @@
}
private Map getModulePackages(Map moduleMap, IModule module, Map candidatesMap)
+ throws ResolveException
{
Map map = (Map) moduleMap.get(module);
@@ -1247,6 +1274,7 @@
* is a ResolvedPackage.
**/
private Map calculateModulePackages(IModule module, Map candidatesMap)
+ throws ResolveException
{
//System.out.println("calculateModulePackages("+module+")");
Map importedPackages = calculateImportedPackages(module, candidatesMap);
@@ -1285,6 +1313,7 @@
}
private Map calculateImportedPackages(IModule targetModule, Map candidatesMap)
+ throws ResolveException
{
return (candidatesMap.get(targetModule) == null)
? calculateImportedPackagesResolved(targetModule)
@@ -1292,6 +1321,7 @@
}
private Map calculateImportedPackagesUnresolved(IModule targetModule, Map candidatesMap)
+ throws ResolveException
{
//System.out.println("calculateImportedPackagesUnresolved("+targetModule+")");
Map pkgMap = new HashMap();
@@ -1316,6 +1346,27 @@
ResolvedPackage rp = new ResolvedPackage(pkgName);
rp.m_sourceList.add(ps);
pkgMap.put(rp.m_name, rp);
+ // TODO: FRAMEWORK - Experimental implicit wire concept to try
+ // to deal with code generation.
+ // Get implicitly imported packages as defined by the provider
+ // of our imported package.
+ Map implicitPkgMap = calculateImplicitImportedPackages(ps, candidatesMap, new HashMap());
+ // Merge the implicitly imported packages with our imports and
+ // verify that there is no overlap.
+ for (Iterator i = implicitPkgMap.entrySet().iterator(); i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ if (pkgMap.get(entry.getKey()) != null)
+ {
+ throw new ResolveException(
+ "Implicit import of "
+ + entry.getKey()
+ + " duplicates an existing import.",
+ targetModule,
+ cs.m_requirement);
+ }
+ pkgMap.put(entry.getKey(), entry.getValue());
+ }
}
}
@@ -1323,6 +1374,7 @@
}
private Map calculateImportedPackagesResolved(IModule targetModule)
+ throws ResolveException
{
//System.out.println("calculateImportedPackagesResolved("+targetModule+")");
Map pkgMap = new HashMap();
@@ -1347,6 +1399,84 @@
return pkgMap;
}
+ private Map calculateImplicitImportedPackages(
+ PackageSource psTarget, Map candidatesMap, Map cycleMap)
+ {
+ return (candidatesMap.get(psTarget.m_module) == null)
+ ? calculateImplicitImportedPackagesResolved(psTarget, cycleMap)
+ : calculateImplicitImportedPackagesUnresolved(psTarget, candidatesMap, cycleMap);
+ }
+
+ // TODO: FRAMEWORK - This is currently not defined recursively, but it should be.
+ // Currently, it only assumes that a provider can cause implicit imports for
+ // packages that it exports.
+ private Map calculateImplicitImportedPackagesUnresolved(PackageSource psTarget, Map candidatesMap, Map cycleMap)
+ {
+ Map pkgMap = new HashMap();
+
+ R4Directive[] dirs = ((Capability) psTarget.m_capability).getDirectives();
+ if (dirs != null)
+ {
+ for (int dirIdx = 0; dirIdx < dirs.length; dirIdx++)
+ {
+ if (dirs[dirIdx].getName().equals("x-implicitwire"))
+ {
+ String[] pkgs = ManifestParser.parseDelimitedString(dirs[dirIdx].getValue(), ",");
+ for (int pkgIdx = 0; pkgIdx < pkgs.length; pkgIdx++)
+ {
+ ResolvedPackage rp = new ResolvedPackage(pkgs[pkgIdx].trim());
+ rp.m_sourceList.add(
+ new PackageSource(
+ psTarget.m_module,
+ getExportPackageCapability(psTarget.m_module, pkgs[pkgIdx])));
+ pkgMap.put(rp.m_name, rp);
+ }
+ }
+ }
+ }
+
+ return pkgMap;
+ }
+
+ // TODO: FRAMEWORK - This is currently not defined recursively, but it should be.
+ // Currently, it only assumes that a provider can cause implicit imports for
+ // packages that it exports.
+ private Map calculateImplicitImportedPackagesResolved(PackageSource psTarget, Map cycleMap)
+ {
+ Map pkgMap = new HashMap();
+
+ R4Directive[] dirs = ((Capability) psTarget.m_capability).getDirectives();
+ if (dirs != null)
+ {
+ for (int dirIdx = 0; dirIdx < dirs.length; dirIdx++)
+ {
+ if (dirs[dirIdx].getName().equals("x-implicitwire"))
+ {
+ String[] pkgs = ManifestParser.parseDelimitedString(dirs[dirIdx].getValue(), ",");
+ for (int pkgIdx = 0; pkgIdx < pkgs.length; pkgIdx++)
+ {
+ ResolvedPackage rp = new ResolvedPackage(pkgs[pkgIdx].trim());
+ rp.m_sourceList.add(
+ new PackageSource(
+ psTarget.m_module,
+ getExportPackageCapability(psTarget.m_module, pkgs[pkgIdx])));
+ pkgMap.put(rp.m_name, rp);
+ }
+ }
+ }
+ }
+
+ return pkgMap;
+ }
+
+ private Map calculateCandidateImplicitImportedPackages(IModule module, PackageSource psTarget, Map candidatesMap)
+ {
+//System.out.println("calculateCandidateImplicitPackages("+module+")");
+ Map cycleMap = new HashMap();
+ cycleMap.put(module, module);
+ return calculateImplicitImportedPackages(psTarget, candidatesMap, cycleMap);
+ }
+
private Map calculateExportedPackages(IModule targetModule)
{
//System.out.println("calculateExportedPackages("+targetModule+")");
@@ -1528,7 +1658,7 @@
// current candidate.
Map requiredMap = calculateExportedAndReexportedPackages(ps, candidatesMap, cycleMap);
- // Merge the candidate's exported and re-exported packages
+ // Merge the candidate's exported and required packages
// into the complete set of required packages.
for (Iterator reqIter = requiredMap.entrySet().iterator(); reqIter.hasNext(); )
{
@@ -1902,11 +2032,29 @@
}
else
{
+ // Add wire for imported package.
packageWires.add(new R4Wire(
importer,
cs.m_requirement,
cs.m_candidates[cs.m_idx].m_module,
cs.m_candidates[cs.m_idx].m_capability));
+
+ // TODO: FRAMEWORK - The following is part of an experimental
+ // implicit imported wire concept. The above code is how
+ // the wire should normally be created.
+ // Add wires for any implicitly imported package from provider.
+ Map pkgMap = calculateCandidateImplicitImportedPackages(
+ importer, cs.m_candidates[cs.m_idx], candidatesMap);
+ for (Iterator i = pkgMap.entrySet().iterator(); i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ ResolvedPackage rp = (ResolvedPackage) entry.getValue();
+ packageWires.add(new R4Wire(
+ importer,
+ cs.m_requirement, // TODO: This is not really correct.
+ ((PackageSource) rp.m_sourceList.get(0)).m_module,
+ ((PackageSource) rp.m_sourceList.get(0)).m_capability));
+ }
}
// Create any necessary wires for the selected candidate module.
@@ -2817,4 +2965,4 @@
return sb.toString();
}
-}
\ No newline at end of file
+}