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 2011/05/17 23:20:35 UTC

svn commit: r1104564 [2/12] - in /felix/trunk/framework: ./ src/main/java/org/apache/felix/framework/ src/main/java/org/apache/felix/framework/cache/ src/main/java/org/apache/felix/framework/capabilityset/ src/main/java/org/apache/felix/framework/resol...

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=1104564&r1=1104563&r2=1104564&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Tue May 17 21:20:32 2011
@@ -27,14 +27,9 @@ import java.util.Map.Entry;
 import org.apache.felix.framework.ServiceRegistry.ServiceRegistryCallbacks;
 import org.apache.felix.framework.cache.BundleArchive;
 import org.apache.felix.framework.cache.BundleCache;
-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.resolver.Module;
-import org.apache.felix.framework.capabilityset.Requirement;
 import org.apache.felix.framework.capabilityset.SimpleFilter;
-import org.apache.felix.framework.resolver.Wire;
+import org.apache.felix.framework.resolver.ResolverWire;
 import org.apache.felix.framework.ext.SecurityProvider;
 import org.apache.felix.framework.resolver.ResolveException;
 import org.apache.felix.framework.resolver.Resolver;
@@ -49,7 +44,9 @@ import org.apache.felix.framework.util.S
 import org.apache.felix.framework.util.ThreadGate;
 import org.apache.felix.framework.util.Util;
 import org.apache.felix.framework.util.manifestparser.R4LibraryClause;
-import org.apache.felix.framework.util.manifestparser.RequirementImpl;
+import org.apache.felix.framework.wiring.BundleCapabilityImpl;
+import org.apache.felix.framework.wiring.BundleRequirementImpl;
+import org.apache.felix.framework.wiring.BundleWireImpl;
 import org.osgi.framework.AdminPermission;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
@@ -73,6 +70,10 @@ import org.osgi.framework.ServiceReferen
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.framework.hooks.service.FindHook;
 import org.osgi.framework.hooks.service.ListenerHook;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWire;
 import org.osgi.service.packageadmin.ExportedPackage;
 import org.osgi.service.startlevel.StartLevel;
 
@@ -125,6 +126,9 @@ public class Felix extends BundleImpl im
     // CONCURRENCY: Access guarded by the global lock for writes,
     // but no lock for reads since it is copy on write.
     private volatile List<BundleImpl> m_uninstalledBundles;
+    // Object to keep track of dependencies among bundle revisions.
+    private final BundleRevisionDependencies m_dependencies =
+        new BundleRevisionDependencies();
 
     // Framework's active start level.
     private volatile int m_activeStartLevel = FelixConstants.FRAMEWORK_INACTIVE_STARTLEVEL;
@@ -367,12 +371,12 @@ public class Felix extends BundleImpl im
                 m_logger,
                 (String) m_configMap.get(Constants.FRAMEWORK_EXECUTIONENVIRONMENT)));
 
-        // Create the extension manager, which we will use as the module
-        // definition for creating the system bundle module.
-        m_extensionManager = new ExtensionManager(m_logger, this);
+        // Create the extension manager, which we will use as the
+        // revision for the system bundle.
+        m_extensionManager = new ExtensionManager(m_logger, m_configMap, this);
         try
         {
-            addModule(m_extensionManager.getModule());
+            addRevision(m_extensionManager.getRevision());
         }
         catch (Exception ex)
         {
@@ -640,7 +644,7 @@ public class Felix extends BundleImpl im
                 // state to be set to RESOLVED.
                 try
                 {
-                    m_resolver.resolve(getCurrentModule());
+                    m_resolver.resolve(getCurrentRevision());
                 }
                 catch (ResolveException ex)
                 {
@@ -872,24 +876,27 @@ public class Felix extends BundleImpl im
                 AdminPermission.EXECUTE));
         }
 
-        // Spec says stop() on SystemBundle should return immediately and
-        // shutdown framework on another thread.
-        new Thread(new Runnable() {
-            public void run()
-            {
-                try
-                {
-                    stopBundle(Felix.this, true);
-                }
-                catch (BundleException ex)
+        if ((getState() & (Bundle.INSTALLED | Bundle.RESOLVED)) == 0)
+        {
+            // Spec says stop() on SystemBundle should return immediately and
+            // shutdown framework on another thread.
+            new Thread(new Runnable() {
+                public void run()
                 {
-                    m_logger.log(
-                        Logger.LOG_ERROR,
-                        "Exception trying to stop framework.",
-                        ex);
+                    try
+                    {
+                        stopBundle(Felix.this, true);
+                    }
+                    catch (BundleException ex)
+                    {
+                        m_logger.log(
+                            Logger.LOG_ERROR,
+                            "Exception trying to stop framework.",
+                            ex);
+                    }
                 }
-            }
-        }, "FelixShutdown").start();
+            }, "FelixShutdown").start();
+        }
     }
 
     public void stop(int options) throws BundleException
@@ -1472,11 +1479,25 @@ public class Felix extends BundleImpl im
         {
             throw new IllegalStateException("The bundle is uninstalled.");
         }
-        else if (Util.isFragment(bundle.getCurrentModule()))
+        else if (Util.isFragment(bundle.getCurrentRevision()))
         {
             return null;
         }
