Modified ExportedPackage.getImportingBundles() to include bundles
that requiring the exporting bundle, in addition to those bundles that
import the package. Also tried to simplify dependency management code
by separating it out. (FELIX-764) 


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@704593 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 b26a3db..f96a20a 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -3092,37 +3092,28 @@
         List list = new ArrayList();
 
         // Get exporting bundle information.
-        FelixBundle exporter = (FelixBundle)
-            (ep).getExportingBundle();
+        FelixBundle exporter = (FelixBundle) ep.getExportingBundle();
 
-        // Search the dependents of the exporter's module revisions
-        // for importers of the specific package.
+        // Get all importers and requirers for all revisions of the bundle.
+        // The spec says that require-bundle should be returned with importers.
         IModule[] expModules = exporter.getInfo().getModules();
         for (int expIdx = 0; (expModules != null) && (expIdx < expModules.length); expIdx++)
         {
-            IModule[] depModules = ((ModuleImpl) expModules[expIdx]).getDependents();
-            for (int depIdx = 0; (depModules != null) && (depIdx < depModules.length); depIdx++)
+            IModule[] dependents = ((ModuleImpl) expModules[expIdx]).getDependentImporters();
+            for (int depIdx = 0; (dependents != null) && (depIdx < dependents.length); depIdx++)
             {
-                // ExportedPackage.getImportingBundles() does not expect bundles
-                // to depend on themselves, so we will filter that case here.
-                if (!expModules[expIdx].equals(depModules[depIdx]))
+                // ExportedPackage.getImportingBundles() does not expect a bundle to
+                // depend on itself, so ignore that case.
+                if (!expModules[expIdx].equals(dependents[depIdx]))
                 {
-                    // See if the dependent module has a wire for the specific
-                    // package. If so, see if the provider module is from the
-                    // exporter and record it if it is.
-                    IWire wire = Util.getWire(depModules[depIdx], ep.getName());
-                    if ((wire != null) && expModules[expIdx].equals(wire.getExporter()) &&
-                        wire.getRequirement().isSatisfied(
-                        new Capability(ICapability.PACKAGE_NAMESPACE, null, new R4Attribute[] {
-                            new R4Attribute(ICapability.PACKAGE_PROPERTY, ep.getName(), false),
-                            new R4Attribute(ICapability.VERSION_PROPERTY, ep.getVersion(), false)
-                        })))
-                    {
-                        // Add the bundle to the list of importers.
-                        list.add(getBundle(Util.getBundleIdFromModuleId(depModules[depIdx].getId())));
-                    }
+                    list.add(getBundle(Util.getBundleIdFromModuleId(dependents[depIdx].getId())));
                 }
             }
+            dependents = ((ModuleImpl) expModules[expIdx]).getDependentRequirers();
+            for (int depIdx = 0; (dependents != null) && (depIdx < dependents.length); depIdx++)
+            {
+                list.add(getBundle(Util.getBundleIdFromModuleId(dependents[depIdx].getId())));
+            }
         }
 
         // Return the results.
@@ -3266,23 +3257,23 @@
         fireFrameworkEvent(FrameworkEvent.PACKAGES_REFRESHED, this, null);
     }
 
-    private void populateImportGraph(FelixBundle exporter, Map map)
+    private void populateDependentGraph(FelixBundle exporter, Map map)
     {
         // Get all dependent bundles of this bundle.
-        Bundle[] importers = getDependentBundles(exporter);
+        Bundle[] dependents = getDependentBundles(exporter);
 
-        for (int impIdx = 0;
-            (importers != null) && (impIdx < importers.length);
-            impIdx++)
+        for (int depIdx = 0;
+            (dependents != null) && (depIdx < dependents.length);
+            depIdx++)
         {
             // Avoid cycles if the bundle is already in map.
-            if (!map.containsKey(importers[impIdx]))
+            if (!map.containsKey(dependents[depIdx]))
             {
                 // Add each importing bundle to map.
-                map.put(importers[impIdx], importers[impIdx]);
+                map.put(dependents[depIdx], dependents[depIdx]);
                 // Now recurse into each bundle to get its importers.
-                populateImportGraph(
-                    (FelixBundle) importers[impIdx], map);
+                populateDependentGraph(
+                    (FelixBundle) dependents[depIdx], map);
             }
         }
     }
