felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickh...@apache.org
Subject svn commit: r898817 - /felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java
Date Wed, 13 Jan 2010 16:03:07 GMT
Author: rickhall
Date: Wed Jan 13 16:03:07 2010
New Revision: 898817

URL: http://svn.apache.org/viewvc?rev=898817&view=rev
Log:
Calculate resolve module package spaces.

Modified:
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java

Modified: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java?rev=898817&r1=898816&r2=898817&view=diff
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java
(original)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto3/Proto3Resolver.java
Wed Jan 13 16:03:07 2010
@@ -152,7 +152,7 @@
 
     private static void dumpModulePkgs(Module module, Packages packages)
     {
-        System.out.println(module);
+        System.out.println(module + " (" + (module.isResolved() ? "RESOLVED)" : "UNRESOLVED)"));
         System.out.println("  EXPORTED");
         for (Entry<String, Blame> entry : packages.m_exportedPkgs.entrySet())
         {
@@ -249,14 +249,8 @@
             m_invokeCounts.put(methodName, count);
         }
 
-        // If the module is resolved, then it is consistent by definition,
-        // so just return.
-        if (module.isResolved())
-        {
-            return;
-        }
         // If the module is in the cycle map, then just return.
-        else if (cycleMap.containsKey(module))
+        if (cycleMap.containsKey(module))
         {
             return;
         }
@@ -265,52 +259,87 @@
 //System.out.println("+++ RESOLVING " + module);
         calculateExportedPackages(module, incomingReqs, modulePkgMap);
 
-        List<Requirement> reqs = module.getRequirements();
-        for (Requirement req : reqs)
+        if (module.isResolved())
         {
-            // Get the candidates for the current requirement.
-            Set<Capability> candCaps = candidateMap.get(req);
-            // Optional requirements may not have any candidates.
-            if (candCaps == null)
-            {
-                continue;
-            }
+//            Packages pkgs = modulePkgMap.get(module);
+//            calculateResolvedPackages(module, incomingReqs, pkgs);
+            for (Wire wire : module.getWires())
+            {
+                // Try to resolve the candidate.
+                findConsistentCandidates(
+                    wire.getCapability().getModule(),
+                    incomingReqs,
+                    candidateMap,
+                    modulePkgMap,
+                    cycleMap);
 
-            List<Requirement> outgoingReqs = new ArrayList<Requirement>(incomingReqs);
-            outgoingReqs.add(req);
+                // If we are here, the candidate was consistent. Try to
+                // merge the candidate into the target module's packages.
+                mergeResolvedCandidatePackages(
+                    module,
+                    incomingReqs,
+                    wire.getCapability(),
+                    modulePkgMap);
 
-            for (Iterator<Capability> it = candCaps.iterator(); it.hasNext(); )
+                // If we are here, we merged the candidate successfully,
+                // so we can continue with the next requirement
+                break;
+            }
+        }
+        else
+        {
+            List<Requirement> reqs = module.getRequirements();
+            for (Requirement req : reqs)
             {
-                Capability candCap = it.next();
-System.out.println("+++ TRYING CAND " + candCap + " FOR " + req);
-                try
+                // Get the candidates for the current requirement.
+                Set<Capability> candCaps = candidateMap.get(req);
+                // Optional requirements may not have any candidates.
+                if (candCaps == null)
                 {
-                    // Try to resolve the candidate.
-                    findConsistentCandidates(
-                        candCap.getModule(),
-                        outgoingReqs,
-                        candidateMap,
-                        modulePkgMap,
-                        cycleMap);
-
-                    // If we are here, the candidate resolved. Try to merge
-                    // the candidate's into the target module's packages.
-                    mergeCandidatePackages(module, outgoingReqs, candCap, modulePkgMap, candidateMap);
-
-                    // If we are here, we merged the candidate successfully,
-                    // so we can continue with the next requirement
-                    break;
+                    continue;
                 }
-                catch (ResolveException ex)
+
+                List<Requirement> outgoingReqs = new ArrayList<Requirement>(incomingReqs);
+                outgoingReqs.add(req);
+
+                for (Iterator<Capability> it = candCaps.iterator(); it.hasNext(); )
                 {
+                    Capability candCap = it.next();
+System.out.println("+++ TRYING CAND " + candCap + " FOR " + req);
+                    try
+                    {
+                        // Try to resolve the candidate.
+                        findConsistentCandidates(
+                            candCap.getModule(),
+                            outgoingReqs,
+                            candidateMap,
+                            modulePkgMap,
+                            cycleMap);
+
+                        // If we are here, the candidate was consistent. Try to
+                        // merge the candidate into the target module's packages.
+                        mergeCandidatePackages(
+                            module,
+                            outgoingReqs,
+                            candCap,
+                            modulePkgMap,
+                            candidateMap);
+
+                        // If we are here, we merged the candidate successfully,
+                        // so we can continue with the next requirement
+                        break;
+                    }
+                    catch (ResolveException ex)
+                    {
 System.out.println("RE: " + ex);
 ex.printStackTrace();
-//                    it.remove();
-                    if (!it.hasNext() && !req.isOptional())
-                    {
-//                        candidateMap.remove(req);
-                        throw new ResolveException("Unresolved constraint "
-                            + req + " in " + module);
+//                        it.remove();
+                        if (!it.hasNext() && !req.isOptional())
+                        {
+//                            candidateMap.remove(req);
+                            throw new ResolveException("Unresolved constraint "
+                                + req + " in " + module);
+                        }
                     }
                 }
             }
@@ -431,7 +460,6 @@
 System.out.println("+++ MERGING " + candBlame.m_cap + " INTO " + current);
             String pkgName = (String)
                 candBlame.m_cap.getAttribute(Capability.PACKAGE_ATTR).getValue();
-            Packages candPkgs = modulePkgMap.get(candBlame.m_cap.getModule());
 
             // Since this capability represents a package, it will become
             // a hard constraint on the module's package space, so we need
@@ -554,7 +582,7 @@
         }
     }
 
-// TODO: PROTO2 RESOLVER - We end up with duplicates in uses constraints,
+// TODO: PROTO3 RESOLVER - We end up with duplicates in uses constraints,
 //       see scenario 2 for an example.
     private void verifyAndMergeUses(
         Module current, Packages currentPkgs,
@@ -583,24 +611,24 @@
         cycleMap.put(pkgName, list);
 
 //System.out.println("+++ VERIFYING USES " + current + " FOR " + candBlame);
-        for (Capability candCapSource : getPackageSources(candBlame.m_cap, modulePkgMap,
new ArrayList<Capability>()))
+        for (Capability candSourceCap : getPackageSources(candBlame.m_cap, modulePkgMap,
new ArrayList<Capability>()))
         {
-            for (String usedPkgName : candCapSource.getUses())
+            for (String usedPkgName : candSourceCap.getUses())
             {
                 Blame currentExportedBlame = currentPkgs.m_exportedPkgs.get(usedPkgName);
                 Blame currentImportedBlame = currentPkgs.m_importedPkgs.get(usedPkgName);
 // TODO: PROTO3 RESOLVER - What do we do with required packages?
                 List<Blame> currentRequiredBlames = currentPkgs.m_requiredPkgs.get(usedPkgName);
 
-                Packages sourcePkgs = modulePkgMap.get(candCapSource.getModule());
-System.out.println("+++ candCapSource " + candCapSource);
-System.out.println("+++ candCapSource.getModule() " + candCapSource.getModule() + " (" +
candCapSource.getModule().isResolved() + ")");
-System.out.println("+++ sourcePkgs " + sourcePkgs);
-System.out.println("+++ sourcePkgs.m_exportedPkgs " + sourcePkgs.m_exportedPkgs);
-                Blame sourceBlame = sourcePkgs.m_exportedPkgs.get(usedPkgName);
-                sourceBlame = (sourceBlame != null)
-                    ? sourceBlame
-                    : sourcePkgs.m_importedPkgs.get(usedPkgName);
+                Packages candSourcePkgs = modulePkgMap.get(candSourceCap.getModule());
+System.out.println("+++ candSourceCap " + candSourceCap);
+System.out.println("+++ candSourceCap.getModule() " + candSourceCap.getModule() + " (" +
candSourceCap.getModule().isResolved() + ")");
+System.out.println("+++ candSourcePkgs " + candSourcePkgs);
+System.out.println("+++ candSourcePkgs.m_exportedPkgs " + candSourcePkgs.m_exportedPkgs);
+                Blame candSourceBlame = candSourcePkgs.m_exportedPkgs.get(usedPkgName);
+                candSourceBlame = (candSourceBlame != null)
+                    ? candSourceBlame
+                    : candSourcePkgs.m_importedPkgs.get(usedPkgName);
 //                sourceCap = (sourceCap != null)
 //                    ? sourceCap
 //                    : sourcePkgs.m_requiredPkgs.get(usedPkgName);
@@ -608,7 +636,7 @@
                 // If the candidate doesn't actually have a constraint for
                 // the used package, then just ignore it since this is likely
                 // an error in its metadata.
-                if (sourceBlame == null)
+                if (candSourceBlame == null)
                 {
                     return;
                 }
@@ -625,23 +653,23 @@
                         usedCaps = new ArrayList<Blame>();
                         currentPkgs.m_usedPkgs.put(usedPkgName, usedCaps);
                     }
-//System.out.println("+++ MERGING CB " + candBlame + " SB " + sourceBlame);
+System.out.println("+++ MERGING CB " + candBlame + " SB " + candSourceBlame);
 //                    usedCaps.add(new Blame(candBlame.m_reqs, sourceBlame.m_cap));
-                    usedCaps.add(sourceBlame);
+                    usedCaps.add(candSourceBlame);
                     return;
                 }
                 else if ((currentExportedBlame != null)
-                    && !isCompatible(currentExportedBlame.m_cap, sourceBlame.m_cap,
modulePkgMap))
+                    && !isCompatible(currentExportedBlame.m_cap, candSourceBlame.m_cap,
modulePkgMap))
                 {
                     throw new ResolveException("Constraint violation for package '" + usedPkgName
                         + "' when resolving module " + current
                         + " between existing constraint "
                         + currentExportedBlame
                         + " and candidate constraint "
-                        + sourceBlame);
+                        + candSourceBlame);
                 }
                 else if ((currentImportedBlame != null)
-                    && !isCompatible(currentImportedBlame.m_cap, sourceBlame.m_cap,
modulePkgMap))
+                    && !isCompatible(currentImportedBlame.m_cap, candSourceBlame.m_cap,
modulePkgMap))
                 {
 //System.out.println("+++ CIB " + currentImportedBlame + " SB " + sourceBlame);
                     // Try to remove the previously selected candidate associated
@@ -671,7 +699,7 @@
                         + " between existing constraint "
                         + currentImportedBlame
                         + " and candidate constraint "
-                        + sourceBlame);
+                        + candSourceBlame);
                 }
 
                 // This does not need to be recursive, even though "uses" constraints
