felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickh...@apache.org
Subject svn commit: r903824 - in /felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework: Felix.java FelixResolverState.java ModuleImpl.java resolver/Resolver.java resolver/ResolverImpl.java
Date Wed, 27 Jan 2010 20:52:07 GMT
Author: rickhall
Date: Wed Jan 27 20:52:06 2010
New Revision: 903824

URL: http://svn.apache.org/viewvc?rev=903824&view=rev
Log:
Add initial support for dynamic imports.

Modified:
    felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/Felix.java
    felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/FelixResolverState.java
    felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/ModuleImpl.java
    felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/Resolver.java
    felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java

Modified: felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/Felix.java?rev=903824&r1=903823&r2=903824&view=diff
==============================================================================
--- felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/Felix.java
(original)
+++ felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/Felix.java
Wed Jan 27 20:52:06 2010
@@ -3906,25 +3906,23 @@
             }
         }
 
-        public Wire resolveDynamicImport(Module importer, String pkgName) throws ResolveException
+        public Wire resolve(Module module, String pkgName) throws ResolveException
         {
             Wire candidateWire = null;
-// TODO: FELIX3 - Fix dynamic imports!
-/*
-            // 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
+            // We cannot dynamically import if the module is not 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))
+            if (module.isResolved()
+                && (ResolverImpl.findAllowedDynamicImport(m_resolverState, module,
pkgName) != null))
             {
                 // Acquire global lock.
                 boolean locked = acquireGlobalLock();
                 if (!locked)
                 {
                     throw new ResolveException(
-                        "Unable to acquire global lock for resolve.", importer, null);
+                        "Unable to acquire global lock for resolve.", module, null);
                 }
 
                 try
@@ -3933,42 +3931,34 @@
                     // dynamically importing the package, which can happen if two
                     // threads are racing to do so. If we have an existing wire,
                     // then just return it instead.
-                    IWire[] wires = importer.getWires();
-                    for (int i = 0; (wires != null) && (i < wires.length); i++)
+                    List<Wire> wires = module.getWires();
+                    for (int i = 0; (wires != null) && (i < wires.size()); i++)
                     {
-                        if (wires[i].hasPackage(pkgName))
+                        if (wires.get(i).hasPackage(pkgName))
                         {
-                            return wires[i];
+                            return wires.get(i);
                         }
                     }
 
-                    Object[] result = m_resolver.resolveDynamicImport(m_resolverState, importer,
pkgName);
-                    if (result != null)
+                    Map<Module, List<Wire>> wireMap =
+                        m_resolver.resolve(m_resolverState, module, pkgName);
+
+                    if ((wireMap != null) && wireMap.containsKey(module))
                     {
-                        candidateWire = (IWire) result[0];
-                        Map resolvedModuleWireMap = (Map) result[1];
+                        List<Wire> dynamicWires = wireMap.remove(module);
+                        candidateWire = dynamicWires.get(0);
 
                         // Mark all modules as resolved.
-                        markResolvedModules(resolvedModuleWireMap);
+                        markResolvedModules(wireMap);
 
                         // Dynamically add new wire to importing module.
                         if (candidateWire != null)
                         {
-                            wires = importer.getWires();
-                            IWire[] newWires = null;
-                            if (wires == null)
-                            {
-                                newWires = new IWire[1];
-                            }
-                            else
-                            {
-                                newWires = new IWire[wires.length + 1];
-                                System.arraycopy(wires, 0, newWires, 0, wires.length);
-                            }
-
-                            newWires[newWires.length - 1] = candidateWire;
-                            ((ModuleImpl) importer).setWires(newWires);
-m_logger.log(Logger.LOG_DEBUG, "DYNAMIC WIRE: " + newWires[newWires.length - 1]);
+                            wires = new ArrayList(wires.size() + 1);
+                            wires.addAll(module.getWires());
+                            wires.add(candidateWire);
+                            ((ModuleImpl) module).setWires(wires);
+m_logger.log(Logger.LOG_DEBUG, "DYNAMIC WIRE: " + wires.get(wires.size() - 1));
                         }
                     }
                 }
@@ -3978,7 +3968,7 @@
                     releaseGlobalLock();
                 }
             }
-*/
+
             return candidateWire;
         }
 

