Modified the resolver so that it correctly discards exported packages from
resolved bundles that also import the same package and they were wired to
a provider other than themself. (FELIX-736)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@698755 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 efcb713..1116c83 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
@@ -596,13 +596,13 @@
break;
}
}
- // If delegate is true then there are no bundles
- // providing exports for this package and the instigating
- // class was not from a bundle. Therefore,
+ // If delegate is true then there are no bundles
+ // providing exports for this package and the instigating
+ // class was not from a bundle. Therefore,
// delegate to the parent class loader in case
// that this is not due to outside code calling a method
// on the bundle interface (e.g., Bundle.loadClass()).
- if (delegate && !Bundle.class.isInstance(classes[i - 1]))
+ if (delegate && !Bundle.class.isInstance(classes[i - 1]))
{
try
{
@@ -637,7 +637,7 @@
for (int dynIdx = 0; (dynamics != null) && (dynIdx < dynamics.length); dynIdx++)
{
IRequirement target =
- createDynamicRequirementTarget(dynamics[dynIdx], pkgName);
+ createDynamicRequirement(dynamics[dynIdx], pkgName);
if (target != null)
{
// See if there is a candidate exporter that satisfies the
@@ -736,8 +736,7 @@
return true;
}
- private IRequirement createDynamicRequirementTarget(
- IRequirement dynReq, String pkgName)
+ private IRequirement createDynamicRequirement(IRequirement dynReq, String pkgName)
{
IRequirement req = null;
@@ -1133,7 +1132,6 @@
m_logger.log(Logger.LOG_ERROR, "Unable to attach fragments", ex);
}
}
-//dumpResolvedPackages();
} // End of synchronized block on module manager.
// Fire resolved events for all resolved modules;
@@ -1441,38 +1439,16 @@
for (Iterator i = pkgIndexMap.entrySet().iterator(); i.hasNext(); )
{
Map.Entry entry = (Map.Entry) i.next();
- System.out.println(entry.getKey().getClass());
- System.out.println(entry.getValue().getClass());
-/*
- ICapability[] caps = (ICapability[]) entry.getValue();
- if ((caps != null) && (caps.length > 0))
+ IModule[] modules = (IModule[]) entry.getValue();
+ if ((modules != null) && (modules.length > 0))
{
- System.out.println(" " + entry.getKey());
- for (int j = 0; j < caps.length; j++)
+ if (!((modules.length == 1) && modules[0].getId().equals("0")))
{
- System.out.println(" " + caps[j]);
- }
- }
-*/
- }
- }
- }
-
- private void dumpResolvedPackages()
- {
- synchronized (this)
- {
- System.out.println("RESOLVED CAPABILITY MAP:");
- for (Iterator i = m_resolvedCapMap.entrySet().iterator(); i.hasNext(); )
- {
- Map.Entry entry = (Map.Entry) i.next();
- ICapability[] caps = (ICapability[]) entry.getValue();
- if ((caps != null) && (caps.length > 0))
- {
- System.out.println(" " + entry.getKey());
- for (int j = 0; j < caps.length; j++)
- {
- System.out.println(" " + caps[j]);
+ System.out.println(" " + entry.getKey());
+ for (int j = 0; j < modules.length; j++)
+ {
+ System.out.println(" " + modules[j]);
+ }
}
}
}
@@ -2437,9 +2413,12 @@
private Map createWires(Map candidatesMap, IModule rootModule)
{
+ // Get a map of all modules and their resolved wires.
Map resolvedModuleWireMap =
populateWireMap(candidatesMap, rootModule, new HashMap());
Iterator iter = resolvedModuleWireMap.entrySet().iterator();
+ // Iterate over the map to mark the modules as resolved and
+ // update our resolver data structures.
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry) iter.next();
@@ -2453,48 +2432,25 @@
if (wires.length > 0)
{
((ModuleImpl) module).setWires(wires);
+for (int wireIdx = 0; (wires != null) && (wireIdx < wires.length); wireIdx++)
+{
+ m_logger.log(Logger.LOG_DEBUG, "WIRE: " + wires[wireIdx]);
+}
}
- // Remove the wire's exporting module from the "unresolved"
- // package map and put it into the "resolved" package map;
- // these steps may be a no-op.
- for (int wireIdx = 0;
- (wires != null) && (wireIdx < wires.length);
- wireIdx++)
- {
-m_logger.log(Logger.LOG_DEBUG, "WIRE: " + wires[wireIdx]);
- }
-
- // Also add the module's capabilities to the "resolved" map
- // if the capability is not matched by a requirement. If the
- // capability is matched by a requirement.
+ // At this point, we need to remove all of the resolved module's
+ // capabilities from the "unresolved" package map and put them in
+ // in the "resolved" package map, with the exception of any
+ // package exports that are also imported. In that case we need
+ // to make sure that the import actually points to the resolved
+ // module and not another module. If it points to another module
+ // then the capability should be ignored, since the framework
+ // decided to honor the import and discard the export.
ICapability[] caps = module.getDefinition().getCapabilities();
- IRequirement[] reqs = module.getDefinition().getRequirements();
+
+ // First remove all existing capabilities from the "unresolved" map.
for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
{
- // We want to put all of the resolved module's capabilities
- // into the resolved capability map, except those package
- // exports that ended up being imported instead of exported
- // because the module both imported and exported the same
- // package. In this case, the export capability should be
- // ignored because the framework discarded it.
-// TODO: RB - Bug here because a requirement for a package need not overlap the
-// capability for that package and this assumes it does. This might
-// require us to introduce the notion of a substitutable capability.
-/*
- boolean ignoreCap = false;
- for (int reqIdx = 0;
- !ignoreCap && (reqs != null) && (reqIdx < reqs.length);
- reqIdx++)
- {
- if (reqs[reqIdx].isSatisfied(caps[capIdx]))
- {
- ignoreCap = true;
- }
- }
-*/
- // Removed all package capabilities from the unresolved
- // package index, since the module is now resolved.
if (caps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
{
// Get package name.
@@ -2507,30 +2463,72 @@
(IModule[]) m_unresolvedPkgIndexMap.get(pkgName),
module));
}
+ }
- ICapability[] resolvedCaps = (ICapability[]) m_resolvedCapMap.get(module);
- resolvedCaps = addCapabilityToArray(resolvedCaps, caps[capIdx]);
- m_resolvedCapMap.put(module, resolvedCaps);
-
- // If the capability is a package, then add the exporter module
- // of the wire to the "resolved" package index and remove it
- // from the "unresolved" package index.
- if (caps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ // Next create a copy of the module's capabilities so we can
+ // null out any capabilities that should be ignored.
+ ICapability[] capsCopy = (caps == null) ? null : new ICapability[caps.length];
+ if (capsCopy != null)
+ {
+ System.arraycopy(caps, 0, capsCopy, 0, caps.length);
+ }
+ // Loop through the module's capabilities to determine which ones
+ // can be ignored by seeing which ones satifies the wire requirements.
+// TODO: RB - Bug here because a requirement for a package need not overlap the
+// capability for that package and this assumes it does. This might
+// require us to introduce the notion of a substitutable capability.
+ for (int capIdx = 0; (capsCopy != null) && (capIdx < capsCopy.length); capIdx++)
+ {
+ // Loop through all wires to see if the current capability
+ // satisfies any of the wire requirements.
+ for (int wireIdx = 0; (wires != null) && (wireIdx < wires.length); wireIdx++)
{
- // Add to "resolved" package index.
- indexPackageCapability(
- m_resolvedPkgIndexMap,
- module,
- caps[capIdx]);
- // Remove from "unresolved" package index.
+ // If the wire requirement is satisfied by the current capability,
+ // then check to see if the wire is to the module itself. If it
+ // is to another module, then null the current capability since
+ // it was both providing and requiring the same capability and
+ // the resolve process chose to import rather than provide that
+ // capability, therefore we should ignore it.
+ if (wires[wireIdx].getRequirement().isSatisfied(capsCopy[capIdx]))
+ {
+ if (!wires[wireIdx].getExporter().equals(module))
+ {
+ capsCopy[capIdx] = null;
+ }
+ break;
+ }
+ }
+ }
+
+ // Now loop through all capabilities and add them to the "resolved"
+ // capability and package index maps, ignoring any that were nulled out.
+ for (int capIdx = 0; (capsCopy != null) && (capIdx < capsCopy.length); capIdx++)
+ {
+ if (capsCopy[capIdx] != null)
+ {
+ ICapability[] resolvedCaps = (ICapability[]) m_resolvedCapMap.get(module);
+ resolvedCaps = addCapabilityToArray(resolvedCaps, capsCopy[capIdx]);
+ m_resolvedCapMap.put(module, resolvedCaps);
+
+ // If the capability is a package, then add the exporter module
+ // of the wire to the "resolved" package index and remove it
+ // from the "unresolved" package index.
+ if (capsCopy[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ {
+ // Add to "resolved" package index.
+ indexPackageCapability(
+ m_resolvedPkgIndexMap,
+ module,
+ capsCopy[capIdx]);
+ }
}
}
}
-System.out.println("UNRESOLVED INDEX:");
-dumpPackageIndexMap(m_unresolvedPkgIndexMap);
-System.out.println("RESOLVED INDEX:");
-dumpPackageIndexMap(m_resolvedPkgIndexMap);
+//System.out.println("UNRESOLVED INDEX:");
+//dumpPackageIndexMap(m_unresolvedPkgIndexMap);
+//System.out.println("RESOLVED INDEX:");
+//dumpPackageIndexMap(m_resolvedPkgIndexMap);
return resolvedModuleWireMap;
}
@@ -3379,7 +3377,7 @@
IRequirement[] dynamics = module.getDefinition().getDynamicRequirements();
for (int dynIdx = 0; dynIdx < dynamics.length; dynIdx++)
{
- IRequirement target = createDynamicRequirementTarget(dynamics[dynIdx], pkgName);
+ IRequirement target = createDynamicRequirement(dynamics[dynIdx], pkgName);
if (target != null)
{
// Try to see if there is an exporter available.