You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2008/08/11 21:33:15 UTC

svn commit: r684886 - in /felix/trunk/framework/src/main/java/org/apache/felix/framework: Felix.java searchpolicy/R4SearchPolicyCore.java util/manifestparser/ManifestParser.java util/manifestparser/Requirement.java

Author: rickhall
Date: Mon Aug 11 12:33:15 2008
New Revision: 684886

URL: http://svn.apache.org/viewvc?rev=684886&view=rev
Log:
We were not correctly checking attributes when resolving dynamic imports.
We were creating our requirement using a filter instead of directives and
attributes and a requirement constructed in this fashion does not check
anything other than what is in the filter. Changed dynamic import resolution
to use the directive/attribute constructor of Requirement instead. (FELIX-676)

Modified:
    felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
    felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=684886&r1=684885&r2=684886&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Mon Aug 11 12:33:15 2008
@@ -2956,7 +2956,6 @@
                 new Requirement(
                     ICapability.PACKAGE_NAMESPACE,
                     null,
-                    null,
                     new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, pkgName, false) }));
 
         if (exporters != null)
@@ -2965,7 +2964,6 @@
 
             Requirement req = new Requirement(ICapability.PACKAGE_NAMESPACE,
                 null,
-                null,
                 new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, pkgName, false) });
 
             for (int pkgIdx = 0; pkgIdx < exporters.length; pkgIdx++)
@@ -3088,7 +3086,6 @@
                             new Requirement(
                                 ICapability.PACKAGE_NAMESPACE,
                                 null,
-                                null,
                                 new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, ((Capability) caps[capIdx]).getPackageName(), false) }));
 
                         // Search through the current providers to find the target

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java?rev=684886&r1=684885&r2=684886&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java Mon Aug 11 12:33:15 2008
@@ -38,6 +38,7 @@
 import org.apache.felix.framework.util.Util;
 import org.apache.felix.framework.util.manifestparser.Capability;
 import org.apache.felix.framework.util.manifestparser.ManifestParser;
+import org.apache.felix.framework.util.manifestparser.R4Attribute;
 import org.apache.felix.framework.util.manifestparser.R4Directive;
 import org.apache.felix.framework.util.manifestparser.R4Library;
 import org.apache.felix.framework.util.manifestparser.Requirement;
@@ -616,6 +617,46 @@
         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;
@@ -634,36 +675,12 @@
             // there is a matching one for the package from which we want to
             // load a class.
             IRequirement[] dynamics = importer.getDefinition().getDynamicRequirements();
