No longer acquire global lock to check if it is possible to dynamically
import. (FELIX-1534)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@831119 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index 877da9c..fa9a97e 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -3881,7 +3881,13 @@
         {
             IWire candidateWire = null;
 
-            if (importer.isResolved())
+            // We cannot dynamically import if the module is already resolved or
+            // if it is not allowed, so check that first. Note: We check if the
+            // dynamic import is allowed without holding any locks, but this is
+            // okay since the resolver will double check later after we have
+            // acquired the global lock below.
+            if (importer.isResolved()
+                && (Resolver.findAllowedDynamicImport(importer, pkgName) != null))
             {
                 // Acquire global lock.
                 boolean locked = acquireGlobalLock();
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
index c713ed6..0873b3a 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
@@ -122,127 +122,16 @@
         ICapability candidate = null;
         Map resolvedModuleWireMap = 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
-            // load a class.
-            IRequirement[] dynamics = importer.getDynamicRequirements();
-            for (int dynIdx = 0; (dynamics != null) && (dynIdx < dynamics.length); dynIdx++)
-            {
-                IRequirement target =
-                    createDynamicRequirement(dynamics[dynIdx], pkgName);
-                if (target != null)
-                {
-                    // See if there is a candidate exporter that satisfies the
-                    // constrained dynamic requirement.
-                    try
-                    {
-                        // Get "resolved" and "unresolved" candidates and put
-                        // the "resolved" candidates first.
-                        ICapability[] resolved = state.getResolvedCandidates(target);
-                        ICapability[] unresolved = state.getUnresolvedCandidates(target);
-                        ICapability[] candidates =
-                            new ICapability[resolved.length + unresolved.length];
-                        System.arraycopy(resolved, 0, candidates, 0, resolved.length);
-                        System.arraycopy(
-                            unresolved, 0, candidates, resolved.length, unresolved.length);
-
-                        // Take the first candidate that can resolve.
-                        for (int candIdx = 0;
-                            (candidate == null) && (candIdx < candidates.length);
-                            candIdx++)
-                        {
-                            try
-                            {
-                                // If a map is returned, then the candidate resolved
-                                // consistently with the importer.
-                                resolvedModuleWireMap =
-                                    resolveDynamicImportCandidate(
-                                        state, candidates[candIdx].getModule(), importer);
-                                if (resolvedModuleWireMap != null)
-                                {
-                                    candidate = candidates[candIdx];
-                                }
-                            }
-                            catch (ResolveException ex)
-                            {
-                                // Ignore candidates that cannot resolve.
-                            }
-                        }
-
-                        if (candidate != null)
-                        {
-                            // Create the wire and add it to the module.
-                            Object[] result = new Object[2];
-                            result[0] = new R4Wire(
-                                importer, dynamics[dynIdx], candidate.getModule(),
-                                candidate);
-                            result[1] = resolvedModuleWireMap;
-                            return result;
-                        }
-                    }
-                    catch (Exception ex)
-                    {
-                        m_logger.log(Logger.LOG_ERROR, "Unable to dynamically import package.", ex);
-                    }
-                }
-            }
-        }
-
-        return null;
-    }
-
-// TODO: FRAGMENT - This is only public so we could avoid merging fragments when
-//       when it wasn't necessary for dynamic imports. We need to rethink how we
-//       do fragment merging...probably merging as bundles are installed would be
-//       better.
-    public static 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.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 static IRequirement createDynamicRequirement(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).getTargetName();
-        boolean wildcard = (dynPkgName.lastIndexOf(".*") >= 0);
-        // Remove the "*", but keep the "." if wildcarded.
-        dynPkgName = (wildcard)
-            ? dynPkgName.substring(0, dynPkgName.length() - 1) : 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)))
+        // We can only create a dynamic import if the following
+        // conditions are met:
+        // 1. The package in question is not already imported.
+        // 2. The package in question is not accessible via require-bundle.
+        // 3. The package in question is not exported by the bundle.
+        // 4. The package in question matches a dynamic import of the bundle.
+        // The following call checks all of these conditions and returns
+        // a matching dynamic requirement if possible.
+        IRequirement dynReq = findAllowedDynamicImport(importer, pkgName);
+        if (dynReq != null)
         {
             // Create a new requirement based on the dynamic requirement,
             // but substitute the precise package name for which we are
@@ -261,10 +150,115 @@
                     break;
                 }
             }
-            req = new Requirement(ICapability.PACKAGE_NAMESPACE, dirs, newAttrs);
+            IRequirement target = new Requirement(ICapability.PACKAGE_NAMESPACE, dirs, newAttrs);
+
+            // See if there is a candidate exporter that satisfies the
+            // constrained dynamic requirement.
+            try
+            {
+                // Get "resolved" and "unresolved" candidates and put
+                // the "resolved" candidates first.
+                ICapability[] resolved = state.getResolvedCandidates(target);
+                ICapability[] unresolved = state.getUnresolvedCandidates(target);
+                ICapability[] candidates =
+                    new ICapability[resolved.length + unresolved.length];
+                System.arraycopy(resolved, 0, candidates, 0, resolved.length);
+                System.arraycopy(
+                    unresolved, 0, candidates, resolved.length, unresolved.length);
+
+                // Take the first candidate that can resolve.
+                for (int candIdx = 0;
+                    (candidate == null) && (candIdx < candidates.length);
+                    candIdx++)
+                {
+                    try
+                    {
+                        // If a map is returned, then the candidate resolved
+                        // consistently with the importer.
+                        resolvedModuleWireMap =
+                            resolveDynamicImportCandidate(
+                                state, candidates[candIdx].getModule(), importer);
+                        if (resolvedModuleWireMap != null)
+                        {
+                            candidate = candidates[candIdx];
+                        }
+                    }
+                    catch (ResolveException ex)
+                    {
+                        // Ignore candidates that cannot resolve.
+                    }
+                }
+
+                if (candidate != null)
+                {
+                    // Create the wire and add it to the module.
+                    Object[] result = new Object[2];
+                    result[0] = new R4Wire(
+                        importer, dynReq, candidate.getModule(),
+                        candidate);
+                    result[1] = resolvedModuleWireMap;
+                    return result;
+                }
+            }
+            catch (Exception ex)
+            {
+                m_logger.log(Logger.LOG_ERROR, "Unable to dynamically import package.", ex);
+            }
         }
 
-        return req;
+        return null;
+    }
+
+    public static IRequirement findAllowedDynamicImport(IModule importer, String pkgName)
+    {
+        // If any of the module exports this package, then we cannot
+        // attempt to dynamically import it.
+        ICapability[] caps = importer.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 null;
+            }
+        }
+        // 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 null;
+            }
+        }
+
+        // Loop through the importer's dynamic requirements to determine if
+        // there is a matching one for the package from which we want to
+        // load a class.
+        IRequirement[] dynamics = importer.getDynamicRequirements();
+        for (int dynIdx = 0;
+            (dynamics != null) && (dynIdx < dynamics.length);
+            dynIdx++)
+        {
+            // First check to see if the dynamic requirement matches the
+            // package name; this means we have to do wildcard matching.
+            String dynPkgName = ((Requirement) dynamics[dynIdx]).getTargetName();
+            boolean wildcard = (dynPkgName.lastIndexOf(".*") >= 0);
+            // Remove the "*", but keep the "." if wildcarded.
+            dynPkgName = (wildcard)
+                ? dynPkgName.substring(0, dynPkgName.length() - 1) : 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)))
+            {
+                return dynamics[dynIdx];
+            }
+        }
+
+        return null;
     }
 
     private Map resolveDynamicImportCandidate(