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 2009/12/24 15:58:30 UTC

svn commit: r893769 - /felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto2/Proto2Resolver.java

Author: rickhall
Date: Thu Dec 24 14:58:30 2009
New Revision: 893769

URL: http://svn.apache.org/viewvc?rev=893769&view=rev
Log:
Focus on module package space.

Modified:
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto2/Proto2Resolver.java

Modified: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto2/Proto2Resolver.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto2/Proto2Resolver.java?rev=893769&r1=893768&r2=893769&view=diff
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto2/Proto2Resolver.java (original)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/proto2/Proto2Resolver.java Thu Dec 24 14:58:30 2009
@@ -118,22 +118,22 @@
     {
         System.out.println(module);
         System.out.println("  EXPORTED");
-        for (Entry<String, Constraint> entry : packages.m_exportedPkgs.entrySet())
+        for (Entry<String, Capability> entry : packages.m_exportedPkgs.entrySet())
         {
             System.out.println("    " + entry.getKey() + " - " + entry.getValue());
         }
         System.out.println("  IMPORTED");
-        for (Entry<String, Constraint> entry : packages.m_importedPkgs.entrySet())
+        for (Entry<String, Capability> entry : packages.m_importedPkgs.entrySet())
         {
             System.out.println("    " + entry.getKey() + " - " + entry.getValue());
         }
         System.out.println("  REQUIRED");
-        for (Entry<String, Constraint> entry : packages.m_requiredPkgs.entrySet())
+        for (Entry<String, List<Capability>> entry : packages.m_requiredPkgs.entrySet())
         {
             System.out.println("    " + entry.getKey() + " - " + entry.getValue());
         }
         System.out.println("  USED");
-        for (Entry<String, List<Constraint>> entry : packages.m_usedPkgs.entrySet())
+        for (Entry<String, List<Capability>> entry : packages.m_usedPkgs.entrySet())
         {
             System.out.println("    " + entry.getKey() + " - " + entry.getValue());
         }
@@ -220,47 +220,105 @@
 
         if (candCap.getNamespace().equals(Capability.PACKAGE_NAMESPACE))
         {
+            mergeCandidatePackage(current, false, 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: PROTO2 RESOLVER - For now assume only exports, but eventually we also
+//       have to support re-exported packages.
+            for (Entry<String, Capability> entry : candPkgs.m_exportedPkgs.entrySet())
+            {
+                mergeCandidatePackage(current, true, entry.getValue(), modulePkgMap);
+            }
+        }
+    }
+
+    private void mergeCandidatePackage(
+        Module current, boolean requires,
+        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))
+        {
 System.out.println("+++ MERGING " + candCap + " INTO " + current);
             String pkgName = (String)
                 candCap.getAttribute(Capability.PACKAGE_ATTR).getValue();
-
             Packages candPkgs = modulePkgMap.get(candCap.getModule());
-            Constraint candConstraint = candPkgs.m_exportedPkgs.get(pkgName);
+
+            // 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);
-            Constraint currentExportedConstraint = currentPkgs.m_exportedPkgs.get(pkgName);
-            Constraint currentImportedConstraint = currentPkgs.m_importedPkgs.get(pkgName);
-            Constraint currentRequiredConstraint = currentPkgs.m_requiredPkgs.get(pkgName);
-
-            if (((currentExportedConstraint != null)
-                    && !currentExportedConstraint.m_sources.containsAll(candConstraint.m_sources))
-                || ((currentImportedConstraint != null)
-                    && !currentImportedConstraint.m_sources.containsAll(candConstraint.m_sources))
-                || ((currentRequiredConstraint != null)
-                    && !currentRequiredConstraint.m_sources.containsAll(candConstraint.m_sources)))
+            Capability currentExportedCap = currentPkgs.m_exportedPkgs.get(pkgName);
+            Capability currentImportedCap = currentPkgs.m_importedPkgs.get(pkgName);
+            List<Capability> currentRequiredCaps = currentPkgs.m_requiredPkgs.get(pkgName);
+
+            if (!requires &&
+                (((currentExportedCap != null) && !currentExportedCap.equals(candCap))
+                || ((currentImportedCap != null) && !currentImportedCap.equals(candCap))
+                || ((currentRequiredCaps != null) && !currentRequiredCaps.contains(candCap))))
             {
+dumpModulePkgs(current, currentPkgs);
                 throw new ResolveException("Constraint violation between "
                     + current + " and " + candCap.getModule()
                     + " for " + pkgName);
             }
 
-            List<Constraint> currentUsedSources = currentPkgs.m_usedPkgs.get(pkgName);
-            checkExistingUsesConstraints(current, pkgName, currentUsedSources, candConstraint);
+            //
+            // Second, check to see if the capability conflicts with
+            // any existing uses constraints
+            //
+
+            List<Capability> currentUsedCapabilities = currentPkgs.m_usedPkgs.get(pkgName);
+            checkExistingUsesConstraints(current, pkgName, currentUsedCapabilities, candCap);
+
+            //
+            // Last, check to see if any uses constraints implied by the
+            // candidate conflict with any of the existing hard constraints.
+            //
 
+            // For now, create a copy of the module's package space and
+            // add the current candidate to the imported packages.
             Packages currentPkgsCopy = new Packages(currentPkgs);
 
-            // Add the candidate package to the current set of packages.
-            currentPkgsCopy.m_importedPkgs.put(pkgName, candConstraint);
-
-            // Verify the candidate's uses constraints do not conflict.
-            for (Capability cap : candConstraint.m_sources)
+            if (requires)
             {
-                for (String usedPkg : cap.getUses())
+                if (currentRequiredCaps == null)
                 {
-                    verifyUses(current, currentPkgsCopy, candCap, modulePkgMap, usedPkg);
+                    currentRequiredCaps = new ArrayList<Capability>();
+                    currentPkgsCopy.m_requiredPkgs.put(pkgName, currentRequiredCaps);
                 }
+// TODO: PROTO2 RESOLVER - This is potentially modifying the original, we need to modify a copy.
+                currentRequiredCaps.add(candCap);
+            }
+            else
+            {
+                currentPkgsCopy.m_importedPkgs.put(pkgName, candCap);
             }
 
+            // Verify and merge the candidate's transitive uses constraints.
+            verifyAndMergeUses(current, currentPkgsCopy, candCap, modulePkgMap);
+
+            // If we are here, then there were no conflict, so we should update
+            // the module's package space.
             currentPkgs.m_exportedPkgs.putAll(currentPkgsCopy.m_exportedPkgs);
             currentPkgs.m_importedPkgs.putAll(currentPkgsCopy.m_importedPkgs);
             currentPkgs.m_requiredPkgs.putAll(currentPkgsCopy.m_requiredPkgs);
@@ -270,30 +328,29 @@
     }
 
     private void checkExistingUsesConstraints(
-        Module current, String pkgName, List<Constraint> existingConstraints,
-        Constraint candConstraint)
+        Module current, String pkgName, List<Capability> currentUsedCapabilities,
+        Capability candCap)
     {
-        for (int i = 0; (existingConstraints != null) && (i < existingConstraints.size()); i++)
+        for (int i = 0; (currentUsedCapabilities != null) && (i < currentUsedCapabilities.size()); i++)
         {
-            if (!existingConstraints.get(i).m_sources.containsAll(candConstraint.m_sources))
+            if (!currentUsedCapabilities.contains(candCap))
             {
                 throw new ResolveException("Constraint violation for package '" + pkgName
                     + "' when resolving module " + current
                     + " between existing constraint "
-                    + existingConstraints.get(i).m_capability.getModule()
-                    + " " + existingConstraints.get(i).m_sources
-                    + " and candidate constraint " + candConstraint.m_capability.getModule()
-                    + " " + candConstraint.m_sources);
+                    + current
+                    + " " + currentUsedCapabilities
+                    + " and candidate constraint " + candCap.getModule()
+                    + " " + candCap);
             }
         }
     }
 
 // TODO: PROTO2 RESOLVER - We end up with duplicates in uses constraints,
 //       see scenario 2 for an example.
