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 2010/03/01 19:47:07 UTC

svn commit: r917641 - /felix/sandbox/rickhall/framework-proto/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java

Author: rickhall
Date: Mon Mar  1 18:47:06 2010
New Revision: 917641

URL: http://svn.apache.org/viewvc?rev=917641&view=rev
Log:
Reexport visibility support ported from resolver prototype.

Modified:
    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/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=917641&r1=917640&r2=917641&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 Mon Mar  1 18:47:06 2010
@@ -37,7 +37,6 @@
 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.Util;
 import org.apache.felix.framework.util.manifestparser.R4Library;
 import org.apache.felix.framework.util.manifestparser.RequirementImpl;
 import org.osgi.framework.Constants;
@@ -63,7 +62,6 @@
     {
 System.out.println("+++ PROTO3 RESOLVER");
         m_logger = logger;
-// TODO: FELIX3 - Need to implement execution environment checking.
         m_fwkExecEnvStr = (fwkExecEnvStr != null) ? fwkExecEnvStr.trim() : null;
         m_fwkExecEnvSet = parseExecutionEnvironments(fwkExecEnvStr);
 
@@ -84,6 +82,8 @@
             m_invokeCounts.put(methodName, count);
         }
 
+        Map<Module, List<Wire>> wireMap = new HashMap<Module, List<Wire>>();
+
         Map<Module, Packages> modulePkgMap = new HashMap<Module, Packages>();
 
         if (!module.isResolved())
@@ -129,10 +129,11 @@
                 throw rethrow;
             }
 //dumpModulePkgMap(modulePkgMap);
-        }
 
-        Map<Module, List<Wire>> wireMap =
-            populateWireMap(module, modulePkgMap, new HashMap<Module, List<Wire>>());
+            wireMap =
+                populateWireMap(module, modulePkgMap, wireMap,
+                candidateMap);
+        }
 
         if (m_isInvokeCount)
         {
@@ -161,6 +162,8 @@
         {
             m_candidatePermutations.clear();
 
+            Map<Module, List<Wire>> wireMap = new HashMap<Module, List<Wire>>();
+
             Map<Module, Packages> modulePkgMap = new HashMap<Module, Packages>();
 
 //System.out.println("+++ DYNAMICALLY RESOLVING " + module + " - " + pkgName);
@@ -197,9 +200,9 @@
                 throw rethrow;
             }
 //dumpModulePkgMap(modulePkgMap);
-            Map<Module, List<Wire>> wireMap =
+            wireMap =
                 populateDynamicWireMap(
-                    module, pkgName, modulePkgMap, new HashMap<Module, List<Wire>>());
+                    module, pkgName, modulePkgMap, wireMap, candidateMap);
 
 //System.out.println("+++ DYNAMIC SUCCESS: " + wireMap.get(module));
             return wireMap;