Modified: felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/FelixResolverState.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/FelixResolverState.java?rev=903824&r1=903823&r2=903824&view=diff
==============================================================================
--- felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/FelixResolverState.java
(original)
+++ felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/FelixResolverState.java
Wed Jan 27 20:52:06 2010
@@ -770,7 +770,8 @@
         }
     }
 
-    /*public */synchronized List<Module> getModules()
+// TODO: FELIX3 - Try to eliminate this.
+    public synchronized List<Module> getModules()
     {
         return m_modules;
     }

Modified: felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/ModuleImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/ModuleImpl.java?rev=903824&r1=903823&r2=903824&view=diff
==============================================================================
--- felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/ModuleImpl.java
(original)
+++ felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/ModuleImpl.java
Wed Jan 27 20:52:06 2010
@@ -935,7 +935,7 @@
             Wire wire = null;
             try
             {
-                wire = m_resolver.resolveDynamicImport(this, pkgName);
+                wire = m_resolver.resolve(this, pkgName);
             }
             catch (ResolveException ex)
             {
@@ -1342,7 +1342,7 @@
         Wire wire = null;
         try
         {
-            wire = m_resolver.resolveDynamicImport(this, pkgName);
+            wire = m_resolver.resolve(this, pkgName);
         }
         catch (ResolveException ex)
         {

Modified: felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/Resolver.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/Resolver.java?rev=903824&r1=903823&r2=903824&view=diff
==============================================================================
--- felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/Resolver.java
(original)
+++ felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/Resolver.java
Wed Jan 27 20:52:06 2010
@@ -29,6 +29,7 @@
 public interface Resolver
 {
     Map<Module, List<Wire>> resolve(ResolverState state, Module module);
+    Map<Module, List<Wire>> resolve(ResolverState state, Module module, String
pkgName);
 
     public static interface ResolverState
     {

Modified: felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java?rev=903824&r1=903823&r2=903824&view=diff
==============================================================================
--- felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
(original)
+++ felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
Wed Jan 27 20:52:06 2010
@@ -28,12 +28,16 @@
 import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.TreeSet;
+import org.apache.felix.framework.FelixResolverState;
 import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.capabilityset.Attribute;
 import org.apache.felix.framework.capabilityset.Capability;
 import org.apache.felix.framework.capabilityset.CapabilitySet;
+import org.apache.felix.framework.capabilityset.Directive;
 import org.apache.felix.framework.capabilityset.Module;
 import org.apache.felix.framework.capabilityset.Requirement;
 import org.apache.felix.framework.capabilityset.Wire;
+import org.apache.felix.framework.util.manifestparser.RequirementImpl;
 
 // 1. Treat hard pkg constraints separately from implied package constraints
 // 2. Map pkg constraints to a set of capabilities, not a single capability.
@@ -81,6 +85,8 @@
 
         if (!module.isResolved())
         {
+            m_candidatePermutations.clear();
+
 System.out.println("+++ RESOLVING " + module);
             Map<Requirement, Set<Capability>> candidateMap =
                 new HashMap<Requirement, Set<Capability>>();
@@ -100,6 +106,7 @@
                 try
                 {
                     findConsistentCandidates(
+                        false,
                         module,
                         new ArrayList(),
                         candidateMap,
@@ -132,27 +139,158 @@
         return wireMap;
     }
 
+    public Map<Module, List<Wire>> resolve(ResolverState state, Module module,
String pkgName)
+    {
+        Capability candidate = null;
+
+        // We can only create a dynamic import if the following
+        // conditions are met:
+        // 1. The specified module is resolved.
+        // 2. The package in question is not already imported.
+        // 3. The package in question is not accessible via require-bundle.
+        // 4. The package in question is not exported by the bundle.
+        // 5. 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.
+        Requirement dynReq = findAllowedDynamicImport(state, module, pkgName);
+        if (dynReq != null)
+        {
+            m_candidatePermutations.clear();
+
+            Map<Module, Packages> modulePkgMap = new HashMap<Module, Packages>();
+
+System.out.println("+++ DYNAMICALLY RESOLVING " + module + " - " + dynReq);
+            Map<Requirement, Set<Capability>> candidateMap =
+                new HashMap<Requirement, Set<Capability>>();
+
+            populateDynamicCandidates(state, module, dynReq, candidateMap, new HashSet<Module>());
+            m_candidatePermutations.add(candidateMap);
+            ResolveException rethrow = null;
+
+            do
+            {
+                rethrow = null;
+
+                candidateMap = m_candidatePermutations.remove(0);
+dumpCandidateMap(state, candidateMap);
+
+                try
+                {
+                    findConsistentCandidates(
+                        true,
+                        module,
+                        new ArrayList(),
+                        candidateMap,
+                        modulePkgMap,
+                        new HashMap<Module, Object>());
+                }
+                catch (ResolveException ex)
+                {
+                    rethrow = ex;
+                    System.out.println("RE: " + ex);
+                }
+            }
+            while ((rethrow != null) && (m_candidatePermutations.size() > 0));
+
+            if (rethrow != null)
+            {
+                throw rethrow;
+            }
+//dumpModulePkgMap(modulePkgMap);
+            Map<Module, List<Wire>> wireMap =
+                populateDynamicWireMap(
+                    module, pkgName, modulePkgMap, new HashMap<Module, List<Wire>>());
+
+            return wireMap;
+        }
+
+        return null;
+    }
+
+    // TODO: FELIX3 - It would be nice to make this private.
+    public static Requirement findAllowedDynamicImport(
+        ResolverState state, Module module, String pkgName)
+    {
+        // Unresolved modules cannot dynamically import, nor can the default
+        // package be dynamically imported.
+        if (!module.isResolved() || pkgName.length() == 0)
+        {
+            return null;
+        }
+
+        // If any of the module exports this package, then we cannot
+        // attempt to dynamically import it.
+        List<Capability> caps = module.getCapabilities();
+        for (int i = 0; (caps != null) && (i < caps.size()); i++)
+        {
+            if (caps.get(i).getNamespace().equals(Capability.PACKAGE_NAMESPACE)
+                && caps.get(i).getAttribute(Capability.PACKAGE_ATTR).getValue().equals(pkgName))
+            {
+                return null;
+            }
+        }
+        // If any of our wires have this package, then we cannot
+        // attempt to dynamically import it.
+        List<Wire> wires = module.getWires();
+        for (int i = 0; (wires != null) && (i < wires.size()); i++)
+        {
+            if (wires.get(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.
+        List<Directive> dirs = new ArrayList(0);
+        List<Attribute> attrs = new ArrayList(1);
+        attrs.add(new Attribute(Capability.PACKAGE_ATTR, pkgName, false));
+        Requirement req = new RequirementImpl(Capability.PACKAGE_NAMESPACE, dirs, attrs);
+        Set<Capability> candidates = state.getCandidates(module, req);
+        List<Requirement> dynamics = module.getDynamicRequirements();
+        for (int dynIdx = 0;
+            (candidates.size() > 0) && (dynIdx < dynamics.size());
+            dynIdx++)
+        {
+            for (Capability cap : candidates)
+            {
+                if (CapabilitySet.matches(cap, dynamics.get(dynIdx).getFilter()))
+                {
+                    return dynamics.get(dynIdx);
+                }
+            }
+        }
+
+        return null;
+    }
+
     private static void dumpCandidateMap(
         ResolverState state, Map<Requirement, Set<Capability>> candidateMap)
     {
-/*
-        System.out.println("=== CANDIDATE MAP ===");
-        for (Module module : ((ResolverStateImpl) state).getModules())
+        System.out.println("=== BEGIN CANDIDATE MAP ===");
+        for (Module module : ((FelixResolverState) state).getModules())
         {
-            if (!module.isResolved())
+            System.out.println("  " + module
+                 + " (" + (module.isResolved() ? "RESOLVED)" : "UNRESOLVED)"));
+            for (Requirement req : module.getRequirements())
             {
-                System.out.println("  " + module);
-                for (Requirement req : module.getRequirements())
+                Set<Capability> candidates = candidateMap.get(req);
+                if ((candidates != null) && (candidates.size() > 0))
                 {
-                    Set<Capability> candidates = candidateMap.get(req);
-                    if ((candidates != null) && (candidates.size() > 0))
-                    {
-                        System.out.println("    " + req + ": " + candidates);
-                    }
+                    System.out.println("    " + req + ": " + candidates);
+                }
+            }
+            for (Requirement req : module.getDynamicRequirements())
+            {
+                Set<Capability> candidates = candidateMap.get(req);
+                if ((candidates != null) && (candidates.size() > 0))
+                {
+                    System.out.println("    " + req + ": " + candidates);
                 }
             }
         }
-*/
+        System.out.println("=== END CANDIDATE MAP ===");
     }
 
     private static void dumpModulePkgMap(Map<Module, Packages> modulePkgMap)
@@ -251,8 +389,61 @@
         }
     }
 
+    private static void populateDynamicCandidates(
+        ResolverState state, Module module, Requirement dynReq,
+        Map<Requirement, Set<Capability>> candidateMap, Set<Module> cycles)
+    {
+        if (m_isInvokeCount)
+        {
+            String methodName = new Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() + 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
+        // Detect cycles.
+        if (cycles.contains(module))
+        {
+            return;
+        }
+        cycles.add(module);
+
+        // Find candidates for all requirements for the target module.
+        Set<Capability> candidates = state.getCandidates(module, dynReq);
+        for (Iterator<Capability> itCandCap = candidates.iterator(); itCandCap.hasNext();
)
+        {
+            Capability candCap = itCandCap.next();
+            if (!candCap.getModule().isResolved())
+            {
+                try
+                {
+                    populateCandidates(state, candCap.getModule(), candidateMap, cycles);
+                }
+                catch (ResolveException ex)
+                {
+System.out.println("RE: Candidate not resolveable: " + ex);
+                    itCandCap.remove();
+                }
+            }
+        }
+
+        // Put candidates for all requirements into the global candidate map.
+        if (candidates.size() > 0)
+        {
+            candidateMap.put(dynReq, candidates);
+
+            // Add existing wires as candidates.
+            for (Wire wire : module.getWires())
+            {
+                Set<Capability> cs = new TreeSet();
+                cs.add(wire.getCapability());
+                candidateMap.put(wire.getRequirement(), cs);
+            }
+        }
+    }
+
     private void findConsistentCandidates(
-        Module module, List<Requirement> incomingReqs, Map<Requirement, Set<Capability>>
candidateMap,
+        boolean dynamic, Module module, List<Requirement> incomingReqs, Map<Requirement,
Set<Capability>> candidateMap,
         Map<Module, Packages> modulePkgMap, Map<Module, Object> cycleMap)
     {
         if (m_isInvokeCount)
@@ -273,7 +464,7 @@
 //System.out.println("+++ RESOLVING " + module);
         calculateExportedPackages(module, incomingReqs, modulePkgMap);
 
-        if (module.isResolved())
+        if (!dynamic && module.isResolved())
         {
 //            Packages pkgs = modulePkgMap.get(module);
 //            calculateResolvedPackages(module, incomingReqs, pkgs);
@@ -281,6 +472,7 @@
             {
                 // Try to resolve the candidate.
                 findConsistentCandidates(
+                    false,
                     wire.getCapability().getModule(),
                     incomingReqs,
                     candidateMap,
@@ -303,7 +495,8 @@
         }
         else
         {
-            List<Requirement> reqs = module.getRequirements();
+            List<Requirement> reqs = new ArrayList(module.getRequirements());
+            reqs.addAll(module.getDynamicRequirements());
             for (Requirement req : reqs)
             {
                 // Get the candidates for the current requirement.
@@ -325,6 +518,7 @@
                     {
                         // Try to resolve the candidate.
                         findConsistentCandidates(
+                            false,
                             candCap.getModule(),
                             outgoingReqs,
                             candidateMap,
@@ -679,7 +873,7 @@
 System.out.println("+++ MERGING CB " + candBlame + " SB " + candSourceBlame);
 //                    usedCaps.add(new Blame(candBlame.m_reqs, sourceBlame.m_cap));
                     usedCaps.add(candSourceBlame);
-                    return;
+//                    return;
                 }
                 else if (!current.isResolved())
                 {
@@ -697,7 +891,7 @@
                     else if ((currentImportedBlame != null)
                         && !isCompatible(currentImportedBlame.m_cap, candSourceBlame.m_cap,
modulePkgMap))
                     {
-    //System.out.println("+++ CIB " + currentImportedBlame + " SB " + sourceBlame);
+//System.out.println("+++ CIB " + currentImportedBlame + " SB " + sourceBlame);
                         // Try to remove the previously selected candidate associated
                         // with the requirement blamed for adding the constraint. This
                         // Permutate the candidate map.
@@ -712,7 +906,7 @@
                                 Iterator it = candidates.iterator();
                                 it.next();
                                 it.remove();
-    // TODO: PROTO3 RESOLVER - We could check before doing the candidate map copy.
+// TODO: PROTO3 RESOLVER - We could check before doing the candidate map copy.
                                 if (candidates.size() > 0)
                                 {
                                     m_candidatePermutations.add(copy);
@@ -729,6 +923,9 @@
                             + candSourceBlame, null, null);
                     }
                 }
+
+                verifyAndMergeUses(current, currentPkgs, candSourceBlame,
+                    modulePkgMap, candidateMap, cycleMap);
             }
         }
     }
@@ -767,43 +964,6 @@
         return sources;
     }
 
-    private static void calculateResolvedPackages(
-        Module module, List<Requirement> incomingReqs, Packages pkgs)
-    {
-        for (Wire wire : module.getWires())
-        {
-            if (wire.getCapability().getNamespace().equals(Capability.PACKAGE_NAMESPACE))
-            {
-                pkgs.m_importedPkgs.put(
-                    (String) wire.getCapability().getAttribute(Capability.PACKAGE_ATTR).getValue(),
-                    new Blame(incomingReqs, wire.getCapability()));
-                calculateResolvedUses(wire.getCapability(), pkgs.m_usedPkgs);
-            }
-            else if (wire.getCapability().getNamespace().equals(Capability.MODULE_NAMESPACE))
-            {
-                for (Capability cap : wire.getCapability().getModule().getCapabilities())
-                {
-                    if (cap.getNamespace().equals(Capability.PACKAGE_ATTR))
-                    {
-                        String pkgName = (String) cap.getAttribute(Capability.PACKAGE_ATTR).getValue();
-                        List<Blame> requiredBlames = pkgs.m_requiredPkgs.get(pkgName);
-                        if (requiredBlames == null)
-                        {
-                            requiredBlames = new ArrayList<Blame>();
-                            pkgs.m_requiredPkgs.put(pkgName, requiredBlames);
-                        }
-                        requiredBlames.add(new Blame(incomingReqs, cap));
-                        calculateResolvedUses(wire.getCapability(), pkgs.m_usedPkgs);
-                    }
-                }
-            }
-        }
-    }
-
-    private static void calculateResolvedUses(Capability cap, Map<String, List<Blame>>
usedPkgs)
-    {
-    }
-
     private static Map<Requirement, Set<Capability>> copyCandidateMap(
         Map<Requirement, Set<Capability>> candidateMap)
     {
@@ -911,6 +1071,49 @@
         return wireMap;
     }
 
+    private static Map<Module, List<Wire>> populateDynamicWireMap(
+        Module module, String pkgName, Map<Module, Packages> modulePkgMap,
+        Map<Module, List<Wire>> wireMap)
+    {
+        if (m_isInvokeCount)
+        {
+            String methodName = new Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+            Long count = m_invokeCounts.get(methodName);
+            count = (count == null) ? new Long(1) : new Long(count.longValue() + 1);
+            m_invokeCounts.put(methodName, count);
+        }
+
+        wireMap.put(module, m_emptyWires);
+
+        List<Wire> packageWires = new ArrayList<Wire>();
+
+        Packages pkgs = modulePkgMap.get(module);
+        for (Entry<String, Blame> entry : pkgs.m_importedPkgs.entrySet())
+        {
+            if (!entry.getValue().m_cap.getModule().isResolved())
+            {
+                populateWireMap(entry.getValue().m_cap.getModule(), modulePkgMap, wireMap);
+            }
+
+            // Ignore modules that import themselves.
+            if (!module.equals(entry.getValue().m_cap.getModule())
+                && entry.getValue().m_cap.getAttribute(
+                    Capability.PACKAGE_ATTR).getValue().equals(pkgName))
+            {
+                packageWires.add(
+                    new WireImpl(
+                        module,
+                        entry.getValue().m_reqs.get(0),
+                        entry.getValue().m_cap.getModule(),
+                        entry.getValue().m_cap));
+            }
+        }
+
+        wireMap.put(module, packageWires);
+
+        return wireMap;
+    }
+
     private static Capability getModuleCapability(Module module)
     {
         for (Capability cap : module.getCapabilities())



Mime
View raw message