-    private void verifyUses(
+    private void verifyAndMergeUses(
         Module current, Packages currentPkgs,
-        Capability candCap, Map<Module, Packages> modulePkgMap,
-        String pkgName)
+        Capability candCap, Map<Module, Packages> modulePkgMap)
     {
         if (m_isInvokeCount)
         {
@@ -302,72 +359,73 @@
             count = (count == null) ? new Long(1) : new Long(count.longValue() + 1);
             m_invokeCounts.put(methodName, count);
         }
-        Constraint currentExportedConstraint = currentPkgs.m_exportedPkgs.get(pkgName);
-        Constraint currentImportedConstraint = currentPkgs.m_importedPkgs.get(pkgName);
-        Constraint currentRequiredConstraint = currentPkgs.m_requiredPkgs.get(pkgName);
-
-        Packages candPkgs = modulePkgMap.get(candCap.getModule());
-        Constraint candConstraint = candPkgs.m_exportedPkgs.get(pkgName);
-        candConstraint = (candConstraint != null)
-            ? candConstraint
-            : candPkgs.m_importedPkgs.get(pkgName);
-        candConstraint = (candConstraint != null)
-            ? candConstraint
-            : candPkgs.m_requiredPkgs.get(pkgName);
-
-        // 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 (candConstraint == null)
-        {
-            return;
-        }
 
-        // If there is no current mapping for this package, then
-        // we can just return.
-        if ((currentExportedConstraint == null)
-            && (currentImportedConstraint == null)
-            && (currentRequiredConstraint == null))
+        for (Capability candCapSource : getPackageSources(candCap, modulePkgMap))
         {
-            List<Constraint> constraints = currentPkgs.m_usedPkgs.get(pkgName);
-            if (constraints == null)
+            for (String usedPkgName : candCapSource.getUses())
             {
-                constraints = new ArrayList<Constraint>();
-                currentPkgs.m_usedPkgs.put(pkgName, constraints);
-            }
-            constraints.add(candConstraint);
-            return;
-        }
+                Capability currentExportedCap = currentPkgs.m_exportedPkgs.get(usedPkgName);
+                Capability currentImportedCap = currentPkgs.m_importedPkgs.get(usedPkgName);
+                List<Capability> currentRequiredCaps = currentPkgs.m_requiredPkgs.get(usedPkgName);
+
+                Packages sourcePkgs = modulePkgMap.get(candCapSource.getModule());
+                Capability sourceCap = sourcePkgs.m_exportedPkgs.get(usedPkgName);
+                sourceCap = (sourceCap != null)
+                    ? sourceCap
+                    : sourcePkgs.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 (sourceCap == null)
+                {
+                    return;
+                }
 
-        if ((currentExportedConstraint != null)
-            && !currentExportedConstraint.m_sources.containsAll(candConstraint.m_sources))
-        {
-            throw new ResolveException("Constraint violation for package '" + pkgName
-                + "' when resolving module " + current
-                + " between existing constraint "
-                + currentExportedConstraint.m_capability.getModule()
-                + " " + currentExportedConstraint.m_sources
-                + " and candidate constraint " + candConstraint.m_capability.getModule()
-                + " " + candConstraint.m_sources);
-        }
-        else if ((currentImportedConstraint != null)
-            && !currentImportedConstraint.m_sources.containsAll(candConstraint.m_sources))
-        {
-            throw new ResolveException("Constraint violation for package '" + pkgName
-                + "' when resolving module " + current
-                + " between existing constraint "
-                + currentImportedConstraint.m_capability.getModule()
-                + " " + currentImportedConstraint.m_sources
-                + " and candidate constraint " + candConstraint.m_capability.getModule()
-                + " " + candConstraint.m_sources);
-        }
+                // If there is no current mapping for this package, then
+                // we can just return.
+                if ((currentExportedCap == null)
+                    && (currentImportedCap == null)
+                    && (currentRequiredCaps == null))
+                {
+                    List<Capability> usedCaps = currentPkgs.m_usedPkgs.get(usedPkgName);
+                    if (usedCaps == null)
+                    {
+                        usedCaps = new ArrayList<Capability>();
+                        currentPkgs.m_usedPkgs.put(usedPkgName, usedCaps);
+                    }
+                    usedCaps.add(sourceCap);
+                    return;
+                }
 
-        // Verify the candidate's uses constraints do not conflict.
-        for (Capability cap : candConstraint.m_sources)
-        {
-            for (String usedPkg : cap.getUses())
-            {
-                verifyUses(current, currentPkgs, cap, modulePkgMap, usedPkg);
+                if ((currentExportedCap != null)
+                    && !currentExportedCap.equals(sourceCap))
+                {
+                    throw new ResolveException("Constraint violation for package '" + usedPkgName
+                        + "' when resolving module " + current
+                        + " between existing constraint "
+                        + currentExportedCap.getModule()
+                        + " " + currentExportedCap
+                        + " and candidate constraint " + sourceCap.getModule()
+                        + " " + sourceCap);
+                }
+                else if ((currentImportedCap != null)
+                    && !currentImportedCap.equals(sourceCap))
+                {
+                    throw new ResolveException("Constraint violation for package '" + usedPkgName
+                        + "' when resolving module " + current
+                        + " between existing constraint "
+                        + currentImportedCap.getModule()
+                        + " " + currentImportedCap
+                        + " and candidate constraint " + sourceCap.getModule()
+                        + " " + sourceCap);
+                }
+
+                // Verify the candidate's uses constraints do not conflict.
+                verifyAndMergeUses(current, currentPkgs, sourceCap, modulePkgMap);
             }
         }
     }