@@ -687,6 +715,192 @@
         }
     }
 
+    private void mergeResolvedCandidatePackages(
+        Module current, List<Requirement> outgoingReqs,
+        Capability candCap, Map<Module, Packages> modulePkgMap)
+    {
+        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);
+        }
+
+        if (candCap.getNamespace().equals(Capability.PACKAGE_NAMESPACE))
+        {
+            mergeResolvedCandidatePackage(
+                current, false, new Blame(outgoingReqs, candCap), modulePkgMap);
+        }
+        else if (candCap.getNamespace().equals(Capability.MODULE_NAMESPACE))
+        {
+            // Get the candidate's package space to determine which packages
+            // will be visible to the current module.
+            Packages candPkgs = modulePkgMap.get(candCap.getModule());
+
+// TODO: PROTO3 RESOLVER - For now assume only exports, but eventually we also
+//       have to support re-exported packages.
+            for (Entry<String, Blame> entry : candPkgs.m_exportedPkgs.entrySet())
+            {
+                mergeResolvedCandidatePackage(
+                    current,
+                    true,
+                    new Blame(outgoingReqs, entry.getValue().m_cap),
+                    modulePkgMap);
+            }
+        }
+    }
+
+    private void mergeResolvedCandidatePackage(
+        Module current, boolean requires,
+        Blame candBlame, Map<Module, Packages> modulePkgMap)
+    {
+        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);
+        }
+
+// TODO: PROTO3 RESOLVER - Check for merging where module imports from itself,
+//       then it should be listed as an export.
+        if (candBlame.m_cap.getNamespace().equals(Capability.PACKAGE_NAMESPACE))
+        {
+System.out.println("+++ MERGING " + candBlame.m_cap + " INTO " + current);
+            String pkgName = (String)
+                candBlame.m_cap.getAttribute(Capability.PACKAGE_ATTR).getValue();
+
+            // Since this capability represents a package, it will become
+            // a hard constraint on the module's package space, so we need
+            // to make sure it doesn't conflict with any other hard constraints
+            // or any other uses constraints.
+
+            //
+            // First, check to see if the capability conflicts with
+            // any existing hard constraints.
+            //
+
+            Packages currentPkgs = modulePkgMap.get(current);
+            Blame currentExportedBlame = currentPkgs.m_exportedPkgs.get(pkgName);
+            Blame currentImportedBlame = currentPkgs.m_importedPkgs.get(pkgName);
+            List<Blame> currentRequiredBlames = currentPkgs.m_requiredPkgs.get(pkgName);
+
+            if (!requires &&
+                (((currentExportedBlame != null) && !currentExportedBlame.m_cap.equals(candBlame.m_cap))
+                || ((currentImportedBlame != null) && !currentImportedBlame.m_cap.equals(candBlame.m_cap))
+                || ((currentRequiredBlames != null) && !currentRequiredBlames.contains(candBlame))))
+            {
+                throw new ResolveException("Constraint violation between "
+                    + current + " and " + candBlame.m_cap.getModule()
+                    + " for " + pkgName);
+            }
+
+            if (requires)
+            {
+                if (currentRequiredBlames == null)
+                {
+                    currentRequiredBlames = new ArrayList<Blame>();
+                    currentPkgs.m_requiredPkgs.put(pkgName, currentRequiredBlames);
+                }
+// TODO: PROTO2 RESOLVER - This is potentially modifying the original, we need to modify
a copy.
+                currentRequiredBlames.add(candBlame);
+            }
+            else
+            {
+                currentPkgs.m_importedPkgs.put(pkgName, candBlame);
+            }
+
+            // Verify and merge the candidate's transitive uses constraints.
+            mergeResolvedUses(
+                current,
+                currentPkgs,
+                candBlame,
+                modulePkgMap,
+                new HashMap<String, List<Module>>());
+dumpModulePkgs(current, currentPkgs);
+        }
+    }
+
+// TODO: PROTO3 RESOLVER - We end up with duplicates in uses constraints,
+//       see scenario 2 for an example.
+    private void mergeResolvedUses(
+        Module current, Packages currentPkgs,
+        Blame candBlame, Map<Module, Packages> modulePkgMap,
+        Map<String, List<Module>> cycleMap)
+    {
+        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);
+        }
+
+        // Check for cycles.
+        String pkgName = (String)
+            candBlame.m_cap.getAttribute(Capability.PACKAGE_ATTR).getValue();
+        List<Module> list = cycleMap.get(pkgName);
+        if ((list != null) && list.contains(current))
+        {
+            return;
+        }
+        list = (list == null) ? new ArrayList<Module>() : list;
+        list.add(current);
+        cycleMap.put(pkgName, list);
+
+//System.out.println("+++ VERIFYING USES " + current + " FOR " + candBlame);
+        for (Capability candSourceCap : getPackageSources(candBlame.m_cap, modulePkgMap,
new ArrayList<Capability>()))
+        {
+            for (String usedPkgName : candSourceCap.getUses())
+            {
+                Blame currentExportedBlame = currentPkgs.m_exportedPkgs.get(usedPkgName);
+                Blame currentImportedBlame = currentPkgs.m_importedPkgs.get(usedPkgName);
+// TODO: PROTO3 RESOLVER - What do we do with required packages?
+                List<Blame> currentRequiredBlames = currentPkgs.m_requiredPkgs.get(usedPkgName);
+
+                Packages candSourcePkgs = modulePkgMap.get(candSourceCap.getModule());
+System.out.println("+++ candSourceCap " + candSourceCap);
+System.out.println("+++ candSourceCap.getModule() " + candSourceCap.getModule() + " (" +
candSourceCap.getModule().isResolved() + ")");
+System.out.println("+++ candSourcePkgs " + candSourcePkgs);
+System.out.println("+++ candSourcePkgs.m_exportedPkgs " + candSourcePkgs.m_exportedPkgs);
+                Blame candSourceBlame = candSourcePkgs.m_exportedPkgs.get(usedPkgName);
+                candSourceBlame = (candSourceBlame != null)
+                    ? candSourceBlame
+                    : candSourcePkgs.m_importedPkgs.get(usedPkgName);
+//                sourceCap = (sourceCap != null)
+//                    ? sourceCap
+//                    : sourcePkgs.m_requiredPkgs.get(usedPkgName);
+
+                // If the candidate doesn't actually have a constraint for
+                // the used package, then just ignore it since this is likely
+                // an error in its metadata.
+                if (candSourceBlame == null)
+                {
+                    return;
+                }
+
+                // If there is no current mapping for this package, then
+                // we can just return.
+                if ((currentExportedBlame == null)
+                    && (currentImportedBlame == null)
+                    && (currentRequiredBlames == null))
+                {
+                    List<Blame> usedCaps = currentPkgs.m_usedPkgs.get(usedPkgName);
+                    if (usedCaps == null)
+                    {
+                        usedCaps = new ArrayList<Blame>();
+                        currentPkgs.m_usedPkgs.put(usedPkgName, usedCaps);
+                    }
+System.out.println("+++ MERGING CB " + candBlame + " SB " + candSourceBlame);
+//                    usedCaps.add(new Blame(candBlame.m_reqs, sourceBlame.m_cap));
+                    usedCaps.add(candSourceBlame);
+                    return;
+                }
+            }
+        }
+    }
+
     private static boolean isCompatible(
         Capability currentCap, Capability candCap, Map<Module, Packages> modulePkgMap)
     {
@@ -706,14 +920,6 @@
         if (cap.getNamespace().equals(Capability.PACKAGE_NAMESPACE))
         {
             Packages pkgs = modulePkgMap.get(cap.getModule());
-            if ((pkgs == null) && cap.getModule().isResolved())
-            {
-                pkgs = new Packages();
-                calculateResolvedPackages(cap.getModule(), pkgs);
-                modulePkgMap.put(cap.getModule(), pkgs);
-System.out.println("RESOLVED PACKAGES:");
-dumpModulePkgs(cap.getModule(), pkgs);
-            }
             sources.add(cap);
             String pkgName = cap.getAttribute(Capability.PACKAGE_ATTR).getValue().toString();
             List<Blame> required = pkgs.m_requiredPkgs.get(pkgName);
@@ -729,32 +935,16 @@
         return sources;
     }
 
-    private static void calculateResolvedPackages(Module module, Packages pkgs)
+    private static void calculateResolvedPackages(
+        Module module, List<Requirement> incomingReqs, Packages pkgs)
     {
-        List<Capability> caps = module.getCapabilities();
-        if (caps.size() > 0)
-        {
-            for (int i = 0; i < caps.size(); i++)
-            {
-// TODO: PROTO3 RESOLVER - Assume if a module imports the same package it
-//       exports that the import will overlap the export.
-                if (caps.get(i).getNamespace().equals(Capability.PACKAGE_NAMESPACE)
-                    && !hasOverlappingImport(module, caps.get(i)))
-                {
-                    pkgs.m_exportedPkgs.put(
-                        (String) caps.get(i).getAttribute(Capability.PACKAGE_ATTR).getValue(),
-                        new Blame(null, caps.get(i)));
-                }
-            }
-        }
-
         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(null, wire.getCapability()));
+                    new Blame(incomingReqs, wire.getCapability()));
                 calculateResolvedUses(wire.getCapability(), pkgs.m_usedPkgs);
             }
             else if (wire.getCapability().getNamespace().equals(Capability.MODULE_NAMESPACE))
@@ -770,7 +960,7 @@
                             requiredBlames = new ArrayList<Blame>();
                             pkgs.m_requiredPkgs.put(pkgName, requiredBlames);
                         }
-                        requiredBlames.add(new Blame(null, cap));
+                        requiredBlames.add(new Blame(incomingReqs, cap));
                         calculateResolvedUses(wire.getCapability(), pkgs.m_usedPkgs);
                     }
                 }



Mime
View raw message