@@ -4295,7 +4286,7 @@
                         FelixBundle target = (FelixBundle) newTargets[targetIdx];
                         map.put(target, target);
                         // Add all importing bundles to map.
-                        populateImportGraph(target, map);
+                        populateDependentGraph(target, map);
                     }
 
                     bundles = (FelixBundle[]) map.values().toArray(new FelixBundle[map.size()]);
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/ModuleImpl.java b/framework/src/main/java/org/apache/felix/moduleloader/ModuleImpl.java
index 90902ac..bba010d 100644
--- a/framework/src/main/java/org/apache/felix/moduleloader/ModuleImpl.java
+++ b/framework/src/main/java/org/apache/felix/moduleloader/ModuleImpl.java
@@ -33,7 +33,9 @@
     private IContentLoader m_contentLoader = null;
     private IModule[] m_fragments = null;
     private IWire[] m_wires = null;
-    private IModule[] m_dependents = new IModule[0];
+    private IModule[] m_dependentHosts = new IModule[0];
+    private IModule[] m_dependentImporters = new IModule[0];
+    private IModule[] m_dependentRequirers = new IModule[0];
 
     ModuleImpl(Logger logger, String id, IModuleDefinition md)
     {
@@ -69,20 +71,21 @@
         // dependencies when we are uninstalling the module.
         for (int i = 0; (m_fragments != null) && (i < m_fragments.length); i++)
         {
-            ((ModuleImpl) m_fragments[i]).removeDependent(this);
+            ((ModuleImpl) m_fragments[i]).removeDependentHost(this);
         }
 
         // Update the dependencies on the new fragments.
         m_fragments = fragments;
+
+        // We need to add ourself as a dependent of each fragment
+        // module. We also need to create an array of fragment contents
+        // to attach to our content loader.
         if (m_fragments != null)
         {
-            // We need to add ourself as a dependent of each fragment
-            // module. We also need to create an array of fragment contents
-            // to attach to our content loader.
             IContent[] fragmentContents = new IContent[m_fragments.length];
             for (int i = 0; (m_fragments != null) && (i < m_fragments.length); i++)
             {
-                ((ModuleImpl) m_fragments[i]).addDependent(this);
+                ((ModuleImpl) m_fragments[i]).addDependentHost(this);
                 fragmentContents[i] =
                     m_fragments[i].getContentLoader().getContent()
                         .getEntryAsContent(FelixConstants.CLASS_PATH_DOT);
@@ -99,66 +102,105 @@
 
     public synchronized void setWires(IWire[] wires)
     {
-        // Remove module from old wire modules' dependencies.
+        // Remove module from old wire modules' dependencies,
+        // since we are no longer dependent on any the moduels
+        // from the old wires.
         for (int i = 0; (m_wires != null) && (i < m_wires.length); i++)
         {
-            ((ModuleImpl) m_wires[i].getExporter()).removeDependent(this);
+            if (m_wires[i].getCapability().getNamespace().equals(ICapability.MODULE_NAMESPACE))
+            {
+                ((ModuleImpl) m_wires[i].getExporter()).removeDependentRequirer(this);
+            }
+            else if (m_wires[i].getCapability().getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+            {
+                ((ModuleImpl) m_wires[i].getExporter()).removeDependentImporter(this);
+            }
         }
+
         m_wires = wires;
-        // Add module to new wire modules' dependencies.
-        for (int i = 0; (wires != null) && (i < wires.length); i++)
+
+        // Add ourself as a dependent to the new wires' modules.
+        for (int i = 0; (m_wires != null) && (i < m_wires.length); i++)
         {
-            ((ModuleImpl) m_wires[i].getExporter()).addDependent(this);
+            if (m_wires[i].getCapability().getNamespace().equals(ICapability.MODULE_NAMESPACE))
+            {
+                ((ModuleImpl) m_wires[i].getExporter()).addDependentRequirer(this);
+            }
+            else if (m_wires[i].getCapability().getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+            {
+                ((ModuleImpl) m_wires[i].getExporter()).addDependentImporter(this);
+            }
         }
     }
 
-    private synchronized void addDependent(IModule module)
+    public synchronized IModule[] getDependentHosts()
     {
-        // Make sure the dependent module is not already present.
-        for (int i = 0; i < m_dependents.length; i++)
-        {
-            if (m_dependents[i].equals(module))
-            {
-                return;
-            }
-        }
-        IModule[] tmp = new IModule[m_dependents.length + 1];
-        System.arraycopy(m_dependents, 0, tmp, 0, m_dependents.length);
-        tmp[m_dependents.length] = module;
-        m_dependents = tmp;
+        return m_dependentHosts;
     }
 
-    private synchronized void removeDependent(IModule module)
+    public synchronized void addDependentHost(IModule module)
     {
-        // Make sure the dependent module is not already present.
-        for (int i = 0; i < m_dependents.length; i++)
-        {
-            if (m_dependents[i].equals(module))
-            {
-                // If this is the module, then point to empty list.
-                if ((m_dependents.length - 1) == 0)
-                {
-                    m_dependents = new IModule[0];
-                }
-                // Otherwise, we need to do some array copying.
-                else
-                {
-                    IModule[] tmp = new IModule[m_dependents.length - 1];
-                    System.arraycopy(m_dependents, 0, tmp, 0, i);
-                    if (i < tmp.length)
-                    {
-                        System.arraycopy(
-                            m_dependents, i + 1, tmp, i, tmp.length - i);
-                    }
-                    m_dependents = tmp;
-                }
-            }
-        }
+        m_dependentHosts = addDependent(m_dependentHosts, module);
+    }
+
+    public synchronized void removeDependentHost(IModule module)
+    {
+        m_dependentHosts = removeDependent(m_dependentHosts, module);
+    }
+
+    public synchronized IModule[] getDependentImporters()
+    {
+        return m_dependentImporters;
+    }
+
+    public synchronized void addDependentImporter(IModule module)
+    {
+        m_dependentImporters = addDependent(m_dependentImporters, module);
+    }
+
+    public synchronized void removeDependentImporter(IModule module)
+    {
+        m_dependentImporters = removeDependent(m_dependentImporters, module);
+    }
+
+    public synchronized IModule[] getDependentRequirers()
+    {
+        return m_dependentRequirers;
+    }
+
+    public synchronized void addDependentRequirer(IModule module)
+    {
+        m_dependentRequirers = addDependent(m_dependentRequirers, module);
+    }
+
+    public synchronized void removeDependentRequirer(IModule module)
+    {
+        m_dependentRequirers = removeDependent(m_dependentRequirers, module);
     }
 
     public synchronized IModule[] getDependents()
     {
-        return m_dependents;
+        IModule[] dependents = new IModule[
+            m_dependentHosts.length + m_dependentImporters.length + m_dependentRequirers.length];
+        System.arraycopy(
+            m_dependentHosts,
+            0,
+            dependents,
+            0,
+            m_dependentHosts.length);
+        System.arraycopy(
+            m_dependentImporters,
+            0,
+            dependents,
+            m_dependentHosts.length,
+            m_dependentImporters.length);
+        System.arraycopy(
+            m_dependentRequirers,
+            0,
+            dependents,
+            m_dependentHosts.length + m_dependentImporters.length,
+            m_dependentRequirers.length);
+        return dependents;
     }
 
     public Class getClass(String name) throws ClassNotFoundException
@@ -213,4 +255,51 @@
     {
         return m_id;
     }
+
+    private static IModule[] addDependent(IModule[] modules, IModule module)
+    {
+        // Make sure the dependent module is not already present.
+        for (int i = 0; i < modules.length; i++)
+        {
+            if (modules[i].equals(module))
+            {
+                return modules;
+            }
+        }
+        IModule[] tmp = new IModule[modules.length + 1];
+        System.arraycopy(modules, 0, tmp, 0, modules.length);
+        tmp[modules.length] = module;
+        return tmp;
+    }
+
+    private static IModule[] removeDependent(IModule[] modules, IModule module)
+    {
+        IModule[] tmp = modules;
+
+        // Make sure the dependent module is not already present.
+        for (int i = 0; i < modules.length; i++)
+        {
+            if (modules[i].equals(module))
+            {
+                // If this is the module, then point to empty list.
+                if ((modules.length - 1) == 0)
+                {
+                    tmp = new IModule[0];
+                }
+                // Otherwise, we need to do some array copying.
+                else
+                {
+                    tmp = new IModule[modules.length - 1];
+                    System.arraycopy(modules, 0, tmp, 0, i);
+                    if (i < tmp.length)
+                    {
+                        System.arraycopy(modules, i + 1, tmp, i, tmp.length - i);
+                    }
+                }
+                break;
+            }
+        }
+
+        return tmp;
+    }
 }
\ No newline at end of file