Fixed a bug where class loader delegation for dynamic imports was happening
when it shouldn't. Specifically, if a bundle exports a given package or
has any sort of wire for that package (i.e., import-package or require-bundle),
then it should not be able to dynamically import that package. Previously,
only existing imported packages were being checked, not exported packages
or packages acquired through require-bundle. (FELIX-724)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@695618 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 e22f08d..1c8b60f 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
@@ -613,59 +613,15 @@
return null;
}
- private IRequirement createDynamicRequirementTarget(
- IRequirement dynReq, String pkgName)
- {
- IRequirement req = null;
-
- // First check to see if the dynamic requirement matches the
- // package name; this means we have to do wildcard matching.
- String dynPkgName = ((Requirement) dynReq).getPackageName();
- boolean wildcard = (dynPkgName.lastIndexOf(".*") >= 0);
- dynPkgName = (wildcard)
- ? dynPkgName.substring(0, dynPkgName.length() - 2) : dynPkgName;
- // If the dynamic requirement matches the package name, then
- // create a new requirement for the specific package.
- if (dynPkgName.equals("*") ||
- pkgName.equals(dynPkgName) ||
- (wildcard && pkgName.startsWith(dynPkgName + ".")))
- {
- // Create a new requirement based on the dynamic requirement,
- // but substitute the precise package name for which we are
- // looking, because it is not possible to use the potentially
- // wildcarded version in the dynamic requirement.
- R4Directive[] dirs = ((Requirement) dynReq).getDirectives();
- R4Attribute[] attrs = ((Requirement) dynReq).getAttributes();
- R4Attribute[] newAttrs = new R4Attribute[attrs.length];
- System.arraycopy(attrs, 0, newAttrs, 0, attrs.length);
- for (int attrIdx = 0; attrIdx < newAttrs.length; attrIdx++)
- {
- if (newAttrs[attrIdx].getName().equals(ICapability.PACKAGE_PROPERTY))
- {
- newAttrs[attrIdx] = new R4Attribute(
- ICapability.PACKAGE_PROPERTY, pkgName, false);
- break;
- }
- }
- req = new Requirement(ICapability.PACKAGE_NAMESPACE, dirs, newAttrs);
- }
-
- return req;
- }
-
private IWire attemptDynamicImport(IModule importer, String pkgName)
{
R4Wire wire = null;
PackageSource candidate = null;
- // There is an overriding assumption here that a package is
- // never split across bundles. If a package can be split
- // across bundles, then this will fail.
-
- // Only attempt to dynamically import a package if the module does
- // not already have a wire for the package; this may be the case if
- // the class being searched for actually does not exist.
- if (Util.getWire(importer, pkgName) == null)
+ // We can only search dynamic imports if the bundle
+ // doesn't import, export, nor require the package in
+ // question. Check these conditions first.
+ if (isDynamicImportAllowed(importer, pkgName))
{
// Loop through the importer's dynamic requirements to determine if
// there is a matching one for the package from which we want to
@@ -746,6 +702,73 @@
return null;
}
+ private boolean isDynamicImportAllowed(IModule importer, String pkgName)
+ {
+ // If any of the module exports this package, then we cannot
+ // attempt to dynamically import it.
+ ICapability[] caps = importer.getDefinition().getCapabilities();
+ for (int i = 0; (caps != null) && (i < caps.length); i++)
+ {
+ if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
+ && caps[i].getProperties().get(ICapability.PACKAGE_PROPERTY).equals(pkgName))
+ {
+ return false;
+ }
+ }
+ // If any of our wires have this package, then we cannot
+ // attempt to dynamically import it.
+ IWire[] wires = importer.getWires();
+ for (int i = 0; (wires != null) && (i < wires.length); i++)
+ {
+ if (wires[i].hasPackage(pkgName))
+ {
+ return false;
+ }
+ }
+ // Ok to attempt to dynamically import the package.
+ return true;
+ }
+
+ private IRequirement createDynamicRequirementTarget(
+ IRequirement dynReq, String pkgName)
+ {
+ IRequirement req = null;
+
+ // First check to see if the dynamic requirement matches the
+ // package name; this means we have to do wildcard matching.
+ String dynPkgName = ((Requirement) dynReq).getPackageName();
+ boolean wildcard = (dynPkgName.lastIndexOf(".*") >= 0);
+ dynPkgName = (wildcard)
+ ? dynPkgName.substring(0, dynPkgName.length() - 2) : dynPkgName;
+ // If the dynamic requirement matches the package name, then
+ // create a new requirement for the specific package.
+ if (dynPkgName.equals("*") ||
+ pkgName.equals(dynPkgName) ||
+ (wildcard && pkgName.startsWith(dynPkgName + ".")))
+ {
+ // Create a new requirement based on the dynamic requirement,
+ // but substitute the precise package name for which we are
+ // looking, because it is not possible to use the potentially
+ // wildcarded version in the dynamic requirement.
+ R4Directive[] dirs = ((Requirement) dynReq).getDirectives();
+ R4Attribute[] attrs = ((Requirement) dynReq).getAttributes();
+ R4Attribute[] newAttrs = new R4Attribute[attrs.length];
+ System.arraycopy(attrs, 0, newAttrs, 0, attrs.length);
+ for (int attrIdx = 0; attrIdx < newAttrs.length; attrIdx++)
+ {
+ if (newAttrs[attrIdx].getName().equals(ICapability.PACKAGE_PROPERTY))
+ {
+ newAttrs[attrIdx] = new R4Attribute(
+ ICapability.PACKAGE_PROPERTY, pkgName, false);
+ break;
+ }
+ }
+ req = new Requirement(ICapability.PACKAGE_NAMESPACE, dirs, newAttrs);
+ }
+
+ return req;
+ }
+
private boolean resolveDynamicImportCandidate(IModule provider, IModule importer)
throws ResolveException
{
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java
index 7085e59..e4fdfed 100755
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java
@@ -27,10 +27,10 @@
public class R4Wire implements IWire
{
- private IModule m_importer = null;
- private IRequirement m_requirement = null;
- private IModule m_exporter = null;
- private ICapability m_capability = null;
+ private final IModule m_importer;
+ private final IRequirement m_requirement;
+ private final IModule m_exporter;
+ private final ICapability m_capability;
public R4Wire(IModule importer, IRequirement requirement,
IModule exporter, ICapability capability)
@@ -76,6 +76,15 @@
/* (non-Javadoc)
* @see org.apache.felix.framework.searchpolicy.IWire#getClass(java.lang.String)
*/
+ public boolean hasPackage(String pkgName)
+ {
+ return (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
+ m_capability.getProperties().get(ICapability.PACKAGE_PROPERTY).equals(pkgName));
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.felix.framework.searchpolicy.IWire#getClass(java.lang.String)
+ */
public Class getClass(String name) throws ClassNotFoundException
{
Class clazz = null;
@@ -181,4 +190,4 @@
}
return m_importer + " -> " + m_capability + " -> " + m_exporter;
}
-}
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java
index 1f18f79..b60967f 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java
@@ -30,12 +30,12 @@
public class R4WireModule implements IWire
{
- private IModule m_importer = null;
- private IRequirement m_requirement = null;
- private IModule m_exporter = null;
- private ICapability m_capability = null;
- private Map m_pkgMap = null;
-
+ private final IModule m_importer;
+ private final IRequirement m_requirement;
+ private final IModule m_exporter;
+ private final ICapability m_capability;
+ private final Map m_pkgMap;
+
public R4WireModule(IModule importer, IRequirement requirement,
IModule exporter, ICapability capability, Map pkgMap)
{
@@ -45,7 +45,7 @@
m_capability = capability;
m_pkgMap = pkgMap;
}
-
+
/* (non-Javadoc)
* @see org.apache.felix.framework.searchpolicy.IWire#getImporter()
*/
@@ -53,7 +53,7 @@
{
return m_importer;
}
-
+
/* (non-Javadoc)
* @see org.apache.felix.framework.searchpolicy.IWire#getRequirement()
*/
@@ -69,7 +69,7 @@
{
return m_exporter;
}
-
+
/* (non-Javadoc)
* @see org.apache.felix.framework.searchpolicy.IWire#getCapability()
*/
@@ -79,6 +79,14 @@
}
/* (non-Javadoc)
+ * @see org.apache.felix.framework.searchpolicy.IWire#hasPackage(java.lang.String)
+ */
+ public boolean hasPackage(String pkgName)
+ {
+ return (m_pkgMap.get(pkgName) != null);
+ }
+
+ /* (non-Javadoc)
* @see org.apache.felix.framework.searchpolicy.IWire#getClass(java.lang.String)
*/
public Class getClass(String name) throws ClassNotFoundException
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/IWire.java b/framework/src/main/java/org/apache/felix/moduleloader/IWire.java
index abb871e..f0f0204 100644
--- a/framework/src/main/java/org/apache/felix/moduleloader/IWire.java
+++ b/framework/src/main/java/org/apache/felix/moduleloader/IWire.java
@@ -27,6 +27,7 @@
public IRequirement getRequirement();
public IModule getExporter();
public ICapability getCapability();
+ public boolean hasPackage(String pkgName);
public Class getClass(String name) throws ClassNotFoundException;
public URL getResource(String name) throws ResourceNotFoundException;
public Enumeration getResources(String name) throws ResourceNotFoundException;