-            for (int i = 0; (dynamics != null) && (i < dynamics.length); i++)
+            for (int dynIdx = 0; (dynamics != null) && (dynIdx < dynamics.length); dynIdx++)
             {
-                // Ignore any dynamic requirements whose packages don't match.
-                String dynPkgName = ((Requirement) dynamics[i]).getPackageName();
-                boolean wildcard = (dynPkgName.lastIndexOf(".*") >= 0);
-                dynPkgName = (wildcard)
-                    ? dynPkgName.substring(0, dynPkgName.length() - 2) : dynPkgName;
-                if (dynPkgName.equals("*") ||
-                    pkgName.equals(dynPkgName) ||
-                    (wildcard && pkgName.startsWith(dynPkgName + ".")))
-                {
-                    // Constrain the current dynamic requirement to include
-                    // the precise package name for which we are searching; this
-                    // is necessary because we cannot easily determine which
-                    // package name a given dynamic requirement matches, since
-                    // it is only a filter.
-
-                    IRequirement req = null;
-                    try
-                    {
-                        req = new Requirement(
-                            ICapability.PACKAGE_NAMESPACE,
-                            "(&" + dynamics[i].getFilter().toString()
-                                + "(package=" + pkgName + "))");
-                    }
-                    catch (InvalidSyntaxException ex)
-                    {
-                        // This should never happen.
-                    }
-
+                IRequirement target =
+                    createDynamicRequirementTarget(dynamics[dynIdx], pkgName);
+                if (target != null)
+                {
                     // See if there is a candidate exporter that satisfies the
                     // constrained dynamic requirement.
                     try
@@ -673,8 +690,8 @@
                         {
                             // Get "in use" and "available" candidates and put
                             // the "in use" candidates first.
-                            PackageSource[] inuse = getInUseCandidates(req);
-                            PackageSource[] available = getUnusedCandidates(req);
+                            PackageSource[] inuse = getInUseCandidates(target);
+                            PackageSource[] available = getUnusedCandidates(target);
                             PackageSource[] candidates = new PackageSource[inuse.length + available.length];
                             System.arraycopy(inuse, 0, candidates, 0, inuse.length);
                             System.arraycopy(available, 0, candidates, inuse.length, available.length);
@@ -714,7 +731,7 @@
 
                                 // Create the wire and add it to the module.
                                 wire = new R4Wire(
-                                    importer, dynamics[i], candidate.m_module, candidate.m_capability);
+                                    importer, dynamics[dynIdx], candidate.m_module, candidate.m_capability);
                                 newWires[newWires.length - 1] = wire;
                                 ((ModuleImpl) importer).setWires(newWires);
 m_logger.log(Logger.LOG_DEBUG, "WIRE: " + newWires[newWires.length - 1]);
@@ -1492,7 +1509,7 @@
      * modules to resolve its dependencies violate any singleton constraints.
      * Actually, it just creates a map of resolved singleton modules and then
      * delegates all checking to another recursive method.
-     * 
+     *
      * @param targetModule the module that is the root of the tree of modules to check.
      * @param moduleMap a map to cache the package space of each module.
      * @param candidatesMap a map containing the all candidates to resolve all
@@ -1523,7 +1540,7 @@
      * dependency modules to verify that they do not violate a singleton constraint.
      * If the target module is a singleton, then it checks that againts existing
      * singletons. Then it checks all current unresolved candidates recursively.
-     * 
+     *
      * @param targetModule the module that is the root of the tree of modules to check.
      * @param singletonMap the current map of singleton symbolic names.
      * @param moduleMap a map to cache the package space of each module.
@@ -3507,67 +3524,69 @@
         }
 */
         // Next, check to see if the package is dynamically imported by the module.
-// TODO: RB - Fix dynamic import diagnostic.
-//        IRequirement imp = createDynamicImportTarget(module, pkgName);
-        IRequirement imp = null;
-        if (imp != null)
-        {
-            // Try to see if there is an exporter available.
-            PackageSource[] exporters = getInUseCandidates(imp);
-            exporters = (exporters.length == 0)
-                ? getUnusedCandidates(imp) : exporters;
-
-            // An exporter might be available, but it may have attributes
-            // that do not match the importer's required attributes, so
-            // check that case by simply looking for an exporter of the
-            // desired package without any attributes.
-            if (exporters.length == 0)
+        IRequirement[] dynamics = module.getDefinition().getDynamicRequirements();
+        for (int dynIdx = 0; dynIdx < dynamics.length; dynIdx++)
+        {
+            IRequirement target = createDynamicRequirementTarget(dynamics[dynIdx], pkgName);
+            if (target != null)
             {
-                try
-                {
-                    IRequirement pkgReq = new Requirement(
-                        ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
-                    exporters = getInUseCandidates(pkgReq);
-                    exporters = (exporters.length == 0)
-                        ? getUnusedCandidates(pkgReq) : exporters;
-                }
-                catch (InvalidSyntaxException ex)
+                // Try to see if there is an exporter available.
+                PackageSource[] exporters = getInUseCandidates(target);
+                exporters = (exporters.length == 0)
+                    ? getUnusedCandidates(target) : exporters;
+
+                // An exporter might be available, but it may have attributes
+                // that do not match the importer's required attributes, so
+                // check that case by simply looking for an exporter of the
+                // desired package without any attributes.
+                if (exporters.length == 0)
                 {
-                    // This should never happen.
+                    try
+                    {
+                        IRequirement pkgReq = new Requirement(
+                            ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
+                        exporters = getInUseCandidates(pkgReq);
+                        exporters = (exporters.length == 0)
+                            ? getUnusedCandidates(pkgReq) : exporters;
+                    }
+                    catch (InvalidSyntaxException ex)
+                    {
+                        // This should never happen.
+                    }
                 }
-            }
 
-            long expId = (exporters.length == 0)
-                ? -1 : Util.getBundleIdFromModuleId(exporters[0].m_module.getId());
+                long expId = (exporters.length == 0)
+                    ? -1 : Util.getBundleIdFromModuleId(exporters[0].m_module.getId());
 
-            StringBuffer sb = new StringBuffer("*** Class '");
-            sb.append(name);
-            sb.append("' was not found, but this is likely normal since package '");
-            sb.append(pkgName);
-            sb.append("' is dynamically imported by bundle ");
-            sb.append(impId);
-            sb.append(".");
-            if (exporters.length > 0)
-            {
-                try
+                StringBuffer sb = new StringBuffer("*** Class '");
+                sb.append(name);
+                sb.append("' was not found, but this is likely normal since package '");
+                sb.append(pkgName);
+                sb.append("' is dynamically imported by bundle ");
+                sb.append(impId);
+                sb.append(".");
+                if (exporters.length > 0)
                 {
-                    if (!imp.isSatisfied(
-                        Util.getSatisfyingCapability(exporters[0].m_module,
-                            new Requirement(ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")"))))
+                    try
                     {
-                        sb.append(" However, bundle ");
-                        sb.append(expId);
-                        sb.append(" does export this package with attributes that do not match.");
+                        if (!target.isSatisfied(
+                            Util.getSatisfyingCapability(exporters[0].m_module,
+                                new Requirement(ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")"))))
+                        {
+                            sb.append(" However, bundle ");
+                            sb.append(expId);
+                            sb.append(" does export this package with attributes that do not match.");
+                        }
+                    }
+                    catch (InvalidSyntaxException ex)
+                    {
+                        // This should never happen.
                     }
                 }
-                catch (InvalidSyntaxException ex)
-                {
-                    // This should never happen.
-                }
-            }
-            sb.append(" ***");
+                sb.append(" ***");
 
-            return sb.toString();
+                return sb.toString();
+            }
         }
         IRequirement pkgReq = null;
         try

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java?rev=684886&r1=684885&r2=684886&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java Mon Aug 11 12:33:15 2008
@@ -594,7 +594,6 @@
                     // and add version if missing.
                     m_requirements[reqIdx] = new Requirement(
                         ICapability.PACKAGE_NAMESPACE,
-                        (String) pkgName.getValue(),
                         null,
                         new R4Attribute[] { pkgName, pkgVersion });
                 }
@@ -636,10 +635,7 @@
 
                 map.put(
                     m_capabilities[i].getProperties().get(ICapability.PACKAGE_PROPERTY),
-                    new Requirement(
-                        ICapability.PACKAGE_NAMESPACE,
-                        (String) m_capabilities[i].getProperties().get(ICapability.PACKAGE_PROPERTY),
-                        null, attrs));
+                    new Requirement(ICapability.PACKAGE_NAMESPACE, null, attrs));
             }
         }
         m_requirements =
@@ -978,7 +974,6 @@
                 reqList.add(
                     new Requirement(
                         ICapability.PACKAGE_NAMESPACE,
-                        null,
                         (R4Directive[]) clauses[clauseIdx][CLAUSE_DIRECTIVES_INDEX],
                         newAttrs));
             }
@@ -1033,7 +1028,6 @@
                 reqList.add(
                     new Requirement(
                         ICapability.MODULE_NAMESPACE,
-                        null,
                         (R4Directive[]) clauses[clauseIdx][CLAUSE_DIRECTIVES_INDEX],
                         newAttrs));
             }

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java?rev=684886&r1=684885&r2=684886&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java Mon Aug 11 12:33:15 2008
@@ -42,7 +42,7 @@
         m_filter = new FilterImpl(filterStr);
     }
 
-    public Requirement(String namespace, String pkgName, R4Directive[] directives, R4Attribute[] attributes)
+    public Requirement(String namespace, R4Directive[] directives, R4Attribute[] attributes)
     {
         m_namespace = namespace;
         m_directives = directives;