-        return bundle.getCurrentModule().getResourceByDelegation(name);
+// TODO: OSGi R4.3 - Currently, we try to resolve resource requests in
+//       findClassOrResourceByDelegation() and fall back to local resource
+//       searching if it fails. Perhaps we should attempt the resolve here
+//       and do the local searching here. This means we could get rid of
+//       resolve attempts in findClassOrResourceByDelegation().
+        if (bundle.getCurrentRevision().getWiring() == null)
+        {
+            return ((BundleRevisionImpl) bundle.getCurrentRevision())
+                .getResourceLocal(name);
+        }
+        else
+        {
+            return ((BundleWiringImpl) bundle.getCurrentRevision().getWiring())
+                .getResourceByDelegation(name);
+        }
     }
 
     /**
@@ -1488,11 +1509,25 @@ public class Felix extends BundleImpl im
         {
             throw new IllegalStateException("The bundle is uninstalled.");
         }
-        else if (Util.isFragment(bundle.getCurrentModule()))
+        else if (Util.isFragment(bundle.getCurrentRevision()))
         {
             return null;
         }
-        return bundle.getCurrentModule().getResourcesByDelegation(name);
+// TODO: OSGi R4.3 - Currently, we try to resolve resource requests in
+//       findResourcesByDelegation() and fall back to local resource
+//       searching if it fails. Perhaps we should attempt the resolve here
+//       and do the local searching here. This means we could get rid of
+//       resolve attempts in findResourcesByDelegation().
+        if (bundle.getCurrentRevision().getWiring() == null)
+        {
+            return ((BundleRevisionImpl) bundle.getCurrentRevision())
+                .getResourcesLocal(name);
+        }
+        else
+        {
+            return ((BundleWiringImpl) bundle.getCurrentRevision().getWiring())
+                .getResourcesByDelegation(name);
+        }
     }
 
     /**
@@ -1505,7 +1540,7 @@ public class Felix extends BundleImpl im
             throw new IllegalStateException("The bundle is uninstalled.");
         }
 
-        URL url = bundle.getCurrentModule().getEntry(name);
+        URL url = ((BundleRevisionImpl) bundle.getCurrentRevision()).getEntry(name);
 
         // Some JAR files do not contain directory entries, so if
         // the entry wasn't found and is a directory, scan the entries
@@ -1544,7 +1579,7 @@ public class Felix extends BundleImpl im
             throw new IllegalStateException("The bundle is uninstalled.");
         }
 
-        // Get the entry enumeration from the module content and
+        // Get the entry enumeration from the revision content and
         // create a wrapper enumeration to filter it.
         Enumeration enumeration =
             new EntryFilterEnumeration(bundle, false, path, "*", false, false);
@@ -1562,7 +1597,7 @@ public class Felix extends BundleImpl im
         // Try to resolve the bundle per the spec.
         resolveBundles(new Bundle[] { bundle });
 
-        // Get the entry enumeration from the module content and
+        // Get the entry enumeration from the revision content and
         // create a wrapper enumeration to filter it.
         Enumeration enumeration =
             new EntryFilterEnumeration(bundle, true, path, filePattern, recurse, true);
@@ -1633,7 +1668,7 @@ public class Felix extends BundleImpl im
         {
             throw new IllegalStateException("Bundle is uninstalled");
         }
-        else if (Util.isFragment(bundle.getCurrentModule()))
+        else if (Util.isFragment(bundle.getCurrentRevision()))
         {
             throw new ClassNotFoundException("Fragments cannot load classes.");
         }
@@ -1651,7 +1686,8 @@ public class Felix extends BundleImpl im
                 throw new ClassNotFoundException(name, ex);
             }
         }
-        return bundle.getCurrentModule().getClassByDelegation(name);
+        return ((BundleWiringImpl)
+            bundle.getCurrentRevision().getWiring()).getClassByDelegation(name);
     }
 
     /**
@@ -1690,7 +1726,8 @@ public class Felix extends BundleImpl im
 
         // Record whether the bundle is using its declared activation policy.
         boolean wasDeferred = bundle.isDeclaredActivationPolicyUsed()
-            && (bundle.getCurrentModule().getDeclaredActivationPolicy() == Module.LAZY_ACTIVATION);
+            && (((BundleRevisionImpl) bundle.getCurrentRevision())
+                .getDeclaredActivationPolicy() == BundleRevisionImpl.LAZY_ACTIVATION);
         bundle.setDeclaredActivationPolicyUsed(
             (options & Bundle.START_ACTIVATION_POLICY) != 0);
 
@@ -1706,7 +1743,7 @@ public class Felix extends BundleImpl im
 
             // As per the OSGi spec, fragment bundles can not be started and must
             // throw a BundleException when there is an attempt to start one.
-            if (Util.isFragment(bundle.getCurrentModule()))
+            if (Util.isFragment(bundle.getCurrentRevision()))
             {
                 throw new BundleException("Fragment bundles can not be started.");
             }
@@ -1811,8 +1848,9 @@ public class Felix extends BundleImpl im
             // If the bundle's activation policy is eager or activation has already
             // been triggered, then activate the bundle immediately.
             if (!bundle.isDeclaredActivationPolicyUsed()
-                || (bundle.getCurrentModule().getDeclaredActivationPolicy() != Module.LAZY_ACTIVATION)
-                || ((ModuleImpl) bundle.getCurrentModule()).isActivationTriggered())
+                || (((BundleRevisionImpl) bundle.getCurrentRevision())
+                    .getDeclaredActivationPolicy() != BundleRevisionImpl.LAZY_ACTIVATION)
+                || ((BundleRevisionImpl) bundle.getCurrentRevision()).isActivationTriggered())
             {
                 // Record the event type for the final event and activate.
                 eventType = BundleEvent.STARTED;
@@ -2001,8 +2039,8 @@ public class Felix extends BundleImpl im
 
             // First get the update-URL from our header.
             String updateLocation = (String)
-                bundle.getCurrentModule().getHeaders().get(
-                    Constants.BUNDLE_UPDATELOCATION);
+                ((BundleRevisionImpl) bundle.getCurrentRevision())
+                    .getHeaders().get(Constants.BUNDLE_UPDATELOCATION);
 
             // If no update location specified, use original location.
             if (updateLocation == null)
@@ -2019,7 +2057,7 @@ public class Felix extends BundleImpl im
 
             try
             {
-                // Revising the bundle creates a new module, which modifies
+                // Revising the bundle creates a new revision, which modifies
                 // the global state, so we need to acquire the global lock
                 // before revising.
                 boolean locked = acquireGlobalLock();
@@ -2051,7 +2089,7 @@ public class Felix extends BundleImpl im
                         {
                             m_extensionManager.addExtensionBundle(this, bundle);
 // TODO: REFACTOR - Perhaps we could move this into extension manager.
-                            m_resolver.addModule(m_extensionManager.getModule());
+                            m_resolver.addRevision(m_extensionManager.getRevision());
 // TODO: REFACTOR - Not clear why this is here. We should look at all of these steps more closely.
                             setBundleStateAndNotify(bundle, Bundle.RESOLVED);
                         }
@@ -2115,7 +2153,8 @@ public class Felix extends BundleImpl im
                 {
                     try
                     {
-                        if (!bundle.isUsed() && !bundle.isExtension())
+                        if (!m_dependencies.hasDependents(bundle)
+                            && !bundle.isExtension())
                         {
                             try
                             {
@@ -2137,9 +2176,9 @@ public class Felix extends BundleImpl im
                 }
             }
 
-            // If the old state was active, but the new module is a fragment,
+            // If the old state was active, but the new revision is a fragment,
             // then mark the persistent state to inactive.
-            if ((oldState == Bundle.ACTIVE) && Util.isFragment(bundle.getCurrentModule()))
+            if ((oldState == Bundle.ACTIVE) && Util.isFragment(bundle.getCurrentRevision()))
             {
                 bundle.setPersistentStateInactive();
                 m_logger.log(bundle, Logger.LOG_WARNING,
@@ -2232,7 +2271,7 @@ public class Felix extends BundleImpl im
 
             // As per the OSGi spec, fragment bundles can not be stopped and must
             // throw a BundleException when there is an attempt to stop one.
-            if (Util.isFragment(bundle.getCurrentModule()))
+            if (Util.isFragment(bundle.getCurrentRevision()))
             {
                 throw new BundleException("Fragment bundles can not be stopped: " + bundle);
             }
@@ -2244,7 +2283,8 @@ public class Felix extends BundleImpl im
                     throw new IllegalStateException("Cannot stop an uninstalled bundle.");
                 case Bundle.STARTING:
                     if (bundle.isDeclaredActivationPolicyUsed()
-                        && bundle.getCurrentModule().getDeclaredActivationPolicy() != Module.LAZY_ACTIVATION)
+                        && ((BundleRevisionImpl) bundle.getCurrentRevision())
+                            .getDeclaredActivationPolicy() != BundleRevisionImpl.LAZY_ACTIVATION)
                     {
                         throw new BundleException(
                             "Stopping a starting or stopping bundle is currently not supported.");
@@ -2454,7 +2494,7 @@ public class Felix extends BundleImpl im
             {
                 // If the bundle is not used by anyone, then garbage
                 // collect it now.
-                if (!bundle.isUsed())
+                if (!m_dependencies.hasDependents(bundle))
                 {
                     try
                     {
@@ -2610,7 +2650,7 @@ public class Felix extends BundleImpl im
                 else
                 {
                     m_extensionManager.addExtensionBundle(this, bundle);
-                    m_resolver.addModule(m_extensionManager.getModule());
+                    m_resolver.addRevision(m_extensionManager.getRevision());
                 }
             }
             catch (Throwable ex)
@@ -3132,11 +3172,11 @@ public class Felix extends BundleImpl im
 
     }
 
-    Object getService(Bundle bundle, ServiceReference ref)
+    <S> S getService(Bundle bundle, ServiceReference<S> ref)
     {
         try
         {
-            return m_registry.getService(bundle, ref);
+            return (S) m_registry.getService(bundle, ref);
         }
         catch (ServiceException ex)
         {
@@ -3213,8 +3253,8 @@ public class Felix extends BundleImpl im
                 Class sbClass = null;
                 try
                 {
-                    sbClass = m_extensionManager
-                        .getModule().getClassByDelegation(clazz.getName());
+                    sbClass = ((BundleWiringImpl) m_extensionManager
+                        .getRevision().getWiring()).getClassByDelegation(clazz.getName());
                 }
                 catch (ClassNotFoundException ex)
                 {
@@ -3249,16 +3289,19 @@ public class Felix extends BundleImpl im
     ExportedPackage[] getExportedPackages(String pkgName)
     {
         // First, get all exporters of the package.
-        List<Directive> dirs = new ArrayList<Directive>(0);
-        List<Attribute> attrs = new ArrayList<Attribute>(1);
-        attrs.add(new Attribute(Capability.PACKAGE_ATTR, pkgName, false));
-        Requirement req = new RequirementImpl(null, Capability.PACKAGE_NAMESPACE, dirs, attrs);
-        Set<Capability> exports = m_resolver.getCandidates(req, false);
+        Map<String, Object> attrs = new HashMap<String, Object>(1);
+        attrs.put(BundleCapabilityImpl.PACKAGE_ATTR, pkgName);
+        BundleRequirementImpl req = new BundleRequirementImpl(
+            null,
+            BundleCapabilityImpl.PACKAGE_NAMESPACE,
+            Collections.EMPTY_MAP,
+            attrs);
+        Set<BundleCapability> exports = m_resolver.getCandidates(req, false);
 
         // We only want resolved capabilities.
-        for (Iterator<Capability> it = exports.iterator(); it.hasNext(); )
+        for (Iterator<BundleCapability> it = exports.iterator(); it.hasNext(); )
         {
-            if (!it.next().getModule().isResolved())
+            if (it.next().getRevision().getWiring() == null)
             {
                 it.remove();
             }
@@ -3268,39 +3311,41 @@ public class Felix extends BundleImpl im
         {
             List pkgs = new ArrayList();
 
-            for (Iterator<Capability> it = exports.iterator(); it.hasNext(); )
+            for (Iterator<BundleCapability> it = exports.iterator(); it.hasNext(); )
             {
-                // Get the bundle associated with the current exporting module.
-                BundleImpl bundle = (BundleImpl) it.next().getModule().getBundle();
+                // Get the bundle associated with the current exporting revision.
+                BundleImpl bundle = (BundleImpl) it.next().getRevision().getBundle();
 
                 // We need to find the version of the exported package, but this
                 // is tricky since there may be multiple versions of the package
                 // offered by a given bundle, since multiple revisions of the
                 // bundle JAR file may exist if the bundle was updated without
                 // refreshing the framework. In this case, each revision of the
-                // bundle JAR file is represented as a module in the BundleInfo
-                // module array, which is ordered from oldest to newest. We assume
-                // that the first module found to be exporting the package is the
-                // provider of the package, which makes sense since it must have
-                // been resolved first.
-                List<Module> modules = bundle.getModules();
-                for (int modIdx = 0; modIdx < modules.size(); modIdx++)
-                {
-                    List<Capability> ec = modules.get(modIdx).getCapabilities();
-                    for (int i = 0; (ec != null) && (i < ec.size()); i++)
+                // bundle JAR file is represented as a revision ordered from
+                // oldest to newest. We assume that the first revision found to
+                // be exporting the package is the provider of the package,
+                // which makes sense since it must have been resolved first.
+                for (BundleRevision br : bundle.getRevisions())
+                {
+                    List<BundleCapability> caps = (br.getWiring() == null)
+                        ? br.getDeclaredCapabilities(null)
+                        : br.getWiring().getCapabilities(null);
+                    for (BundleCapability cap : caps)
                     {
-                        if (ec.get(i).getNamespace().equals(req.getNamespace())
-                            && CapabilitySet.matches(ec.get(i), req.getFilter()))
+                        if (cap.getNamespace().equals(req.getNamespace())
+                            && CapabilitySet.matches(cap, req.getFilter()))
                         {
                             pkgs.add(
                                 new ExportedPackageImpl(
-                                    this, bundle, modules.get(modIdx), ec.get(i)));
+                                    this, bundle, br, cap));
                         }
                     }
                 }
             }
 
-            return (pkgs.isEmpty()) ? null : (ExportedPackage[]) pkgs.toArray(new ExportedPackage[pkgs.size()]);
+            return (pkgs.isEmpty())
+                ? null
+                : (ExportedPackage[]) pkgs.toArray(new ExportedPackage[pkgs.size()]);
         }
 
         return null;
@@ -3378,46 +3423,45 @@ public class Felix extends BundleImpl im
     **/
     private void getExportedPackages(BundleImpl bundle, List list)
     {
-        // Since a bundle may have many modules associated with it,
-        // one for each revision in the cache, search each module
-        // for each revision to get all exports.
-        List<Module> modules = bundle.getModules();
-        for (int modIdx = 0; modIdx < modules.size(); modIdx++)
-        {
-            List<Capability> caps = modules.get(modIdx).getCapabilities();
+        // Since a bundle may have many revisions associated with it,
+        // one for each revision in the cache, search each revision
+        // to get all exports.
+        for (BundleRevision br : bundle.getRevisions())
+        {
+            List<BundleCapability> caps = (br.getWiring() == null)
+                ? br.getDeclaredCapabilities(null)
+                : br.getWiring().getCapabilities(null);
             if ((caps != null) && (caps.size() > 0))
             {
-                for (int capIdx = 0; capIdx < caps.size(); capIdx++)
+                for (BundleCapability cap : caps)
                 {
-                    // See if the target bundle's module is one of the
+                    // See if the target bundle's revisions is one of the
                     // resolved exporters of the package.
-                    if (caps.get(capIdx).getNamespace().equals(Capability.PACKAGE_NAMESPACE))
+                    if (cap.getNamespace().equals(BundleCapabilityImpl.PACKAGE_NAMESPACE))
                     {
                         String pkgName = (String)
-                            caps.get(capIdx).getAttribute(Capability.PACKAGE_ATTR).getValue();
-                        List<Directive> dirs = new ArrayList<Directive>(0);
-                        List<Attribute> attrs = new ArrayList<Attribute>(1);
-                        attrs.add(new Attribute(Capability.PACKAGE_ATTR, pkgName, false));
-                        Requirement req =
-                            new RequirementImpl(null, Capability.PACKAGE_NAMESPACE, dirs, attrs);
-                        Set<Capability> exports = m_resolver.getCandidates(req, false);
-                        // We only want resolved capabilities.
-                        for (Iterator<Capability> it = exports.iterator(); it.hasNext(); )
-                        {
-                            if (!it.next().getModule().isResolved())
-                            {
-                                it.remove();
-                            }
-                        }
+                            cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR);
+                        Map<String, Object> attrs = new HashMap<String, Object>(1);
+                        attrs.put(BundleCapabilityImpl.PACKAGE_ATTR, pkgName);
+                        BundleRequirementImpl req =
+                            new BundleRequirementImpl(
+                            null,
+                            BundleCapabilityImpl.PACKAGE_NAMESPACE,
+                            Collections.EMPTY_MAP,
+                            attrs);
+                        Set<BundleCapability> providers = m_resolver.getCandidates(req, false);
 
-
-                        // Search through the current providers to find the target module.
-                        for (Capability cap : exports)
+                        // Search through the current providers to find the target revision.
+                        // We only want resolved capabilities.
+                        if (providers != null)
                         {
-                            if (cap == caps.get(capIdx))
+                            for (BundleCapability provider : providers)
                             {
-                                list.add(new ExportedPackageImpl(
-                                    this, bundle, modules.get(modIdx), caps.get(capIdx)));
+                                if ((provider.getRevision().getWiring() != null)
+                                    && (provider == cap))
+                                {
+                                    list.add(new ExportedPackageImpl(this, bundle, br, cap));
+                                }
                             }
                         }
                     }
@@ -3426,64 +3470,16 @@ public class Felix extends BundleImpl im
         }
     }
 
-    List<Bundle> getDependentBundles(BundleImpl exporter)
+    // Needed by ExportedPackageImpl.
+    Set<Bundle> getImportingBundles(BundleImpl exporter, BundleCapability cap)
     {
-        // Create list for storing importing bundles.
-        List<Bundle> list = new ArrayList();
-
-        // Get all dependent modules from all exporter module revisions.
-        List<Module> modules = exporter.getModules();
-        for (int modIdx = 0; modIdx < modules.size(); modIdx++)
-        {
-            List<Module> dependents = ((ModuleImpl) modules.get(modIdx)).getDependents();
-            for (int depIdx = 0;
-                (dependents != null) && (depIdx < dependents.size());
-                depIdx++)
-            {
-                list.add(dependents.get(depIdx).getBundle());
-            }
-        }
-
-        return list;
+        return m_dependencies.getImportingBundles(exporter, cap);
     }
 
-    List<Bundle> getImportingBundles(ExportedPackage ep)
+    // Needed by RequiredBundleImpl.
+    Set<Bundle> getRequiringBundles(BundleImpl bundle)
     {
-        // Create list for storing importing bundles.
-        List<Bundle> list = new ArrayList();
-
-        // Get exporting bundle information.
-        BundleImpl exporter = (BundleImpl) ep.getExportingBundle();
-
-        // Get all importers and requirers for all revisions of the bundle.
-        // The spec says that require-bundle should be returned with importers.
-        List<Module> expModules = exporter.getModules();
-        for (int expIdx = 0; (expModules != null) && (expIdx < expModules.size()); expIdx++)
-        {
-            // Include any importers that have wires to the specific
-            // exported package.
-            List<Module> dependents = ((ModuleImpl) expModules.get(expIdx)).getDependentImporters();
-            for (int depIdx = 0; (dependents != null) && (depIdx < dependents.size()); depIdx++)
-            {
-                List<Wire> wires = dependents.get(depIdx).getWires();
-                for (int wireIdx = 0; (wires != null) && (wireIdx < wires.size()); wireIdx++)
-                {
-                    if ((wires.get(wireIdx).getExporter() == expModules.get(expIdx))
-                        && (wires.get(wireIdx).hasPackage(ep.getName())))
-                    {
-                        list.add(dependents.get(depIdx).getBundle());
-                    }
-                }
-            }
-            dependents = ((ModuleImpl) expModules.get(expIdx)).getDependentRequirers();
-            for (int depIdx = 0; (dependents != null) && (depIdx < dependents.size()); depIdx++)
-            {
-                list.add(dependents.get(depIdx).getBundle());
-            }
-        }
-
-        // Return the results.
-        return list;
+        return m_dependencies.getRequiringBundles(bundle);
     }
 
     boolean resolveBundles(Bundle[] targets)
@@ -3554,13 +3550,13 @@ public class Felix extends BundleImpl im
     {
         try
         {
-            m_resolver.resolve(bundle.getCurrentModule());
+            m_resolver.resolve(bundle.getCurrentRevision());
         }
         catch (ResolveException ex)
         {
-            if (ex.getModule() != null)
+            if (ex.getRevision() != null)
             {
-                Bundle b = ex.getModule().getBundle();
+                Bundle b = ex.getRevision().getBundle();
                 throw new BundleException(
                     "Unresolved constraint in bundle "
                     + b + ": " + ex.getMessage());
@@ -3627,18 +3623,18 @@ public class Felix extends BundleImpl im
         {
             // Create map of bundles that import the packages
             // from the target bundles.
-            Map map = new HashMap();
+            Set<Bundle> set = new HashSet<Bundle>();
             for (int targetIdx = 0; targetIdx < newTargets.length; targetIdx++)
             {
                 // Add the current target bundle to the map of
                 // bundles to be refreshed.
                 BundleImpl target = (BundleImpl) newTargets[targetIdx];
-                map.put(target, target);
+                set.add(target);
                 // Add all importing bundles to map.
-                populateDependentGraph(target, map);
+                populateDependentGraph(target, set);
             }
 
-            bundles = (BundleImpl[]) map.values().toArray(new BundleImpl[map.size()]);
+            bundles = (BundleImpl[]) set.toArray(new BundleImpl[set.size()]);
         }
 
         // Now refresh each bundle.
@@ -3732,23 +3728,23 @@ public class Felix extends BundleImpl im
         fireFrameworkEvent(FrameworkEvent.PACKAGES_REFRESHED, this, null);
     }
 
-    private void populateDependentGraph(BundleImpl exporter, Map map)
+    private void populateDependentGraph(BundleImpl exporter, Set<Bundle> set)
     {
         // Get all dependent bundles of this bundle.
-        List<Bundle> dependents = getDependentBundles(exporter);
+        Set<Bundle> dependents = m_dependencies.getDependentBundles(exporter);
 
-        for (int depIdx = 0;
-            (dependents != null) && (depIdx < dependents.size());
-            depIdx++)
-        {
-            // Avoid cycles if the bundle is already in map.
-            if (!map.containsKey(dependents.get(depIdx)))
-            {
-                // Add each importing bundle to map.
-                map.put(dependents.get(depIdx), dependents.get(depIdx));
-                // Now recurse into each bundle to get its importers.
-                populateDependentGraph(
-                    (BundleImpl) dependents.get(depIdx), map);
+        if (dependents != null)
+        {
+            for (Bundle b : dependents)
+            {
+                // Avoid cycles if the bundle is already in set.
+                if (!set.contains(b))
+                {
+                    // Add each dependent bundle to set.
+                    set.add(b);
+                    // Now recurse into each bundle to get its dependents.
+                    populateDependentGraph((BundleImpl) b, set);
+                }
             }
         }
     }
@@ -3796,7 +3792,7 @@ public class Felix extends BundleImpl im
 
         // Get the activator class from the header map.
         BundleActivator activator = null;
-        Map headerMap = impl.getCurrentModule().getHeaders();
+        Map headerMap = ((BundleRevisionImpl) impl.getCurrentRevision()).getHeaders();
         String className = (String) headerMap.get(Constants.BUNDLE_ACTIVATOR);
         // Try to instantiate activator class if present.
         if (className != null)
@@ -3805,7 +3801,8 @@ public class Felix extends BundleImpl im
             Class clazz;
             try
             {
-                clazz = impl.getCurrentModule().getClassByDelegation(className);
+                clazz = ((BundleWiringImpl)
+                    impl.getCurrentRevision().getWiring()).getClassByDelegation(className);
             }
             catch (ClassNotFoundException ex)
             {
@@ -3834,6 +3831,8 @@ public class Felix extends BundleImpl im
         {
             // See if we need to fire UNRESOLVED event.
             boolean fire = (bundle.getState() != Bundle.INSTALLED);
+            // Remove dependencies.
+            m_dependencies.removeDependencies(bundle);
             // Reset the bundle object.
             ((BundleImpl) bundle).refresh();
             // Fire UNRESOLVED event if necessary
@@ -4103,42 +4102,44 @@ public class Felix extends BundleImpl im
             m_resolverState = resolverState;
         }
 
-        void addModule(Module m)
+        void addRevision(BundleRevision br)
         {
-            m_resolverState.addModule(m);
+            m_resolverState.addRevision(br);
         }
 
-        void removeModule(Module m)
+        void removeRevision(BundleRevision br)
         {
-            m_resolverState.removeModule(m);
+            m_resolverState.removeRevision(br);
         }
 
-        Set<Capability> getCandidates(Requirement req, boolean obeyMandatory)
+        Set<BundleCapability> getCandidates(BundleRequirementImpl req, boolean obeyMandatory)
         {
             return m_resolverState.getCandidates(req, obeyMandatory);
         }
 
-        void resolve(Module rootModule) throws ResolveException
+        void resolve(BundleRevision rootRevision) throws ResolveException
         {
             // Although there is a race condition to check the bundle state
             // then lock it, we do this because we don't want to acquire the
-            // a lock just to check if the module is resolved, which itself
-            // is a safe read. If the module isn't resolved, we end up double
+            // a lock just to check if the revision is resolved, which itself
+            // is a safe read. If the revision isn't resolved, we end up double
             // check the resolved status later.
-            if (!rootModule.isResolved())
+// TODO: OSGi R4.3 - This locking strategy here depends on how we ultimately
+//       implement getWiring(), which may change.
+            if (rootRevision.getWiring() == null)
             {
                 // Acquire global lock.
                 boolean locked = acquireGlobalLock();
                 if (!locked)
                 {
                     throw new ResolveException(
-                        "Unable to acquire global lock for resolve.", rootModule, null);
+                        "Unable to acquire global lock for resolve.", rootRevision, null);
                 }
 
-                Map<Module, List<Wire>> wireMap = null;
+                Map<BundleRevision, List<ResolverWire>> wireMap = null;
                 try
                 {
-                    BundleImpl bundle = (BundleImpl) rootModule.getBundle();
+                    BundleImpl bundle = (BundleImpl) rootRevision.getBundle();
 
                     // Extensions are resolved differently.
                     if (bundle.isExtension())
@@ -4146,12 +4147,12 @@ public class Felix extends BundleImpl im
                         return;
                     }
 
-                    // Resolve the module.
+                    // Resolve the revision.
                     wireMap = m_resolver.resolve(
-                        m_resolverState, rootModule, m_resolverState.getFragments());
+                        m_resolverState, rootRevision, m_resolverState.getFragments());
 
-                    // Mark all modules as resolved.
-                    markResolvedModules(wireMap);
+                    // Mark all revisions as resolved.
+                    markResolvedRevisions(wireMap);
                 }
                 finally
                 {
@@ -4163,61 +4164,72 @@ public class Felix extends BundleImpl im
             }
         }
 
-        Wire resolve(Module module, String pkgName) throws ResolveException
+        BundleRevision resolve(BundleRevision revision, String pkgName)
+            throws ResolveException
         {
-            Wire candidateWire = null;
-            // We cannot dynamically import if the module is not already resolved
+            BundleRevision provider = null;
+
+            // We cannot dynamically import if the revision 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 (module.isResolved() && isAllowedDynamicImport(module, pkgName))
+            if ((revision.getWiring() != null) && isAllowedDynamicImport(revision, pkgName))
             {
                 // Acquire global lock.
                 boolean locked = acquireGlobalLock();
                 if (!locked)
                 {
                     throw new ResolveException(
-                        "Unable to acquire global lock for resolve.", module, null);
+                        "Unable to acquire global lock for resolve.", revision, null);
                 }
 
-                Map<Module, List<Wire>> wireMap = null;
+                Map<BundleRevision, List<ResolverWire>> wireMap = null;
                 try
                 {
                     // Double check to make sure that someone hasn't beaten us to
                     // 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.
-                    List<Wire> wires = module.getWires();
-                    for (int i = 0; (wires != null) && (i < wires.size()); i++)
-                    {
-                        if (wires.get(i).hasPackage(pkgName))
-                        {
-                            return wires.get(i);
-                        }
-                    }
+                    provider = ((BundleWiringImpl) revision.getWiring())
+                        .getImportedPackageSource(pkgName);
+                    if (provider == null)
+                    {
+                        wireMap = m_resolver.resolve(
+                            m_resolverState, revision, pkgName,
+                            m_resolverState.getFragments());
 
-                    wireMap = m_resolver.resolve(
-                        m_resolverState, module, pkgName, m_resolverState.getFragments());
+                        if ((wireMap != null) && wireMap.containsKey(revision))
+                        {
+                            List<ResolverWire> dynamicWires = wireMap.remove(revision);
+                            ResolverWire dynamicWire = dynamicWires.get(0);
 
-                    if ((wireMap != null) && wireMap.containsKey(module))
-                    {
-                        List<Wire> dynamicWires = wireMap.remove(module);
-                        candidateWire = dynamicWires.get(0);
+                            // Mark all revisions as resolved.
+                            markResolvedRevisions(wireMap);
 
-                        // Mark all modules as resolved.
-                        markResolvedModules(wireMap);
+                            // Dynamically add new wire to importing revision.
+                            if (dynamicWire != null)
+                            {
+                                m_dependencies.addDependent(
+                                    dynamicWire.getProvider(),
+                                    dynamicWire.getCapability(),
+                                    revision);
+
+                                ((BundleWiringImpl) revision.getWiring())
+                                    .addDynamicWire(
+                                        new BundleWireImpl(
+                                            dynamicWire.getRequirer(),
+                                            dynamicWire.getRequirement(),
+                                            dynamicWire.getProvider(),
+                                            dynamicWire.getCapability()));
+
+                                m_logger.log(
+                                    Logger.LOG_DEBUG,
+                                    "DYNAMIC WIRE: " + dynamicWire);
 
-                        // Dynamically add new wire to importing module.
-                        if (candidateWire != null)
-                        {
-                            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));
+                                provider = ((BundleWiringImpl) revision.getWiring())
+                                    .getImportedPackageSource(pkgName);
+                            }
                         }
                     }
                 }
@@ -4230,64 +4242,63 @@ public class Felix extends BundleImpl im
                 fireResolvedEvents(wireMap);
             }
 
-            return candidateWire;
+            return provider;
         }
 
         // This method duplicates a lot of logic from:
         // ResolverImpl.getDynamicImportCandidates()
-        boolean isAllowedDynamicImport(Module module, String pkgName)
+        boolean isAllowedDynamicImport(BundleRevision revision, String pkgName)
         {
-            // Unresolved modules cannot dynamically import, nor can the default
+            // Unresolved revisions cannot dynamically import, nor can the default
             // package be dynamically imported.
-            if (!module.isResolved() || pkgName.length() == 0)
+            if ((revision.getWiring() == null) || pkgName.length() == 0)
             {
                 return false;
             }
 
-            // If the module doesn't have dynamic imports, then just return
+            // If the revision doesn't have dynamic imports, then just return
             // immediately.
-            List<Requirement> dynamics = module.getDynamicRequirements();
+            List<BundleRequirement> dynamics =
+                Util.getDynamicRequirements(revision.getWiring().getRequirements(null));
             if ((dynamics == null) || dynamics.isEmpty())
             {
                 return false;
             }
 
-            // If any of the module exports this package, then we cannot
+            // If the revision 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++)
+            for (BundleCapability cap : revision.getWiring().getCapabilities(null))
             {
-                if (caps.get(i).getNamespace().equals(Capability.PACKAGE_NAMESPACE)
-                    && caps.get(i).getAttribute(Capability.PACKAGE_ATTR).getValue().equals(pkgName))
+                if (cap.getNamespace().equals(BundleCapabilityImpl.PACKAGE_NAMESPACE)
+                    && cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR).equals(pkgName))
                 {
                     return false;
                 }
             }
-            // 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 this revision already imports or requires this package, then
+            // we cannot dynamically import it.
+            if (((BundleWiringImpl) revision.getWiring()).hasPackageSource(pkgName))
             {
-                if (wires.get(i).hasPackage(pkgName))
-                {
-                    return false;
-                }
+                return false;
             }
 
             // 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 = Collections.EMPTY_LIST;
-            List<Attribute> attrs = new ArrayList(1);
-            attrs.add(new Attribute(Capability.PACKAGE_ATTR, pkgName, false));
-            Requirement req = new RequirementImpl(
-                module, Capability.PACKAGE_NAMESPACE, dirs, attrs);
-            Set<Capability> candidates = m_resolverState.getCandidates(req, false);
+            Map<String, Object> attrs = new HashMap(1);
+            attrs.put(BundleCapabilityImpl.PACKAGE_ATTR, pkgName);
+            BundleRequirementImpl req = new BundleRequirementImpl(
+                revision,
+                BundleCapabilityImpl.PACKAGE_NAMESPACE,
+                Collections.EMPTY_MAP,
+                attrs);
+            Set<BundleCapability> candidates = m_resolverState.getCandidates(req, false);
 
             return !candidates.isEmpty();
         }
 
-        private void markResolvedModules(Map<Module, List<Wire>> wireMap)
+        private void markResolvedRevisions(Map<BundleRevision, List<ResolverWire>> wireMap)
             throws ResolveException
         {
 // DO THIS IN THREE PASSES:
@@ -4299,145 +4310,194 @@ public class Felix extends BundleImpl im
             {
                 // First pass: Loop through the wire map to find the host wires
                 // for any fragments and map a host to all of its fragments.
-                Map<Module, List<Module>> hosts = new HashMap<Module, List<Module>>();
-                for (Entry<Module, List<Wire>> entry : wireMap.entrySet())
+                Map<BundleRevision, List<BundleRevision>> hosts =
+                    new HashMap<BundleRevision, List<BundleRevision>>();
+                for (Entry<BundleRevision, List<ResolverWire>> entry : wireMap.entrySet())
                 {
-                    Module module = entry.getKey();
-                    List<Wire> wires = entry.getValue();
+                    BundleRevision revision = entry.getKey();
+                    List<ResolverWire> wires = entry.getValue();
 
-                    if (Util.isFragment(module))
+                    if (Util.isFragment(revision))
                     {
-                        for (Iterator<Wire> itWires = wires.iterator(); itWires.hasNext(); )
+                        for (Iterator<ResolverWire> itWires = wires.iterator();
+                            itWires.hasNext(); )
                         {
-                            Wire w = itWires.next();
-                            List<Module> fragments = hosts.get(w.getExporter());
+                            ResolverWire w = itWires.next();
+                            List<BundleRevision> fragments = hosts.get(w.getProvider());
                             if (fragments == null)
                             {
-                                fragments = new ArrayList<Module>();
-                                hosts.put(w.getExporter(), fragments);
+                                fragments = new ArrayList<BundleRevision>();
+                                hosts.put(w.getProvider(), fragments);
                             }
-                            fragments.add(w.getImporter());
+                            fragments.add(w.getRequirer());
                         }
                     }
                 }
 
-                // Second pass: Loop through the wire map to set wires and attach
-                // fragments, if any.
-                for (Entry<Module, List<Wire>> entry : wireMap.entrySet())
-                {
-                    Module module = entry.getKey();
-                    List<Wire> wires = entry.getValue();
+                // Second pass: Loop through the wire map to do three things:
+                // 1) convert resolver wires to bundle wires 2) create wiring
+                // objects for revisions and 3) record dependencies among
+                // revisions. We don't actually set the wirings here because
+                // that indicates that a revision is resolved and we don't want
+                // to mark anything as resolved unless we succussfully create
+                // all wirings.
+                Map<BundleRevision, BundleWiringImpl> wirings =
+                    new HashMap<BundleRevision, BundleWiringImpl>(wireMap.size());
+                for (Entry<BundleRevision, List<ResolverWire>> entry : wireMap.entrySet())
+                {
+                    BundleRevision revision = entry.getKey();
+                    List<ResolverWire> resolverWires = entry.getValue();
+
+                    List<BundleWire> bundleWires =
+                        new ArrayList<BundleWire>(resolverWires.size());
+
+                    // Loop through resolver wires to calculate the package
+                    // space implied by the wires as well as to record the
+                    // dependencies.
+                    Map<String, BundleRevision> importedPkgs =
+                        new HashMap<String, BundleRevision>();
+                    Map<String, List<BundleRevision>> requiredPkgs =
+                        new HashMap<String, List<BundleRevision>>();
+                    for (ResolverWire rw : resolverWires)
+                    {
+                        bundleWires.add(
+                            new BundleWireImpl(
+                                rw.getRequirer(),
+                                rw.getRequirement(),
+                                rw.getProvider(),
+                                rw.getCapability()));
 
-// TODO: FRAGMENT RESOLVER - Better way to handle log level?
-                    for (Iterator<Wire> itWires = wires.iterator(); itWires.hasNext(); )
-                    {
-                        Wire w = itWires.next();
-                        if (!Util.isFragment(module))
-                        {
-                            m_logger.log(Logger.LOG_DEBUG, "WIRE: " + w);
-                        }
-                        else
+                        m_dependencies.addDependent(
+                            rw.getProvider(), rw.getCapability(), rw.getRequirer());
+
+                        if (Util.isFragment(revision))
                         {
                             m_logger.log(
                                 Logger.LOG_DEBUG,
                                 "FRAGMENT WIRE: "
-                                + module + " -> hosted by -> " + w.getExporter());
-                        }
-                    }
-
-                    // Set the module's wires. If the module is a resolved
-                    // fragment, then we must actually append any new host
-                    // wires to the existing ones.
-                    if (Util.isFragment(module) && module.isResolved())
-                    {
-                        wires.addAll(module.getWires());
-                    }
-                    ((ModuleImpl) module).setWires(wires);
-
-                    // Attach fragments, if any.
-                    List<Module> fragments = hosts.get(module);
-                    if (fragments != null)
-                    {
-                        try
-                        {
-                            ((ModuleImpl) module).attachFragments(fragments);
+                                + this + " -> hosted by -> " + rw.getProvider());
                         }
-                        catch (Exception ex)
+                        else
                         {
-                            // This is a fatal error, so undo everything and
-                            // throw an exception.
-                            for (Entry<Module, List<Wire>> reentry : wireMap.entrySet())
-                            {
-                                module = reentry.getKey();
-
-                                // Undo wires.
-                                ((ModuleImpl) module).setWires(null);
+                            m_logger.log(Logger.LOG_DEBUG, "WIRE: " + rw);
 
-                                fragments = hosts.get(module);
-                                if (fragments != null)
+                            if (rw.getCapability().getNamespace()
+                                .equals(BundleCapabilityImpl.PACKAGE_NAMESPACE))
+                            {
+                                importedPkgs.put(
+                                    (String) rw.getCapability().getAttributes()
+                                        .get(BundleCapabilityImpl.PACKAGE_ATTR),
+                                    rw.getProvider());
+                            }
+                            else if (rw.getCapability().getNamespace()
+                                .equals(BundleCapabilityImpl.BUNDLE_NAMESPACE))
+                            {
+                                Set<String> pkgs = calculateExportedAndReexportedPackages(
+                                        rw.getProvider(),
+                                        wireMap,
+                                        new HashSet<String>(),
+                                        new HashSet<BundleRevision>());
+                                for (String pkg : pkgs)
                                 {
-                                    try
+                                    List<BundleRevision> revs = requiredPkgs.get(pkg);
+                                    if (revs == null)
                                     {
-                                        // Undo fragments.
-                                        ((ModuleImpl) module).attachFragments(null);
+                                        revs = new ArrayList<BundleRevision>();
+                                        requiredPkgs.put(pkg, revs);
                                     }
-                                    catch (Exception ex2)
-                                    {
-                                        // We are in big trouble.
-                                        RuntimeException rte = new RuntimeException(
-                                            "Unable to clean up resolver failure.", ex2);
-                                        m_logger.log(
-                                            Logger.LOG_ERROR,
-                                            rte.getMessage(), ex2);
-                                        throw rte;
-                                    }
-
-                                    // Reindex host with no fragments.
-                                    m_resolverState.addModule(module);
+                                    revs.add(rw.getProvider());
                                 }
                             }
+                        }
+                    }
 
-                            ResolveException re = new ResolveException(
-                                "Unable to attach fragments to " + module,
-                                module, null);
-                            re.initCause(ex);
-                            m_logger.log(
-                                Logger.LOG_ERROR,
-                                re.getMessage(), ex);
-                            throw re;
+                    List<BundleRevision> fragments = hosts.get(revision);
+                    try
+                    {
+                        wirings.put(
+                            revision,
+                            new BundleWiringImpl(
+                                m_logger,
+                                m_configMap,
+                                this,
+                                (BundleRevisionImpl) revision,
+                                fragments,
+                                bundleWires,
+                                importedPkgs,
+                                requiredPkgs));
+                    }
+                    catch (Exception ex)
+                    {
+                        // This is a fatal error, so undo everything and
+                        // throw an exception.
+                        for (Entry<BundleRevision, BundleWiringImpl> wiringEntry
+                            : wirings.entrySet())
+                        {
+                            // Dispose of wiring.
+                            try
+                            {
+                                wiringEntry.getValue().dispose();
+                            }
+                            catch (Exception ex2)
+                            {
+                                // We are in big trouble.
+                                RuntimeException rte = new RuntimeException(
+                                    "Unable to clean up resolver failure.", ex2);
+                                m_logger.log(
+                                    Logger.LOG_ERROR,
+                                    rte.getMessage(), ex2);
+                                throw rte;
+                            }
+
+                            // Reindex host with no fragments.
+                            m_resolverState.addRevision(revision);
                         }
 
-                        // Reindex host with attached fragments.
-                        m_resolverState.addModule(module);
+                        ResolveException re = new ResolveException(
+                            "Unable to resolve " + revision,
+                            revision, null);
+                        re.initCause(ex);
+                        m_logger.log(
+                            Logger.LOG_ERROR,
+                            re.getMessage(), ex);
+                        throw re;
                     }
                 }
 
-                // Third pass: Loop through the wire map to mark modules as resolved
+                // Third pass: Loop through the wire map to mark revision as resolved
                 // and update the resolver state.
-                for (Entry<Module, List<Wire>> entry : wireMap.entrySet())
+                for (Entry<BundleRevision, BundleWiringImpl> entry : wirings.entrySet())
                 {
-                    Module module = entry.getKey();
-                    // Mark module as resolved.
-                    ((ModuleImpl) module).setResolved();
+                    BundleRevisionImpl revision = (BundleRevisionImpl) entry.getKey();
+
+                    // Mark revision as resolved.
+                    revision.resolve(entry.getValue());
+                    
                     // Update resolver state to remove substituted capabilities.
-                    if (!Util.isFragment(module))
+                    if (!Util.isFragment(revision))
                     {
-                        m_resolverState.removeSubstitutedCapabilities(module);
+                        // Update resolver state by reindexing host with attached
+                        // fragments and removing any substituted exports.
+// TODO: OSGi R4.3 - We could avoid reindexing for fragments if we check it
+//       the revision has fragments or not.
+                        m_resolverState.addRevision(revision);
+                        m_resolverState.removeSubstitutedCapabilities(revision);
                     }
-                    // Update the state of the module's bundle to resolved as well.
-                    markBundleResolved(module);
+
+                    // Update the state of the revision's bundle to resolved as well.
+                    markBundleResolved(revision);
                 }
             }
         }
 
-        private void markBundleResolved(Module module)
+        private void markBundleResolved(BundleRevision revision)
         {
             // Update the bundle's state to resolved when the
-            // current module is resolved; just ignore resolve
+            // current revision is resolved; just ignore resolve
             // events for older revisions since this only occurs
             // when an update is done on an unresolved bundle
             // and there was no refresh performed.
-            BundleImpl bundle = (BundleImpl) module.getBundle();
+            BundleImpl bundle = (BundleImpl) revision.getBundle();
 
             // Lock the bundle first.
             try
@@ -4451,7 +4511,7 @@ public class Felix extends BundleImpl im
                 {
                     // There is nothing we can do.
                 }
-                if (bundle.getCurrentModule() == module)
+                if (bundle.getCurrentRevision() == revision)
                 {
                     if (bundle.getState() != Bundle.INSTALLED)
                     {
@@ -4471,29 +4531,97 @@ public class Felix extends BundleImpl im
             }
         }
 
-        private void fireResolvedEvents(Map<Module, List<Wire>> wireMap)
+        private void fireResolvedEvents(Map<BundleRevision, List<ResolverWire>> wireMap)
         {
             if (wireMap != null)
             {
-                Iterator<Entry<Module, List<Wire>>> iter = wireMap.entrySet().iterator();
+                Iterator<Entry<BundleRevision, List<ResolverWire>>> iter = wireMap.entrySet().iterator();
                 // Iterate over the map to fire necessary RESOLVED events.
                 while (iter.hasNext())
                 {
-                    Entry<Module, List<Wire>> entry = iter.next();
-                    Module module = entry.getKey();
+                    Entry<BundleRevision, List<ResolverWire>> entry = iter.next();
+                    BundleRevision revision = entry.getKey();
 
                     // Fire RESOLVED events for all fragments.
-                    List<Module> fragments = ((ModuleImpl) module).getFragments();
+                    List<BundleRevision> fragments =
+                        ((BundleWiringImpl) revision.getWiring()).getFragments();
                     for (int i = 0; (fragments != null) && (i < fragments.size()); i++)
                     {
                         fireBundleEvent(BundleEvent.RESOLVED, fragments.get(i).getBundle());
                     }
-                    fireBundleEvent(BundleEvent.RESOLVED, module.getBundle());
+                    fireBundleEvent(BundleEvent.RESOLVED, revision.getBundle());
                 }
             }
         }
     }
 
+    private static Set<String> calculateExportedAndReexportedPackages(
+        BundleRevision br,
+        Map<BundleRevision, List<ResolverWire>> wireMap,
+        Set<String> pkgs,
+        Set<BundleRevision> cycles)
+    {
+        if (!cycles.contains(br))
+        {
+            cycles.add(br);
+
+            // Add all exported packages.
+            for (BundleCapability cap : br.getDeclaredCapabilities(null))
+            {
+                if (cap.getNamespace().equals(BundleCapabilityImpl.PACKAGE_NAMESPACE))
+                {
+                    pkgs.add((String)
+                        cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR));
+                }
+            }
+
+            // Now check to see if any required bundles are required with reexport
+            // visibility, since we need to include those packages too.
+            if (br.getWiring() == null)
+            {
+                for (ResolverWire rw : wireMap.get(br))
+                {
+                    if (rw.getCapability().getNamespace().equals(
+                        BundleCapabilityImpl.BUNDLE_NAMESPACE))
+                    {
+                        String dir = rw.getRequirement()
+                            .getDirectives().get(Constants.VISIBILITY_DIRECTIVE);
+                        if ((dir != null) && (dir.equals(Constants.VISIBILITY_REEXPORT)))
+                        {
+                            calculateExportedAndReexportedPackages(
+                                rw.getProvider(),
+                                wireMap,
+                                pkgs,
+                                cycles);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for (BundleWire bw : br.getWiring().getRequiredWires(null))
+                {
+                    if (bw.getCapability().getNamespace().equals(
+                        BundleCapabilityImpl.BUNDLE_NAMESPACE))
+                    {
+                        String dir = bw.getRequirement()
+                            .getDirectives().get(Constants.VISIBILITY_DIRECTIVE);
+                        if ((dir != null) && (dir.equals(Constants.VISIBILITY_REEXPORT)))
+                        {
+                            calculateExportedAndReexportedPackages(
+                                bw.getProviderWiring().getRevision(),
+                                wireMap,
+                                pkgs,
+                                cycles);
+                        }
+                    }
+                }
+            }
+        }
+
+        return pkgs;
+    }
+
     class SystemBundleActivator implements BundleActivator
     {
         public void start(BundleContext context) throws Exception
@@ -4682,14 +4810,16 @@ public class Felix extends BundleImpl im
                 // current state.
                 if (m_bundle.getState() == Bundle.UNINSTALLED)
                 {
+                    // Remove dependencies.
+                    m_dependencies.removeDependencies(m_bundle);
                     m_bundle.closeAndDelete();
                     m_bundle = null;
                 }
                 else
                 {
-                    // This removes all old bundle modules from memory and
-                    // all old revisions from disk. It only maintains the
-                    // newest version in the bundle cache.
+                    // This removes all old bundle revisions from memory and
+                    // from disk. It only maintains the newest revision in the
+                    // bundle cache.
                     refreshBundle(m_bundle);
                 }
             }

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/FilterImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/FilterImpl.java?rev=1104564&r1=1104563&r2=1104564&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/FilterImpl.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/FilterImpl.java Tue May 17 21:20:32 2011
@@ -18,20 +18,23 @@
  */
 package org.apache.felix.framework;
 
-import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.List;
-import org.apache.felix.framework.capabilityset.Attribute;
-import org.apache.felix.framework.capabilityset.Capability;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import org.apache.felix.framework.ServiceRegistrationImpl.ServiceReferenceImpl;
 import org.apache.felix.framework.capabilityset.CapabilitySet;
-import org.apache.felix.framework.capabilityset.Directive;
 import org.apache.felix.framework.capabilityset.SimpleFilter;
-import org.apache.felix.framework.resolver.Module;
 import org.apache.felix.framework.util.StringMap;
+import org.apache.felix.framework.wiring.BundleCapabilityImpl;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.wiring.BundleRevision;
 
 public class FilterImpl implements Filter
 {
@@ -51,19 +54,24 @@ public class FilterImpl implements Filte
 
     public boolean match(ServiceReference sr)
     {
-        return CapabilitySet.matches(new ServiceReferenceCapability(sr), m_filter);
+        return CapabilitySet.matches((ServiceReferenceImpl) sr, m_filter);
     }
 
-    public boolean match(Dictionary dctnr)
+    public boolean match(Dictionary<String, ? > dctnr)
     {
         return CapabilitySet.matches(new DictionaryCapability(dctnr, false), m_filter);
     }
 
-    public boolean matchCase(Dictionary dctnr)
+    public boolean matchCase(Dictionary<String, ? > dctnr)
     {
         return CapabilitySet.matches(new DictionaryCapability(dctnr, true), m_filter);
     }
 
+    public boolean matches(Map<String, ?> map)
+    {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
     public boolean equals(Object o)
     {
         return toString().equals(o.toString());
@@ -79,12 +87,53 @@ public class FilterImpl implements Filte
         return m_filter.toString();
     }
 
-    static class DictionaryCapability implements Capability
+    static class DictionaryCapability extends BundleCapabilityImpl
+    {
+        private final Map m_map;
+
+        public DictionaryCapability(Dictionary dict, boolean caseSensitive)
+        {
+            super(null, null, Collections.EMPTY_MAP, Collections.EMPTY_MAP);
+            m_map = new DictionaryMap(dict, caseSensitive);
+        }
+
+        @Override
+        public BundleRevision getRevision()
+        {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public String getNamespace()
+        {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public Map<String, String> getDirectives()
+        {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public Map<String, Object> getAttributes()
+        {
+            return m_map;
+        }
+
+        @Override
+        public List<String> getUses()
+        {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+    }
+
+    private static class DictionaryMap implements Map
     {
         private final StringMap m_map;
         private final Dictionary m_dict;
 
-        public DictionaryCapability(Dictionary dict, boolean caseSensitive)
+        public DictionaryMap(Dictionary dict, boolean caseSensitive)
         {
             m_dict = dict;
             if (!caseSensitive)
@@ -114,29 +163,29 @@ public class FilterImpl implements Filte
             }
         }
 
-        public Module getModule()
+        public int size()
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public String getNamespace()
+        public boolean isEmpty()
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public Directive getDirective(String name)
+        public boolean containsKey(Object o)
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public List<Directive> getDirectives()
+        public boolean containsValue(Object o)
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public Attribute getAttribute(String name)
+        public Object get(Object o)
         {
-            String key = name;
+            String key = (String) o;
             Object value = null;
             if (m_dict != null)
             {
@@ -145,7 +194,7 @@ public class FilterImpl implements Filte
                 // the key.
                 if (m_map != null)
                 {
-                    key = (String) m_map.get(name);
+                    key = (String) m_map.get(o);
                 }
                 // If the key could not be found in the case insensitive
                 // key map, then avoid doing the dictionary lookup on it.
@@ -154,63 +203,42 @@ public class FilterImpl implements Filte
                     value = m_dict.get(key);
                 }
             }
-            return (value == null) ? null : new Attribute(key, value, false);
-        }
-
-        public List<Attribute> getAttributes()
-        {
-            return new ArrayList();
+            return value;
         }
 
-        public List<String> getUses()
+        public Object put(Object k, Object v)
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
-    }
 
-    static class ServiceReferenceCapability implements Capability
-    {
-        private final ServiceReference m_sr;
-
-        public ServiceReferenceCapability(ServiceReference sr)
-        {
-            m_sr = sr;
-        }
-
-        public Module getModule()
+        public Object remove(Object o)
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public String getNamespace()
+        public void putAll(Map map)
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public Directive getDirective(String name)
+        public void clear()
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public List<Directive> getDirectives()
+        public Set<Object> keySet()
         {
             throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public Attribute getAttribute(String name)
+        public Collection<Object> values()
         {
-            Object value = m_sr.getProperty(name);
-            return (value == null) ? null : new Attribute(name, value, false);
-        }
-
-        public List<Attribute> getAttributes()
-        {
-            return new ArrayList();
+            throw new UnsupportedOperationException("Not supported yet.");
         }
 
-        public List<String> getUses()
+        public Set<Entry<Object, Object>> entrySet()
         {
-            throw new UnsupportedOperationException("Not supported yet.");
+            return Collections.EMPTY_SET;
         }
     }
-}
+}
\ No newline at end of file

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java?rev=1104564&r1=1104563&r2=1104564&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java Tue May 17 21:20:32 2011
@@ -19,14 +19,14 @@
 package org.apache.felix.framework;
 
 import java.util.*;
-import org.apache.felix.framework.resolver.Module;
-import org.apache.felix.framework.resolver.Wire;
 import org.apache.felix.framework.util.VersionRange;
 import org.osgi.framework.AdminPermission;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWire;
 import org.osgi.service.packageadmin.ExportedPackage;
 import org.osgi.service.packageadmin.PackageAdmin;
 import org.osgi.service.packageadmin.RequiredBundle;
@@ -114,7 +114,7 @@ class PackageAdminImpl implements Packag
             String sym = bundles[i].getSymbolicName();
             if ((sym != null) && sym.equals(symbolicName))
             {
-                Version v = ((BundleImpl) bundles[i]).getCurrentModule().getVersion();
+                Version v = ((BundleImpl) bundles[i]).getCurrentRevision().getVersion();
                 if ((vr == null) || vr.isInRange(v))
                 {
                     list.add(bundles[i]);
@@ -129,8 +129,8 @@ class PackageAdminImpl implements Packag
         Arrays.sort(bundles,new Comparator() {
             public int compare(Object o1, Object o2)
             {
-                Version v1 = ((BundleImpl) o1).getCurrentModule().getVersion();
-                Version v2 = ((BundleImpl) o2).getCurrentModule().getVersion();
+                Version v1 = ((BundleImpl) o1).getCurrentRevision().getVersion();
+                Version v2 = ((BundleImpl) o2).getCurrentRevision().getVersion();
                 // Compare in reverse order to get descending sort.
                 return v2.compareTo(v1);
             }
@@ -140,7 +140,8 @@ class PackageAdminImpl implements Packag
 
     public int getBundleType(Bundle bundle)
     {
-        Map headerMap = ((BundleImpl) bundle).getCurrentModule().getHeaders();
+        Map headerMap = ((BundleRevisionImpl)
+            ((BundleImpl) bundle).getCurrentRevision()).getHeaders();
         if (headerMap.containsKey(Constants.FRAGMENT_HOST))
         {
             return PackageAdmin.BUNDLE_TYPE_FRAGMENT;
@@ -195,15 +196,14 @@ class PackageAdminImpl implements Packag
         if ((getBundleType(bundle) & BUNDLE_TYPE_FRAGMENT) == 0)
         {
             List<Bundle> list = new ArrayList<Bundle>();
-            // Iterate through modules
-            List<Module> modules = ((BundleImpl) bundle).getModules();
-            for (int modIdx = 0; modIdx < modules.size(); modIdx++)
+            // Iterate through revisions
+            for (BundleRevision revision : ((BundleImpl) bundle).getRevisions())
             {
                 // Get attached fragments.
-                ModuleImpl module = (ModuleImpl) modules.get(modIdx);
-                if (module.isResolved())
+                if (revision.getWiring() != null)
                 {
-                    List<Module> fragments = module.getFragments();
+                    List<BundleRevision> fragments =
+                        ((BundleWiringImpl) revision.getWiring()).getFragments();
                     for (int i = 0; (fragments != null) && (i < fragments.size()); i++)
                     {
                         Bundle b = fragments.get(i).getBundle();
@@ -215,7 +215,7 @@ class PackageAdminImpl implements Packag
                 }
             }
             // Convert list to an array.
-            return (list.size() == 0)
+            return (list.isEmpty())
                 ? null
                 : (Bundle[]) list.toArray(new Bundle[list.size()]);
         }
@@ -228,18 +228,16 @@ class PackageAdminImpl implements Packag
         if ((getBundleType(bundle) & BUNDLE_TYPE_FRAGMENT) != 0)
         {
             List<Bundle> list = new ArrayList<Bundle>();
-            // Iterate through modules
-            List<Module> modules = ((BundleImpl) bundle).getModules();
-            for (int modIdx = 0; modIdx < modules.size(); modIdx++)
+            // Iterate through revisions
+            for (BundleRevision revision : ((BundleImpl) bundle).getRevisions())
             {
                 // Get hosts
-                ModuleImpl module = (ModuleImpl) modules.get(modIdx);
-                if (module.isResolved())
+                if (revision.getWiring() != null)
                 {
-                    List<Wire> hostWires = module.getWires();
+                    List<BundleWire> hostWires = revision.getWiring().getRequiredWires(null);
                     for (int i = 0; (hostWires != null) && (i < hostWires.size()); i++)
                     {
-                        Bundle b = hostWires.get(i).getExporter().getBundle();
+                        Bundle b = hostWires.get(i).getProviderWiring().getBundle();
                         if (b != null)
                         {
                             list.add(b);
@@ -258,17 +256,15 @@ class PackageAdminImpl implements Packag
     public RequiredBundle[] getRequiredBundles(String symbolicName)
     {
         List list = new ArrayList();
-        Bundle[] bundles = m_felix.getBundles();
-        for (int i = 0; i < bundles.length; i++)
+        for (Bundle bundle : m_felix.getBundles())
         {
-            BundleImpl impl = (BundleImpl) bundles[i];
             if ((symbolicName == null)
-                || (symbolicName.equals(impl.getCurrentModule().getSymbolicName())))
+                || (symbolicName.equals(bundle.getSymbolicName())))
             {
-                list.add(new RequiredBundleImpl(m_felix, impl));
+                list.add(new RequiredBundleImpl(m_felix, (BundleImpl) bundle));
             }
         }
-        return (list.size() == 0)
+        return (list.isEmpty())
             ? null
             : (RequiredBundle[]) list.toArray(new RequiredBundle[list.size()]);
     }

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/RequiredBundleImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/RequiredBundleImpl.java?rev=1104564&r1=1104563&r2=1104564&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/RequiredBundleImpl.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/RequiredBundleImpl.java Tue May 17 21:20:32 2011
@@ -18,10 +18,7 @@
  */
 package org.apache.felix.framework;
 
-import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
-import org.apache.felix.framework.resolver.Module;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Version;
 import org.osgi.service.packageadmin.RequiredBundle;
@@ -51,38 +48,18 @@ class RequiredBundleImpl implements Requ
 
     public Bundle[] getRequiringBundles()
     {
-        // Spec says to return null for stale bundles.
+        // If the package is stale, then return null per the spec.
         if (m_bundle.isStale())
         {
             return null;
         }
-
-        // We need to find all modules that require any of the modules
-        // associated with this bundle and save the associated bundle
-        // of the dependent modules.
-        Set bundleSet = new HashSet();
-        // Loop through all of this bundle's modules.
-        List<Module> modules = m_bundle.getModules();
-        for (int modIdx = 0; (modules != null) && (modIdx < modules.size()); modIdx++)
-        {
-            // For each of this bundle's modules, loop through all of the
-            // modules that require it and add them to the module list.
-            List<Module> dependents = ((ModuleImpl) modules.get(modIdx)).getDependentRequirers();
-            for (int depIdx = 0; (dependents != null) && (depIdx < dependents.size()); depIdx++)
-            {
-                if (dependents.get(depIdx).getBundle() != null)
-                {
-                    bundleSet.add(dependents.get(depIdx).getBundle());
-                }
-            }
-        }
-        // Convert to an array.
-        return (Bundle[]) bundleSet.toArray(new Bundle[bundleSet.size()]);
+        Set<Bundle> set = m_felix.getRequiringBundles(m_bundle);
+        return set.toArray(new Bundle[set.size()]);
     }
 
     public Version getVersion()
     {
-        return m_bundle.getCurrentModule().getVersion();
+        return m_bundle.getVersion();
     }
 
     public boolean isRemovalPending()
@@ -95,7 +72,7 @@ class RequiredBundleImpl implements Requ
         if (m_toString == null)
         {
             m_toString = m_bundle.getSymbolicName()
-                + "; version=" + m_bundle.getCurrentModule().getVersion();
+                + "; version=" + m_bundle.getVersion();
         }
         return m_toString;
     }