@@ -507,11 +565,9 @@
                 if (caps.get(i).getNamespace().equals(Capability.PACKAGE_NAMESPACE)
                     && !hasOverlappingImport(module, caps.get(i)))
                 {
-                    List<Capability> sources = new ArrayList<Capability>();
-                    sources.add(caps.get(i));
                     packages.m_exportedPkgs.put(
                         (String) caps.get(i).getAttribute(Capability.PACKAGE_ATTR).getValue(),
-                        new Constraint(caps.get(i), sources));
+                        caps.get(i));
                 }
             }
         }
@@ -541,16 +597,35 @@
         return false;
     }
 
+    private static List<Capability> getPackageSources(
+        Capability cap, Map<Module, Packages> modulePkgMap)
+    {
+        List<Capability> sources = null;
+        if (cap.getNamespace().equals(Capability.PACKAGE_NAMESPACE))
+        {
+            Packages pkgs = modulePkgMap.get(cap.getModule());
+            sources = new ArrayList<Capability>();
+            sources.add(cap);
+            String pkgName = cap.getAttribute(Capability.PACKAGE_ATTR).getValue().toString();
+            List<Capability> required = pkgs.m_requiredPkgs.get(pkgName);
+            if (required != null)
+            {
+                sources.addAll(required);
+            }
+        }
+        return sources;
+    }
+
     private class Packages
     {
-        public final Map<String, Constraint> m_exportedPkgs
-            = new HashMap<String, Constraint>();
-        public final Map<String, Constraint> m_importedPkgs
-            = new HashMap<String, Constraint>();
-        public final Map<String, Constraint> m_requiredPkgs
-            = new HashMap<String, Constraint>();
-        public final Map<String, List<Constraint>> m_usedPkgs
-            = new HashMap<String, List<Constraint>>();
+        public final Map<String, Capability> m_exportedPkgs
+            = new HashMap<String, Capability>();
+        public final Map<String, Capability> m_importedPkgs
+            = new HashMap<String, Capability>();
+        public final Map<String, List<Capability>> m_requiredPkgs
+            = new HashMap<String, List<Capability>>();
+        public final Map<String, List<Capability>> m_usedPkgs
+            = new HashMap<String, List<Capability>>();
 
         public Packages()
         {
@@ -564,20 +639,4 @@
             m_usedPkgs.putAll(packages.m_usedPkgs);
         }
     }
-
-    private class Constraint
-    {
-        public final Capability m_capability;
-        public final List<Capability> m_sources;
-        public Constraint(Capability capability, List<Capability> sources)
-        {
-            m_capability = capability;
-            m_sources = sources;
-        }
-
-        public String toString()
-        {
-            return m_capability + " SOURCES " + m_sources;
-        }
-    }
 }
\ No newline at end of file