@@ -691,6 +694,12 @@
                     {
 System.out.println("RE: " + ex);
 ex.printStackTrace();
+
+// TODO: FELIX3 RESOLVER - Is it ok to remove the failed candidate? By removing
+//       it we keep the candidateMap up to date with the selected candidate, but
+//       theoretically this eliminates some potential combinations. Are those
+//       combinations guaranteed to be failures so eliminating them is ok?
+                        it.remove();
                         if (!it.hasNext() && !req.isOptional())
                         {
                             throw new ResolveException("Unresolved constraint "
@@ -776,6 +785,11 @@
                 {
 System.out.println("RE: " + ex);
 ex.printStackTrace();
+// TODO: FELIX3 RESOLVER - Is it ok to remove the failed candidate? By removing
+//       it we keep the candidateMap up to date with the selected candidate, but
+//       theoretically this eliminates some potential combinations. Are those
+//       combinations guaranteed to be failures so eliminating them is ok?
+                    it.remove();
                     if (!it.hasNext() && !req.isOptional())
                     {
                         throw new ResolveException("Unresolved constraint "
@@ -882,8 +896,21 @@
                 List<Blame> blames = entry.getValue();
                 for (Blame blame : blames)
                 {
-                    if (blame.m_reqs.get(blame.m_reqs.size() - 1)
-                        .getDirective(Constants.VISIBILITY_DIRECTIVE) != null)
+// TODO: FELIX3 RESOLVER - Since a single module requirement can include many packages,
+//       it is likely we call merge too many times for the same module req. If we knew
+//       which candidates were being used to resolve this candidate's module dependencies,
+//       then we could just try to merge them directly. This info would also help in
+//       in creating wires, since we ultimately want to create wires for the selected
+//       candidates, which we are trying to deduce from the package space, but if we
+//       knew the selected candidates, we'd be done.
+                    if (blame.m_cap.getModule().equals(current))
+                    {
+                        continue;
+                    }
+
+                    Directive dir = blame.m_reqs.get(blame.m_reqs.size() - 1)
+                        .getDirective(Constants.VISIBILITY_DIRECTIVE);
+                    if ((dir != null) && dir.getValue().equals(Constants.VISIBILITY_REEXPORT))
                     {
                         mergeCandidatePackage(
                             current,
@@ -984,7 +1011,7 @@
                     currentRequiredBlames = new ArrayList<Blame>();
                     currentPkgsCopy.m_requiredPkgs.put(pkgName, currentRequiredBlames);
                 }
-// TODO: PROTO2 RESOLVER - This is potentially modifying the original, we need to modify a copy.
+// TODO: PROTO3 RESOLVER - This is potentially modifying the original, we need to modify a copy.
                 currentRequiredBlames.add(candBlame);
             }
             else
@@ -1269,7 +1296,7 @@
 
     private static Map<Module, List<Wire>> populateWireMap(
         Module module, Map<Module, Packages> modulePkgMap,
-        Map<Module, List<Wire>> wireMap)
+        Map<Module, List<Wire>> wireMap, Map<Requirement, Set<Capability>> candidateMap)
     {
         if (m_isInvokeCount)
         {
@@ -1286,87 +1313,36 @@
             List<Wire> packageWires = new ArrayList<Wire>();
             List<Wire> moduleWires = 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()))
-                {
-                    packageWires.add(
-                        new WireImpl(module,
-                            entry.getValue().m_reqs.get(entry.getValue().m_reqs.size() - 1),
-                            entry.getValue().m_cap.getModule(),
-                            entry.getValue().m_cap));
-                }
-            }
-            List<Requirement> rbReqs = new ArrayList<Requirement>();
             for (Requirement req : module.getRequirements())
             {
-                if (req.getNamespace().equals(Capability.MODULE_NAMESPACE))
+                Set<Capability> cands = candidateMap.get(req);
+                if ((cands != null) && (cands.size() > 0))
                 {
-                    rbReqs.add(req);
-                }
-            }
-            if (!rbReqs.isEmpty())
-            {
-                Map<Requirement, Capability> rbMap =
-                    new HashMap<Requirement, Capability>();
-// TODO: FELIX3 - This approach isn't very efficient since it keeps recalculating the
-//       module wire for each package exported by the candidate module.
-                for (Entry<String, List<Blame>> entry : pkgs.m_requiredPkgs.entrySet())
-                {
-                    for (Blame blame : entry.getValue())
+                    Capability cand = cands.iterator().next();
+                    if (!cand.getModule().isResolved())
                     {
-                        // Ignore packages required from self, which can
-                        // happen in cycles.
-                        if (!blame.m_cap.getModule().equals(module))
-                        {
-                            for (Requirement rbReq : rbReqs)
-                            {
-                                if (blame.m_reqs.get(blame.m_reqs.size() - 1).equals(rbReq))
-                                {
-                                    List<Capability> moduleCaps =
-                                        Util.getCapabilityByNamespace(
-                                            blame.m_cap.getModule(), Capability.MODULE_NAMESPACE);
-                                    Capability cap = rbMap.get(rbReq);
-                                    if (cap == null)
-                                    {
-                                        rbMap.put(rbReq, moduleCaps.get(0));
-                                    }
-                                    if (!blame.m_cap.getModule().isResolved())
-                                    {
-                                        populateWireMap(
-                                            blame.m_cap.getModule(), modulePkgMap, wireMap);
-                                    }
-                                    break;
-                                }
-                            }
-                        }
+                        populateWireMap(cand.getModule(),
+                            modulePkgMap, wireMap, candidateMap);
                     }
-                }
-
-                // Loop through RB requirements to keep the wires in the
-                // correct order, which is required by the spec.
-                for (Requirement rbReq : rbReqs)
-                {
-                    Capability cap = rbMap.get(rbReq);
-                    if (cap != null)
+                    // Ignore modules that import themselves.
+                    if (req.getNamespace().equals(Capability.PACKAGE_NAMESPACE)
+                        && !module.equals(cand.getModule()))
                     {
-                        // Ignore modules that import themselves.
-                        if (!module.equals(cap.getModule()))
-                        {
-                            moduleWires.add(
-                                new WireModuleImpl(module,
-                                    rbReq,
-                                    cap.getModule(),
-                                    cap,
-                                    pkgs.getRequiredPackages(cap.getModule())));
-                        }
+                        packageWires.add(
+                            new WireImpl(module,
+                                req,
+                                cand.getModule(),
+                                cand));
+                    }
+                    else if (req.getNamespace().equals(Capability.MODULE_NAMESPACE))
+                    {
+                        Packages candPkgs = modulePkgMap.get(cand.getModule());
+                        moduleWires.add(
+                            new WireModuleImpl(module,
+                                req,
+                                cand.getModule(),
+                                cand,
+                                candPkgs.getExportedAndReexportedPackages()));
                     }
                 }
             }
@@ -1381,7 +1357,7 @@
 
     private static Map<Module, List<Wire>> populateDynamicWireMap(
         Module module, String pkgName, Map<Module, Packages> modulePkgMap,
-        Map<Module, List<Wire>> wireMap)
+        Map<Module, List<Wire>> wireMap, Map<Requirement, Set<Capability>> candidateMap)
     {
         if (m_isInvokeCount)
         {
@@ -1400,7 +1376,8 @@
         {
             if (!entry.getValue().m_cap.getModule().isResolved())
             {
-                populateWireMap(entry.getValue().m_cap.getModule(), modulePkgMap, wireMap);
+                populateWireMap(entry.getValue().m_cap.getModule(), modulePkgMap, wireMap,
+                    candidateMap);
             }
 
             // Ignore modules that import themselves.
@@ -1551,14 +1528,22 @@
             m_usedPkgs.putAll(packages.m_usedPkgs);
         }
 
-        public List<String> getRequiredPackages(Module source)
+        public List<String> getExportedAndReexportedPackages()
         {
             List<String> pkgs = new ArrayList();
+            for (Entry<String, Blame> entry : m_exportedPkgs.entrySet())
+            {
+                pkgs.add((String)
+                    entry.getValue().m_cap.getAttribute(Capability.PACKAGE_ATTR).getValue());
+            }
             for (Entry<String, List<Blame>> entry : m_requiredPkgs.entrySet())
             {
                 for (Blame blame : entry.getValue())
                 {
-                    if (blame.m_cap.getModule().equals(source))
+                    Directive dir = blame.m_reqs.get(
+                        blame.m_reqs.size() - 1).getDirective(Constants.VISIBILITY_DIRECTIVE);
+                    if ((dir != null)
+                        && dir.getValue().equals(Constants.VISIBILITY_REEXPORT))
                     {
                         pkgs.add((String)
                             blame.m_cap.getAttribute(Capability.PACKAGE_ATTR).getValue());