Major refactoring of module layer. Removed IModuleDefition and IContentLoader,
merged functionality into IModule/ModuleImpl. Removed IModuleFactory. Removed
ISearchPolicy merged functionality into ContentClassLoader, now called
ModuleClassLoader. Merged BundleInfo with BundleImpl, Felix now extends
BundleImpl. Still needs much more clean up. (FELIX-851)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@732800 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
index 2d00d87..b596e6d 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
@@ -29,10 +29,10 @@
 {
     private Logger m_logger = null;
     private Felix m_felix = null;
-    private FelixBundle m_bundle = null;
+    private BundleImpl m_bundle = null;
     private boolean m_valid = true;
 
-    protected BundleContextImpl(Logger logger, Felix felix, FelixBundle bundle)
+    protected BundleContextImpl(Logger logger, Felix felix, BundleImpl bundle)
     {
         m_logger = logger;
         m_felix = felix;
@@ -381,7 +381,7 @@
     {
         if (m_valid)
         {
-            switch (m_bundle.getInfo().getState())
+            switch (m_bundle.getState())
             {
                 case Bundle.ACTIVE:
                 case Bundle.STARTING:
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index 2377933..5ceb622 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -21,45 +21,122 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.security.ProtectionDomain;
 import java.util.*;
 
+import org.apache.felix.framework.cache.BundleArchive;
+import org.apache.felix.framework.searchpolicy.ModuleImpl;
+import org.apache.felix.framework.searchpolicy.URLPolicyImpl;
+import org.apache.felix.framework.util.manifestparser.ManifestParser;
+import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.apache.felix.moduleloader.IModule;
 import org.osgi.framework.*;
 
-class BundleImpl extends FelixBundle
+class BundleImpl implements Bundle
 {
-    private final long m_id;
-    private final Felix m_felix;
-    private volatile RegularBundleInfo m_info = null;
+    private final Felix m_feli;
 
-    protected BundleImpl(Felix felix, RegularBundleInfo info)
+    private final BundleArchive m_archive;
+    private IModule[] m_modules = new IModule[0];
+    private int m_state;
+    private BundleActivator m_activator = null;
+    private BundleContext m_context = null;
+    private final Map m_cachedHeaders = new HashMap();
+    private long m_cachedHeadersTimestamp;
+
+    // Indicates whether the bundle has been updated/uninstalled
+    // and is waiting to be refreshed.
+    private boolean m_removalPending = false;
+    // Indicates whether the bundle is stale, meaning that it has
+    // been refreshed and completely removed from the framework.
+    private boolean m_stale = false;
+
+    // Indicates whether the bundle is an extension, meaning that it is
+    // installed as an extension bundle to the framework (i.e., can not be
+    // removed or updated until a framework restart.
+    private boolean m_extension = false;
+
+    // Used for bundle locking.
+    private int m_lockCount = 0;
+    private Thread m_lockThread = null;
+
+    BundleImpl(Felix felix, BundleArchive archive) throws Exception
     {
-        m_felix = felix;
-        m_info = info;
-        m_id = info.getBundleId();
+        m_feli = felix;
+        m_archive = archive;
+        m_state = Bundle.INSTALLED;
+        m_stale = false;
+        m_activator = null;
+        m_context = null;
+
+        // TODO: REFACTOR - Null check is a hHack due to system bundle.
+        if (m_archive != null)
+        {
+            createAndAddModule();
+        }
     }
 
-    /* package private */ BundleInfo getInfo()
+    // TODO: REFACTOR - We need this method so the system bundle can override it.
+    Felix getFramework()
     {
-        return m_info;
+        return m_feli;
     }
 
-    /*
-     * Only used when refreshing a bundle.
-    **/
-    /* package private */ void setInfo(RegularBundleInfo info)
+    void reset() throws Exception
     {
-        m_info = info;
+        m_modules = new IModule[0];
+        createAndAddModule();
+        m_state = Bundle.INSTALLED;
+        m_stale = false;
+        m_cachedHeaders.clear();
+        m_cachedHeadersTimestamp = 0;
+        m_removalPending = false;
     }
 
-    public BundleContext getBundleContext()
+    // TODO: REFACTOR - This method is sort of a hack. Since the system bundle
+    //       doesn't have an archive, it can override this method to return its
+    //       manifest.
+    Map getCurrentManifestFromArchive() throws Exception
+    {
+        return m_archive.getRevision(
+            m_archive.getRevisionCount() - 1).getManifestHeader();
+    }
+
+    synchronized BundleActivator getActivator()
+    {
+        return m_activator;
+    }
+
+    synchronized void setActivator(BundleActivator activator)
+    {
+        m_activator = activator;
+    }
+
+    public synchronized BundleContext getBundleContext()
     {
 // TODO: SECURITY - We need a security check here.
-        return m_info.getBundleContext();
+        return m_context;
+    }
+
+    synchronized void setBundleContext(BundleContext context)
+    {
+        m_context = context;
     }
 
     public long getBundleId()
     {
-        return m_id;
+        try
+        {
+            return m_archive.getId();
+        }
+        catch (Exception ex)
+        {
+            getFramework().getLogger().log(
+                Logger.LOG_ERROR,
+                "Error getting the identifier from bundle archive.",
+                ex);
+            return -1;
+        }
     }
 
     public URL getEntry(String name)
@@ -79,7 +156,7 @@
             }
         }
 
-        return m_felix.getBundleEntry(this, name);
+        return getFramework().getBundleEntry(this, name);
     }
 
     public Enumeration getEntryPaths(String path)
@@ -99,7 +176,7 @@
             }
         }
 
-        return m_felix.getBundleEntryPaths(this, path);
+        return getFramework().getBundleEntryPaths(this, path);
     }
 
     public Enumeration findEntries(String path, String filePattern, boolean recurse)
@@ -119,7 +196,7 @@
             }
         }
 
-        return m_felix.findBundleEntries(this, path, filePattern, recurse);
+        return getFramework().findBundleEntries(this, path, filePattern, recurse);
     }
 
     public Dictionary getHeaders()
@@ -142,12 +219,161 @@
             locale = Locale.getDefault().toString();
         }
 
-        return m_felix.getBundleHeaders(this, locale);
+        return getFramework().getBundleHeaders(this, locale);
+    }
+
+    Map getCurrentLocalizedHeader(String locale)
+    {
+        synchronized (m_cachedHeaders)
+        {
+            // If the bundle has been updated, clear the cached headers
+            if (getLastModified() > m_cachedHeadersTimestamp)
+            {
+                m_cachedHeaders.clear();
+            }
+            else
+            {
+                // Check if headers for this locale have already been resolved
+                if (m_cachedHeaders.containsKey(locale))
+                {
+                    return (Map) m_cachedHeaders.get(locale);
+                }
+            }
+        }
+
+        Map rawHeaders = getCurrentModule().getHeaders();
+        Map headers = new HashMap(rawHeaders.size());
+        headers.putAll(rawHeaders);
+
+        // Check to see if we actually need to localize anything
+        boolean needsLocalization = false;
+        for (Iterator it = headers.values().iterator(); it.hasNext(); )
+        {
+            if (((String) it.next()).startsWith("%"))
+            {
+                needsLocalization = true;
+                break;
+            }
+        }
+
+        if (!needsLocalization)
+        {
+            // If localization is not needed, just cache the headers and return them as-is
+            // Not sure if this is useful
+            updateHeaderCache(locale, headers);
+            return headers;
+        }
+
+        // Do localization here and return the localized headers
+        String basename = (String) headers.get(Constants.BUNDLE_LOCALIZATION);
+        if (basename == null)
+        {
+            basename = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
+        }
+
+        // Create ordered list of files to load properties from
+        List resourceList = createResourceList(basename, locale);
+
+        // Create a merged props file with all available props for this locale
+        Properties mergedProperties = new Properties();
+        for (Iterator it = resourceList.iterator(); it.hasNext(); )
+        {
+            URL temp = this.getCurrentModule().getResourceFromModule(it.next() + ".properties");
+            if (temp == null)
+            {
+                continue;
+            }
+            try
+            {
+                mergedProperties.load(temp.openConnection().getInputStream());
+            }
+            catch (IOException ex)
+            {
+                // File doesn't exist, just continue loop
+            }
+        }
+
+        // Resolve all localized header entries
+        for (Iterator it = headers.entrySet().iterator(); it.hasNext(); )
+        {
+            Map.Entry entry = (Map.Entry) it.next();
+            String value = (String) entry.getValue();
+            if (value.startsWith("%"))
+            {
+                String newvalue;
+                String key = value.substring(value.indexOf("%") + 1);
+                newvalue = mergedProperties.getProperty(key);
+                if (newvalue==null)
+                {
+                    newvalue = key;
+                }
+                entry.setValue(newvalue);
+            }
+        }
+
+        updateHeaderCache(locale, headers);
+        return headers;
+    }
+
+    private void updateHeaderCache(String locale, Map localizedHeaders)
+    {
+        synchronized (m_cachedHeaders)
+        {
+            m_cachedHeaders.put(locale, localizedHeaders);
+            m_cachedHeadersTimestamp = System.currentTimeMillis();
+        }
+    }
+
+    private List createResourceList(String basename, String locale)
+    {
+        List result = new ArrayList(4);
+
+        StringTokenizer tokens;
+        StringBuffer tempLocale = new StringBuffer(basename);
+
+        result.add(tempLocale.toString());
+
+        if (locale.length() > 0)
+        {
+            tokens = new StringTokenizer(locale, "_");
+            while (tokens.hasMoreTokens())
+            {
+                tempLocale.append("_").append(tokens.nextToken());
+                result.add(tempLocale.toString());
+            }
+        }
+        return result;
     }
 
     public long getLastModified()
     {
-        return m_info.getLastModified();
+        try
+        {
+            return m_archive.getLastModified();
+        }
+        catch (Exception ex)
+        {
+            getFramework().getLogger().log(
+                Logger.LOG_ERROR,
+                "Error reading last modification time from bundle archive.",
+                ex);
+            return 0;
+        }
+    }
+
+    void setLastModified(long l)
+    {
+        try
+        {
+            m_archive.setLastModified(l);
+        }
+        catch (Exception ex)
+        {
+            getFramework().getLogger().log(
+                Logger.LOG_ERROR,
+                "Error writing last modification time to bundle archive.",
+                ex);
+        }
     }
 
     public String getLocation()
@@ -159,7 +385,23 @@
             ((SecurityManager) sm).checkPermission(new AdminPermission(this,
                 AdminPermission.METADATA));
         }
-        return m_felix.getBundleLocation(this);
+        return _getLocation();
+    }
+
+    String _getLocation()
+    {
+        try
+        {
+            return m_archive.getLocation();
+        }
+        catch (Exception ex)
+        {
+            getFramework().getLogger().log(
+                Logger.LOG_ERROR,
+                "Error getting location from bundle archive.",
+                ex);
+            return null;
+        }
     }
 
     /**
@@ -184,7 +426,7 @@
             }
         }
 
-        return m_felix.getBundleResource(this, name);
+        return getFramework().getBundleResource(this, name);
     }
 
     public Enumeration getResources(String name) throws IOException
@@ -204,7 +446,7 @@
             }
         }
 
-        return m_felix.getBundleResources(this, name);
+        return getFramework().getBundleResources(this, name);
     }
 
     /**
@@ -219,7 +461,7 @@
 
         if (sm != null)
         {
-            ServiceReference[] refs = m_felix.getBundleRegisteredServices(this);
+            ServiceReference[] refs = getFramework().getBundleRegisteredServices(this);
 
             if (refs == null)
             {
@@ -228,7 +470,7 @@
 
             List result = new ArrayList();
 
-            for (int i = 0;i < refs.length;i++)
+            for (int i = 0; i < refs.length; i++)
             {
                 String[] objectClass = (String[]) refs[i].getProperty(
                     Constants.OBJECTCLASS);
@@ -238,7 +480,7 @@
                     continue;
                 }
 
-                for (int j = 0;j < objectClass.length;j++)
+                for (int j = 0; j < objectClass.length; j++)
                 {
                     try
                     {
@@ -265,7 +507,7 @@
         }
         else
         {
-            return m_felix.getBundleRegisteredServices(this);
+            return getFramework().getBundleRegisteredServices(this);
         }
     }
 
@@ -275,7 +517,7 @@
 
         if (sm != null)
         {
-            ServiceReference[] refs = m_felix.getBundleServicesInUse(this);
+            ServiceReference[] refs = getFramework().getBundleServicesInUse(this);
 
             if (refs == null)
             {
@@ -284,7 +526,7 @@
 
             List result = new ArrayList();
 
-            for (int i = 0;i < refs.length;i++)
+            for (int i = 0; i < refs.length; i++)
             {
                 String[] objectClass = (String[]) refs[i].getProperty(
                     Constants.OBJECTCLASS);
@@ -294,7 +536,7 @@
                     continue;
                 }
 
-                for (int j = 0;j < objectClass.length;j++)
+                for (int j = 0; j < objectClass.length; j++)
                 {
                     try
                     {
@@ -320,22 +562,143 @@
             return (ServiceReference[]) result.toArray(new ServiceReference[result.size()]);
         }
 
-        return m_felix.getBundleServicesInUse(this);
+        return getFramework().getBundleServicesInUse(this);
     }
 
-    public int getState()
+    public synchronized int getState()
     {
-        return m_info.getState();
+        return m_state;
+    }
+
+    synchronized void setState(int i)
+    {
+        m_state = i;
+    }
+
+    int getPersistentState()
+    {
+        try
+        {
+            return m_archive.getPersistentState();
+        }
+        catch (Exception ex)
+        {
+            getFramework().getLogger().log(
+                Logger.LOG_ERROR,
+                "Error reading persistent state from bundle archive.",
+                ex);
+            return Bundle.INSTALLED;
+        }
+    }
+
+    void setPersistentStateInactive()
+    {
+        try
+        {
+            m_archive.setPersistentState(Bundle.INSTALLED);
+        }
+        catch (Exception ex)
+        {
+            getFramework().getLogger().log(Logger.LOG_ERROR,
+                "Error writing persistent state to bundle archive.",
+                ex);
+        }
+    }
+
+    void setPersistentStateActive()
+    {
+        try
+        {
+            m_archive.setPersistentState(Bundle.ACTIVE);
+        }
+        catch (Exception ex)
+        {
+            getFramework().getLogger().log(
+                Logger.LOG_ERROR,
+                "Error writing persistent state to bundle archive.",
+                ex);
+        }
+    }
+
+    void setPersistentStateUninstalled()
+    {
+        try
+        {
+            m_archive.setPersistentState(Bundle.UNINSTALLED);
+        }
+        catch (Exception ex)
+        {
+            getFramework().getLogger().log(
+                Logger.LOG_ERROR,
+                "Error writing persistent state to bundle archive.",
+                ex);
+        }
+    }
+
+    int getStartLevel(int defaultLevel)
+    {
+        try
+        {
+            return m_archive.getStartLevel();
+        }
+        catch (Exception ex)
+        {
+            getFramework().getLogger().log(
+                Logger.LOG_ERROR,
+                "Error reading start level from bundle archive.",
+                ex);
+            return defaultLevel;
+        }
+    }
+
+    void setStartLevel(int i)
+    {
+        try
+        {
+            m_archive.setStartLevel(i);
+        }
+        catch (Exception ex)
+        {
+            getFramework().getLogger().log(
+                Logger.LOG_ERROR,
+                "Error writing start level to bundle archive.",
+                ex);
+        }
+    }
+
+    synchronized boolean isStale()
+    {
+        return m_stale;
+    }
+
+    synchronized void setStale()
+    {
+        m_stale = true;
+    }
+
+    synchronized boolean isExtension()
+    {
+        return m_extension;
+    }
+
+    synchronized void setExtension(boolean extension)
+    {
+        m_extension = extension;
     }
 
     public String getSymbolicName()
     {
-        return m_info.getSymbolicName();
+        return getCurrentModule().getSymbolicName();
     }
 
     public boolean hasPermission(Object obj)
     {
-        return m_felix.bundleHasPermission(this, obj);
+        return getFramework().bundleHasPermission(this, obj);
+    }
+
+    Object getSignerMatcher()
+    {
+        return getFramework().getSignerMatcher(this);
     }
 
     public Class loadClass(String name) throws ClassNotFoundException
@@ -349,13 +712,13 @@
                 ((SecurityManager) sm).checkPermission(new AdminPermission(this,
                     AdminPermission.CLASS));
             }
-            catch (Exception e)
+            catch (Exception ex)
             {
-                throw new ClassNotFoundException("No permission.", e);
+                throw new ClassNotFoundException("No permission.", ex);
             }
         }
 
-        return m_felix.loadBundleClass(this, name);
+        return getFramework().loadBundleClass(this, name);
     }
 
     public void start() throws BundleException
@@ -379,7 +742,7 @@
                 AdminPermission.EXECUTE));
         }
 
-        m_felix.startBundle(this, ((options & Bundle.START_TRANSIENT) == 0));
+        getFramework().startBundle(this, ((options & Bundle.START_TRANSIENT) == 0));
     }
 
     public void update() throws BundleException
@@ -397,7 +760,7 @@
                 AdminPermission.LIFECYCLE));
         }
 
-        m_felix.updateBundle(this, is);
+        getFramework().updateBundle(this, is);
     }
 
     public void stop() throws BundleException
@@ -415,7 +778,7 @@
                 AdminPermission.EXECUTE));
         }
 
-        m_felix.stopBundle(this, ((options & Bundle.STOP_TRANSIENT) == 0));
+        getFramework().stopBundle(this, ((options & Bundle.STOP_TRANSIENT) == 0));
     }
 
     public void uninstall() throws BundleException
@@ -428,12 +791,12 @@
                 AdminPermission.LIFECYCLE));
         }
 
-        m_felix.uninstallBundle(this);
+        getFramework().uninstallBundle(this);
     }
 
     public String toString()
     {
-        String sym = m_info.getSymbolicName();
+        String sym = getCurrentModule().getSymbolicName();
         if (sym != null)
         {
             return sym + " [" + getBundleId() +"]";
@@ -441,8 +804,250 @@
         return "[" + getBundleId() +"]";
     }
 
-    Object getSignerMatcher()
+    synchronized boolean isRemovalPending()
     {
-        return m_felix.getSignerMatcher(this);
+        return m_removalPending;
+    }
+
+    synchronized void setRemovalPending(boolean removalPending)
+    {
+        m_removalPending = removalPending;
+    }
+
+    //
+    // Module management.
+    //
+
+    /**
+     * Returns an array of all modules associated with the bundle represented by
+     * this <tt>BundleInfo</tt> object. A module in the array corresponds to a
+     * revision of the bundle's JAR file and is ordered from oldest to newest.
+     * Multiple revisions of a bundle JAR file might exist if a bundle is
+     * updated, without refreshing the framework. In this case, exports from
+     * the prior revisions of the bundle JAR file are still offered; the
+     * current revision will be bound to packages from the prior revision,
+     * unless the packages were not offered by the prior revision. There is
+     * no limit on the potential number of bundle JAR file revisions.
+     * @return array of modules corresponding to the bundle JAR file revisions.
+    **/
+    synchronized IModule[] getModules()
+    {
+        return m_modules;
+    }
+
+    /**
+     * Determines if the specified module is associated with this bundle.
+     * @param module the module to determine if it is associate with this bundle.
+     * @return <tt>true</tt> if the specified module is in the array of modules
+     *         associated with this bundle, <tt>false</tt> otherwise.
+    **/
+    synchronized boolean hasModule(IModule module)
+    {
+        for (int i = 0; i < m_modules.length; i++)
+        {
+            if (m_modules[i] == module)
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the newest module, which corresponds to the last module
+     * in the module array.
+     * @return the newest module.
+    **/
+    synchronized IModule getCurrentModule()
+    {
+        return m_modules[m_modules.length - 1];
+    }
+
+    synchronized boolean isUsed()
+    {
+        boolean used = false;
+        for (int i = 0; !used && (i < m_modules.length); i++)
+        {
+            IModule[] dependents = ((ModuleImpl) m_modules[i]).getDependents();
+            for (int j = 0; (dependents != null) && (j < dependents.length) && !used; j++)
+            {
+                if (dependents[j] != m_modules[i])
+                {
+                    used = true;
+                }
+            }
+        }
+        return used;
+    }
+
+    synchronized void revise(String location, InputStream is) throws Exception
+    {
+        // This operation will increase the revision count for the bundle.
+        m_archive.revise(location, is);
+        createAndAddModule();
+    }
+
+    synchronized boolean rollbackRevise() throws Exception
+    {
+        return m_archive.rollbackRevise();
+    }
+
+    // TODO: REFACTOR - Hack for the system bundle.
+    synchronized void addModule(IModule module)
+    {
+        ((ModuleImpl) module).setBundle(this);
+
+        IModule[] dest = new IModule[m_modules.length + 1];
+        System.arraycopy(m_modules, 0, dest, 0, m_modules.length);
+        dest[m_modules.length] = module;
+        m_modules = dest;
+    }
+
+    synchronized void createAndAddModule() throws Exception
+    {
+        // Get and parse the manifest from the most recent revision to
+        // create an associated module for it.
+        Map headerMap = getCurrentManifestFromArchive();
+        ManifestParser mp = new ManifestParser(
+            getFramework().getLogger(), getFramework().getConfig(), headerMap);
+
+        // Verify that the bundle symbolic name and version is unique.
+        if (mp.getManifestVersion().equals("2"))
+        {
+            Version bundleVersion = mp.getBundleVersion();
+            bundleVersion = (bundleVersion == null) ? Version.emptyVersion : bundleVersion;
+            String symName = mp.getSymbolicName();
+
+            Bundle[] bundles = getFramework().getBundles();
+            for (int i = 0; (bundles != null) && (i < bundles.length); i++)
+            {
+                long id = ((BundleImpl) bundles[i]).getBundleId();
+                if (id != getBundleId())
+                {
+                    String sym = bundles[i].getSymbolicName();
+                    Version ver = Version.parseVersion((String) ((BundleImpl) bundles[i])
+                        .getCurrentModule().getHeaders().get(Constants.BUNDLE_VERSION));
+                    if (symName.equals(sym) && bundleVersion.equals(ver))
+                    {
+                        throw new BundleException("Bundle symbolic name and version are not unique: " + sym + ':' + ver);
+                    }
+                }
+            }
+        }
+
+        // Now that we have parsed and verified the module metadata, we
+        // can actually create the module. Note, if this is an extension
+        // bundle it's exports are removed, aince they will be added to
+        // the system bundle directly later on.
+        final int revision = m_archive.getRevisionCount() - 1;
+        IModule module = new ModuleImpl(
+            getFramework().getLogger(),
+            getFramework().getConfig(),
+            getFramework().getResolver(),
+            Long.toString(getBundleId()) + "." + Integer.toString(revision),
+            m_archive.getRevision(revision).getContent(),
+            headerMap,
+// TODO: REFACTOR - Karl, does this work correctly if the module is updated to
+//       an extension bundle or vice versa?
+            (ExtensionManager.isExtensionBundle(headerMap)) ? null : mp.getCapabilities(),
+            mp.getRequirements(),
+            mp.getDynamicRequirements(),
+            mp.getLibraries());
+
+        // Set the content loader's URL policy.
+        module.setURLPolicy(
+// TODO: REFACTOR - SUCKS NEEDING URL POLICY PER MODULE.
+            new URLPolicyImpl(
+                getFramework().getLogger(),
+                getFramework().getBundleStreamHandler(),
+                module));
+
+        // Verify that all native libraries exist in advance; this will
+        // throw an exception if the native library does not exist.
+        // TODO: CACHE - It would be nice if this check could be done
+        //               some place else in the module, perhaps.
+        R4Library[] libs = module.getNativeLibraries();
+        for (int i = 0; (libs != null) && (i < libs.length); i++)
+        {
+            String entryName = libs[i].getEntryName();
+            if (entryName != null)
+            {
+                if (module.getContent().getEntryAsNativeLibrary(entryName) == null)
+                {
+                    throw new BundleException("Native library does not exist: " + entryName);
+// TODO: REFACTOR - We have a memory leak here since we added a module above
+//                  and then don't remove it in case of an error; this may also
+//                  be a general issue for installing/updating bundles, so check.
+//                  This will likely go away when we refactor out the module
+//                  factory, but we will track it under FELIX-835 until then.
+                }
+            }
+        }
+
+        ((ModuleImpl) module).setBundle(this);
+
+        IModule[] dest = new IModule[m_modules.length + 1];
+        System.arraycopy(m_modules, 0, dest, 0, m_modules.length);
+        dest[m_modules.length] = module;
+        m_modules = dest;
+    }
+
+    void setProtectionDomain(ProtectionDomain pd)
+    {
+        getCurrentModule().setSecurityContext(pd);
+    }
+
+    synchronized ProtectionDomain getProtectionDomain()
+    {
+        ProtectionDomain pd = null;
+
+        for (int i = m_modules.length - 1; (i >= 0) && (pd == null); i--)
+        {
+            pd = (ProtectionDomain) m_modules[i].getSecurityContext();
+        }
+
+        return pd;
+    }
+
+    //
+    // Locking related methods.
+    //
+
+    synchronized boolean isLockable()
+    {
+        return (m_lockCount == 0) || (m_lockThread == Thread.currentThread());
+    }
+
+    synchronized void lock()
+    {
+        if ((m_lockCount > 0) && (m_lockThread != Thread.currentThread()))
+        {
+            throw new IllegalStateException("Bundle is locked by another thread.");
+        }
+        m_lockCount++;
+        m_lockThread = Thread.currentThread();
+    }
+
+    synchronized void unlock()
+    {
+        if (m_lockCount == 0)
+        {
+            throw new IllegalStateException("Bundle is not locked.");
+        }
+        if ((m_lockCount > 0) && (m_lockThread != Thread.currentThread()))
+        {
+            throw new IllegalStateException("Bundle is locked by another thread.");
+        }
+        m_lockCount--;
+        if (m_lockCount == 0)
+        {
+            m_lockThread = null;
+        }
+    }
+
+    synchronized void syncLock(BundleImpl impl)
+    {
+        m_lockCount = impl.m_lockCount;
+        m_lockThread = impl.m_lockThread;
     }
 }
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleInfo.java b/framework/src/main/java/org/apache/felix/framework/BundleInfo.java
deleted file mode 100644
index 032d6ae..0000000
--- a/framework/src/main/java/org/apache/felix/framework/BundleInfo.java
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework;
-
-import java.io.IOException;
-import java.net.URL;
-import java.security.ProtectionDomain;
-import java.util.*;
-
-import org.apache.felix.moduleloader.IContentLoader;
-import org.apache.felix.moduleloader.IModule;
-import org.apache.felix.moduleloader.ModuleImpl;
-import org.osgi.framework.*;
-
-abstract class BundleInfo
-{
-    private final Logger m_logger;
-    private boolean m_removalPending = false;
-    private IModule[] m_modules = null;
-    private int m_state = 0;
-    private BundleActivator m_activator = null;
-    private BundleContext m_context = null;
-    private Map m_cachedHeaders = new HashMap();
-    private long m_cachedHeadersTimestamp;
-
-    // Indicates whether the bundle is stale, meaning that it has
-    // been refreshed and completely removed from the framework.
-    private boolean m_stale = false;
-
-    // Indicates whether the bundle is an extension, meaning that it is
-    // installed as an extension bundle to the framework (i.e., can not be
-    // removed or updated until a framework restart.
-    private boolean m_extension = false;
-
-    // Used for bundle locking.
-    private int m_lockCount = 0;
-    private Thread m_lockThread = null;
-
-    public BundleInfo(Logger logger, IModule module)
-    {
-        m_logger = logger;
-        m_modules = (module == null) ? new IModule[0] : new IModule[] { module };
-        m_state = Bundle.INSTALLED;
-        m_stale = false;
-        m_activator = null;
-        m_context = null;
-    }
-
-    public Logger getLogger()
-    {
-        return m_logger;
-    }
-
-    public synchronized boolean isRemovalPending()
-    {
-        return m_removalPending;
-    }
-
-    public synchronized void setRemovalPending(boolean removalPending)
-    {
-        m_removalPending = removalPending;
-    }
-
-    /**
-     * Returns an array of all modules associated with the bundle represented by
-     * this <tt>BundleInfo</tt> object. A module in the array corresponds to a
-     * revision of the bundle's JAR file and is ordered from oldest to newest.
-     * Multiple revisions of a bundle JAR file might exist if a bundle is
-     * updated, without refreshing the framework. In this case, exports from
-     * the prior revisions of the bundle JAR file are still offered; the
-     * current revision will be bound to packages from the prior revision,
-     * unless the packages were not offered by the prior revision. There is
-     * no limit on the potential number of bundle JAR file revisions.
-     * @return array of modules corresponding to the bundle JAR file revisions.
-    **/
-    public synchronized IModule[] getModules()
-    {
-        return m_modules;
-    }
-
-    /**
-     * Determines if the specified module is associated with this bundle.
-     * @param module the module to determine if it is associate with this bundle.
-     * @return <tt>true</tt> if the specified module is in the array of modules
-     *         associated with this bundle, <tt>false</tt> otherwise.
-    **/
-    public synchronized boolean hasModule(IModule module)
-    {
-        for (int i = 0; i < m_modules.length; i++)
-        {
-            if (m_modules[i] == module)
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns the newest module, which corresponds to the last module
-     * in the module array.
-     * @return the newest module.
-    **/
-    public synchronized IModule getCurrentModule()
-    {
-        return m_modules[m_modules.length - 1];
-    }
-
-    /**
-     * Add a module that corresponds to a new bundle JAR file revision for
-     * the bundle associated with this <tt>BundleInfo</tt> object.
-     * @param module the module to add.
-    **/
-    public synchronized void addModule(IModule module)
-    {
-        IModule[] dest = new IModule[m_modules.length + 1];
-        System.arraycopy(m_modules, 0, dest, 0, m_modules.length);
-        dest[m_modules.length] = module;
-        m_modules = dest;
-    }
-
-    /**
-     * This marks all modules as stale when the associated bundle has
-     * been uninstalled. This is necessary since uninstalled bundles
-     * should not be used for fragments or fragment hosts.
-    **/
-    public synchronized void markModulesStale()
-    {
-        for (int i = 0; i < m_modules.length; i++)
-        {
-            ((ModuleImpl) m_modules[i]).setStale();
-        }
-    }
-
-    public abstract String getSymbolicName();
-
-    public abstract long getBundleId();
-
-    public abstract String getLocation();
-
-    public abstract int getStartLevel(int defaultLevel);
-
-    public abstract void setStartLevel(int i);
-
-    public abstract Map getCurrentHeader();
-
-    public Map getCurrentLocalizedHeader(String locale)
-    {
-        synchronized (m_cachedHeaders)
-        {
-            // If the bundle has been updated, clear the cached headers
-            if (getLastModified() > m_cachedHeadersTimestamp)
-            {
-                m_cachedHeaders.clear();
-            }
-            else
-            {
-                // Check if headers for this locale have already been resolved
-                if (m_cachedHeaders.containsKey(locale))
-                {
-                    return (Map) m_cachedHeaders.get(locale);
-                }
-            }
-        }
-
-        Map rawHeaders = getCurrentHeader();
-        Map headers = new HashMap(rawHeaders.size());
-        headers.putAll(rawHeaders);
-
-        // Check to see if we actually need to localize anything
-        boolean needsLocalization = false;
-        for (Iterator it = headers.values().iterator(); it.hasNext(); )
-        {
-            if (((String) it.next()).startsWith("%"))
-            {
-                needsLocalization = true;
-                break;
-            }
-        }
-
-        if (!needsLocalization)
-        {
-            // If localization is not needed, just cache the headers and return them as-is
-            // Not sure if this is useful
-            updateHeaderCache(locale, headers);
-            return headers;
-        }
-
-        // Do localization here and return the localized headers
-        IContentLoader loader = this.getCurrentModule().getContentLoader();
-
-        String basename = (String) headers.get(Constants.BUNDLE_LOCALIZATION);
-        if (basename == null)
-        {
-            basename = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
-        }
-
-        // Create ordered list of files to load properties from
-        List resourceList = createResourceList(basename, locale);
-
-        // Create a merged props file with all available props for this locale
-        Properties mergedProperties = new Properties();
-        for (Iterator it = resourceList.iterator(); it.hasNext(); )
-        {
-            URL temp = loader.getResource(it.next() + ".properties");
-            if (temp == null)
-            {
-                continue;
-            }
-            try
-            {
-                mergedProperties.load(temp.openConnection().getInputStream());
-            }
-            catch (IOException ex)
-            {
-                // File doesn't exist, just continue loop
-            }
-        }
-
-        // Resolve all localized header entries
-        for (Iterator it = headers.entrySet().iterator(); it.hasNext(); )
-        {
-            Map.Entry entry = (Map.Entry) it.next();
-            String value = (String) entry.getValue();
-            if (value.startsWith("%"))
-            {
-                String newvalue;
-                String key = value.substring(value.indexOf("%") + 1);
-                newvalue = mergedProperties.getProperty(key);
-                if (newvalue==null)
-                {
-                    newvalue = key;
-                }
-                entry.setValue(newvalue);
-            }
-        }
-
-        updateHeaderCache(locale, headers);
-        return headers;
-    }
-
-    private void updateHeaderCache(String locale, Map localizedHeaders)
-    {
-        synchronized (m_cachedHeaders)
-        {
-            m_cachedHeaders.put(locale, localizedHeaders);
-            m_cachedHeadersTimestamp = System.currentTimeMillis();
-        }
-    }
-
-    private List createResourceList(String basename, String locale)
-    {
-        List result = new ArrayList(4);
-
-        StringTokenizer tokens;
-        StringBuffer tempLocale = new StringBuffer(basename);
-
-        result.add(tempLocale.toString());
-
-        if (locale.length() > 0)
-        {
-            tokens = new StringTokenizer(locale, "_");
-            while (tokens.hasMoreTokens())
-            {
-                tempLocale.append("_").append(tokens.nextToken());
-                result.add(tempLocale.toString());
-            }
-        }
-        return result;
-    }
-
-    public synchronized int getState()
-    {
-        return m_state;
-    }
-
-    public synchronized void setState(int i)
-    {
-        m_state = i;
-    }
-
-    public abstract long getLastModified();
-
-    public abstract void setLastModified(long l);
-
-    public abstract int getPersistentState();
-
-    public abstract void setPersistentStateInactive();
-
-    public abstract void setPersistentStateActive();
-
-    public abstract void setPersistentStateUninstalled();
-
-    public synchronized BundleContext getBundleContext()
-    {
-        return m_context;
-    }
-
-    public synchronized void setBundleContext(BundleContext context)
-    {
-        m_context = context;
-    }
-
-    public synchronized BundleActivator getActivator()
-    {
-        return m_activator;
-    }
-
-    public synchronized void setActivator(BundleActivator activator)
-    {
-        m_activator = activator;
-    }
-
-    public synchronized boolean isStale()
-    {
-        return m_stale;
-    }
-
-    public synchronized void setStale()
-    {
-        m_stale = true;
-    }
-
-    public synchronized boolean isExtension()
-    {
-        return m_extension;
-    }
-
-    public synchronized void setExtension(boolean extension)
-    {
-        m_extension = extension;
-    }
-
-    //
-    // Locking related methods.
-    // NOTE: These methods are not synchronized because it is assumed they
-    // will only ever be called when the caller is in a synchronized block.
-    //
-
-    public synchronized boolean isLockable()
-    {
-        return (m_lockCount == 0) || (m_lockThread == Thread.currentThread());
-    }
-
-    public synchronized void lock()
-    {
-        if ((m_lockCount > 0) && (m_lockThread != Thread.currentThread()))
-        {
-            throw new IllegalStateException("Bundle is locked by another thread.");
-        }
-        m_lockCount++;
-        m_lockThread = Thread.currentThread();
-    }
-
-    public synchronized void unlock()
-    {
-        if (m_lockCount == 0)
-        {
-            throw new IllegalStateException("Bundle is not locked.");
-        }
-        if ((m_lockCount > 0) && (m_lockThread != Thread.currentThread()))
-        {
-            throw new IllegalStateException("Bundle is locked by another thread.");
-        }
-        m_lockCount--;
-        if (m_lockCount == 0)
-        {
-            m_lockThread = null;
-        }
-    }
-
-    public synchronized void syncLock(BundleInfo info)
-    {
-        m_lockCount = info.m_lockCount;
-        m_lockThread = info.m_lockThread;
-    }
-
-    public synchronized void setProtectionDomain(ProtectionDomain pd)
-    {
-        getCurrentModule().getContentLoader().setSecurityContext(pd);
-    }
-
-    public synchronized ProtectionDomain getProtectionDomain()
-    {
-        ProtectionDomain pd = null;
-
-        for (int i = m_modules.length - 1; (i >= 0) && (pd == null); i--)
-        {
-            pd = (ProtectionDomain)
-                m_modules[i].getContentLoader().getSecurityContext();
-        }
-
-        return pd;
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java b/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
index 11ceb6a..dd301ae 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
@@ -28,13 +28,13 @@
 public class BundleProtectionDomain extends ProtectionDomain
 {
     private final Felix m_felix;
-    private final FelixBundle m_bundle;
+    private final BundleImpl m_bundle;
 
-    public BundleProtectionDomain(Felix felix, FelixBundle bundle) 
+    BundleProtectionDomain(Felix felix, BundleImpl bundle)
         throws MalformedURLException
     {
         super(new CodeSource(new URL(new URL(null, "location:", 
-            new FakeURLStreamHandler()), felix.getBundleLocation(bundle), 
+            new FakeURLStreamHandler()), bundle._getLocation(),
             new FakeURLStreamHandler()), (Certificate[]) null), null);
         m_felix = felix;
         m_bundle = bundle;
@@ -50,7 +50,7 @@
         return m_felix.impliesBundlePermission(this, permission, true);
     }
 
-    FelixBundle getBundle()
+    BundleImpl getBundle()
     {
         return m_bundle;
     }
@@ -73,4 +73,4 @@
     {
         return "[" + m_bundle + "]";
     }
-}
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/ExportedPackageImpl.java b/framework/src/main/java/org/apache/felix/framework/ExportedPackageImpl.java
index 5aac0e7..02cd2f7 100644
--- a/framework/src/main/java/org/apache/felix/framework/ExportedPackageImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ExportedPackageImpl.java
@@ -27,14 +27,14 @@
 class ExportedPackageImpl implements ExportedPackage
 {
     private final Felix m_felix;
-    private final FelixBundle m_exportingBundle;
+    private final BundleImpl m_exportingBundle;
     private final IModule m_exportingModule;
     private final Capability m_export;
     private String m_toString = null;
     private String m_versionString = null;
 
     public ExportedPackageImpl(
-        Felix felix, FelixBundle exporter, IModule module, Capability export)
+        Felix felix, BundleImpl exporter, IModule module, Capability export)
     {
         m_felix = felix;
         m_exportingBundle = exporter;
@@ -45,7 +45,7 @@
     public Bundle getExportingBundle()
     {
         // If the package is stale, then return null per the spec.
-        if (m_exportingBundle.getInfo().isStale())
+        if (m_exportingBundle.isStale())
         {
             return null;
         }
@@ -55,7 +55,7 @@
     public Bundle[] getImportingBundles()
     {
         // If the package is stale, then return null per the spec.
-        if (m_exportingBundle.getInfo().isStale())
+        if (m_exportingBundle.isStale())
         {
             return null;
         }
@@ -87,7 +87,7 @@
 
     public boolean isRemovalPending()
     {
-        return m_exportingBundle.getInfo().isRemovalPending();
+        return m_exportingBundle.isRemovalPending();
     }
 
     public String toString()
diff --git a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
index a35e106..c8d752d 100644
--- a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
+++ b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
@@ -21,7 +21,6 @@
 import java.io.IOException;
 import java.net.InetAddress;
 import java.io.InputStream;
-import java.net.JarURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
@@ -37,21 +36,20 @@
 import java.util.Properties;
 import java.util.Set;
 
+import org.apache.felix.framework.Felix.FelixResolver;
+import org.apache.felix.framework.searchpolicy.ModuleImpl;
 import org.apache.felix.framework.util.FelixConstants;
-import org.apache.felix.framework.util.SecurityManagerEx;
+import org.apache.felix.framework.util.StringMap;
 import org.apache.felix.framework.util.Util;
 import org.apache.felix.framework.util.manifestparser.Capability;
 import org.apache.felix.framework.util.manifestparser.ManifestParser;
 import org.apache.felix.framework.util.manifestparser.R4Attribute;
 import org.apache.felix.framework.util.manifestparser.R4Directive;
-import org.apache.felix.framework.util.manifestparser.R4Library;
 import org.apache.felix.moduleloader.ICapability;
 import org.apache.felix.moduleloader.IContent;
-import org.apache.felix.moduleloader.IContentLoader;
-import org.apache.felix.moduleloader.IModuleDefinition;
-import org.apache.felix.moduleloader.IRequirement;
-import org.apache.felix.moduleloader.ISearchPolicy;
+import org.apache.felix.moduleloader.IModule;
 import org.apache.felix.moduleloader.IURLPolicy;
+import org.apache.felix.moduleloader.ResourceNotFoundException;
 import org.osgi.framework.AdminPermission;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
@@ -82,7 +80,7 @@
 // with the parent classloader and one instance per framework instance that
 // keeps track of extension bundles and systembundle exports for that framework
 // instance.
-class ExtensionManager extends URLStreamHandler implements IModuleDefinition, IContentLoader, IContent
+class ExtensionManager extends URLStreamHandler implements IContent
 {
     // The private instance that is added to Felix.class.getClassLoader() -
     // will be null if extension bundles are not supported (i.e., we are not
@@ -110,10 +108,10 @@
     }
 
     private Logger m_logger = null;
-    private BundleInfo m_sbi = null;
+    private final Map m_headerMap = new StringMap(false);
+    private final IModule m_module;
     private ICapability[] m_capabilities = null;
     private Set m_exportNames = null;
-    private ISearchPolicy m_searchPolicy = null;
     private IURLPolicy m_urlPolicy = null;
     private Object m_securityContext = null;
     private final List m_extensions;
@@ -124,6 +122,8 @@
     // classloader.
     private ExtensionManager()
     {
+// TODO: REFACTOR - Karl, is this correct?
+        m_module = new ExtensionManagerModule();
         m_extensions = new ArrayList();
         m_names = new HashSet();
         m_sourceToExtensions = new HashMap();
@@ -140,28 +140,24 @@
      * @param config the configuration to read properties from.
      * @param systemBundleInfo the info to change if we need to add exports.
      */
-    ExtensionManager(Logger logger, Map configMap, BundleInfo sbi)
+    ExtensionManager(Logger logger, Map configMap)
     {
+        m_module = new ExtensionManagerModule();
         m_extensions = null;
         m_names = null;
         m_sourceToExtensions = null;
         m_logger = logger;
-        m_sbi = sbi;
 
 // TODO: FRAMEWORK - Not all of this stuff really belongs here, probably only exports.
         // Populate system bundle header map.
-        // Note: This is a reference to the actual header map,
-        // so these changes are saved. Kind of hacky.
-        Map map = m_sbi.getCurrentHeader();
-        // Initialize header map as a case insensitive map.
-        map.put(FelixConstants.BUNDLE_VERSION,
+        m_headerMap.put(FelixConstants.BUNDLE_VERSION,
             configMap.get(FelixConstants.FELIX_VERSION_PROPERTY));
-        map.put(FelixConstants.BUNDLE_SYMBOLICNAME,
+        m_headerMap.put(FelixConstants.BUNDLE_SYMBOLICNAME,
             FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
-        map.put(FelixConstants.BUNDLE_NAME, "System Bundle");
-        map.put(FelixConstants.BUNDLE_DESCRIPTION,
+        m_headerMap.put(FelixConstants.BUNDLE_NAME, "System Bundle");
+        m_headerMap.put(FelixConstants.BUNDLE_DESCRIPTION,
             "This bundle is system specific; it implements various system services.");
-        map.put(FelixConstants.EXPORT_SERVICE,
+        m_headerMap.put(FelixConstants.EXPORT_SERVICE,
             "org.osgi.service.packageadmin.PackageAdmin," +
             "org.osgi.service.startlevel.StartLevel," +
             "org.osgi.service.url.URLHandlers");
@@ -180,7 +176,7 @@
         try
         {
             setCapabilities(
-                addModuleCapability(map,
+                addModuleCapability(m_headerMap,
                     ManifestParser.parseExportHeader(syspkgs)));
         }
         catch (Exception ex)
@@ -193,6 +189,11 @@
         }
     }
 
+    public IModule getModule()
+    {
+        return m_module;
+    }
+
     private ICapability[] addModuleCapability(Map headerMap, ICapability[] caps)
     {
         try
@@ -245,7 +246,7 @@
     /**
      * Check whether the given manifest headers are from an extension bundle.
      */
-    boolean isExtensionBundle(Map headers)
+    static boolean isExtensionBundle(Map headers)
     {
         return (ManifestParser.parseExtensionBundleHeader((String)
                 headers.get(Constants.FRAGMENT_HOST)) != null);
@@ -265,7 +266,7 @@
      *          AdminPermission.EXTENSIONLIFECYCLE and security is enabled.
      * @throws Exception in case something goes wrong.
      */
-    void addExtensionBundle(Felix felix, FelixBundle bundle)
+    void addExtensionBundle(Felix felix, BundleImpl bundle)
         throws SecurityException, BundleException, Exception
     {
         Object sm = System.getSecurityManager();
@@ -275,13 +276,13 @@
                 new AdminPermission(bundle, AdminPermission.EXTENSIONLIFECYCLE));
         }
 
-        if (!((BundleProtectionDomain) bundle.getInfo().getProtectionDomain()).impliesDirect(new AllPermission()))
+        if (!((BundleProtectionDomain) bundle.getProtectionDomain()).impliesDirect(new AllPermission()))
         {
             throw new SecurityException("Extension Bundles must have AllPermission");
         }
 
         R4Directive dir = ManifestParser.parseExtensionBundleHeader((String)
-            bundle.getInfo().getCurrentHeader().get(Constants.FRAGMENT_HOST));
+            bundle.getCurrentModule().getHeaders().get(Constants.FRAGMENT_HOST));
 
         // We only support classpath extensions (not bootclasspath).
         if (!Constants.EXTENSION_FRAMEWORK.equals(dir.getValue()))
@@ -296,21 +297,21 @@
 
         try
         {
-            bundle.getInfo().setExtension(true);
+            bundle.setExtension(true);
 
             // Merge the exported packages with the exported packages of the systembundle.
             ICapability[] exports = null;
             try
             {
                 exports = ManifestParser.parseExportHeader((String)
-                    bundle.getInfo().getCurrentHeader().get(Constants.EXPORT_PACKAGE));
+                    bundle.getCurrentModule().getHeaders().get(Constants.EXPORT_PACKAGE));
             }
             catch (Exception ex)
             {
                 m_logger.log(
                     Logger.LOG_ERROR,
                     "Error parsing extension bundle export statement: "
-                    + bundle.getInfo().getCurrentHeader().get(Constants.EXPORT_PACKAGE), ex);
+                    + bundle.getCurrentModule().getHeaders().get(Constants.EXPORT_PACKAGE), ex);
                 return;
             }
 
@@ -328,14 +329,14 @@
                 throw new UnsupportedOperationException(
                     "Unable to add extension bundle to FrameworkClassLoader - Maybe not an URLClassLoader?");
             }
-            ICapability[] temp = new ICapability[getCapabilities().length + exports.length];
-            System.arraycopy(getCapabilities(), 0, temp, 0, getCapabilities().length);
-            System.arraycopy(exports, 0, temp, getCapabilities().length, exports.length);
+            ICapability[] temp = new ICapability[m_capabilities.length + exports.length];
+            System.arraycopy(m_capabilities, 0, temp, 0, m_capabilities.length);
+            System.arraycopy(exports, 0, temp, m_capabilities.length, exports.length);
             setCapabilities(temp);
         }
         catch (Exception ex)
         {
-            bundle.getInfo().setExtension(false);
+            bundle.setExtension(false);
             throw ex;
         }
         finally
@@ -343,7 +344,7 @@
             felix.releaseBundleLock(felix);
         }
 
-        bundle.getInfo().setState(Bundle.RESOLVED);
+        bundle.setState(Bundle.RESOLVED);
     }
 
     /**
@@ -353,10 +354,10 @@
      * @param felix the framework instance the extension bundle is installed in.
      * @param bundle the extension bundle to start if it has a Felix specific activator.
      */
-    void startExtensionBundle(Felix felix, FelixBundle bundle)
+    void startExtensionBundle(Felix felix, BundleImpl bundle)
     {
         String activatorClass = (String)
-        bundle.getInfo().getCurrentHeader().get(
+        bundle.getCurrentModule().getHeaders().get(
             FelixConstants.FELIX_EXTENSION_ACTIVATOR);
 
         if (activatorClass != null)
@@ -370,11 +371,11 @@
 // TODO: KARL - This is kind of hacky, can we improve it?
                 felix.m_activatorList.add(activator);
 
-                BundleContext context = m_sbi.getBundleContext();
+                BundleContext context = felix.getBundleContext();
 
-                bundle.getInfo().setBundleContext(context);
+                bundle.setBundleContext(context);
 
-                if (felix.getInfo().getState() == Bundle.ACTIVE)
+                if (felix.getState() == Bundle.ACTIVE)
                 {
                     Felix.m_secureAction.startActivator(activator, context);
                 }
@@ -403,37 +404,13 @@
         }
     }
 
-    //
-    // IModuleDefinition
-    //
-    public ICapability[] getCapabilities()
-    {
-        return m_capabilities;
-    }
-
     void setCapabilities(ICapability[] capabilities)
     {
         m_capabilities = capabilities;
 
         // Note: This is a reference to the actual header map,
         // so these changes are saved. Kind of hacky.
-        Map map = m_sbi.getCurrentHeader();
-        map.put(Constants.EXPORT_PACKAGE, convertCapabilitiesToHeaders(map));
-    }
-
-    public IRequirement[] getDynamicRequirements()
-    {
-        return null;
-    }
-
-    public R4Library[] getLibraries()
-    {
-        return null;
-    }
-
-    public IRequirement[] getRequirements()
-    {
-        return null;
+        m_headerMap.put(Constants.EXPORT_PACKAGE, convertCapabilitiesToHeaders(m_headerMap));
     }
 
     private String convertCapabilitiesToHeaders(Map headers)
@@ -468,105 +445,6 @@
     }
 
     //
-    // IContentLoader
-    //
-
-    public void open()
-    {
-        // Nothing needed here.
-    }
-
-    public void close()
-    {
-        // Nothing needed here.
-    }
-
-    public IContent getContent()
-    {
-        return this;
-    }
-
-    public ISearchPolicy getSearchPolicy()
-    {
-        return m_searchPolicy;
-    }
-
-    public void setSearchPolicy(ISearchPolicy searchPolicy)
-    {
-        m_searchPolicy = searchPolicy;
-    }
-
-    public IURLPolicy getURLPolicy()
-    {
-        return m_urlPolicy;
-    }
-
-    public void setURLPolicy(IURLPolicy urlPolicy)
-    {
-        m_urlPolicy = urlPolicy;
-    }
-
-    public Class getClass(String name)
-    {
-        if (!m_exportNames.contains(Util.getClassPackage(name)))
-        {
-            return null;
-        }
-
-        try
-        {
-            return getClass().getClassLoader().loadClass(name);
-        }
-        catch (ClassNotFoundException ex)
-        {
-            m_logger.log(
-                Logger.LOG_WARNING,
-                ex.getMessage(),
-                ex);
-        }
-        return null;
-    }
-
-    public URL getResource(String name)
-    {
-        return getClass().getClassLoader().getResource(name);
-    }
-
-    public Enumeration getResources(String name)
-    {
-       try
-       {
-           return getClass().getClassLoader().getResources(name);
-       }
-       catch (IOException ex)
-       {
-           return null;
-       }
-    }
-
-    public URL getResourceFromContent(String name)
-    {
-        // There is no content for the system bundle, so return null.
-        return null;
-    }
-
-    public boolean hasInputStream(int index, String urlPath)
-    {
-        return (getClass().getClassLoader().getResource(urlPath) != null);
-    }
-
-    public InputStream getInputStream(int index, String urlPath)
-    {
-        return getClass().getClassLoader().getResourceAsStream(urlPath);
-    }
-
-    public String findLibrary(String name)
-    {
-        // No native libs associated with the system bundle.
-        return null;
-    }
-
-    //
     // Classpath Extension
     //
 
@@ -585,7 +463,7 @@
 
         for (Iterator iter = m_extensions.iterator(); iter.hasNext();)
         {
-            URL result = ((FelixBundle) iter.next()).getInfo().getCurrentModule().getContentLoader().getResourceFromContent(path);
+            URL result = ((BundleImpl) iter.next()).getCurrentModule().getResourceFromContent(path);
 
             if (result != null)
             {
@@ -647,6 +525,11 @@
         }
     }
 
+    public void close()
+    {
+        // Do nothing on close, since we have nothing open.
+    }
+
     public Enumeration getEntries()
     {
         return new Enumeration()
@@ -737,4 +620,170 @@
             return "";
         }
     }
+
+    class ExtensionManagerModule extends ModuleImpl
+    {
+        ExtensionManagerModule()
+        {
+            super(m_logger, null, null, "0", null, null, null, null, null, null);
+        }
+
+        public Map getHeaders()
+        {
+            return m_headerMap;
+        }
+
+        public ICapability[] getCapabilities()
+        {
+            return m_capabilities;
+        }
+
+        public String getSymbolicName()
+        {
+            return FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME;
+        }
+
+        public Class getClassByDelegation(String name) throws ClassNotFoundException
+        {
+            // System bundle does not delegate to other modules.
+            return getClassFromModule(name);
+        }
+
+        public URL getResourceByDelegation(String name)
+        {
+            // System bundle does not delegate to other modules.
+            return getResourceFromModule(name);
+        }
+
+        public Enumeration getResourcesByDelegation(String name)
+        {
+            // System bundle does not delegate to other modules.
+            return getResourcesFromModule(name);
+        }
+
+        public Logger getLogger()
+        {
+            return m_logger;
+        }
+
+        public Map getConfig()
+        {
+            return null;
+        }
+
+        public FelixResolver getResolver()
+        {
+            return null;
+        }
+
+        public synchronized IContent[] getClassPath()
+        {
+            throw new UnsupportedOperationException("Should not be used!");
+        }
+
+        public synchronized void attachFragmentContents(IContent[] fragmentContents)
+            throws Exception
+        {
+            throw new UnsupportedOperationException("Should not be used!");
+        }
+
+        public void close()
+        {
+            // Nothing needed here.
+        }
+
+        public IContent getContent()
+        {
+            return ExtensionManager.this;
+        }
+
+        public synchronized void setURLPolicy(IURLPolicy urlPolicy)
+        {
+            m_urlPolicy = urlPolicy;
+        }
+
+        public synchronized IURLPolicy getURLPolicy()
+        {
+            return m_urlPolicy;
+        }
+
+        public void setSecurityContext(Object securityContext)
+        {
+            throw new UnsupportedOperationException("Should not be used!");
+        }
+
+        public Object getSecurityContext()
+        {
+            throw new UnsupportedOperationException("Should not be used!");
+        }
+
+        public Class findClassByDelegation(String name) throws ClassNotFoundException
+        {
+            return getClassFromModule(name);
+        }
+
+        public URL findResourceByDelegation(String name) throws ResourceNotFoundException
+        {
+            return getResourceFromModule(name);
+        }
+
+        public Enumeration findResourcesByDelegation(String name) throws ResourceNotFoundException
+        {
+            return getResourcesFromModule(name);
+        }
+
+        public Class getClassFromModule(String name)
+        {
+            if (!m_exportNames.contains(Util.getClassPackage(name)))
+            {
+                return null;
+            }
+
+            try
+            {
+                return getClass().getClassLoader().loadClass(name);
+            }
+            catch (ClassNotFoundException ex)
+            {
+                m_logger.log(
+                    Logger.LOG_WARNING,
+                    ex.getMessage(),
+                    ex);
+            }
+            return null;
+        }
+
+        public URL getResourceFromModule(String name)
+        {
+            return getClass().getClassLoader().getResource(name);
+        }
+
+        public Enumeration getResourcesFromModule(String name)
+        {
+           try
+           {
+               return getClass().getClassLoader().getResources(name);
+           }
+           catch (IOException ex)
+           {
+               return null;
+           }
+        }
+
+        public URL getResourceFromContent(String name)
+        {
+            // There is no content for the system bundle, so return null.
+            return null;
+        }
+
+        public boolean hasInputStream(int index, String urlPath)
+        {
+            return (getClass().getClassLoader().getResource(urlPath) != null);
+        }
+
+        public InputStream getInputStream(int index, String urlPath)
+        {
+            return getClass().getClassLoader().getResourceAsStream(urlPath);
+        }
+    }
 }
\ No newline at end of file
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 8806f10..0acee2a 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -36,7 +36,7 @@
 import org.osgi.service.packageadmin.ExportedPackage;
 import org.osgi.service.startlevel.StartLevel;
 
-public class Felix extends FelixBundle implements Framework
+public class Felix extends BundleImpl implements Framework
 {
     // The secure action used to do privileged calls
     static final SecureAction m_secureAction = new SecureAction();
@@ -45,18 +45,16 @@
     ExtensionManager m_extensionManager;
 
     // Logging related member variables.
-    private Logger m_logger = null;
+    private final Logger m_logger;
     // Immutable config properties.
-    private Map m_configMap = null;
+    private final Map m_configMap;
     // Mutable configuration properties passed into constructor.
-    private Map m_configMutableMap = null;
+    private final Map m_configMutableMap;
 
     // MODULE FACTORY.
-    private IModuleFactory m_factory = null;
     private final Resolver m_resolver;
     private final FelixResolverState m_resolverState;
     private final FelixResolver m_felixResolver;
-    private R4SearchPolicyCore m_policyCore = null;
 
     // Lock object used to determine if an individual bundle
     // lock or the global lock can be acquired.
@@ -86,22 +84,18 @@
     private final Object[] m_installedBundleLock_Priority2 = new Object[0];
 
     // An array of uninstalled bundles before a refresh occurs.
-    private FelixBundle[] m_uninstalledBundles = null;
+    private BundleImpl[] m_uninstalledBundles = null;
     // This lock must be acquired to modify m_uninstalledBundles;
     // to help avoid deadlock this lock as priority 3 and should
     // be acquired before locks with lower priority.
     private final Object[] m_uninstalledBundlesLock_Priority3 = new Object[0];
 
     // Framework's active start level.
-    private int m_activeStartLevel =
-        FelixConstants.FRAMEWORK_INACTIVE_STARTLEVEL;
+    private int m_activeStartLevel = FelixConstants.FRAMEWORK_INACTIVE_STARTLEVEL;
 
     // Local file system cache.
     private BundleCache m_cache = null;
 
-    // System bundle bundle info instance.
-    private BundleInfo m_sbi;
-
     // System bundle activator list.
     List m_activatorList = null;
 
@@ -116,7 +110,7 @@
     private ServiceRegistry m_registry = null;
 
     // Reusable bundle URL stream handler.
-    private URLStreamHandler m_bundleStreamHandler = null;
+    private final URLStreamHandler m_bundleStreamHandler;
 
     // Execution environment.
     private String m_executionEnvironment = "";
@@ -248,8 +242,9 @@
      * @param configMap A map for obtaining configuration properties,
      *        may be <tt>null</tt>.
     **/
-    public Felix(Map configMap)
+    public Felix(Map configMap) throws Exception
     {
+        super(null, null);
         // Copy the configuration properties; convert keys to strings.
         m_configMutableMap = new StringMap(false);
         if (configMap != null)
@@ -268,8 +263,14 @@
         // the system bundle is activated. The system bundle's context
         // will be set in the init() method after the system bundle
         // is activated.
-        m_logger = (Logger) m_configMutableMap.get(FelixConstants.LOG_LOGGER_PROP);
-        m_logger = (m_logger == null) ? new Logger() : m_logger;
+        if (m_configMutableMap.get(FelixConstants.LOG_LOGGER_PROP) != null)
+        {
+            m_logger = (Logger) m_configMutableMap.get(FelixConstants.LOG_LOGGER_PROP);
+        }
+        else
+        {
+            m_logger = new Logger();
+        }
         try
         {
             m_logger.setLogLevel(
@@ -292,24 +293,11 @@
         m_resolverState = new FelixResolverState(m_logger);
         m_felixResolver = new FelixResolver(m_resolver, m_resolverState);
 
-        // Create search policy for module loader.
-        m_policyCore = new R4SearchPolicyCore(m_logger, m_configMap, m_felixResolver);
-
-        // Create the module factory and attach it to the search policy.
-        m_factory = new ModuleFactoryImpl(m_logger);
-
-        // Create the system bundle info object, which will hold state info.
-        m_sbi = new SystemBundleInfo(m_logger, null);
         // Create the extension manager, which we will use as the module
         // definition for creating the system bundle module.
-        m_extensionManager = new ExtensionManager(m_logger, m_configMap, m_sbi);
-        m_sbi.addModule(m_factory.createModule("0", m_extensionManager));
-        m_resolverState.addModule(m_sbi.getCurrentModule());
-        // Set the extension manager as the content loader for the system
-        // bundle module.
-        m_extensionManager.setSearchPolicy(
-            new R4SearchPolicy(m_policyCore, m_sbi.getCurrentModule()));
-        m_factory.setContentLoader(m_sbi.getCurrentModule(), m_extensionManager);
+        m_extensionManager = new ExtensionManager(m_logger, m_configMap);
+        addModule(m_extensionManager.getModule());
+        m_resolverState.addModule(getCurrentModule());
         // Lastly, set the system bundle's protection domain.
         try
         {
@@ -321,6 +309,26 @@
         }
     }
 
+    Logger getLogger()
+    {
+        return m_logger;
+    }
+
+    Map getConfig()
+    {
+        return m_configMap;
+    }
+
+    FelixResolver getResolver()
+    {
+        return m_felixResolver;
+    }
+
+    URLStreamHandler getBundleStreamHandler()
+    {
+        return m_bundleStreamHandler;
+    }
+
     private Map createUnmodifiableMap(Map mutableMap)
     {
         Map result = Collections.unmodifiableMap(mutableMap);
@@ -341,19 +349,20 @@
         return result;
     }
 
-    //
-    // System Bundle methods.
-    //
-
-    /* package private */ BundleInfo getInfo()
+    // TODO: REFACTOR - This method is sort of a hack. Since the system bundle
+    //       can't set its own framework value, it can override this method to
+    //       return itself to the BundleImpl methods.
+    Felix getFramework()
     {
-        return m_sbi;
+        return this;
     }
 
-    public BundleContext getBundleContext()
+    // TODO: REFACTOR - This method is sort of a hack. Since the system bundle
+    //       doesn't have an archive, it can override this method to return its
+    //       manifest.
+    Map getCurrentManifestFromArchive() throws Exception
     {
-// TODO: SECURITY - We need a security check here.
-        return m_sbi.getBundleContext();
+        return getCurrentModule().getHeaders();
     }
 
     public long getBundleId()
@@ -361,243 +370,63 @@
         return 0;
     }
 
-    public URL getEntry(String name)
-    {
-        Object sm = System.getSecurityManager();
-
-        if (sm != null)
-        {
-            try
-            {
-                ((SecurityManager) sm).checkPermission(new AdminPermission(this,
-                    AdminPermission.RESOURCE));
-            }
-            catch (Exception e)
-            {
-                return null; // No permission
-            }
-        }
-
-        return getBundleEntry(this, name);
-    }
-
-    public Enumeration getEntryPaths(String path)
-    {
-        Object sm = System.getSecurityManager();
-
-        if (sm != null)
-        {
-            try
-            {
-                ((SecurityManager) sm).checkPermission(new AdminPermission(this,
-                    AdminPermission.RESOURCE));
-            }
-            catch (Exception e)
-            {
-                return null; // No permission
-            }
-        }
-
-        return getBundleEntryPaths(this, path);
-    }
-
-    public Enumeration findEntries(String path, String filePattern, boolean recurse)
-    {
-        Object sm = System.getSecurityManager();
-
-        if (sm != null)
-        {
-            try
-            {
-                ((SecurityManager) sm).checkPermission(new AdminPermission(this,
-                    AdminPermission.RESOURCE));
-            }
-            catch (Exception e)
-            {
-                return null; // No permission
-            }
-        }
-
-        return findBundleEntries(this, path, filePattern, recurse);
-    }
-
-    public Dictionary getHeaders()
-    {
-        return getHeaders(Locale.getDefault().toString());
-    }
-
-    public Dictionary getHeaders(String locale)
-    {
-        Object sm = System.getSecurityManager();
-
-        if (sm != null)
-        {
-            ((SecurityManager) sm).checkPermission(new AdminPermission(this,
-                AdminPermission.METADATA));
-        }
-        return getBundleHeaders(this, locale);
-    }
-
     public long getLastModified()
     {
-        return m_sbi.getLastModified();
+        return 0;
     }
 
-    public String getLocation()
+    void setLastModified(long l)
     {
-        Object sm = System.getSecurityManager();
+        // Ignore.
+    }
 
-        if (sm != null)
-        {
-            ((SecurityManager) sm).checkPermission(new AdminPermission(this,
-                AdminPermission.METADATA));
-        }
+    String _getLocation()
+    {
         return Constants.SYSTEM_BUNDLE_LOCATION;
     }
 
-    public URL getResource(String name)
+    public int getPersistentState()
     {
-        return getBundleResource(this, name);
+        return Bundle.ACTIVE;
     }
 
-    public Enumeration getResources(String name) throws IOException
+    public void setPersistentStateInactive()
     {
-        Object sm = System.getSecurityManager();
-
-        if (sm != null)
-        {
-            try
-            {
-                ((SecurityManager) sm).checkPermission(new AdminPermission(this,
-                    AdminPermission.RESOURCE));
-            }
-            catch (Exception e)
-            {
-                return null; // No permission
-            }
-        }
-
-        return getBundleResources(this, name);
+        // Ignore.
     }
 
-    public ServiceReference[] getRegisteredServices()
+    public void setPersistentStateActive()
     {
-        Object sm = System.getSecurityManager();
-
-        if (sm != null)
-        {
-            ServiceReference[] refs = getBundleRegisteredServices(this);
-
-            if (refs == null)
-            {
-                return refs;
-            }
-
-            List result = new ArrayList();
-
-            for (int i = 0; i < refs.length; i++)
-            {
-                String[] objectClass = (String[]) refs[i].getProperty(
-                    Constants.OBJECTCLASS);
-
-                if (objectClass == null)
-                {
-                    continue;
-                }
-
-                for (int j = 0; j < objectClass.length; j++)
-                {
-                    try
-                    {
-                        ((SecurityManager) sm).checkPermission(new ServicePermission(
-                            objectClass[j], ServicePermission.GET));
-
-                        result.add(refs[i]);
-
-                        break;
-                    }
-                    catch (Exception ex)
-                    {
-                        // Silently ignore.
-                    }
-                }
-            }
-
-            if (result.isEmpty())
-            {
-                return null;
-            }
-
-            return (ServiceReference[]) result.toArray(new ServiceReference[result.size()]);
-        }
-        else
-        {
-            return getBundleRegisteredServices(this);
-        }
+        // Ignore.
     }
 
-    public ServiceReference[] getServicesInUse()
+    public void setPersistentStateUninstalled()
     {
-        Object sm = System.getSecurityManager();
-
-        if (sm != null)
-        {
-            ServiceReference[] refs = getBundleServicesInUse(this);
-
-            if (refs == null)
-            {
-                return refs;
-            }
-
-            List result = new ArrayList();
-
-            for (int i = 0; i < refs.length; i++)
-            {
-                String[] objectClass = (String[]) refs[i].getProperty(
-                    Constants.OBJECTCLASS);
-
-                if (objectClass == null)
-                {
-                    continue;
-                }
-
-                for (int j = 0; j < objectClass.length; j++)
-                {
-                    try
-                    {
-                        ((SecurityManager) sm).checkPermission(new ServicePermission(
-                            objectClass[j], ServicePermission.GET));
-
-                        result.add(refs[i]);
-
-                        break;
-                    }
-                    catch (Exception e)
-                    {
-                        // Silently ignore.
-                    }
-                }
-            }
-
-            if (result.isEmpty())
-            {
-                return null;
-            }
-
-            return (ServiceReference[]) result.toArray(new ServiceReference[result.size()]);
-        }
-
-        return getBundleServicesInUse(this);
+        // Ignore.
     }
 
-    public int getState()
+    /**
+     * Overrides standard <tt>BundleImpl.getStartLevel()</tt> behavior to
+     * always return zero for the system bundle.
+     * @param defaultLevel This parameter is ignored by the system bundle.
+     * @return Always returns zero.
+    **/
+    int getStartLevel(int defaultLevel)
     {
-        return m_sbi.getState();
+        return 0;
     }
 
-    public String getSymbolicName()
+    /**
+     * Overrides standard <tt>BundleImpl.setStartLevel()</tt> behavior to
+     * always throw an exception since the system bundle's start level cannot
+     * be changed.
+     * @param level This parameter is ignored by the system bundle.
+     * @throws IllegalArgumentException Always throws exception since system
+     *         bundle's start level cannot be changed.
+    **/
+    void setStartLevel(int level)
     {
-        return Constants.SYSTEM_BUNDLE_SYMBOLICNAME;
+        throw new IllegalArgumentException("Cannot set the system bundle's start level.");
     }
 
     public boolean hasPermission(Object obj)
@@ -605,31 +434,6 @@
         return true;
     }
 
-    Object getSignerMatcher()
-    {
-        return null;
-    }
-
-    public Class loadClass(String name) throws ClassNotFoundException
-    {
-        Object sm = System.getSecurityManager();
-
-        if (sm != null)
-        {
-            try
-            {
-                ((SecurityManager) sm).checkPermission(new AdminPermission(this,
-                    AdminPermission.CLASS));
-            }
-            catch (Exception e)
-            {
-                throw new ClassNotFoundException("No permission.", e);
-            }
-        }
-
-        return loadBundleClass(this, name);
-    }
-
     /**
      * This method initializes the framework, which is comprised of resolving
      * the system bundle, reloading any cached bundles, and activating the system
@@ -644,7 +448,7 @@
     public synchronized void init() throws BundleException
     {
         // The system bundle can only be initialized if it currently isn't started.
-        final int state = m_sbi.getState();
+        final int state = getState();
         if ((state == Bundle.INSTALLED) || (state == Bundle.RESOLVED))
         {
             // Get any system bundle activators.
@@ -689,14 +493,14 @@
             m_installedBundleIndex = new TreeMap();
 
             // Add the system bundle to the set of installed bundles.
-            m_installedBundleMap.put(m_sbi.getLocation(), this);
+            m_installedBundleMap.put(_getLocation(), this);
             m_installedBundleIndex.put(new Long(0), this);
 
             // Manually resolve the system bundle, which will cause its
             // state to be set to RESOLVED.
             try
             {
-                m_felixResolver.resolve(m_sbi.getCurrentModule());
+                m_felixResolver.resolve(getCurrentModule());
             }
             catch (ResolveException ex)
             {
@@ -790,23 +594,22 @@
             });
 
             // The framework is now in its startup sequence.
-            m_sbi.setState(Bundle.STARTING);
+            setState(Bundle.STARTING);
 
             // Now it is possible for threads to wait for the framework to stop,
             // so create a gate for that purpose.
             m_shutdownGate = new ThreadGate();
 
             // Create system bundle activator and bundle context so we can activate it.
-            m_sbi.setActivator(new SystemBundleActivator());
-            m_sbi.setBundleContext(new BundleContextImpl(m_logger, this, this));
+            setActivator(new SystemBundleActivator());
+            setBundleContext(new BundleContextImpl(m_logger, this, this));
             try
             {
                 Felix.m_secureAction.startActivator(
-                    m_sbi.getActivator(), m_sbi.getBundleContext());
+                    getActivator(), getBundleContext());
             }
             catch (Throwable ex)
             {
-                m_factory = null;
                 EventDispatcher.shutdown();
                 m_logger.log(Logger.LOG_ERROR, "Unable to start system bundle.", ex);
                 throw new RuntimeException("Unable to start system bundle.");
@@ -814,7 +617,7 @@
 
             // Now that the system bundle is successfully created we can give
             // its bundle context to the logger so that it can track log services.
-            m_logger.setSystemBundleContext(m_sbi.getBundleContext());
+            m_logger.setSystemBundleContext(getBundleContext());
         }
     }
 
@@ -827,64 +630,73 @@
      *
      * @throws org.osgi.framework.BundleException if any error occurs.
     **/
-    public synchronized void start() throws BundleException
+    public void start() throws BundleException
     {
-        final int state = m_sbi.getState();
-        // Initialize if necessary.
-        if ((state == Bundle.INSTALLED) || (state == Bundle.RESOLVED))
+        int startLevel = FelixConstants.FRAMEWORK_DEFAULT_STARTLEVEL;
+
+        synchronized (this)
         {
-            init();
+            final int state = getState();
+            // Initialize if necessary.
+            if ((state == Bundle.INSTALLED) || (state == Bundle.RESOLVED))
+            {
+                init();
+            }
+
+            // If the current state is STARTING, then the system bundle can be started.
+            if (state == Bundle.STARTING)
+            {
+                // Get the framework's default start level.
+                String s = (String) m_configMap.get(Constants.FRAMEWORK_BEGINNING_STARTLEVEL);
+                if (s != null)
+                {
+                    try
+                    {
+                        startLevel = Integer.parseInt(s);
+                    }
+                    catch (NumberFormatException ex)
+                    {
+                        startLevel = FelixConstants.FRAMEWORK_DEFAULT_STARTLEVEL;
+                    }
+                }
+            }
         }
 
-        // If the current state is STARTING, then the system bundle can be started.
-        if (m_sbi.getState() == Bundle.STARTING)
+        // Set the start level using the start level service;
+        // this ensures that all start level requests are
+        // serialized.
+        StartLevel sl = null;
+        try
         {
-            // Get the framework's default start level.
-            int startLevel = FelixConstants.FRAMEWORK_DEFAULT_STARTLEVEL;
-            String s = (String) m_configMap.get(Constants.FRAMEWORK_BEGINNING_STARTLEVEL);
-            if (s != null)
-            {
-                try
-                {
-                    startLevel = Integer.parseInt(s);
-                }
-                catch (NumberFormatException ex)
-                {
-                    startLevel = FelixConstants.FRAMEWORK_DEFAULT_STARTLEVEL;
-                }
-            }
+            sl = (StartLevel) getService(
+                getBundle(0), getServiceReferences((BundleImpl) getBundle(0),
+                StartLevel.class.getName(), null, true)[0]);
+        }
+        catch (InvalidSyntaxException ex)
+        {
+            // Should never happen.
+        }
 
-            // Set the start level using the start level service;
-            // this ensures that all start level requests are
-            // serialized.
-            try
-            {
-                StartLevel sl = (StartLevel) getService(
-                    getBundle(0),getServiceReferences((FelixBundle) getBundle(0),
-                    StartLevel.class.getName(), null, true)[0]);
-                if (sl instanceof StartLevelImpl)
-                {
-                    ((StartLevelImpl) sl).setStartLevelAndWait(startLevel);
-                }
-                else
-                {
-                    sl.setStartLevel(startLevel);
-                }
-            }
-            catch (InvalidSyntaxException ex)
-            {
-                // Should never happen.
-            }
+        if (sl instanceof StartLevelImpl)
+        {
+            ((StartLevelImpl) sl).setStartLevelAndWait(startLevel);
+        }
+        else
+        {
+            sl.setStartLevel(startLevel);
+        }
 
+        synchronized (this)
+        {
             // The framework is now running.
-            m_sbi.setState(Bundle.ACTIVE);
-
-            // Fire started event for system bundle.
-            fireBundleEvent(BundleEvent.STARTED, this);
-
-            // Send a framework event to indicate the framework has started.
-            fireFrameworkEvent(FrameworkEvent.STARTED, this, null);
+            setState(Bundle.ACTIVE);
         }
+
+        // Fire started event for system bundle.
+        fireBundleEvent(BundleEvent.STARTED, this);
+
+        // Send a framework event to indicate the framework has started.
+        fireFrameworkEvent(FrameworkEvent.STARTED, this, null);
     }
 
     public void start(int options) throws BundleException
@@ -984,7 +796,7 @@
      * implements functionality for the Start Level service.
      * @return The active start level of the framework.
     **/
-    protected int getStartLevel()
+    synchronized int getActiveStartLevel()
     {
         return m_activeStartLevel;
     }
@@ -999,18 +811,19 @@
      * directly.
      * @param requestedLevel The new start level of the framework.
     **/
-    protected void setFrameworkStartLevel(int requestedLevel)
+    void setActiveStartLevel(int requestedLevel)
     {
         Bundle[] bundles = null;
 
         // Synchronization for changing the start level is rather loose.
-        // The install lock is grabbed initially to atomically change the
-        // framework's start level and to grab a sorted snapshot of the
-        // currently installed bundles, but then this lock is freed immediately.
-        // No locks are held while processing the currently installed bundles
-        // for starting/stopping based on the new start level. The only locking
-        // that occurs is for individual bundles when startBundle()/stopBundle()
-        // is called, but this locking is done in the respective method.
+        // The object lock is acquired initially to change the framework's
+        // active start level and then the install lock is acquired to attain
+        // a sorted snapshot of the currently installed bundles, but then this
+        // lock is freed immediately. No locks are held while processing the
+        // currently installed bundles for starting/stopping based on the new
+        // active start level. The only locking that occurs is for individual
+        // bundles when startBundle()/stopBundle() is called, but this locking
+        // is done in the respective method.
         //
         // This approach does mean that it is possible for a for individual
         // bundle states to change during this operation. For example, bundle
@@ -1026,15 +839,17 @@
         // for two requests to change the framework's start level to interfere
         // with each other.
 
-        synchronized (m_installedBundleLock_Priority2)
+        boolean lowering;
+        synchronized (this)
         {
             // Determine if we are lowering or raising the
-            // active start level.
-            boolean lowering = (requestedLevel < m_activeStartLevel);
-
-            // Record new start level.
+            // active start level, then udpate active start level.
+            lowering = (requestedLevel < getActiveStartLevel());
             m_activeStartLevel = requestedLevel;
+        }
 
+        synchronized (m_installedBundleLock_Priority2)
+        {
             // Get a snapshot of all installed bundles.
             bundles = getBundles();
 
@@ -1049,15 +864,15 @@
                 comparator = new Comparator() {
                     public int compare(Object o1, Object o2)
                     {
-                        FelixBundle b1 = (FelixBundle) o1;
-                        FelixBundle b2 = (FelixBundle) o2;
-                        if (b1.getInfo().getStartLevel(getInitialBundleStartLevel())
-                            < b2.getInfo().getStartLevel(getInitialBundleStartLevel()))
+                        BundleImpl b1 = (BundleImpl) o1;
+                        BundleImpl b2 = (BundleImpl) o2;
+                        if (b1.getStartLevel(getInitialBundleStartLevel())
+                            < b2.getStartLevel(getInitialBundleStartLevel()))
                         {
                             return 1;
                         }
-                        else if (b1.getInfo().getStartLevel(getInitialBundleStartLevel())
-                            > b2.getInfo().getStartLevel(getInitialBundleStartLevel()))
+                        else if (b1.getStartLevel(getInitialBundleStartLevel())
+                            > b2.getStartLevel(getInitialBundleStartLevel()))
                         {
                             return -1;
                         }
@@ -1075,15 +890,15 @@
                 comparator = new Comparator() {
                     public int compare(Object o1, Object o2)
                     {
-                        FelixBundle b1 = (FelixBundle) o1;
-                        FelixBundle b2 = (FelixBundle) o2;
-                        if (b1.getInfo().getStartLevel(getInitialBundleStartLevel())
-                            > b2.getInfo().getStartLevel(getInitialBundleStartLevel()))
+                        BundleImpl b1 = (BundleImpl) o1;
+                        BundleImpl b2 = (BundleImpl) o2;
+                        if (b1.getStartLevel(getInitialBundleStartLevel())
+                            > b2.getStartLevel(getInitialBundleStartLevel()))
                         {
                             return 1;
                         }
-                        else if (b1.getInfo().getStartLevel(getInitialBundleStartLevel())
-                            < b2.getInfo().getStartLevel(getInitialBundleStartLevel()))
+                        else if (b1.getStartLevel(getInitialBundleStartLevel())
+                            < b2.getStartLevel(getInitialBundleStartLevel()))
                         {
                             return -1;
                         }
@@ -1102,12 +917,12 @@
         // Stop or start the bundles according to the start level.
         for (int i = 0; (bundles != null) && (i < bundles.length); i++)
         {
-            FelixBundle impl = (FelixBundle) bundles[i];
+            BundleImpl impl = (BundleImpl) bundles[i];
 
             // Ignore the system bundle, since its start() and
             // stop() methods get called explicitly in Felix.start()
-            // and Felix.shutdown(), respectively.
-            if (impl.getInfo().getBundleId() == 0)
+            // and Felix.stop(), respectively.
+            if (impl.getBundleId() == 0)
             {
                 continue;
             }
@@ -1118,9 +933,9 @@
             try
             {
                 // Start the bundle if necessary.
-                if ((impl.getInfo().getPersistentState() == Bundle.ACTIVE) &&
-                    (impl.getInfo().getStartLevel(getInitialBundleStartLevel())
-                        <= m_activeStartLevel))
+                if ((impl.getPersistentState() == Bundle.ACTIVE) &&
+                    (impl.getStartLevel(getInitialBundleStartLevel())
+                        <= getActiveStartLevel()))
                 {
                     try
                     {
@@ -1131,13 +946,13 @@
                         fireFrameworkEvent(FrameworkEvent.ERROR, impl, th);
                         m_logger.log(
                             Logger.LOG_ERROR,
-                            "Error starting " + impl.getInfo().getLocation(), th);
+                            "Error starting " + impl._getLocation(), th);
                     }
                 }
                 // Stop the bundle if necessary.
-                else if ((impl.getInfo().getState() == Bundle.ACTIVE) &&
-                    (impl.getInfo().getStartLevel(getInitialBundleStartLevel())
-                        > m_activeStartLevel))
+                else if ((impl.getState() == Bundle.ACTIVE) &&
+                    (impl.getStartLevel(getInitialBundleStartLevel())
+                        > getActiveStartLevel()))
                 {
                     try
                     {
@@ -1148,7 +963,7 @@
                         fireFrameworkEvent(FrameworkEvent.ERROR, impl, th);
                         m_logger.log(
                             Logger.LOG_ERROR,
-                            "Error stopping " + impl.getInfo().getLocation(), th);
+                            "Error stopping " + impl._getLocation(), th);
                     }
                 }
             }
@@ -1162,7 +977,7 @@
             bundles[i] = null;
         }
 
-        if (m_sbi.getState() == Bundle.ACTIVE)
+        if (getState() == Bundle.ACTIVE)
         {
             fireFrameworkEvent(FrameworkEvent.STARTLEVEL_CHANGED, this, null);
         }
@@ -1174,7 +989,7 @@
      * the Start Level service.
      * @return The default start level for newly installed bundles.
     **/
-    protected int getInitialBundleStartLevel()
+    int getInitialBundleStartLevel()
     {
         String s = (String) m_configMap.get(FelixConstants.BUNDLE_STARTLEVEL_PROP);
 
@@ -1204,7 +1019,7 @@
      * @throws java.security.SecurityException If the caller does not
      *         have <tt>AdminPermission</tt>.
     **/
-    protected void setInitialBundleStartLevel(int startLevel)
+    void setInitialBundleStartLevel(int startLevel)
     {
         if (startLevel <= 0)
         {
@@ -1224,14 +1039,14 @@
      * @throws java.lang.IllegalArgumentException If the specified
      *          bundle has been uninstalled.
     **/
-    protected int getBundleStartLevel(Bundle bundle)
+    int getBundleStartLevel(Bundle bundle)
     {
         if (bundle.getState() == Bundle.UNINSTALLED)
         {
             throw new IllegalArgumentException("Bundle is uninstalled.");
         }
 
-        return ((FelixBundle) bundle).getInfo().getStartLevel(getInitialBundleStartLevel());
+        return ((BundleImpl) bundle).getStartLevel(getInitialBundleStartLevel());
     }
 
     /**
@@ -1245,10 +1060,11 @@
      * @throws java.security.SecurityException If the caller does not
      *          have <tt>AdminPermission</tt>.
     **/
-    protected void setBundleStartLevel(Bundle bundle, int startLevel)
+    void setBundleStartLevel(Bundle bundle, int startLevel)
     {
         // Acquire bundle lock.
-        acquireBundleLock((FelixBundle) bundle);
+        BundleImpl impl = (BundleImpl) bundle;
+        acquireBundleLock(impl);
 
         Throwable rethrow = null;
 
@@ -1261,22 +1077,21 @@
 
             if (startLevel >= 1)
             {
-                FelixBundle impl = (FelixBundle) bundle;
-                impl.getInfo().setStartLevel(startLevel);
+                impl.setStartLevel(startLevel);
 
                 try
                 {
                     // Start the bundle if necessary.
-                    if ((impl.getInfo().getPersistentState() == Bundle.ACTIVE) &&
-                        (impl.getInfo().getStartLevel(getInitialBundleStartLevel())
-                            <= m_activeStartLevel))
+                    if ((impl.getPersistentState() == Bundle.ACTIVE) &&
+                        (impl.getStartLevel(getInitialBundleStartLevel())
+                            <= getActiveStartLevel()))
                     {
                         startBundle(impl, false);
                     }
                     // Stop the bundle if necessary.
-                    else if ((impl.getInfo().getState() == Bundle.ACTIVE) &&
-                        (impl.getInfo().getStartLevel(getInitialBundleStartLevel())
-                        > m_activeStartLevel))
+                    else if ((impl.getState() == Bundle.ACTIVE) &&
+                        (impl.getStartLevel(getInitialBundleStartLevel())
+                            > getActiveStartLevel()))
                     {
                         stopBundle(impl, false);
                     }
@@ -1295,7 +1110,7 @@
         finally
         {
             // Always release bundle lock.
-            releaseBundleLock((FelixBundle) bundle);
+            releaseBundleLock(impl);
         }
 
         if (rethrow != null)
@@ -1313,14 +1128,14 @@
      * @throws java.lang.IllegalArgumentException If the specified
      *          bundle has been uninstalled.
     **/
-    protected boolean isBundlePersistentlyStarted(Bundle bundle)
+    boolean isBundlePersistentlyStarted(Bundle bundle)
     {
         if (bundle.getState() == Bundle.UNINSTALLED)
         {
             throw new IllegalArgumentException("Bundle is uninstalled.");
         }
 
-        return (((FelixBundle) bundle).getInfo().getPersistentState() == Bundle.ACTIVE);
+        return (((BundleImpl) bundle).getPersistentState() == Bundle.ACTIVE);
     }
 
     //
@@ -1333,62 +1148,53 @@
      * @param locale
      * @return localized bundle headers dictionary.
     **/
-    protected Dictionary getBundleHeaders(FelixBundle bundle, String locale)
+    Dictionary getBundleHeaders(BundleImpl bundle, String locale)
     {
-        return new MapToDictionary(bundle.getInfo().getCurrentLocalizedHeader(locale));
-    }
-
-    /**
-     * Implementation for Bundle.getLocation().
-    **/
-    protected String getBundleLocation(FelixBundle bundle)
-    {
-        return bundle.getInfo().getLocation();
+        return new MapToDictionary(bundle.getCurrentLocalizedHeader(locale));
     }
 
     /**
      * Implementation for Bundle.getResource().
     **/
-    protected URL getBundleResource(FelixBundle bundle, String name)
+    URL getBundleResource(BundleImpl bundle, String name)
     {
-        if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
+        if (bundle.getState() == Bundle.UNINSTALLED)
         {
             throw new IllegalStateException("The bundle is uninstalled.");
         }
-        return bundle.getInfo().getCurrentModule().getResource(name);
+        return bundle.getCurrentModule().getResourceByDelegation(name);
     }
 
     /**
      * Implementation for Bundle.getResources().
     **/
-    protected Enumeration getBundleResources(FelixBundle bundle, String name)
+    Enumeration getBundleResources(BundleImpl bundle, String name)
     {
-        if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
+        if (bundle.getState() == Bundle.UNINSTALLED)
         {
             throw new IllegalStateException("The bundle is uninstalled.");
         }
-        return bundle.getInfo().getCurrentModule().getResources(name);
+        return bundle.getCurrentModule().getResourcesByDelegation(name);
     }
 
     /**
      * Implementation for Bundle.getEntry().
     **/
-    protected URL getBundleEntry(FelixBundle bundle, String name)
+    URL getBundleEntry(BundleImpl bundle, String name)
     {
-        if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
+        if (bundle.getState() == Bundle.UNINSTALLED)
         {
             throw new IllegalStateException("The bundle is uninstalled.");
         }
-        return bundle.getInfo().getCurrentModule()
-            .getContentLoader().getResourceFromContent(name);
+        return bundle.getCurrentModule().getResourceFromContent(name);
     }
 
     /**
      * Implementation for Bundle.getEntryPaths().
     **/
-    protected Enumeration getBundleEntryPaths(FelixBundle bundle, String path)
+    Enumeration getBundleEntryPaths(BundleImpl bundle, String path)
     {
-        if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
+        if (bundle.getState() == Bundle.UNINSTALLED)
         {
             throw new IllegalStateException("The bundle is uninstalled.");
         }
@@ -1404,8 +1210,8 @@
     /**
      * Implementation for findEntries().
     **/
-    protected Enumeration findBundleEntries(
-        FelixBundle bundle, String path, String filePattern, boolean recurse)
+    Enumeration findBundleEntries(
+        BundleImpl bundle, String path, String filePattern, boolean recurse)
     {
         // Try to resolve the bundle per the spec.
         resolveBundles(new Bundle[] { bundle });
@@ -1419,9 +1225,9 @@
         return (!enumeration.hasMoreElements()) ? null : enumeration;
     }
 
-    protected ServiceReference[] getBundleRegisteredServices(FelixBundle bundle)
+    ServiceReference[] getBundleRegisteredServices(BundleImpl bundle)
     {
-        if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
+        if (bundle.getState() == Bundle.UNINSTALLED)
         {
             throw new IllegalStateException("The bundle is uninstalled.");
         }
@@ -1432,7 +1238,7 @@
         return refs;
     }
 
-    protected ServiceReference[] getBundleServicesInUse(Bundle bundle)
+    ServiceReference[] getBundleServicesInUse(Bundle bundle)
     {
         // Filter list of "in use" service references.
         ServiceReference[] refs = m_registry.getServicesInUse(bundle);
@@ -1440,9 +1246,9 @@
         return refs;
     }
 
-    protected boolean bundleHasPermission(FelixBundle bundle, Object obj)
+    boolean bundleHasPermission(BundleImpl bundle, Object obj)
     {
-        if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
+        if (bundle.getState() == Bundle.UNINSTALLED)
         {
             throw new IllegalStateException("The bundle is uninstalled.");
         }
@@ -1454,7 +1260,7 @@
                 return (obj instanceof java.security.Permission)
                     ? impliesBundlePermission(
                     (BundleProtectionDomain)
-                    bundle.getInfo().getProtectionDomain(),
+                    bundle.getProtectionDomain(),
                     (java.security.Permission) obj, true)
                     : false;
             }
@@ -1474,13 +1280,13 @@
     /**
      * Implementation for Bundle.loadClass().
     **/
-    protected Class loadBundleClass(FelixBundle bundle, String name) throws ClassNotFoundException
+    Class loadBundleClass(BundleImpl bundle, String name) throws ClassNotFoundException
     {
-        if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
+        if (bundle.getState() == Bundle.UNINSTALLED)
         {
             throw new IllegalStateException("Bundle is uninstalled");
         }
-        else if (bundle.getInfo().getState() == Bundle.INSTALLED)
+        else if (bundle.getState() == Bundle.INSTALLED)
         {
             try
             {
@@ -1494,16 +1300,16 @@
                 throw new ClassNotFoundException(name, ex);
             }
         }
-        return bundle.getInfo().getCurrentModule().getClass(name);
+        return bundle.getCurrentModule().getClassByDelegation(name);
     }
 
     /**
      * Implementation for Bundle.start().
     **/
-    protected void startBundle(FelixBundle bundle, boolean record)
-        throws BundleException
+    void startBundle(BundleImpl bundle, boolean record) throws BundleException
     {
         // CONCURRENCY NOTE:
+// TODO: REFACTOR - This concurrency note will no longer be accurate.
         // Starting a bundle may actually impact many bundles, since
         // the bundle being started my need to be resolved, which in
         // turn may need to resolve other bundles. Despite this fact,
@@ -1541,22 +1347,19 @@
         }
     }
 
-    private void _startBundle(FelixBundle bundle, boolean record)
+    private void _startBundle(BundleImpl bundle, boolean record)
         throws BundleException
     {
-        // Get bundle info object.
-        BundleInfo info = bundle.getInfo();
-
         // The spec doesn't say whether it is possible to start an extension
         // We just do nothing
-        if (info.isExtension())
+        if (bundle.isExtension())
         {
             return;
         }
 
         // 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(info.getCurrentModule()))
+        if (Util.isFragment(bundle.getCurrentModule()))
         {
             throw new BundleException("Fragment bundles can not be started.");
         }
@@ -1565,27 +1368,27 @@
         // if we are supposed to record state change.
         if (record)
         {
-            info.setPersistentStateActive();
+            bundle.setPersistentStateActive();
         }
 
         // Check to see if the bundle's start level is greater than the
-        // the framework's start level.
-        if (info.getStartLevel(getInitialBundleStartLevel()) > getStartLevel())
+        // the framework's active start level.
+        if (bundle.getStartLevel(getInitialBundleStartLevel()) > getActiveStartLevel())
         {
             // Throw an exception for transient starts.
             if (!record)
             {
                 throw new BundleException(
                     "Cannot start bundle " + bundle + " because its start level is "
-                    + info.getStartLevel(getInitialBundleStartLevel())
+                    + bundle.getStartLevel(getInitialBundleStartLevel())
                     + ", which is greater than the framework's start level of "
-                    + getStartLevel() + ".");
+                    + getActiveStartLevel() + ".");
             }
             // Ignore persistent starts.
             return;
         }
 
-        switch (info.getState())
+        switch (bundle.getState())
         {
             case Bundle.UNINSTALLED:
                 throw new IllegalStateException("Cannot start an uninstalled bundle.");
@@ -1599,7 +1402,7 @@
                 _resolveBundle(bundle);
                 // No break.
             case Bundle.RESOLVED:
-                info.setState(Bundle.STARTING);
+                bundle.setState(Bundle.STARTING);
                 fireBundleEvent(BundleEvent.STARTING, bundle);
                 break;
         }
@@ -1607,34 +1410,35 @@
         try
         {
             // Set the bundle's context.
-            info.setBundleContext(new BundleContextImpl(m_logger, this, bundle));
+            bundle.setBundleContext(new BundleContextImpl(m_logger, this, bundle));
 
             // Set the bundle's activator.
-            info.setActivator(createBundleActivator(bundle.getInfo()));
+            bundle.setActivator(createBundleActivator(bundle));
 
             // Activate the bundle if it has an activator.
-            if (bundle.getInfo().getActivator() != null)
+            if (bundle.getActivator() != null)
             {
-                m_secureAction.startActivator(info.getActivator(),info.getBundleContext());
+                m_secureAction.startActivator(
+                    bundle.getActivator(), bundle.getBundleContext());
             }
 
             // TODO: CONCURRENCY - Reconsider firing event outside of the
             // bundle lock.
-            info.setState(Bundle.ACTIVE);
+            bundle.setState(Bundle.ACTIVE);
             fireBundleEvent(BundleEvent.STARTED, bundle);
         }
         catch (Throwable th)
         {
             // If there was an error starting the bundle,
             // then reset its state to RESOLVED.
-            info.setState(Bundle.RESOLVED);
+            bundle.setState(Bundle.RESOLVED);
 
             // Clean up the bundle context.
-            ((BundleContextImpl) info.getBundleContext()).invalidate();
-            info.setBundleContext(null);
+            ((BundleContextImpl) bundle.getBundleContext()).invalidate();
+            bundle.setBundleContext(null);
 
             // Clean up the bundle activator
-            info.setActivator(null);
+            bundle.setActivator(null);
 
             // Unregister any services offered by this bundle.
             m_registry.unregisterServices(bundle);
@@ -1666,10 +1470,11 @@
         }
     }
 
-    protected void _resolveBundle(FelixBundle bundle)
+// TODO: REFACTOR - Need to make sure all callers of this method acquire global lock.
+    protected void _resolveBundle(BundleImpl bundle)
         throws BundleException
     {
-        if (bundle.getInfo().isExtension())
+        if (bundle.isExtension())
         {
             return;
         }
@@ -1678,16 +1483,14 @@
         if (System.getSecurityManager() != null)
         {
             BundleProtectionDomain pd = (BundleProtectionDomain)
-                bundle.getInfo().getProtectionDomain();
-
-            IRequirement[] imports =
-                bundle.getInfo().getCurrentModule().getDefinition().getRequirements();
+                bundle.getProtectionDomain();
 
 /*
  TODO: RB - We need to fix this import check by looking at the wire
             associated with it, not the import since we don't know the
             package name associated with the import since it is a filter.
 
+            IRequirement[] imports = bundle.getInfo().getCurrentModule().getRequirements();
             for (int i = 0; i < imports.length; i++)
             {
                 if (imports[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
@@ -1706,8 +1509,7 @@
             }
 */
             // Check export permission for all exports of the current module.
-            ICapability[] exports =
-                bundle.getInfo().getCurrentModule().getDefinition().getCapabilities();
+            ICapability[] exports = bundle.getCurrentModule().getCapabilities();
             for (int i = 0; i < exports.length; i++)
             {
                 if (exports[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
@@ -1727,7 +1529,7 @@
 
         verifyExecutionEnvironment(bundle);
 
-        IModule module = bundle.getInfo().getCurrentModule();
+        IModule module = bundle.getCurrentModule();
         try
         {
             m_felixResolver.resolve(module);
@@ -1748,7 +1550,7 @@
         }
     }
 
-    protected void updateBundle(FelixBundle bundle, InputStream is)
+    void updateBundle(BundleImpl bundle, InputStream is)
         throws BundleException
     {
         // Acquire bundle lock.
@@ -1765,7 +1567,7 @@
         }
     }
 
-    protected void _updateBundle(FelixBundle bundle, InputStream is)
+    void _updateBundle(BundleImpl bundle, InputStream is)
         throws BundleException
     {
         // We guarantee to close the input stream, so put it in a
@@ -1777,8 +1579,7 @@
             Throwable rethrow = null;
 
             // Cannot update an uninstalled bundle.
-            BundleInfo info = bundle.getInfo();
-            final int oldState = info.getState();
+            final int oldState = bundle.getState();
             if (oldState == Bundle.UNINSTALLED)
             {
                 throw new IllegalStateException("The bundle is uninstalled.");
@@ -1786,12 +1587,13 @@
 
             // First get the update-URL from our header.
             String updateLocation = (String)
-                info.getCurrentHeader().get(Constants.BUNDLE_UPDATELOCATION);
+                bundle.getCurrentModule().getHeaders().get(
+                    Constants.BUNDLE_UPDATELOCATION);
 
             // If no update location specified, use original location.
             if (updateLocation == null)
             {
-                updateLocation = info.getLocation();
+                updateLocation = bundle._getLocation();
             }
 
             // Stop the bundle if it is active, but do not change its
@@ -1803,11 +1605,10 @@
 
             try
             {
-                // Get the bundle's archive.
-                BundleArchive archive = m_cache.getArchive(info.getBundleId());
-                // Update the bundle; this operation will increase
-                // the revision count for the bundle.
-                archive.revise(updateLocation, is);
+                bundle.revise(updateLocation, is);
+// REFACTOR - Are we adding this to the resolver state too early?
+                m_resolverState.addModule(bundle.getCurrentModule());
+
                 // Create a module for the new revision; the revision is
                 // base zero, so subtract one from the revision count to
                 // get the revision of the new update.
@@ -1821,38 +1622,23 @@
                             new AdminPermission(bundle, AdminPermission.LIFECYCLE));
                     }
 
-                    // We need to check whether this is an update to an
-                    // extension bundle (info.isExtension) or an update from
-                    // a normal bundle to an extension bundle
-                    // (isExtensionBundle())
-                    Map headerMap = archive.getRevision(
-                        archive.getRevisionCount() - 1).getManifestHeader();
-                    IModule module = createModule(
-                        info.getBundleId(),
-                        archive.getRevisionCount() - 1,
-                        headerMap,
-                        (bundle.getInfo().isExtension() ||
-                        m_extensionManager.isExtensionBundle(
-                            headerMap)));
-
-                    // Add module to bundle info.
-                    info.addModule(module);
-
                     // If this is an update from a normal to an extension bundle
                     // then attach the extension or else if this already is
                     // an extension bundle then don't allow it to be resolved
                     // again as per spec.
-                    if (!bundle.getInfo().isExtension() &&
-                        m_extensionManager.isExtensionBundle(bundle.getInfo().getCurrentHeader()))
+                    if (!bundle.isExtension() &&
+                        ExtensionManager.isExtensionBundle(
+                            bundle.getCurrentModule().getHeaders()))
                     {
                         addSecurity(bundle);
                         m_extensionManager.addExtensionBundle(this, bundle);
-                        m_factory.refreshModule(m_sbi.getCurrentModule());
-                        bundle.getInfo().setState(Bundle.RESOLVED);
+// TODO: REFACTOR - REFRESH RESOLVER STATE.
+//                        m_factory.refreshModule(m_sbi.getCurrentModule());
+                        bundle.setState(Bundle.RESOLVED);
                     }
-                    else if (bundle.getInfo().isExtension())
+                    else if (bundle.isExtension())
                     {
-                        bundle.getInfo().setState(Bundle.INSTALLED);
+                        bundle.setState(Bundle.INSTALLED);
                     }
                     else
                     {
@@ -1863,7 +1649,7 @@
                 {
                     try
                     {
-                        archive.undoRevise();
+                        bundle.rollbackRevise();
                     }
                     catch (Exception busted)
                     {
@@ -1883,42 +1669,27 @@
             // if successful.
             if (rethrow == null)
             {
-                info.setLastModified(System.currentTimeMillis());
+                bundle.setLastModified(System.currentTimeMillis());
 
-                if (!info.isExtension())
+                if (!bundle.isExtension())
                 {
-                    info.setState(Bundle.INSTALLED);
+                    bundle.setState(Bundle.INSTALLED);
                 }
 
                 fireBundleEvent(BundleEvent.UNRESOLVED, bundle);
 
                 // Mark the bundle as removal pending.
-                info.setRemovalPending(true);
+                bundle.setRemovalPending(true);
 
                 fireBundleEvent(BundleEvent.UPDATED, bundle);
 
-                // Determine if the bundle is in use by anyone.
-                boolean used = false;
-                IModule[] modules = info.getModules();
-                for (int i = 0; !used && (i < modules.length); i++)
-                {
-                    IModule[] dependents = ((ModuleImpl) modules[i]).getDependents();
-                    for (int j = 0; (dependents != null) && (j < dependents.length) && !used; j++)
-                    {
-                        if (dependents[j] != modules[i])
-                        {
-                            used = true;
-                        }
-                    }
-                }
-
                 // If the bundle is not used by anyone, then garbage
                 // collect it now.
-                if (!used)
+                if (!bundle.isUsed())
                 {
                     try
                     {
-                        _refreshPackages(new FelixBundle[] { bundle });
+                        _refreshPackages(new BundleImpl[] { bundle });
                     }
                     catch (Exception ex)
                     {
@@ -1931,9 +1702,9 @@
 
             // If the old state was active, but the new module is a fragment,
             // then mark the persistent state to inactive.
-            if ((oldState == Bundle.ACTIVE) && Util.isFragment(info.getCurrentModule()))
+            if ((oldState == Bundle.ACTIVE) && Util.isFragment(bundle.getCurrentModule()))
             {
-                info.setPersistentStateInactive();
+                bundle.setPersistentStateInactive();
                 m_logger.log(Logger.LOG_WARNING,
                     "Previously active bundle was updated to a fragment, resetting state to inactive: "
                     + bundle);
@@ -1970,7 +1741,7 @@
         }
     }
 
-    protected void stopBundle(FelixBundle bundle, boolean record)
+    protected void stopBundle(BundleImpl bundle, boolean record)
         throws BundleException
     {
         // Acquire bundle lock.
@@ -1987,7 +1758,7 @@
         }
     }
 
-    private void _stopBundle(FelixBundle bundle, boolean record)
+    private void _stopBundle(BundleImpl bundle, boolean record)
         throws BundleException
     {
         Throwable rethrow = null;
@@ -1995,19 +1766,17 @@
         // Set the bundle's persistent state to inactive if necessary.
         if (record)
         {
-            bundle.getInfo().setPersistentStateInactive();
+            bundle.setPersistentStateInactive();
         }
 
-        BundleInfo info = bundle.getInfo();
-
         // 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(info.getCurrentModule()))
+        if (Util.isFragment(bundle.getCurrentModule()))
         {
             throw new BundleException("Fragment bundles can not be stopped: " + bundle);
         }
 
-        switch (info.getState())
+        switch (bundle.getState())
         {
             case Bundle.UNINSTALLED:
                 throw new IllegalStateException("Cannot stop an uninstalled bundle.");
@@ -2019,16 +1788,16 @@
                 return;
             case Bundle.ACTIVE:
                 // Set bundle state..
-                info.setState(Bundle.STOPPING);
+                bundle.setState(Bundle.STOPPING);
                 fireBundleEvent(BundleEvent.STOPPING, bundle);
                 break;
         }
 
         try
         {
-            if (info.getActivator() != null)
+            if (bundle.getActivator() != null)
             {
-                m_secureAction.stopActivator(info.getActivator(), info.getBundleContext());
+                m_secureAction.stopActivator(bundle.getActivator(), bundle.getBundleContext());
             }
         }
         catch (Throwable th)
@@ -2039,14 +1808,14 @@
 
         // Do not clean up after the system bundle since it will
         // clean up after itself.
-        if (info.getBundleId() != 0)
+        if (bundle.getBundleId() != 0)
         {
             // Clean up the bundle context.
-            ((BundleContextImpl) info.getBundleContext()).invalidate();
-            info.setBundleContext(null);
+            ((BundleContextImpl) bundle.getBundleContext()).invalidate();
+            bundle.setBundleContext(null);
 
             // Clean up the bundle activator.
-            info.setActivator(null);
+            bundle.setActivator(null);
 
             // Unregister any services offered by this bundle.
             m_registry.unregisterServices(bundle);
@@ -2058,7 +1827,7 @@
             // listeners for a bundle when it is stopped.
             m_dispatcher.removeListeners(bundle);
 
-            info.setState(Bundle.RESOLVED);
+            bundle.setState(Bundle.RESOLVED);
             fireBundleEvent(BundleEvent.STOPPED, bundle);
         }
 
@@ -2082,11 +1851,12 @@
             }
 
             // Rethrow all other exceptions as a BundleException.
-            throw new BundleException("Activator stop error in bundle " + bundle + ".", rethrow);
+            throw new BundleException(
+                "Activator stop error in bundle " + bundle + ".", rethrow);
         }
     }
 
-    protected void uninstallBundle(FelixBundle bundle) throws BundleException
+    protected void uninstallBundle(BundleImpl bundle) throws BundleException
     {
         // Acquire bundle lock.
         acquireBundleLock(bundle);
@@ -2102,26 +1872,25 @@
         }
     }
 
-    private void _uninstallBundle(FelixBundle bundle) throws BundleException
+    private void _uninstallBundle(BundleImpl bundle) throws BundleException
     {
-        BundleInfo info = bundle.getInfo();
-        if (info.getState() == Bundle.UNINSTALLED)
+        if (bundle.getState() == Bundle.UNINSTALLED)
         {
             throw new IllegalStateException("Bundle " + bundle + " is uninstalled.");
         }
 
         // Extension Bundles are not removed until the framework is shutdown
-        if (info.isExtension())
+        if (bundle.isExtension())
         {
-            info.setPersistentStateUninstalled();
-            info.setState(Bundle.INSTALLED);
+            bundle.setPersistentStateUninstalled();
+            bundle.setState(Bundle.INSTALLED);
             return;
         }
 
         // The spec says that uninstall should always succeed, so
         // catch an exception here if stop() doesn't succeed and
         // rethrow it at the end.
-        if (info.getState() == Bundle.ACTIVE)
+        if (bundle.getState() == Bundle.ACTIVE)
         {
             try
             {
@@ -2134,10 +1903,10 @@
         }
 
         // Remove the bundle from the installed map.
-        FelixBundle target = null;
+        BundleImpl target = null;
         synchronized (m_installedBundleLock_Priority2)
         {
-            target = (FelixBundle) m_installedBundleMap.remove(info.getLocation());
+            target = (BundleImpl) m_installedBundleMap.remove(bundle.getLocation());
             m_installedBundleIndex.remove(new Long(target.getBundleId()));
         }
 
@@ -2146,11 +1915,10 @@
         if (target != null)
         {
             // Set the bundle's persistent state to uninstalled.
-            info.setPersistentStateUninstalled();
+            bundle.setPersistentStateUninstalled();
 
             // Mark the bundle as removal pending.
-            info.setRemovalPending(true);
-            info.markModulesStale();
+            bundle.setRemovalPending(true);
 
             // Put bundle in uninstalled bundle array.
             rememberUninstalledBundle(bundle);
@@ -2162,34 +1930,19 @@
         }
 
         // Set state to uninstalled.
-        info.setState(Bundle.UNINSTALLED);
-        info.setLastModified(System.currentTimeMillis());
+        bundle.setState(Bundle.UNINSTALLED);
+        bundle.setLastModified(System.currentTimeMillis());
 
         // Fire bundle event.
         fireBundleEvent(BundleEvent.UNINSTALLED, bundle);
 
-        // Determine if the bundle is in use by anyone.
-        boolean used = false;
-        IModule[] modules = info.getModules();
-        for (int i = 0; !used && (i < modules.length); i++)
-        {
-            IModule[] dependents = ((ModuleImpl) modules[i]).getDependents();
-            for (int j = 0; (dependents != null) && (j < dependents.length) && !used; j++)
-            {
-                if (dependents[j] != modules[i])
-                {
-                    used = true;
-                }
-            }
-        }
-
         // If the bundle is not used by anyone, then garbage
         // collect it now.
-        if (!used)
+        if (!bundle.isUsed())
         {
             try
             {
-                _refreshPackages(new FelixBundle[] { bundle });
+                _refreshPackages(new BundleImpl[] { bundle });
             }
             catch (Exception ex)
             {
@@ -2228,7 +1981,7 @@
     private Bundle installBundle(long id, String location, InputStream is)
         throws BundleException
     {
-        FelixBundle bundle = null;
+        BundleImpl bundle = null;
 
         // Acquire an install lock.
         acquireInstallLock(location);
@@ -2244,7 +1997,7 @@
 
             // If bundle location is already installed, then
             // return it as required by the OSGi specification.
-            bundle = (FelixBundle) getBundle(location);
+            bundle = (BundleImpl) getBundle(location);
             if (bundle != null)
             {
                 return bundle;
@@ -2308,17 +2061,16 @@
             try
             {
                 BundleArchive archive = m_cache.getArchive(id);
-                Map headerMap = archive.getRevision(
-                    archive.getRevisionCount() - 1).getManifestHeader();
-                bundle = new BundleImpl(
-                    this, createBundleInfo(
-                        archive, headerMap, m_extensionManager.isExtensionBundle(headerMap)));
+
+                // Create bundle.
+                bundle = new BundleImpl(this, archive);
 
                 verifyExecutionEnvironment(bundle);
 
                 addSecurity(bundle);
 
-                if (!bundle.getInfo().isExtension())
+// TODO: REFACTOR - Karl, why do we do this check so late?
+                if (!bundle.isExtension())
                 {
                     Object sm = System.getSecurityManager();
                     if (sm != null)
@@ -2330,9 +2082,13 @@
                 else
                 {
                     m_extensionManager.addExtensionBundle(this, bundle);
-                    m_factory.refreshModule(m_sbi.getCurrentModule());
+// TODO: REFACTOR - REFRESH RESOLVER STATE.
+//                    m_factory.refreshModule(m_sbi.getCurrentModule());
                 }
 
+                // Get the bundle's module and add it to the resolver state.
+                IModule module = bundle.getCurrentModule();
+                m_resolverState.addModule(module);
             }
             catch (Throwable ex)
             {
@@ -2354,7 +2110,7 @@
 
                 if (bundle != null)
                 {
-                    bundle.getInfo().setRemovalPending(true);
+                    bundle.setRemovalPending(true);
                 }
 
                 if ((System.getSecurityManager() != null) &&
@@ -2373,8 +2129,8 @@
             if (isNew)
             {
                 // This will persistently set the bundle's start level.
-                bundle.getInfo().setStartLevel(getInitialBundleStartLevel());
-                bundle.getInfo().setLastModified(System.currentTimeMillis());
+                bundle.setStartLevel(getInitialBundleStartLevel());
+                bundle.setLastModified(System.currentTimeMillis());
             }
 
             synchronized (m_installedBundleLock_Priority2)
@@ -2383,10 +2139,9 @@
                 m_installedBundleIndex.put(new Long(bundle.getBundleId()), bundle);
             }
 
-            if (bundle.getInfo().isExtension())
+            if (bundle.isExtension())
             {
-                FelixBundle systemBundle = (FelixBundle) getBundle(0);
-                acquireBundleLock(systemBundle);
+                acquireBundleLock(this);
 
                 try
                 {
@@ -2394,7 +2149,7 @@
                 }
                 finally
                 {
-                    releaseBundleLock(systemBundle);
+                    releaseBundleLock(this);
                 }
             }
         }
@@ -2431,11 +2186,12 @@
      * @throws BundleException if the bundle's required execution environment does
      *         not match the current execution environment.
     **/
-    private void verifyExecutionEnvironment(FelixBundle bundle)
+    private void verifyExecutionEnvironment(BundleImpl bundle)
         throws BundleException
     {
         String bundleEnvironment = (String)
-            bundle.getInfo().getCurrentHeader().get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
+            bundle.getCurrentModule().getHeaders().get(
+                Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
         if (bundleEnvironment != null)
         {
             bundleEnvironment = bundleEnvironment.trim();
@@ -2541,7 +2297,7 @@
     {
         synchronized (m_installedBundleLock_Priority2)
         {
-            FelixBundle bundle = (FelixBundle) m_installedBundleIndex.get(new Long(id));
+            BundleImpl bundle = (BundleImpl) m_installedBundleIndex.get(new Long(id));
             if (bundle != null)
             {
                 return bundle;
@@ -2668,7 +2424,7 @@
      * @return A <code>ServiceRegistration</code> object or null.
     **/
     protected ServiceRegistration registerService(
-        FelixBundle bundle, String[] classNames, Object svcObj, Dictionary dict)
+        BundleImpl bundle, String[] classNames, Object svcObj, Dictionary dict)
     {
         if (classNames == null)
         {
@@ -2686,10 +2442,9 @@
 
         try
         {
-            BundleInfo info = bundle.getInfo();
-
             // Can only register services if starting or active.
-            if (((info.getState() & (Bundle.STARTING | Bundle.ACTIVE)) == 0) && !info.isExtension())
+            if (((bundle.getState() & (Bundle.STARTING | Bundle.ACTIVE)) == 0)
+                && !bundle.isExtension())
             {
                 throw new IllegalStateException(
                     "Can only register services while bundle is active or activating.");
@@ -2753,8 +2508,8 @@
      * @return Array of ServiceReference objects that meet the criteria
      * @throws InvalidSyntaxException
      */
-    protected ServiceReference[] getServiceReferences(
-        FelixBundle bundle, String className, String expr, boolean checkAssignable)
+    ServiceReference[] getServiceReferences(
+        BundleImpl bundle, String className, String expr, boolean checkAssignable)
         throws InvalidSyntaxException
     {
         // Define filter if expression is not null.
@@ -2804,8 +2559,8 @@
      * @return Array of ServiceReference objects that meet the criteria
      * @throws InvalidSyntaxException
      */
-    protected ServiceReference[] getAllowedServiceReferences(
-        FelixBundle bundle, String className, String expr, boolean checkAssignable)
+    ServiceReference[] getAllowedServiceReferences(
+        BundleImpl bundle, String className, String expr, boolean checkAssignable)
         throws InvalidSyntaxException
     {
         ServiceReference[] refs = getServiceReferences(bundle, className, expr, checkAssignable);
@@ -2873,7 +2628,7 @@
         return m_registry.ungetService(bundle, ref);
     }
 
-    protected File getDataFile(FelixBundle bundle, String s)
+    protected File getDataFile(BundleImpl bundle, String s)
     {
         try
         {
@@ -2908,17 +2663,16 @@
     **/
     protected Bundle getBundle(Class clazz)
     {
-        if (clazz.getClassLoader() instanceof ContentClassLoader)
+        if (clazz.getClassLoader() instanceof ModuleClassLoader)
         {
-            IContentLoader contentLoader =
-                ((ContentClassLoader) clazz.getClassLoader()).getContentLoader();
-            IModule[] modules = m_factory.getModules();
+            IModule module =
+                ((ModuleClassLoader) clazz.getClassLoader()).getModule();
+            IModule[] modules = m_resolverState.getModules();
             for (int i = 0; i < modules.length; i++)
             {
-                if (modules[i].getContentLoader() == contentLoader)
+                if (modules[i] == module)
                 {
-                    long id = Util.getBundleIdFromModuleId(modules[i].getId());
-                    return getBundle(id);
+                    return modules[i].getBundle();
                 }
             }
         }
@@ -2954,8 +2708,7 @@
             for (int pkgIdx = 0; pkgIdx < exporters.length; pkgIdx++)
             {
                 // Get the bundle associated with the current exporting module.
-                FelixBundle bundle = (FelixBundle) getBundle(
-                    Util.getBundleIdFromModuleId(exporters[pkgIdx].m_module.getId()));
+                BundleImpl bundle = (BundleImpl) exporters[pkgIdx].m_module.getBundle();
 
                 // We need to find the version of the exported package, but this
                 // is tricky since there may be multiple versions of the package
@@ -2967,10 +2720,10 @@
                 // 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.
-                IModule[] modules = bundle.getInfo().getModules();
+                IModule[] modules = bundle.getModules();
                 for (int modIdx = 0; modIdx < modules.length; modIdx++)
                 {
-                    ICapability[] ec = modules[modIdx].getDefinition().getCapabilities();
+                    ICapability[] ec = modules[modIdx].getCapabilities();
                     for (int i = 0; (ec != null) && (i < ec.length); i++)
                     {
                         if (ec[i].getNamespace().equals(req.getNamespace()) &&
@@ -3006,7 +2759,7 @@
         // exported packages.
         if (b != null)
         {
-            FelixBundle bundle = (FelixBundle) b;
+            BundleImpl bundle = (BundleImpl) b;
             getExportedPackages(bundle, list);
         }
         // Otherwise return all exported packages.
@@ -3026,7 +2779,7 @@
                         (m_uninstalledBundles != null) && (bundleIdx < m_uninstalledBundles.length);
                         bundleIdx++)
                     {
-                        FelixBundle bundle = m_uninstalledBundles[bundleIdx];
+                        BundleImpl bundle = m_uninstalledBundles[bundleIdx];
                         getExportedPackages(bundle, list);
                     }
                 }
@@ -3035,7 +2788,7 @@
                 Bundle[] bundles = getBundles();
                 for (int bundleIdx = 0; bundleIdx < bundles.length; bundleIdx++)
                 {
-                    FelixBundle bundle = (FelixBundle) bundles[bundleIdx];
+                    BundleImpl bundle = (BundleImpl) bundles[bundleIdx];
                     getExportedPackages(bundle, list);
                 }
             }
@@ -3050,15 +2803,15 @@
      * @param bundle The bundle from which to retrieve exported packages.
      * @param list The list to which the exported packages are added
     **/
-    private void getExportedPackages(FelixBundle bundle, List list)
+    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.
-        IModule[] modules = bundle.getInfo().getModules();
+        IModule[] modules = bundle.getModules();
         for (int modIdx = 0; modIdx < modules.length; modIdx++)
         {
-            ICapability[] caps = modules[modIdx].getDefinition().getCapabilities();
+            ICapability[] caps = modules[modIdx].getCapabilities();
             if ((caps != null) && (caps.length > 0))
             {
                 for (int capIdx = 0; capIdx < caps.length; capIdx++)
@@ -3089,16 +2842,13 @@
         }
     }
 
-    Bundle[] getDependentBundles(FelixBundle exporter)
+    Bundle[] getDependentBundles(BundleImpl exporter)
     {
-        // Get exporting bundle.
-        BundleInfo exporterInfo = exporter.getInfo();
-
         // Create list for storing importing bundles.
         List list = new ArrayList();
 
         // Get all dependent modules from all exporter module revisions.
-        IModule[] modules = exporterInfo.getModules();
+        IModule[] modules = exporter.getModules();
         for (int modIdx = 0; modIdx < modules.length; modIdx++)
         {
             IModule[] dependents = ((ModuleImpl) modules[modIdx]).getDependents();
@@ -3106,8 +2856,7 @@
                 (dependents != null) && (depIdx < dependents.length);
                 depIdx++)
             {
-                Bundle b = getBundle(Util.getBundleIdFromModuleId(dependents[depIdx].getId()));
-                list.add(b);
+                list.add(dependents[depIdx].getBundle());
             }
         }
 
@@ -3126,27 +2875,22 @@
         List list = new ArrayList();
 
         // Get exporting bundle information.
-        FelixBundle exporter = (FelixBundle) ep.getExportingBundle();
+        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.
-        IModule[] expModules = exporter.getInfo().getModules();
+        IModule[] expModules = exporter.getModules();
         for (int expIdx = 0; (expModules != null) && (expIdx < expModules.length); expIdx++)
         {
             IModule[] dependents = ((ModuleImpl) expModules[expIdx]).getDependentImporters();
             for (int depIdx = 0; (dependents != null) && (depIdx < dependents.length); depIdx++)
             {
-                // ExportedPackage.getImportingBundles() does not expect a bundle to
-                // depend on itself, so ignore that case.
-                if (!expModules[expIdx].equals(dependents[depIdx]))
-                {
-                    list.add(getBundle(Util.getBundleIdFromModuleId(dependents[depIdx].getId())));
-                }
+                list.add(dependents[depIdx].getBundle());
             }
             dependents = ((ModuleImpl) expModules[expIdx]).getDependentRequirers();
             for (int depIdx = 0; (dependents != null) && (depIdx < dependents.length); depIdx++)
             {
-                list.add(getBundle(Util.getBundleIdFromModuleId(dependents[depIdx].getId())));
+                list.add(dependents[depIdx].getBundle());
             }
         }
 
@@ -3162,7 +2906,7 @@
     protected boolean resolveBundles(Bundle[] targets)
     {
         // Acquire locks for all bundles to be resolved.
-        FelixBundle[] bundles = acquireBundleResolveLocks(targets);
+        BundleImpl[] bundles = acquireBundleResolveLocks(targets);
 
         try
         {
@@ -3199,7 +2943,7 @@
 
     protected void refreshPackages(Bundle[] targets)
     {
-        FelixBundle[] bundles = acquireBundleRefreshLocks(targets);
+        BundleImpl[] bundles = acquireBundleRefreshLocks(targets);
         try
         {
             _refreshPackages(bundles);
@@ -3211,18 +2955,18 @@
         }
     }
 
-    protected void _refreshPackages(FelixBundle[] bundles)
+    protected void _refreshPackages(BundleImpl[] bundles)
     {
         boolean restart = false;
 
-        Bundle systemBundle = getBundle(0);
+        Bundle systemBundle = this;
 
         // We need to restart the framework if either an extension bundle is
         // refreshed or the system bundle is refreshed and any extension bundle
         // has been updated or uninstalled.
         for (int i = 0; (bundles != null) && !restart && (i < bundles.length); i++)
         {
-            if (bundles[i].getInfo().isExtension())
+            if (bundles[i].isExtension())
             {
                 restart = true;
             }
@@ -3231,7 +2975,7 @@
                 Bundle[] allBundles = getBundles();
                 for (int j = 0; !restart && j < allBundles.length; j++)
                 {
-                    if (((FelixBundle) allBundles[j]).getInfo().isExtension() &&
+                    if (((BundleImpl) allBundles[j]).isExtension() &&
                         (allBundles[j].getState() == Bundle.INSTALLED))
                     {
                         restart = true;
@@ -3264,7 +3008,7 @@
             RefreshHelper[] helpers = new RefreshHelper[bundles.length];
             for (int i = 0; i < bundles.length; i++)
             {
-                if (!bundles[i].getInfo().isExtension())
+                if (!bundles[i].isExtension())
                 {
                     helpers[i] = new RefreshHelper(bundles[i]);
                 }
@@ -3294,7 +3038,7 @@
         fireFrameworkEvent(FrameworkEvent.PACKAGES_REFRESHED, this, null);
     }
 
-    private void populateDependentGraph(FelixBundle exporter, Map map)
+    private void populateDependentGraph(BundleImpl exporter, Map map)
     {
         // Get all dependent bundles of this bundle.
         Bundle[] dependents = getDependentBundles(exporter);
@@ -3310,7 +3054,7 @@
                 map.put(dependents[depIdx], dependents[depIdx]);
                 // Now recurse into each bundle to get its importers.
                 populateDependentGraph(
-                    (FelixBundle) dependents[depIdx], map);
+                    (BundleImpl) dependents[depIdx], map);
             }
         }
     }
@@ -3319,23 +3063,6 @@
     // Miscellaneous private methods.
     //
 
-    private RegularBundleInfo createBundleInfo(BundleArchive archive, Map headerMap, boolean isExtension)
-        throws Exception
-    {
-        // Create the module for the bundle; although there should only
-        // ever be one revision at this point, create the module for
-        // the current revision to be safe.
-        IModule module = createModule(
-            archive.getId(), archive.getRevisionCount() - 1, headerMap,
-            isExtension);
-
-        // Finally, create an return the bundle info.
-        RegularBundleInfo info = new RegularBundleInfo(m_logger, module, archive);
-        info.setExtension(isExtension);
-
-        return info;
-    }
-
     private volatile SecurityProvider m_securityProvider;
 
     void setSecurityProvider(SecurityProvider securityProvider)
@@ -3343,9 +3070,9 @@
         m_securityProvider = securityProvider;
     }
 
-    Object getSignerMatcher(FelixBundle bundle)
+    Object getSignerMatcher(BundleImpl bundle)
     {
-        if (m_securityProvider != null)
+        if ((bundle != this) && (m_securityProvider != null))
         {
             return m_securityProvider.getSignerMatcher(bundle);
         }
@@ -3361,129 +3088,25 @@
         return true;
     }
 
-    void addSecurity(final FelixBundle bundle) throws Exception
+    void addSecurity(final BundleImpl bundle) throws Exception
     {
         if (m_securityProvider != null)
         {
             m_securityProvider.checkBundle(bundle);
         }
-        bundle.getInfo().setProtectionDomain(new BundleProtectionDomain(this, bundle));
+        bundle.setProtectionDomain(new BundleProtectionDomain(this, bundle));
     }
 
-    /**
-     * Creates a module for a given bundle by reading the bundle's
-     * manifest meta-data and converting it to work with the underlying
-     * import/export search policy of the module loader.
-     * @param targetId The identifier of the bundle for which the module should
-     *        be created.
-     * @param headerMap The headers map associated with the bundle.
-     * @return The initialized and/or newly created module.
-    **/
-    private IModule createModule(long targetId, int revision, Map headerMap,
-        boolean isExtensionBundle) throws Exception
-    {
-        ManifestParser mp = new ManifestParser(m_logger, m_configMap, headerMap);
-
-        // Verify that the bundle symbolic name and version is unique.
-        if (mp.getManifestVersion().equals("2"))
-        {
-            Version bundleVersion = mp.getBundleVersion();
-            bundleVersion = (bundleVersion == null) ? Version.emptyVersion : bundleVersion;
-            String symName = mp.getSymbolicName();
-
-            Bundle[] bundles = getBundles();
-            for (int i = 0; (bundles != null) && (i < bundles.length); i++)
-            {
-                long id = ((FelixBundle) bundles[i]).getBundleId();
-                String sym = bundles[i].getSymbolicName();
-                Version ver = Version.parseVersion((String) ((FelixBundle) bundles[i])
-                    .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION));
-                if (symName.equals(sym) && bundleVersion.equals(ver) && (targetId != id))
-                {
-                    throw new BundleException("Bundle symbolic name and version are not unique: " + sym + ':' + ver);
-                }
-            }
-        }
-
-        // Now that we have all of the metadata associated with the
-        // module, we need to create the module itself. This is somewhat
-        // complicated because a module is constructed out of several
-        // interrelated pieces (e.g., module definition, content loader,
-        // search policy, url policy). We need to create all of these
-        // pieces and bind them together.
-
-        // Create the module definition for the new module.
-        // Note, in case this is an extension bundle it's exports are removed -
-        // they will be added to the system bundle directly later on.
-        IModuleDefinition md = new ModuleDefinition(
-            headerMap,
-            (isExtensionBundle) ? null : mp.getCapabilities(),
-            mp.getRequirements(),
-            mp.getDynamicRequirements(),
-            mp.getLibraries());
-
-        // Create the module using the module definition.
-        IModule module = m_factory.createModule(
-            Long.toString(targetId) + "." + Integer.toString(revision), md);
-        m_resolverState.addModule(module);
-
-        // Create the content loader from the module archive.
-        IContentLoader contentLoader = new ContentLoaderImpl(
-                m_logger, m_cache.getArchive(targetId).getRevision(revision).getContent());
-        // Set the content loader's search policy.
-        contentLoader.setSearchPolicy(
-                new R4SearchPolicy(m_policyCore, module));
-        // Set the content loader's URL policy.
-        contentLoader.setURLPolicy(
-// TODO: ML - SUCKS NEEDING URL POLICY PER MODULE.
-                new URLPolicyImpl(
-                    m_logger, m_bundleStreamHandler, module));
-
-        // Set the module's content loader to the created content loader.
-        m_factory.setContentLoader(module, contentLoader);
-
-        // Verify that all native libraries exist in advance; this will
-        // throw an exception if the native library does not exist.
-        // TODO: CACHE - It would be nice if this check could be done
-        //               some place else in the module, perhaps.
-        R4Library[] libs = md.getLibraries();
-        for (int i = 0; (libs != null) && (i < libs.length); i++)
-        {
-            String entryName = libs[i].getEntryName();
-            if (entryName != null)
-            {
-                if (contentLoader.getContent().getEntryAsNativeLibrary(entryName) == null)
-                {
-                    // The content loader was opened when trying to find the libraries,
-                    // so make sure to close it since it will be deleted.
-                    contentLoader.close();
-                    // Remove the module we created, since it is not valid and
-                    // has not yet been added to the bundle to be removed later.
-                    m_factory.removeModule(module);
-                    throw new BundleException("Native library does not exist: " + entryName);
-// TODO: REFACTOR - We have a memory leak here since we added a module above
-//                  and then don't remove it in case of an error; this may also
-//                  be a general issue for installing/updating bundles, so check.
-//                  This will likely go away when we refactor out the module
-//                  factory, but we will track it under FELIX-835 until then.
-                }
-            }
-        }
-
-        // Done, so return the module.
-        return module;
-    }
-
-    private BundleActivator createBundleActivator(BundleInfo info)
+    private BundleActivator createBundleActivator(BundleImpl impl)
         throws Exception
     {
         // CONCURRENCY NOTE:
         // This method is called indirectly from startBundle() (via _startBundle()),
-        // which has the exclusion lock, so there is no need to do any locking here.
+        // which has the bundle lock, so there is no need to do any locking here.
 
         // Get the activator class from the header map.
         BundleActivator activator = null;
-        Map headerMap = info.getCurrentHeader();
+        Map headerMap = impl.getCurrentModule().getHeaders();
         String className = (String) headerMap.get(Constants.BUNDLE_ACTIVATOR);
         // Try to instantiate activator class if present.
         if (className != null)
@@ -3492,11 +3115,11 @@
             Class clazz;
             try
             {
-                clazz = info.getCurrentModule().getClass(className);
+                clazz = impl.getCurrentModule().getClassByDelegation(className);
             }
-            catch (ClassNotFoundException ex) {
-                throw new BundleException("Not found: "
-                    + className, ex);
+            catch (ClassNotFoundException ex)
+            {
+                throw new BundleException("Not found: " + className, ex);
             }
             activator = (BundleActivator) clazz.newInstance();
         }
@@ -3504,15 +3127,13 @@
         return activator;
     }
 
-    private void purgeBundle(FelixBundle bundle) throws Exception
+    private void purgeBundle(BundleImpl bundle) throws Exception
     {
         // Acquire bundle lock.
         acquireBundleLock(bundle);
 
         try
         {
-            BundleInfo info = bundle.getInfo();
-
             // In case of a refresh, then we want to physically
             // remove the bundle's modules from the module manager.
             // This is necessary for two reasons: 1) because
@@ -3524,15 +3145,14 @@
             // way to do this is to remove the bundle, but that
             // would be incorrect, because this is a refresh operation
             // and should not trigger bundle REMOVE events.
-            IModule[] modules = info.getModules();
+            IModule[] modules = bundle.getModules();
             for (int i = 0; i < modules.length; i++)
             {
-                m_factory.removeModule(modules[i]);
                 m_resolverState.removeModule(modules[i]);
             }
 
             // Purge all bundle revisions, but the current one.
-            m_cache.getArchive(info.getBundleId()).purge();
+            m_cache.getArchive(bundle.getBundleId()).purge();
         }
         finally
         {
@@ -3541,7 +3161,7 @@
         }
     }
 
-    private void garbageCollectBundle(FelixBundle bundle) throws Exception
+    private void garbageCollectBundle(BundleImpl bundle) throws Exception
     {
         // CONCURRENCY NOTE: There is no reason to lock this bundle,
         // because this method is only called during shutdown or a
@@ -3549,10 +3169,9 @@
 
         // Remove the bundle's associated modules from
         // the module manager.
-        IModule[] modules = bundle.getInfo().getModules();
+        IModule[] modules = bundle.getModules();
         for (int i = 0; i < modules.length; i++)
         {
-            m_factory.removeModule(modules[i]);
             m_resolverState.removeModule(modules[i]);
         }
 
@@ -3786,7 +3405,7 @@
 
         public void resolve(IModule rootModule) throws ResolveException
         {
-            if (!m_resolverState.isResolved(rootModule))
+            if (!rootModule.isResolved())
             {
                 Map resolvedModuleWireMap = m_resolver.resolve(m_resolverState, rootModule);
 
@@ -3799,7 +3418,7 @@
         {
             IWire candidateWire = null;
 
-            if (m_resolverState.isResolved(importer))
+            if (importer.isResolved())
             {
                 Object[] result = m_resolver.resolveDynamicImport(m_resolverState, importer, pkgName);
                 if (result != null)
@@ -3874,19 +3493,17 @@
                         }
                         else
                         {
+m_logger.log(Logger.LOG_DEBUG, "WIRE: " + wires[wireIdx]);
                             wireList.add(wires[wireIdx]);
                         }
                     }
                     wires = (IWire[]) wireList.toArray(new IWire[wireList.size()]);
                     ((ModuleImpl) module).setWires(wires);
-for (int wireIdx = 0; (wires != null) && (wireIdx < wires.length); wireIdx++)
-{
-    m_logger.log(Logger.LOG_DEBUG, "WIRE: " + wires[wireIdx]);
-}
                 }
 
                 // Update the resolver state to show the module as resolved.
-                m_resolverState.setResolved(module, true);
+                ((ModuleImpl) module).setResolved();
+                m_resolverState.moduleResolved(module);
                 // Update the state of the module's bundle to resolved as well.
                 markBundleResolved(module);
 
@@ -3905,7 +3522,8 @@
 m_logger.log(Logger.LOG_DEBUG, "(FRAGMENT) WIRE: " + host + " -> hosts -> " + fragmentList.get(i));
 
                     // Update the resolver state to show the module as resolved.
-                    m_resolverState.setResolved((IModule) fragmentList.get(i), true);
+                    ((ModuleImpl) fragmentList.get(i)).setResolved();
+                    m_resolverState.moduleResolved((IModule) fragmentList.get(i));
                     // Update the state of the module's bundle to resolved as well.
                     markBundleResolved((IModule) fragmentList.get(i));
                 }
@@ -3923,48 +3541,36 @@
 
         private void markBundleResolved(IModule module)
         {
-            // Mark associated bundle as resolved.
+            // Update the bundle's state to resolved when the
+            // current module 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();
+
+            // Lock the bundle first.
             try
             {
-                long id = Util.getBundleIdFromModuleId(module.getId());
-                if (id > 0)
-                {
-                    // Update the bundle's state to resolved when the
-                    // current module 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.
-                    FelixBundle bundle = (FelixBundle) getBundle(id);
-
-                    // Lock the bundle first.
-                    try
-                    {
 // TODO: RESOLVER - Seems like we should release the lock before we fire the event.
-                        acquireBundleLock(bundle);
-                        if (bundle.getInfo().getCurrentModule() == module)
-                        {
-                            if (bundle.getInfo().getState() != Bundle.INSTALLED)
-                            {
-                                m_logger.log(
-                                    Logger.LOG_WARNING,
-                                    "Received a resolve event for a bundle that has already been resolved.");
-                            }
-                            else
-                            {
-                                bundle.getInfo().setState(Bundle.RESOLVED);
-                                fireBundleEvent(BundleEvent.RESOLVED, bundle);
-                            }
-                        }
-                    }
-                    finally
+                acquireBundleLock(bundle);
+                if (bundle.getCurrentModule() == module)
+                {
+                    if (bundle.getState() != Bundle.INSTALLED)
                     {
-                        releaseBundleLock(bundle);
+                        m_logger.log(
+                            Logger.LOG_WARNING,
+                            "Received a resolve event for a bundle that has already been resolved.");
+                    }
+                    else
+                    {
+                        bundle.setState(Bundle.RESOLVED);
+                        fireBundleEvent(BundleEvent.RESOLVED, bundle);
                     }
                 }
             }
-            catch (NumberFormatException ex)
+            finally
             {
-                // Ignore.
+                releaseBundleLock(bundle);
             }
         }
     }
@@ -4008,7 +3614,7 @@
             {
                 // Change framework state from active to stopping.
                 // If framework is not active, then just return.
-                if (m_sbi.getState() != Bundle.STOPPING)
+                if (getState() != Bundle.STOPPING)
                 {
                     return;
                 }
@@ -4039,19 +3645,18 @@
             Bundle[] bundles = getBundles();
             for (int i = 0; i < bundles.length; i++)
             {
-                FelixBundle bundle = (FelixBundle) bundles[i];
-                IModule[] modules = bundle.getInfo().getModules();
+                BundleImpl bundle = (BundleImpl) bundles[i];
+                IModule[] modules = bundle.getModules();
                 for (int j = 0; j < modules.length; j++)
                 {
                     try
                     {
-                        m_factory.removeModule(modules[j]);
                         m_resolverState.removeModule(modules[j]);
                     }
                     catch (Exception ex)
                     {
                         m_logger.log(Logger.LOG_ERROR,
-                           "Unable to clean up " + bundle.getInfo().getLocation(), ex);
+                           "Unable to clean up " + bundle._getLocation(), ex);
                     }
                 }
             }
@@ -4065,10 +3670,8 @@
             bundles = getBundles();
             for (int i = 0; i < bundles.length; i++)
             {
-                FelixBundle bundle = (FelixBundle) bundles[i];
-                BundleInfo info = bundle.getInfo();
-                if ((info instanceof RegularBundleInfo) &&
-                    (((RegularBundleInfo) info).getArchive().getRevisionCount() > 1))
+                BundleImpl bundle = (BundleImpl) bundles[i];
+                if (bundle.isRemovalPending())
                 {
                     try
                     {
@@ -4078,7 +3681,7 @@
                     {
                         fireFrameworkEvent(FrameworkEvent.ERROR, bundle, ex);
                         m_logger.log(Logger.LOG_ERROR, "Unable to purge bundle "
-                            + bundle.getInfo().getLocation(), ex);
+                            + bundle._getLocation(), ex);
                     }
                 }
             }
@@ -4097,7 +3700,7 @@
                     m_logger.log(
                         Logger.LOG_ERROR,
                         "Unable to remove "
-                        + m_uninstalledBundles[i].getInfo().getLocation(), ex);
+                        + m_uninstalledBundles[i]._getLocation(), ex);
                 }
             }
 
@@ -4107,7 +3710,7 @@
                 try
                 {
                     Felix.m_secureAction.stopActivator((BundleActivator)
-                        m_activatorList.get(i), getInfo().getBundleContext());
+                        m_activatorList.get(i), getBundleContext());
                 }
                 catch (Throwable throwable)
                 {
@@ -4126,7 +3729,7 @@
             // Set the framework state to resolved.
             synchronized (Felix.this)
             {
-                m_sbi.setState(Bundle.RESOLVED);
+                setState(Bundle.RESOLVED);
                 m_shutdownGate.open();
                 m_shutdownGate = null;
                 m_shutdownThread = null;
@@ -4141,17 +3744,17 @@
     **/
     private class RefreshHelper
     {
-        private FelixBundle m_bundle = null;
+        private BundleImpl m_bundle = null;
         private int m_oldState = Bundle.INSTALLED;
 
         public RefreshHelper(Bundle bundle)
         {
-            m_bundle = (FelixBundle) bundle;
+            m_bundle = (BundleImpl) bundle;
         }
 
         public void stop()
         {
-            if (m_bundle.getInfo().getState() == Bundle.ACTIVE)
+            if (m_bundle.getState() == Bundle.ACTIVE)
             {
                 m_oldState = Bundle.ACTIVE;
                 try
@@ -4169,14 +3772,12 @@
         {
             try
             {
-                BundleInfo info = m_bundle.getInfo();
-
                 // Mark the bundle as stale.
-                info.setStale();
+                m_bundle.setStale();
 
                 // Remove or purge the bundle depending on its
                 // current state.
-                if (info.getState() == Bundle.UNINSTALLED)
+                if (m_bundle.getState() == Bundle.UNINSTALLED)
                 {
                     // This physically removes the bundle from memory
                     // as well as the bundle cache.
@@ -4203,11 +3804,13 @@
             {
                 try
                 {
-                    RegularBundleInfo info = (RegularBundleInfo) m_bundle.getInfo();
-                    RegularBundleInfo newInfo = createBundleInfo(
-                        info.getArchive(), info.getCurrentHeader(), info.isExtension());
-                    newInfo.syncLock(info);
-                    ((BundleImpl) m_bundle).setInfo(newInfo);
+                    BundleImpl oldImpl = (BundleImpl) m_bundle;
+                    // Create the module for the new revision.
+                    oldImpl.reset();
+                    // Add new module to resolver state.
+// TODO: REFACTOR - It is not clean to have to remember these steps.
+                    m_resolverState.addModule(oldImpl.getCurrentModule());
+// TODO: REFACTOR - Seems like we don't need to repeat this.
                     addSecurity(m_bundle);
                     fireBundleEvent(BundleEvent.UNRESOLVED, m_bundle);
                 }
@@ -4238,7 +3841,7 @@
     // Locking related methods.
     //
 
-    private void rememberUninstalledBundle(FelixBundle bundle)
+    private void rememberUninstalledBundle(BundleImpl bundle)
     {
         synchronized (m_uninstalledBundlesLock_Priority3)
         {
@@ -4255,8 +3858,8 @@
 
             if (m_uninstalledBundles != null)
             {
-                FelixBundle[] newBundles =
-                    new FelixBundle[m_uninstalledBundles.length + 1];
+                BundleImpl[] newBundles =
+                    new BundleImpl[m_uninstalledBundles.length + 1];
                 System.arraycopy(m_uninstalledBundles, 0,
                     newBundles, 0, m_uninstalledBundles.length);
                 newBundles[m_uninstalledBundles.length] = bundle;
@@ -4264,12 +3867,12 @@
             }
             else
             {
-                m_uninstalledBundles = new FelixBundle[] { bundle };
+                m_uninstalledBundles = new BundleImpl[] { bundle };
             }
         }
     }
 
-    private void forgetUninstalledBundle(FelixBundle bundle)
+    private void forgetUninstalledBundle(BundleImpl bundle)
     {
         synchronized (m_uninstalledBundlesLock_Priority3)
         {
@@ -4293,13 +3896,13 @@
                 // If this is the only bundle, then point to empty list.
                 if ((m_uninstalledBundles.length - 1) == 0)
                 {
-                    m_uninstalledBundles = new FelixBundle[0];
+                    m_uninstalledBundles = new BundleImpl[0];
                 }
                 // Otherwise, we need to do some array copying.
                 else
                 {
-                    FelixBundle[] newBundles =
-                        new FelixBundle[m_uninstalledBundles.length - 1];
+                    BundleImpl[] newBundles =
+                        new BundleImpl[m_uninstalledBundles.length - 1];
                     System.arraycopy(m_uninstalledBundles, 0, newBundles, 0, idx);
                     if (idx < newBundles.length)
                     {
@@ -4343,7 +3946,7 @@
         }
     }
 
-    void acquireBundleLock(FelixBundle bundle)
+    void acquireBundleLock(BundleImpl bundle)
     {
         synchronized (m_bundleLock)
         {
@@ -4372,7 +3975,7 @@
             m_lockingThreadMap.put(Thread.currentThread(), counter);
 
             // Wait until the bundle lock is available, then lock it.
-            while (!bundle.getInfo().isLockable())
+            while (!bundle.isLockable())
             {
                 try
                 {
@@ -4383,11 +3986,11 @@
                     // Ignore and just keep waiting.
                 }
             }
-            bundle.getInfo().lock();
+            bundle.lock();
         }
     }
 
-    private boolean acquireBundleLockOrFail(FelixBundle bundle)
+    private boolean acquireBundleLockOrFail(BundleImpl bundle)
     {
         synchronized (m_bundleLock)
         {
@@ -4407,7 +4010,7 @@
             }
 
             // Return immediately if the bundle lock is not available.
-            if (!bundle.getInfo().isLockable())
+            if (!bundle.isLockable())
             {
                 return false;
             }
@@ -4422,12 +4025,12 @@
             m_lockingThreadMap.put(Thread.currentThread(), counter);
 
             // Acquire the bundle lock.
-            bundle.getInfo().lock();
+            bundle.lock();
             return true;
         }
     }
 
-    void releaseBundleLock(FelixBundle bundle)
+    void releaseBundleLock(BundleImpl bundle)
     {
         synchronized (m_bundleLock)
         {
@@ -4451,22 +4054,22 @@
             }
 
             // Unlock the bundle.
-            bundle.getInfo().unlock();
+            bundle.unlock();
             m_bundleLock.notifyAll();
         }
     }
 
-    private FelixBundle[] acquireBundleResolveLocks(Bundle[] targets)
+    private BundleImpl[] acquireBundleResolveLocks(Bundle[] targets)
     {
         // Hold bundles to be locked.
-        FelixBundle[] bundles = null;
+        BundleImpl[] bundles = null;
         // Convert existing target bundle array to bundle impl array.
         if (targets != null)
         {
-            bundles = new FelixBundle[targets.length];
+            bundles = new BundleImpl[targets.length];
             for (int i = 0; i < targets.length; i++)
             {
-                bundles[i] = (FelixBundle) targets[i];
+                bundles[i] = (BundleImpl) targets[i];
             }
         }
 
@@ -4512,8 +4115,8 @@
                     Iterator iter = m_installedBundleMap.values().iterator();
                     while (iter.hasNext())
                     {
-                        FelixBundle bundle = (FelixBundle) iter.next();
-                        if (bundle.getInfo().getState() == Bundle.INSTALLED)
+                        BundleImpl bundle = (BundleImpl) iter.next();
+                        if (bundle.getState() == Bundle.INSTALLED)
                         {
                             list.add(bundle);
                         }
@@ -4523,7 +4126,7 @@
                 // Create an array.
                 if (list.size() > 0)
                 {
-                    bundles = (FelixBundle[]) list.toArray(new FelixBundle[list.size()]);
+                    bundles = (BundleImpl[]) list.toArray(new BundleImpl[list.size()]);
                 }
             }
 
@@ -4531,17 +4134,17 @@
             // necessary since we hold the global lock.
             for (int i = 0; (bundles != null) && (i < bundles.length); i++)
             {
-                bundles[i].getInfo().lock();
+                bundles[i].lock();
             }
         }
 
         return bundles;
     }
 
-    private FelixBundle[] acquireBundleRefreshLocks(Bundle[] targets)
+    private BundleImpl[] acquireBundleRefreshLocks(Bundle[] targets)
     {
         // Hold bundles to be locked.
-        FelixBundle[] bundles = null;
+        BundleImpl[] bundles = null;
 
         synchronized (m_bundleLock)
         {
@@ -4597,10 +4200,8 @@
                     Iterator iter = m_installedBundleMap.values().iterator();
                     while (iter.hasNext())
                     {
-                        FelixBundle bundle = (FelixBundle) iter.next();
-                        BundleInfo info = bundle.getInfo();
-                        if ((info instanceof RegularBundleInfo) &&
-                            (((RegularBundleInfo) info).getArchive().getRevisionCount() > 1))
+                        BundleImpl bundle = (BundleImpl) iter.next();
+                        if (bundle.isRemovalPending())
                         {
                             list.add(bundle);
                         }
@@ -4625,27 +4226,27 @@
                 {
                     // Add the current target bundle to the map of
                     // bundles to be refreshed.
-                    FelixBundle target = (FelixBundle) newTargets[targetIdx];
+                    BundleImpl target = (BundleImpl) newTargets[targetIdx];
                     map.put(target, target);
                     // Add all importing bundles to map.
                     populateDependentGraph(target, map);
                 }
 
-                bundles = (FelixBundle[]) map.values().toArray(new FelixBundle[map.size()]);
+                bundles = (BundleImpl[]) map.values().toArray(new BundleImpl[map.size()]);
             }
 
             // Lock all needed bundles; this is not strictly
             // necessary since we hold the global lock.
             for (int i = 0; (bundles != null) && (i < bundles.length); i++)
             {
-                bundles[i].getInfo().lock();
+                bundles[i].lock();
             }
         }
 
         return bundles;
     }
 
-    private void releaseBundleLocks(FelixBundle[] bundles)
+    private void releaseBundleLocks(BundleImpl[] bundles)
     {
         // Always unlock any locked bundles.
         synchronized (m_bundleLock)
@@ -4676,9 +4277,9 @@
             // Unlock all the bundles.
             for (int i = 0; (bundles != null) && (i < bundles.length); i++)
             {
-                bundles[i].getInfo().unlock();
+                bundles[i].unlock();
             }
             m_bundleLock.notifyAll();
         }
     }
-}
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/FelixBundle.java b/framework/src/main/java/org/apache/felix/framework/FelixBundle.java
deleted file mode 100644
index 4e27160..0000000
--- a/framework/src/main/java/org/apache/felix/framework/FelixBundle.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework;
-
-import org.osgi.framework.Bundle;
-
-abstract class FelixBundle implements Bundle
-{
-    /* package private */ abstract BundleInfo getInfo();
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java b/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
index 8c0dbe5..4e90912 100644
--- a/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
+++ b/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
@@ -24,6 +24,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import org.apache.felix.framework.searchpolicy.ModuleImpl;
 import org.apache.felix.framework.searchpolicy.Resolver;
 import org.apache.felix.framework.searchpolicy.PackageSource;
 import org.apache.felix.framework.util.Util;
@@ -32,7 +33,6 @@
 import org.apache.felix.moduleloader.IModule;
 import org.apache.felix.moduleloader.IRequirement;
 import org.apache.felix.moduleloader.IWire;
-import org.apache.felix.moduleloader.ModuleImpl;
 import org.osgi.framework.Constants;
 import org.osgi.framework.PackagePermission;
 import org.osgi.framework.Version;
@@ -66,7 +66,7 @@
         // exports to simplify later processing when resolving bundles.
         m_moduleList.add(module);
 
-        ICapability[] caps = module.getDefinition().getCapabilities();
+        ICapability[] caps = module.getCapabilities();
 
         // Add exports to unresolved package map.
         for (int i = 0; (caps != null) && (i < caps.length); i++)
@@ -93,7 +93,7 @@
         m_moduleList.remove(module);
 
         // Remove exports from package maps.
-        ICapability[] caps = module.getDefinition().getCapabilities();
+        ICapability[] caps = module.getCapabilities();
         for (int i = 0; (caps != null) && (i < caps.length); i++)
         {
             if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
@@ -132,6 +132,9 @@
         // Set wires to null, which will remove the module from all
         // of its dependent modules.
         ((ModuleImpl) module).setWires(null);
+        // Close the module's content.
+        ((ModuleImpl) module).close();
+
         // Remove the module from the "resolved" map.
 // TODO: RB - Maybe this can be merged with ModuleData.
         m_resolvedCapMap.remove(module);
@@ -139,6 +142,39 @@
         m_moduleDataMap.remove(module);
     }
 
+/* TODO: RESOLVER - We need to figure out what to do with this.
+    public void moduleRefreshed(ModuleEvent event)
+    {
+        synchronized (m_factory)
+        {
+            IModule module = event.getModule();
+            // Remove exports from package maps.
+            ICapability[] caps = event.getModule().getDefinition().getCapabilities();
+            // Add exports to unresolved package map.
+            for (int i = 0; (caps != null) && (i < caps.length); i++)
+            {
+                ICapability[] resolvedCaps = (ICapability[]) m_resolvedCapMap.get(module);
+                resolvedCaps = addCapabilityToArray(resolvedCaps, caps[i]);
+                m_resolvedCapMap.put(module, resolvedCaps);
+
+                // If the capability is a package, then add the exporter module
+                // of the wire to the "resolved" package index and remove it
+                // from the "unresolved" package index.
+                if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+                {
+                    // Get package name.
+                    String pkgName = (String)
+                        caps[i].getProperties().get(ICapability.PACKAGE_PROPERTY);
+                    // Add to "resolved" package index.
+                    indexPackageCapability(
+                        m_resolvedPkgIndexMap,
+                        module,
+                        caps[i]);
+                }
+            }
+        }
+    }
+*/
     private void dumpPackageIndexMap(Map pkgIndexMap)
     {
         for (Iterator i = pkgIndexMap.entrySet().iterator(); i.hasNext(); )
@@ -164,24 +200,10 @@
         return (IModule[]) m_moduleList.toArray(new IModule[m_moduleList.size()]);
     }
 
-    public String getBundleSymbolicName(IModule module)
-    {
-        ICapability[] caps = module.getDefinition().getCapabilities();
-        for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
-        {
-            if (caps[capIdx].getNamespace().equals(ICapability.MODULE_NAMESPACE))
-            {
-                return (String)
-                    caps[capIdx].getProperties().get(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
-            }
-        }
-        return null;
-    }
-
 // TODO: FRAGMENT - Not very efficient.
     private static Version getBundleVersion(IModule module)
     {
-        ICapability[] caps = module.getDefinition().getCapabilities();
+        ICapability[] caps = module.getCapabilities();
         for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
         {
             if (caps[capIdx].getNamespace().equals(ICapability.MODULE_NAMESPACE))
@@ -193,27 +215,9 @@
         return Version.emptyVersion;
     }
 
-    public synchronized boolean isResolved(IModule module)
+    public synchronized void moduleResolved(IModule module)
     {
-        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
-        if (data != null)
-        {
-            return data.m_resolved;
-        }
-        return false;
-    }
-
-    public synchronized void setResolved(IModule module, boolean b)
-    {
-        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
-        if (data == null)
-        {
-            data = new ModuleData(module);
-            m_moduleDataMap.put(module, data);
-        }
-        data.m_resolved = b;
-
-        if (data.m_resolved)
+        if (module.isResolved())
         {
             // At this point, we need to remove all of the resolved module's
             // capabilities from the "unresolved" package map and put them in
@@ -223,7 +227,7 @@
             // module and not another module. If it points to another module
             // then the capability should be ignored, since the framework
             // decided to honor the import and discard the export.
-            ICapability[] caps = module.getDefinition().getCapabilities();
+            ICapability[] caps = module.getCapabilities();
 
             // First remove all existing capabilities from the "unresolved" map.
             for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
@@ -261,18 +265,15 @@
                 // satisfies any of the wire requirements.
                 for (int wireIdx = 0; (wires != null) && (wireIdx < wires.length); wireIdx++)
                 {
-                    // If the wire requirement is satisfied by the current capability,
-                    // then check to see if the wire is to the module itself. If it
-                    // is to another module, then null the current capability since
-                    // it was both providing and requiring the same capability and
-                    // the resolve process chose to import rather than provide that
-                    // capability, therefore we should ignore it.
+                    // If one of the module's capabilities satifies the requirement
+                    // for an existing wire, this means the capability was
+                    // substituted with another provider by the resolver and
+                    // the module's capability was not used. Therefore, we should
+                    // null it here so it doesn't get added the list of resolved
+                    // capabilities for this module.
                     if (wires[wireIdx].getRequirement().isSatisfied(capsCopy[capIdx]))
                     {
-                        if (!wires[wireIdx].getExporter().equals(module))
-                        {
-                            capsCopy[capIdx] = null;
-                        }
+                        capsCopy[capIdx] = null;
                         break;
                     }
                 }
@@ -314,7 +315,7 @@
     {
         List hostList = new ArrayList();
 
-        IRequirement[] reqs = fragment.getDefinition().getRequirements();
+        IRequirement[] reqs = fragment.getRequirements();
         IRequirement hostReq = null;
         for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++)
         {
@@ -328,14 +329,14 @@
         IModule[] modules = getModules();
         for (int modIdx = 0; (hostReq != null) && (modIdx < modules.length); modIdx++)
         {
-            if (!fragment.equals(modules[modIdx]) && !isResolved(modules[modIdx]))
+            if (!fragment.equals(modules[modIdx]) && !modules[modIdx].isResolved())
             {
-                ICapability[] caps = modules[modIdx].getDefinition().getCapabilities();
+                ICapability[] caps = modules[modIdx].getCapabilities();
                 for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
                 {
                     if (caps[capIdx].getNamespace().equals(ICapability.HOST_NAMESPACE)
                         && hostReq.isSatisfied(caps[capIdx])
-                        && !modules[modIdx].isStale())
+                        && !((BundleImpl) modules[modIdx].getBundle()).isStale())
                     {
                         hostList.add(modules[modIdx]);
                         break;
@@ -353,7 +354,7 @@
 // TODO: FRAGMENT - This should check to make sure that the host allows fragments.
         Map fragmentMap = new HashMap();
 
-        ICapability[] caps = host.getDefinition().getCapabilities();
+        ICapability[] caps = host.getCapabilities();
         ICapability bundleCap = null;
         for (int capIdx = 0; capIdx < caps.length; capIdx++)
         {
@@ -369,12 +370,13 @@
         {
             if (!host.equals(modules[modIdx]))
             {
-                IRequirement[] reqs = modules[modIdx].getDefinition().getRequirements();
+                IRequirement[] reqs = modules[modIdx].getRequirements();
                 for (int reqIdx = 0; (reqs != null) && (reqIdx < reqs.length); reqIdx++)
                 {
                     if (reqs[reqIdx].getNamespace().equals(ICapability.HOST_NAMESPACE)
                         && reqs[reqIdx].isSatisfied(bundleCap)
-                        && !modules[modIdx].isStale())
+                        && !((BundleImpl) modules[modIdx].getBundle()).isStale()
+                        && !((BundleImpl) modules[modIdx].getBundle()).isRemovalPending())
                     {
                         indexFragment(fragmentMap, modules[modIdx]);
                         break;
@@ -404,7 +406,7 @@
                 {
 // TODO: RB - Is this permission check correct.
                     if ((System.getSecurityManager() != null) &&
-                        !((BundleProtectionDomain) modules[modIdx].getContentLoader().getSecurityContext()).impliesDirect(
+                        !((BundleProtectionDomain) modules[modIdx].getSecurityContext()).impliesDirect(
                             new PackagePermission(pkgName,
                                 PackagePermission.EXPORT)))
                     {
@@ -439,7 +441,7 @@
 // TODO: RB - Is this permission check correct.
                         if (resolvedCaps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
                             (System.getSecurityManager() != null) &&
-                            !((BundleProtectionDomain) module.getContentLoader().getSecurityContext()).impliesDirect(
+                            !((BundleProtectionDomain) module.getSecurityContext()).impliesDirect(
                                 new PackagePermission(
                                     (String) resolvedCaps[capIdx].getProperties().get(ICapability.PACKAGE_PROPERTY),
                                     PackagePermission.EXPORT)))
@@ -486,7 +488,7 @@
             ICapability cap = Util.getSatisfyingCapability(modules[modIdx], req);
             // If compatible and it is not currently resolved, then add
             // the unresolved candidate to the list.
-            if ((cap != null) && !isResolved(modules[modIdx]))
+            if ((cap != null) && !modules[modIdx].isResolved())
             {
                 PackageSource[] tmp = new PackageSource[candidates.length + 1];
                 System.arraycopy(candidates, 0, tmp, 0, candidates.length);
@@ -574,8 +576,7 @@
 
     private void indexFragment(Map map, IModule module)
     {
-        String symName = getBundleSymbolicName(module);
-        IModule[] modules = (IModule[]) map.get(symName);
+        IModule[] modules = (IModule[]) map.get(module.getSymbolicName());
 
         // We want to add the fragment into the list of matching
         // fragments in sorted order (descending version and
@@ -631,7 +632,7 @@
             }
         }
 
-        map.put(symName, modules);
+        map.put(module.getSymbolicName(), modules);
     }
 
     private static IModule[] removeModuleFromArray(IModule[] modules, IModule m)
@@ -682,7 +683,7 @@
 
     public static ICapability getExportPackageCapability(IModule m, String pkgName)
     {
-        ICapability[] caps = m.getDefinition().getCapabilities();
+        ICapability[] caps = m.getCapabilities();
         for (int i = 0; (caps != null) && (i < caps.length); i++)
         {
             if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
@@ -719,17 +720,4 @@
 
         return caps;
     }
-    //
-    // Simple utility classes.
-    //
-
-    private static class ModuleData
-    {
-        public IModule m_module = null;
-        public boolean m_resolved = false;
-        public ModuleData(IModule module)
-        {
-            m_module = module;
-        }
-    }
 }
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java b/framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java
index 325533e..3bd1b9a 100644
--- a/framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java
+++ b/framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java
@@ -22,7 +22,7 @@
 
 class FindEntriesEnumeration implements Enumeration
 {
-    private FelixBundle m_bundle = null;
+    private BundleImpl m_bundle = null;
     private Enumeration m_enumeration = null;
     private String m_path = null;
     private String[] m_filePattern = null;
@@ -30,12 +30,12 @@
     private Object m_next = null;
 
     public FindEntriesEnumeration(
-        FelixBundle bundle, String path, String filePattern, boolean recurse)
+        BundleImpl bundle, String path, String filePattern, boolean recurse)
     {
         m_bundle = bundle;
         m_path = path;
-        m_enumeration = (m_bundle.getInfo().getCurrentModule().getContentLoader().getContent() == null)
-            ? null : m_bundle.getInfo().getCurrentModule().getContentLoader().getContent().getEntries();
+        m_enumeration = (m_bundle.getCurrentModule().getContent() == null)
+            ? null : m_bundle.getCurrentModule().getContent().getEntries();
         m_recurse = recurse;
 
         // Sanity check the parameters.
@@ -113,8 +113,8 @@
                     if (checkSubstring(m_filePattern, lastElement))
                     {
                         // Convert entry name into an entry URL.
-                        return m_bundle.getInfo().getCurrentModule()
-                            .getContentLoader().getResourceFromContent(entryName);
+                        return m_bundle.getCurrentModule()
+                            .getResourceFromContent(entryName);
                     }
                 }
             }
diff --git a/framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java b/framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java
index bbae4c6..7e18ab4 100644
--- a/framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java
+++ b/framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java
@@ -23,17 +23,16 @@
 
 class GetEntryPathsEnumeration implements Enumeration
 {
-    private FelixBundle m_bundle = null;
+    private BundleImpl m_bundle = null;
     private Enumeration m_enumeration = null;
     private String m_path = null;
     private Object m_next = null;
 
-    public GetEntryPathsEnumeration(FelixBundle bundle, String path)
+    public GetEntryPathsEnumeration(BundleImpl bundle, String path)
     {
         m_bundle = bundle;
         m_path = path;
-        m_enumeration = m_bundle.getInfo().getCurrentModule()
-            .getContentLoader().getContent().getEntries();
+        m_enumeration = m_bundle.getCurrentModule().getContent().getEntries();
 
         // Sanity check the parameters.
         if (m_path == null)
diff --git a/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java b/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
index 7d09d3f..3ccd241 100644
--- a/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
@@ -20,10 +20,10 @@
 
 import java.util.*;
 
+import org.apache.felix.framework.searchpolicy.ModuleImpl;
 import org.apache.felix.framework.util.Util;
 import org.apache.felix.framework.util.VersionRange;
 import org.apache.felix.moduleloader.IModule;
-import org.apache.felix.moduleloader.ModuleImpl;
 import org.osgi.framework.*;
 import org.osgi.service.packageadmin.*;
 
@@ -111,8 +111,8 @@
             String sym = bundles[i].getSymbolicName();
             if ((sym != null) && sym.equals(symbolicName))
             {
-                String s = (String) ((FelixBundle) bundles[i])
-                    .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION);
+                String s = (String) ((BundleImpl) bundles[i])
+                    .getCurrentModule().getHeaders().get(Constants.BUNDLE_VERSION);
                 Version v = (s == null) ? new Version("0.0.0") : new Version(s);
                 if ((vr == null) || vr.isInRange(v))
                 {
@@ -128,10 +128,10 @@
         Arrays.sort(bundles,new Comparator() {
             public int compare(Object o1, Object o2)
             {
-                String s1 = (String) ((FelixBundle) o1)
-                    .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION);
-                String s2 = (String) ((FelixBundle) o2)
-                    .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION);
+                String s1 = (String) ((BundleImpl) o1)
+                    .getCurrentModule().getHeaders().get(Constants.BUNDLE_VERSION);
+                String s2 = (String) ((BundleImpl) o2)
+                    .getCurrentModule().getHeaders().get(Constants.BUNDLE_VERSION);
                 Version v1 = (s1 == null) ? new Version("0.0.0") : new Version(s1);
                 Version v2 = (s2 == null) ? new Version("0.0.0") : new Version(s2);
                 // Compare in reverse order to get descending sort.
@@ -143,7 +143,7 @@
 
     public int getBundleType(Bundle bundle)
     {
-        Map headerMap = ((FelixBundle) bundle).getInfo().getCurrentHeader();
+        Map headerMap = ((BundleImpl) bundle).getCurrentModule().getHeaders();
         if (headerMap.containsKey(Constants.FRAGMENT_HOST))
         {
             return PackageAdmin.BUNDLE_TYPE_FRAGMENT;
@@ -201,13 +201,12 @@
             // Get attached fragments.
             IModule[] modules =
                 ((ModuleImpl)
-                    ((FelixBundle) bundle).getInfo().getCurrentModule()).getFragments();
+                    ((BundleImpl) bundle).getCurrentModule()).getFragments();
             // Convert fragment modules to bundles.
             List list = new ArrayList();
             for (int i = 0; (modules != null) && (i < modules.length); i++)
             {
-                long id = Util.getBundleIdFromModuleId(modules[i].getId());
-                Bundle b = m_felix.getBundle(id);
+                Bundle b = modules[i].getBundle();
                 if (b != null)
                 {
                     list.add(b);
@@ -225,7 +224,7 @@
     {
         if (getBundleType(bundle) == BUNDLE_TYPE_FRAGMENT)
         {
-            return m_felix.getDependentBundles((FelixBundle) bundle);
+            return m_felix.getDependentBundles((BundleImpl) bundle);
         }
         return null;
     }
@@ -236,10 +235,11 @@
         Bundle[] bundles = m_felix.getBundles();
         for (int i = 0; i < bundles.length; i++)
         {
-            FelixBundle fb = (FelixBundle) bundles[i];
-            if ((symbolicName == null) || (symbolicName.equals(fb.getInfo().getSymbolicName())))
+            BundleImpl impl = (BundleImpl) bundles[i];
+            if ((symbolicName == null)
+                || (symbolicName.equals(impl.getCurrentModule().getSymbolicName())))
             {
-                list.add(new RequiredBundleImpl(m_felix, fb));
+                list.add(new RequiredBundleImpl(m_felix, impl));
             }
         }
         return (list.size() == 0)
diff --git a/framework/src/main/java/org/apache/felix/framework/RegularBundleInfo.java b/framework/src/main/java/org/apache/felix/framework/RegularBundleInfo.java
deleted file mode 100644
index d661ad5..0000000
--- a/framework/src/main/java/org/apache/felix/framework/RegularBundleInfo.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework;
-
-import java.util.*;
-
-import org.apache.felix.framework.cache.BundleArchive;
-import org.apache.felix.framework.searchpolicy.ModuleDefinition;
-import org.apache.felix.framework.util.manifestparser.ManifestParser;
-import org.apache.felix.moduleloader.ICapability;
-import org.apache.felix.moduleloader.IModule;
-import org.osgi.framework.*;
-
-class RegularBundleInfo extends BundleInfo
-{
-    private BundleArchive m_archive = null;
-    private String m_cachedSymbolicName = null;
-    private long m_cachedSymbolicNameTimestamp;
-
-    protected RegularBundleInfo(Logger logger, IModule module, BundleArchive archive)
-    {
-        super(logger, module);
-        m_archive = archive;
-    }
-
-    /**
-     *  Returns the bundle archive associated with this bundle.
-     * @return the bundle archive associated with this bundle.
-    **/
-// TODO: SYSTEMBUNDLE - Should this be on BundleInfo and just return in SystemBundleInfo or exception?
-    public BundleArchive getArchive()
-    {
-        return m_archive;
-    }
-
-    public synchronized String getSymbolicName()
-    {
-        // If the bundle has been updated, clear the cached symbolic name.
-        if (getLastModified() > m_cachedSymbolicNameTimestamp)
-        {
-            m_cachedSymbolicName = null;
-            m_cachedSymbolicNameTimestamp = getLastModified();
-            try
-            {
-                // TODO: FRAMEWORK - Rather than reparsing every time, I wonder if
-                //       we should be caching this value some place.
-                final ICapability moduleCap = ManifestParser.parseBundleSymbolicName(getCurrentHeader());
-                if (moduleCap != null)
-                {
-                    m_cachedSymbolicName = (String) moduleCap.getProperties().get(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
-                }
-            }
-            catch (BundleException ex)
-            {
-                // Return null.
-            }
-        }
-        return m_cachedSymbolicName;
-    }
-
-    public long getBundleId()
-    {
-        try
-        {
-            return m_archive.getId();
-        }
-        catch (Exception ex)
-        {
-            getLogger().log(
-                Logger.LOG_ERROR,
-                "Error getting the identifier from bundle archive.",
-                ex);
-            return -1;
-        }
-    }
-
-    public String getLocation()
-    {
-        try
-        {
-            return m_archive.getLocation();
-        }
-        catch (Exception ex)
-        {
-            getLogger().log(
-                Logger.LOG_ERROR,
-                "Error getting location from bundle archive.",
-                ex);
-            return null;
-        }
-    }
-
-    public int getStartLevel(int defaultLevel)
-    {
-        try
-        {
-            return m_archive.getStartLevel();
-        }
-        catch (Exception ex)
-        {
-            getLogger().log(
-                Logger.LOG_ERROR,
-                "Error reading start level from bundle archive.",
-                ex);
-            return defaultLevel;
-        }
-    }
-
-    public void setStartLevel(int i)
-    {
-        try
-        {
-            m_archive.setStartLevel(i);
-        }
-        catch (Exception ex)
-        {
-            getLogger().log(
-                Logger.LOG_ERROR,
-                "Error writing start level to bundle archive.",
-                ex);
-        }
-    }
-
-    public Map getCurrentHeader()
-    {
-        return ((ModuleDefinition) getCurrentModule().getDefinition()).getHeaders();
-    }
-
-    public long getLastModified()
-    {
-        try
-        {
-            return m_archive.getLastModified();
-        }
-        catch (Exception ex)
-        {
-            getLogger().log(
-                Logger.LOG_ERROR,
-                "Error reading last modification time from bundle archive.",
-                ex);
-            return 0;
-        }
-    }
-
-    public void setLastModified(long l)
-    {
-        try
-        {
-            m_archive.setLastModified(l);
-        }
-        catch (Exception ex)
-        {
-            getLogger().log(
-                Logger.LOG_ERROR,
-                "Error writing last modification time to bundle archive.",
-                ex);
-        }
-    }
-
-    public int getPersistentState()
-    {
-        try
-        {
-            return m_archive.getPersistentState();
-        }
-        catch (Exception ex)
-        {
-            getLogger().log(
-                Logger.LOG_ERROR,
-                "Error reading persistent state from bundle archive.",
-                ex);
-            return Bundle.INSTALLED;
-        }
-    }
-
-    public void setPersistentStateInactive()
-    {
-        try
-        {
-            m_archive.setPersistentState(Bundle.INSTALLED);
-        }
-        catch (Exception ex)
-        {
-            getLogger().log(Logger.LOG_ERROR,
-                "Error writing persistent state to bundle archive.",
-                ex);
-        }
-    }
-
-    public void setPersistentStateActive()
-    {
-        try
-        {
-            m_archive.setPersistentState(Bundle.ACTIVE);
-        }
-        catch (Exception ex)
-        {
-            getLogger().log(
-                Logger.LOG_ERROR,
-                "Error writing persistent state to bundle archive.",
-                ex);
-        }
-    }
-
-    public void setPersistentStateUninstalled()
-    {
-        try
-        {
-            m_archive.setPersistentState(Bundle.UNINSTALLED);
-        }
-        catch (Exception ex)
-        {
-            getLogger().log(
-                Logger.LOG_ERROR,
-                "Error writing persistent state to bundle archive.",
-                ex);
-        }
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/RequiredBundleImpl.java b/framework/src/main/java/org/apache/felix/framework/RequiredBundleImpl.java
index f42282b..970b0ef 100644
--- a/framework/src/main/java/org/apache/felix/framework/RequiredBundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/RequiredBundleImpl.java
@@ -22,10 +22,10 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import org.apache.felix.framework.searchpolicy.ModuleImpl;
 import org.apache.felix.framework.util.Util;
 import org.apache.felix.moduleloader.ICapability;
 import org.apache.felix.moduleloader.IModule;
-import org.apache.felix.moduleloader.ModuleImpl;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
@@ -34,9 +34,9 @@
 class RequiredBundleImpl implements RequiredBundle
 {
     private final Felix m_felix;
-    private final FelixBundle m_bundle;
+    private final BundleImpl m_bundle;
 
-    public RequiredBundleImpl(Felix felix, FelixBundle bundle)
+    public RequiredBundleImpl(Felix felix, BundleImpl bundle)
     {
         m_felix = felix;
         m_bundle = bundle;
@@ -55,7 +55,7 @@
     public Bundle[] getRequiringBundles()
     {
         // Spec says to return null for stale bundles.
-        if (m_bundle.getInfo().isStale())
+        if (m_bundle.isStale())
         {
             return null;
         }
@@ -64,7 +64,7 @@
         // associated with this bundle.
         List moduleList = new ArrayList();
         // Loop through all of this bundle's modules.
-        IModule[] modules = m_bundle.getInfo().getModules();
+        IModule[] modules = m_bundle.getModules();
         for (int modIdx = 0; (modules != null) && (modIdx < modules.length); modIdx++)
         {
             // For each of this bundle's modules, loop through all of the
@@ -80,8 +80,7 @@
         Set bundleSet = new HashSet();
         for (int modIdx = 0; modIdx < moduleList.size(); modIdx++)
         {
-            long id = Util.getBundleIdFromModuleId(((IModule) moduleList.get(modIdx)).getId());
-            Bundle bundle = m_felix.getBundle(id);
+            Bundle bundle = ((IModule) moduleList.get(modIdx)).getBundle();
             if (bundle != null)
             {
                 bundleSet.add(bundle);
@@ -94,7 +93,7 @@
     {
         ICapability[] caps = 
             Util.getCapabilityByNamespace(
-                m_bundle.getInfo().getCurrentModule(), ICapability.MODULE_NAMESPACE);
+                m_bundle.getCurrentModule(), ICapability.MODULE_NAMESPACE);
         if ((caps != null) && (caps.length > 0))
         {
             return (Version) caps[0].getProperties().get(Constants.BUNDLE_VERSION_ATTRIBUTE);
@@ -104,6 +103,6 @@
 
     public boolean isRemovalPending()
     {
-        return m_bundle.getInfo().isRemovalPending();
+        return m_bundle.isRemovalPending();
     }
 }
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java b/framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java
index ea02cc9..9f444c9 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java
@@ -122,8 +122,7 @@
         // Get the package.
         String pkgName =
             Util.getClassPackage(className);
-        IModule requesterModule = 
-            ((FelixBundle) requester).getInfo().getCurrentModule();
+        IModule requesterModule = ((BundleImpl) requester).getCurrentModule();
         // Get package wiring from service requester.
         IWire requesterWire = Util.getWire(requesterModule, pkgName);
 
@@ -148,8 +147,7 @@
         }
 
         // Get package wiring from service provider.
-        IModule providerModule = 
-            ((FelixBundle) m_bundle).getInfo().getCurrentModule();
+        IModule providerModule = ((BundleImpl) m_bundle).getCurrentModule();
         IWire providerWire = Util.getWire(providerModule, pkgName);
         
         // Case 2: Only include service reference if the service
@@ -159,12 +157,12 @@
             // If the provider is not the exporter of the requester's package,
             // then try to use the service registration to see if the requester's
             // class is accessible.
-            if (!((FelixBundle) m_bundle).getInfo().hasModule(requesterWire.getExporter()))
+            if (!((BundleImpl) m_bundle).hasModule(requesterWire.getExporter()))
             {
                 try
                 {
                     // Load the class from the requesting bundle.
-                    Class requestClass = requesterModule.getClass(className);
+                    Class requestClass = requesterModule.getClassByDelegation(className);
                     // Get the service registration and ask it to check
                     // if the service object is assignable to the requesting
                     // bundle's class.
diff --git a/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java b/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
index 507c5cf..8dafb70 100644
--- a/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
@@ -38,16 +38,13 @@
 
     private Logger m_logger = null;
     private Felix m_felix = null;
-    private List m_requestList = null;
-    private Bundle m_systemBundle = null;
+    private final List m_requestList = new ArrayList();
     private Thread m_thread = null;
 
     public StartLevelImpl(Logger logger, Felix felix)
     {
         m_logger = logger;
         m_felix = felix;
-        m_requestList = new ArrayList();
-        m_systemBundle = m_felix.getBundle(0);
         // Start a thread to perform asynchronous package refreshes.
         m_thread = new Thread(this, "FelixStartLevel");
         m_thread.setDaemon(true);
@@ -85,7 +82,7 @@
     **/
     public int getStartLevel()
     {
-        return m_felix.getStartLevel();
+        return m_felix.getActiveStartLevel();
     }
 
     /* (non-Javadoc)
@@ -98,7 +95,7 @@
         if (sm != null)
         {
             ((SecurityManager) sm).checkPermission(
-                new AdminPermission(m_systemBundle, AdminPermission.STARTLEVEL));
+                new AdminPermission(m_felix, AdminPermission.STARTLEVEL));
         }
         
         if (startlevel <= 0)
@@ -202,7 +199,7 @@
         if (sm != null)
         {
             ((SecurityManager) sm).checkPermission(
-                new AdminPermission(m_systemBundle, AdminPermission.STARTLEVEL));
+                new AdminPermission(m_felix, AdminPermission.STARTLEVEL));
         }
         m_felix.setInitialBundleStartLevel(startlevel);
     }
@@ -262,7 +259,7 @@
             if (request instanceof Integer)
             {
                 // Set the new framework start level.
-                m_felix.setFrameworkStartLevel(((Integer) request).intValue());
+                m_felix.setActiveStartLevel(((Integer) request).intValue());
             }
             else
             {
diff --git a/framework/src/main/java/org/apache/felix/framework/SystemBundleInfo.java b/framework/src/main/java/org/apache/felix/framework/SystemBundleInfo.java
deleted file mode 100644
index 2268ac7..0000000
--- a/framework/src/main/java/org/apache/felix/framework/SystemBundleInfo.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework;
-
-import java.util.Map;
-import org.apache.felix.framework.util.FelixConstants;
-import org.apache.felix.framework.util.StringMap;
-import org.apache.felix.moduleloader.IModule;
-import org.osgi.framework.Bundle;
-
-class SystemBundleInfo extends BundleInfo
-{
-    private Map m_headerMap = new StringMap(false);
-    private int m_startLevel = FelixConstants.SYSTEMBUNDLE_DEFAULT_STARTLEVEL;
-
-    SystemBundleInfo(Logger logger, IModule module)
-    {
-        super(logger, module);
-    }
-
-    public String getSymbolicName()
-    {
-        return FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME;
-    }
-
-    public long getBundleId()
-    {
-        return 0;
-    }
-
-    public String getLocation()
-    {
-        return FelixConstants.SYSTEM_BUNDLE_LOCATION;
-    }
-
-    public synchronized int getStartLevel(int defaultLevel)
-    {
-        return m_startLevel;
-    }
-
-    public synchronized void setStartLevel(int i)
-    {
-        m_startLevel = i;
-    }
-
-    public Map getCurrentHeader()
-    {
-        return m_headerMap;
-    }
-
-    public long getLastModified()
-    {
-        return 0;
-    }
-
-    public void setLastModified(long l)
-    {
-        // Ignore.
-    }
-
-    public int getPersistentState()
-    {
-        return Bundle.ACTIVE;
-    }
-
-    public void setPersistentStateInactive()
-    {
-        // Ignore.
-    }
-
-    public void setPersistentStateActive()
-    {
-        // Ignore.
-    }
-
-    public void setPersistentStateUninstalled()
-    {
-        // Ignore.
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlers.java b/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
index 07951f0..f2f72f6 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
@@ -33,7 +33,7 @@
 import java.util.Map;
 import java.util.StringTokenizer;
 
-import org.apache.felix.framework.searchpolicy.ContentClassLoader;
+import org.apache.felix.framework.searchpolicy.ModuleClassLoader;
 import org.apache.felix.framework.util.FelixConstants;
 import org.apache.felix.framework.util.SecureAction;
 import org.apache.felix.framework.util.SecurityManagerEx;
@@ -611,7 +611,7 @@
         for (int i = 0; i < stack.length; i++)
         {
             if ((stack[i].getClassLoader() != null) && 
-                ContentClassLoader.class.getName().equals(
+                ModuleClassLoader.class.getName().equals(
                 stack[i].getClassLoader().getClass().getName()))
             {
                 targetClass = stack[i];
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
index 834d577..d6fa817 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
@@ -69,7 +69,7 @@
         //     bundle://<module-id>:<bundle-classpath-index>/<resource-path>
         // Where <module-id> = <bundle-id>.<revision>
         long bundleId = Util.getBundleIdFromModuleId(url.getHost());
-        FelixBundle bundle = (FelixBundle) m_framework.getBundle(bundleId);
+        BundleImpl bundle = (BundleImpl) m_framework.getBundle(bundleId);
         if (bundle == null)
         {
             throw new IOException("No bundle associated with resource: " + url);
@@ -77,7 +77,7 @@
         m_contentTime = bundle.getLastModified();
 
         int revision = Util.getModuleRevisionFromModuleId(url.getHost());
-        IModule[] modules = bundle.getInfo().getModules();
+        IModule[] modules = bundle.getModules();
         if ((modules == null) || (revision >= modules.length))
         {
             throw new IOException("Resource does not exist: " + url);
@@ -102,9 +102,9 @@
         {
             m_classPathIdx = 0;
         }
-        if (!modules[revision].getContentLoader().hasInputStream(m_classPathIdx, url.getPath()))
+        if (!modules[revision].hasInputStream(m_classPathIdx, url.getPath()))
         {
-            URL newurl = modules[revision].getContentLoader().getResource(url.getPath());
+            URL newurl = modules[revision].getResourceByDelegation(url.getPath());
             if (newurl == null)
             {
                 throw new IOException("Resource does not exist: " + url);
@@ -121,8 +121,7 @@
             {
                 throw new IOException("Resource does not exist: " + url);
             }
-            m_is = m_targetModule.getContentLoader()
-                .getInputStream(m_classPathIdx, url.getPath());
+            m_is = m_targetModule.getInputStream(m_classPathIdx, url.getPath());
             m_contentLength = (m_is == null) ? 0 : m_is.available();
             m_contentType = URLConnection.guessContentTypeFromName(url.getFile());
             connected = true;
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java
index 65c2e66..a832056 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersServiceTracker.java
@@ -49,8 +49,7 @@
     **/
     public URLHandlersServiceTracker(Felix framework, String filter)
     {
-        m_context = ((FelixBundle) 
-            framework.getBundle(0)).getInfo().getBundleContext();
+        m_context = ((BundleImpl) framework).getBundleContext();
         m_filter = filter;
 
         synchronized (this)
diff --git a/framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java b/framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java
index bb132f2..8f8551e 100644
--- a/framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java
+++ b/framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java
@@ -22,10 +22,7 @@
 import java.net.URLDecoder;
 
 import org.apache.felix.framework.Logger;
-import org.apache.felix.framework.util.ObjectInputStreamX;
-import org.apache.felix.moduleloader.IModule;
 import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleActivator;
 
 /**
  * <p>
@@ -77,7 +74,6 @@
     private static final transient String BUNDLE_STATE_FILE = "bundle.state";
     private static final transient String BUNDLE_START_LEVEL_FILE = "bundle.startlevel";
     private static final transient String REFRESH_COUNTER_FILE = "refresh.counter";
-    private static final transient String BUNDLE_ACTIVATOR_FILE = "bundle.activator";
     private static final transient String BUNDLE_LASTMODIFIED_FILE = "bundle.lastmodified";
     private static final transient String REVISION_DIRECTORY = "version";
     private static final transient String DATA_DIRECTORY = "data";
@@ -572,90 +568,6 @@
 
     /**
      * <p>
-     * Returns the serialized activator for this archive. This is an
-     * extension to the OSGi specification.
-     * </p>
-     * @return the serialized activator for this archive.
-     * @throws Exception if any error occurs.
-    **/
-    public synchronized BundleActivator getActivator(IModule module)
-        throws Exception
-    {
-        // Get bundle activator file.
-        File activatorFile = new File(m_archiveRootDir, BUNDLE_ACTIVATOR_FILE);
-        // If the activator file doesn't exist, then
-        // assume there isn't one.
-        if (!BundleCache.getSecureAction().fileExists(activatorFile))
-        {
-            return null;
-        }
-
-        // Deserialize the activator object.
-        InputStream is = null;
-        ObjectInputStreamX ois = null;
-        try
-        {
-            is = BundleCache.getSecureAction()
-                .getFileInputStream(activatorFile);
-            ois = new ObjectInputStreamX(is, module);
-            Object o = ois.readObject();
-            return (BundleActivator) o;
-        }
-        catch (Exception ex)
-        {
-            m_logger.log(
-                Logger.LOG_ERROR,
-                getClass().getName() + ": Trying to deserialize - " + ex);
-        }
-        finally
-        {
-            if (ois != null) ois.close();
-            if (is != null) is.close();
-        }
-
-        return null;
-    }
-
-    /**
-     * <p>
-     * Serializes the activator for this archive.
-     * </p>
-     * @param obj the activator to serialize.
-     * @throws Exception if any error occurs.
-    **/
-    public synchronized void setActivator(Object obj) throws Exception
-    {
-        if (!(obj instanceof Serializable))
-        {
-            return;
-        }
-
-        // Serialize the activator object.
-        OutputStream os = null;
-        ObjectOutputStream oos = null;
-        try
-        {
-            os = BundleCache.getSecureAction()
-                .getFileOutputStream(new File(m_archiveRootDir, BUNDLE_ACTIVATOR_FILE));
-            oos = new ObjectOutputStream(os);
-            oos.writeObject(obj);
-        }
-        catch (IOException ex)
-        {
-            m_logger.log(
-                Logger.LOG_ERROR,
-                getClass().getName() + ": Unable to serialize activator - " + ex);
-            throw ex;
-        }
-        finally
-        {
-            if (oos != null) oos.close();
-            if (os != null) os.close();
-        }
-    }
-
-    /**
-     * <p>
      * Returns the number of revisions available for this archive.
      * </p>
      * @return tthe number of revisions available for this archive.
@@ -733,7 +645,7 @@
      * @return true if the undo was a success false if there is no previous revision
      * @throws Exception if any error occurs.
      */
-    public synchronized boolean undoRevise() throws Exception
+    public synchronized boolean rollbackRevise() throws Exception
     {
         // Can only undo the revision if there is more than one.
         if (getRevisionCount() <= 1)
diff --git a/framework/src/main/java/org/apache/felix/framework/cache/DirectoryContent.java b/framework/src/main/java/org/apache/felix/framework/cache/DirectoryContent.java
index c7be028..38901cd 100644
--- a/framework/src/main/java/org/apache/felix/framework/cache/DirectoryContent.java
+++ b/framework/src/main/java/org/apache/felix/framework/cache/DirectoryContent.java
@@ -31,7 +31,7 @@
     private static final transient String LIBRARY_DIRECTORY = "lib";
 
     private Logger m_logger;
-    private Object m_revisionLock;
+    private final Object m_revisionLock;
     private File m_rootDir;
     private File m_dir;
 
@@ -168,7 +168,6 @@
                     }
                 }
             }
-            System.out.println("+++ EXTRACTED JAR DIR " + extractedDir);
             return new JarContent(m_logger, m_revisionLock, extractedDir, file);
         }
 
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java
deleted file mode 100644
index 6ffe043..0000000
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.searchpolicy;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.security.ProtectionDomain;
-import java.security.SecureClassLoader;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.felix.framework.util.Util;
-import org.apache.felix.moduleloader.IContent;
-import org.apache.felix.moduleloader.IContentLoader;
-import org.apache.felix.framework.cache.JarContent;
-import org.apache.felix.moduleloader.ResourceNotFoundException;
-
-public class ContentClassLoader extends SecureClassLoader
-{
-    private static final Constructor m_dexFileClassConstructor;
-    private static final Method m_dexFileClassLoadClass;
-    static
-    {
-        Constructor dexFileClassConstructor = null;
-        Method dexFileClassLoadClass = null;
-        try
-        {
-            Class dexFileClass;
-            try
-            {
-                dexFileClass = Class.forName("dalvik.system.DexFile");
-            }
-            catch (Exception ex)
-            {
-                dexFileClass = Class.forName("android.dalvik.DexFile");
-            }
-            
-            dexFileClassConstructor = dexFileClass.getConstructor(
-                new Class[] { java.io.File.class });
-            dexFileClassLoadClass = dexFileClass.getMethod("loadClass",
-                new Class[] { String.class, ClassLoader.class });
-        }
-        catch (Exception ex)
-        {
-           dexFileClassConstructor = null;
-           dexFileClassLoadClass = null;
-        }
-        m_dexFileClassConstructor = dexFileClassConstructor;
-        m_dexFileClassLoadClass = dexFileClassLoadClass;
-    }
-
-    private ContentLoaderImpl m_contentLoader = null;
-    private ProtectionDomain m_protectionDomain = null;
-    private Map m_jarContentToDexFile = null;
-
-    public ContentClassLoader(ContentLoaderImpl contentLoader,
-        ProtectionDomain protectionDomain)
-    {
-        m_contentLoader = contentLoader;
-        m_protectionDomain = protectionDomain;
-        if (m_dexFileClassConstructor != null)
-        {
-            m_jarContentToDexFile = new HashMap();
-        }
-    }
-
-    public IContentLoader getContentLoader()
-    {
-        return m_contentLoader;
-    }
-
-    protected Class loadClassFromModule(String name)
-        throws ClassNotFoundException
-    {
-        // Ask the search policy for the clas before consulting the module.
-        Class clazz = findClass(name);
-
-        // If not found, then throw an exception.
-        if (clazz == null)
-        {
-            throw new ClassNotFoundException(name);
-        }
-        return clazz;
-    }
-
-    protected Class loadClass(String name, boolean resolve)
-        throws ClassNotFoundException
-    {
-        Class clazz = null;
-
-        // Make sure the class was not already loaded.
-        synchronized (this)
-        {
-            clazz = findLoadedClass(name);
-        }
-
-        if (clazz == null)
-        {
-            // Ask the search policy for the class.
-            clazz = m_contentLoader.getSearchPolicy().findClass(name);
-        }
-
-        // If still not found, then throw an exception.
-        if (clazz == null)
-        {
-            throw new ClassNotFoundException(name);
-        }
-        // Otherwise resolve the class.
-        if (resolve)
-        {
-            resolveClass(clazz);
-        }
-        return clazz;
-    }
-
-    protected Class findClass(String name) throws ClassNotFoundException
-    {
-        // Do a quick check here to see if we can short-circuit this
-        // entire process if the class was already loaded.
-        Class clazz = null;
-        synchronized (this)
-        {
-            clazz = findLoadedClass(name);
-        }
-
-        // Search for class in module.
-        if (clazz == null)
-        {
-            String actual = name.replace('.', '/') + ".class";
-
-            byte[] bytes = null;
-
-            IContent content = null;
-            // Check the module class path.
-            for (int i = 0;
-                (bytes == null) &&
-                (i < m_contentLoader.getClassPath().length); i++)
-            {
-                bytes = m_contentLoader.getClassPath()[i].getEntryAsBytes(actual);
-                content = m_contentLoader.getClassPath()[i];
-            }
-
-            if (bytes != null)
-            {
-                // Before we actually attempt to define the class, grab
-                // the lock for this class loader and make sure than no
-                // other thread has defined this class in the meantime.
-                synchronized (this)
-                {
-                    clazz = findLoadedClass(name);
-
-                    if (clazz == null)
-                    {
-                        // We need to try to define a Package object for the class
-                        // before we call defineClass(). Get the package name and
-                        // see if we have already created the package.
-                        String pkgName = Util.getClassPackage(name);
-                        if (pkgName.length() > 0)
-                        {
-                            if (getPackage(pkgName) == null)
-                            {
-                                Object[] params =
-                                    m_contentLoader.getSearchPolicy()
-                                        .definePackage(pkgName);
-                                if (params != null)
-                                {
-                                    definePackage(
-                                        pkgName,
-                                        (String) params[0],
-                                        (String) params[1],
-                                        (String) params[2],
-                                        (String) params[3],
-                                        (String) params[4],
-                                        (String) params[5],
-                                        null);
-                                }
-                                else
-                                {
-                                    definePackage(pkgName, null, null,
-                                        null, null, null, null, null);
-                                }
-                            }
-                        }
-
-                        // If we can load the class from a dex file do so
-                        if (content instanceof JarContent)
-                        {
-                            try
-                            {
-                                clazz = getDexFileClass((JarContent) content, name, this);
-                            }
-                            catch (Exception ex)
-                            {
-                                // Looks like we can't
-                            }
-                        }
-
-                        if (clazz == null)
-                        {
-                            // If we have a security context, then use it to
-                            // define the class with it for security purposes,
-                            // otherwise define the class without a protection domain.
-                            if (m_protectionDomain != null)
-                            {
-                                clazz = defineClass(name, bytes, 0, bytes.length,
-                                    m_protectionDomain);
-                            }
-                            else
-                            {
-                                clazz = defineClass(name, bytes, 0, bytes.length);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        return clazz;
-    }
-
-    private Class getDexFileClass(JarContent content, String name, ClassLoader loader)
-        throws Exception
-    {
-        if (m_jarContentToDexFile == null)
-        {
-            return null;
-        }
-
-        Object dexFile = null;
-
-        if (!m_jarContentToDexFile.containsKey(content))
-        {
-            try
-            {
-                dexFile = m_dexFileClassConstructor.newInstance(
-                    new Object[] { content.getFile() });
-            }
-            finally
-            {
-                m_jarContentToDexFile.put(content, dexFile);
-            }
-        }
-        else
-        {
-            dexFile = m_jarContentToDexFile.get(content);
-        }
-
-        if (dexFile != null)
-        {
-            return (Class) m_dexFileClassLoadClass.invoke(dexFile,
-                new Object[] { name.replace('.','/'), loader });
-        }
-        return null;
-    }
-
-    public URL getResourceFromModule(String name)
-    {
-        try
-        {
-            return findResource(name);
-        }
-        catch (Throwable th)
-        {
-            // Ignore and just return null.
-        }
-        return null;
-    }
-
-    public URL getResource(String name)
-    {
-        // Ask the search policy for the class before consulting the module.
-        try
-        {
-            return m_contentLoader.getSearchPolicy().findResource(name);
-        }
-        catch (ResourceNotFoundException ex)
-        {
-        }
-        return null;
-    }
-
-    protected URL findResource(String name)
-    {
-        // Ask the search policy for the resource.
-        try
-        {
-            return m_contentLoader.getSearchPolicy().findResource(name);
-        }
-        catch (ResourceNotFoundException ex)
-        {
-        }
-        return null;
-    }
-
-    protected Enumeration findResources(String name)
-    {
-        // Ask the search policy for the resources.
-        try
-        {
-            return m_contentLoader.getSearchPolicy().findResources(name);
-        }
-        catch (ResourceNotFoundException ex)
-        {
-        }
-        return null;
-    }
-
-    protected String findLibrary(String name)
-    {
-        return m_contentLoader.getSearchPolicy().findLibrary(name);
-    }
-
-    public String toString()
-    {
-        return m_contentLoader.toString();
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentLoaderImpl.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentLoaderImpl.java
deleted file mode 100644
index a140f53..0000000
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentLoaderImpl.java
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.searchpolicy;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-import java.util.Vector;
-
-import java.util.jar.Manifest;
-import org.apache.felix.framework.Logger;
-import org.apache.felix.framework.util.FelixConstants;
-import org.apache.felix.framework.util.SecureAction;
-import org.apache.felix.framework.util.StringMap;
-import org.apache.felix.framework.util.manifestparser.ManifestParser;
-import org.apache.felix.moduleloader.*;
-
-public class ContentLoaderImpl implements IContentLoader
-{
-    private final Logger m_logger;
-    private final IContent m_content;
-    private IContent[] m_contentPath;
-    private IContent[] m_fragmentContents = null;
-    private ISearchPolicy m_searchPolicy = null;
-    private IURLPolicy m_urlPolicy = null;
-    private ContentClassLoader m_classLoader;
-    private ProtectionDomain m_protectionDomain = null;
-    private static SecureAction m_secureAction = new SecureAction();
-
-    public ContentLoaderImpl(Logger logger, IContent content)
-    {
-        m_logger = logger;
-        m_content = content;
-    }
-
-    public Logger getLogger()
-    {
-        return m_logger;
-    }
-
-    public synchronized void close()
-    {
-        m_content.close();
-        for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
-        {
-            m_contentPath[i].close();
-        }
-        for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
-        {
-            m_fragmentContents[i].close();
-        }
-        synchronized (this)
-        {
-            m_classLoader = null;
-        }
-    }
-
-    public IContent getContent()
-    {
-        return m_content;
-    }
-
-    public synchronized IContent[] getClassPath()
-    {
-        if (m_contentPath == null)
-        {
-            try
-            {
-                m_contentPath = initializeContentPath();
-            }
-            catch (Exception ex)
-            {
-                m_logger.log(Logger.LOG_ERROR, "Unable to get module class path.", ex);
-            }
-        }
-        return m_contentPath;
-    }
-
-    public synchronized void attachFragmentContents(IContent[] fragmentContents)
-        throws Exception
-    {
-        // Close existing fragment contents.
-        if (m_fragmentContents != null)
-        {
-            for (int i = 0; i < m_fragmentContents.length; i++)
-            {
-                m_fragmentContents[i].close();
-            }
-        }
-        m_fragmentContents = fragmentContents;
-
-        if (m_contentPath != null)
-        {
-            for (int i = 0; i < m_contentPath.length; i++)
-            {
-                m_contentPath[i].close();
-            }
-        }
-        m_contentPath = initializeContentPath();
-    }
-
-    public synchronized void setSearchPolicy(ISearchPolicy searchPolicy)
-    {
-        m_searchPolicy = searchPolicy;
-    }
-
-    public synchronized ISearchPolicy getSearchPolicy()
-    {
-        return m_searchPolicy;
-    }
-
-    public synchronized void setURLPolicy(IURLPolicy urlPolicy)
-    {
-        m_urlPolicy = urlPolicy;
-    }
-
-    public synchronized IURLPolicy getURLPolicy()
-    {
-        return m_urlPolicy;
-    }
-
-    public synchronized void setSecurityContext(Object securityContext)
-    {
-        m_protectionDomain = (ProtectionDomain) securityContext;
-    }
-
-    public synchronized Object getSecurityContext()
-    {
-        return m_protectionDomain;
-    }
-
-    public Class getClass(String name)
-    {
-        synchronized (this)
-        {
-            if (m_classLoader == null)
-            {
-                m_classLoader = m_secureAction.createContentClassLoader(this,
-                    m_protectionDomain);
-            }
-        }
-
-        try
-        {
-            return m_classLoader.loadClassFromModule(name);
-        }
-        catch (ClassNotFoundException ex)
-        {
-            return null;
-        }
-    }
-
-    public URL getResource(String name)
-    {
-        URL url = null;
-
-        // Remove leading slash, if present, but special case
-        // "/" so that it returns a root URL...this isn't very
-        // clean or meaninful, but the Spring guys want it.
-        if (name.equals("/"))
-        {
-            // Just pick a class path index since it doesn't really matter.
-            url = getURLPolicy().createURL(1, name);
-        }
-        else if (name.startsWith("/"))
-        {
-            name = name.substring(1);
-        }
-
-        // Check the module class path.
-        IContent[] contentPath = getClassPath();
-        for (int i = 0;
-            (url == null) &&
-            (i < contentPath.length); i++)
-        {
-            if (contentPath[i].hasEntry(name))
-            {
-                url = getURLPolicy().createURL(i + 1, name);
-            }
-        }
-
-        return url;
-    }
-
-    public Enumeration getResources(String name)
-    {
-        Vector v = new Vector();
-
-        // Special case "/" so that it returns a root URLs for
-        // each bundle class path entry...this isn't very
-        // clean or meaningful, but the Spring guys want it.
-        if (name.equals("/"))
-        {
-            for (int i = 0; i < getClassPath().length; i++)
-            {
-                v.addElement(getURLPolicy().createURL(i + 1, name));
-            }
-        }
-        else
-        {
-            // Remove leading slash, if present.
-            if (name.startsWith("/"))
-            {
-                name = name.substring(1);
-            }
-
-            // Check the module class path.
-            IContent[] contentPath = getClassPath();
-            for (int i = 0; i < contentPath.length; i++)
-            {
-                if (contentPath[i].hasEntry(name))
-                {
-                    // Use the class path index + 1 for creating the path so
-                    // that we can differentiate between module content URLs
-                    // (where the path will start with 0) and module class
-                    // path URLs.
-                    v.addElement(getURLPolicy().createURL(i + 1, name));
-                }
-            }
-        }
-
-        return v.elements();
-    }
-
-    // TODO: API: Investigate how to handle this better, perhaps we need
-    // multiple URL policies, one for content -- one for class path.
-    public URL getResourceFromContent(String name)
-    {
-        URL url = null;
-
-        // Check for the special case of "/", which represents
-        // the root of the bundle according to the spec.
-        if (name.equals("/"))
-        {
-            url = getURLPolicy().createURL(0, "/");
-        }
-
-        if (url == null)
-        {
-            // Remove leading slash, if present.
-            if (name.startsWith("/"))
-            {
-                name = name.substring(1);
-            }
-
-            // Check the module content.
-            if (getContent().hasEntry(name))
-            {
-                // Module content URLs start with 0, whereas module
-                // class path URLs start with the index into the class
-                // path + 1.
-                url = getURLPolicy().createURL(0, name);
-            }
-        }
-
-        return url;
-    }
-
-    public boolean hasInputStream(int index, String urlPath)
-    {
-        if (urlPath.startsWith("/"))
-        {
-            urlPath = urlPath.substring(1);
-        }
-        if (index == 0)
-        {
-            return m_content.hasEntry(urlPath);
-        }
-        return getClassPath()[index - 1].hasEntry(urlPath);
-    }
-
-    public InputStream getInputStream(int index, String urlPath)
-        throws IOException
-    {
-        if (urlPath.startsWith("/"))
-        {
-            urlPath = urlPath.substring(1);
-        }
-        if (index == 0)
-        {
-            return m_content.getEntryAsStream(urlPath);
-        }
-        return getClassPath()[index - 1].getEntryAsStream(urlPath);
-    }
-
-    public synchronized String toString()
-    {
-        return m_searchPolicy.toString();
-    }
-
-    private IContent[] initializeContentPath() throws Exception
-    {
-        List contentList = new ArrayList();
-        calculateContentPath(m_content, contentList, true);
-        for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
-        {
-            calculateContentPath(m_fragmentContents[i], contentList, false);
-        }
-        return (IContent[]) contentList.toArray(new IContent[contentList.size()]);
-    }
-
-    private List calculateContentPath(IContent content, List contentList, boolean searchFragments)
-        throws Exception
-    {
-        // Creating the content path entails examining the bundle's
-        // class path to determine whether the bundle JAR file itself
-        // is on the bundle's class path and then creating content
-        // objects for everything on the class path.
-
-        // Create a list to contain the content path for the specified content.
-        List localContentList = new ArrayList();
-
-        // Get the bundle's manifest header.
-        InputStream is = null;
-        Map headers = null;
-        try
-        {
-// TODO: REFACTOR - It seems that we shouldn't have to get the manifest
-//       here since we already have it in our module definition, but we
-//       don't have access to the module definition here. This is something
-//       to be considered when we refactor the module layer.
-            is = content.getEntryAsStream("META-INF/MANIFEST.MF");
-            headers = new StringMap(new Manifest(is).getMainAttributes(), false);
-        }
-        finally
-        {
-            if (is != null) is.close();
-        }
-
-        // Find class path meta-data.
-        String classPath = (headers == null)
-            ? null : (String) headers.get(FelixConstants.BUNDLE_CLASSPATH);
-        // Parse the class path into strings.
-        String[] classPathStrings = ManifestParser.parseDelimitedString(
-            classPath, FelixConstants.CLASS_PATH_SEPARATOR);
-
-        if (classPathStrings == null)
-        {
-            classPathStrings = new String[0];
-        }
-
-        // Create the bundles class path.
-        for (int i = 0; i < classPathStrings.length; i++)
-        {
-            // Remove any leading slash, since all bundle class path
-            // entries are relative to the root of the bundle.
-            classPathStrings[i] = (classPathStrings[i].startsWith("/"))
-                ? classPathStrings[i].substring(1)
-                : classPathStrings[i];
-
-            // Check for the bundle itself on the class path.
-            if (classPathStrings[i].equals(FelixConstants.CLASS_PATH_DOT))
-            {
-                localContentList.add(content);
-            }
-            else
-            {
-                // Try to find the embedded class path entry in the current
-                // content.
-                IContent embeddedContent = content.getEntryAsContent(classPathStrings[i]);
-                // If the embedded class path entry was not found, it might be
-                // in one of the fragments if the current content is the bundle,
-                // so try to search the fragments if necessary.
-                for (int fragIdx = 0;
-                    searchFragments && (embeddedContent == null)
-                        && (m_fragmentContents != null) && (fragIdx < m_fragmentContents.length);
-                    fragIdx++)
-                {
-                    embeddedContent = m_fragmentContents[fragIdx].getEntryAsContent(classPathStrings[i]);
-                }
-                // If we found the embedded content, then add it to the
-                // class path content list.
-                if (embeddedContent != null)
-                {
-                    localContentList.add(embeddedContent);
-                }
-                else
-                {
-// TODO: FRAMEWORK - Per the spec, this should fire a FrameworkEvent.INFO event;
-//       need to create an "Eventer" class like "Logger" perhaps.
-                    m_logger.log(Logger.LOG_INFO,
-                        "Class path entry not found: "
-                        + classPathStrings[i]);
-                }
-            }
-        }
-
-        // If there is nothing on the class path, then include
-        // "." by default, as per the spec.
-        if (localContentList.size() == 0)
-        {
-            localContentList.add(content);
-        }
-
-        // Now add the local contents to the global content list and return it.
-        contentList.addAll(localContentList);
-        return contentList;
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleClassLoader.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleClassLoader.java
new file mode 100644
index 0000000..e93b911
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleClassLoader.java
@@ -0,0 +1,653 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework.searchpolicy;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.security.ProtectionDomain;
+import java.security.SecureClassLoader;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.cache.JarContent;
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.apache.felix.framework.util.manifestparser.Requirement;
+import org.apache.felix.moduleloader.ICapability;
+import org.apache.felix.moduleloader.IContent;
+import org.apache.felix.moduleloader.IModule;
+import org.apache.felix.moduleloader.IRequirement;
+import org.apache.felix.moduleloader.IWire;
+import org.apache.felix.moduleloader.ResourceNotFoundException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+
+public class ModuleClassLoader extends SecureClassLoader
+{
+    private static final Constructor m_dexFileClassConstructor;
+    private static final Method m_dexFileClassLoadClass;
+    static
+    {
+        Constructor dexFileClassConstructor = null;
+        Method dexFileClassLoadClass = null;
+        try
+        {
+            Class dexFileClass;
+            try
+            {
+                dexFileClass = Class.forName("dalvik.system.DexFile");
+            }
+            catch (Exception ex)
+            {
+                dexFileClass = Class.forName("android.dalvik.DexFile");
+            }
+
+            dexFileClassConstructor = dexFileClass.getConstructor(
+                new Class[] { java.io.File.class });
+            dexFileClassLoadClass = dexFileClass.getMethod("loadClass",
+                new Class[] { String.class, ClassLoader.class });
+        }
+        catch (Exception ex)
+        {
+           dexFileClassConstructor = null;
+           dexFileClassLoadClass = null;
+        }
+        m_dexFileClassConstructor = dexFileClassConstructor;
+        m_dexFileClassLoadClass = dexFileClassLoadClass;
+    }
+
+    private final ModuleImpl m_module;
+    private final ProtectionDomain m_protectionDomain;
+    private final Map m_jarContentToDexFile;
+
+    public ModuleClassLoader(ModuleImpl module, ProtectionDomain protectionDomain)
+    {
+        m_module = module;
+        m_protectionDomain = protectionDomain;
+        if (m_dexFileClassConstructor != null)
+        {
+            m_jarContentToDexFile = new HashMap();
+        }
+        else
+        {
+            m_jarContentToDexFile = null;
+        }
+    }
+
+    public IModule getModule()
+    {
+        return m_module;
+    }
+
+    protected Class loadClass(String name, boolean resolve)
+        throws ClassNotFoundException
+    {
+        Class clazz = null;
+
+        // Make sure the class was not already loaded.
+        synchronized (this)
+        {
+            clazz = findLoadedClass(name);
+        }
+
+        if (clazz == null)
+        {
+            try
+            {
+                return (Class) m_module.findClassOrResourceByDelegation(name, true);
+            }
+            catch (ResourceNotFoundException ex)
+            {
+                // This should never happen since we are asking for a class,
+                // so just ignore it.
+            }
+            catch (ClassNotFoundException cnfe)
+            {
+                ClassNotFoundException ex = cnfe;
+                String msg = name;
+                if (m_module.getLogger().getLogLevel() >= Logger.LOG_DEBUG)
+                {
+                    msg = diagnoseClassLoadError(m_module, name);
+                    ex = new ClassNotFoundException(msg, cnfe);
+                }
+                throw ex;
+            }
+        }
+
+        // Resolve the class and return it.
+        if (resolve)
+        {
+            resolveClass(clazz);
+        }
+        return clazz;
+    }
+
+    protected Class findClass(String name) throws ClassNotFoundException
+    {
+        // Do a quick check here to see if we can short-circuit this
+        // entire process if the class was already loaded.
+        Class clazz = null;
+        synchronized (this)
+        {
+            clazz = findLoadedClass(name);
+        }
+
+        // Search for class in module.
+        if (clazz == null)
+        {
+            String actual = name.replace('.', '/') + ".class";
+
+            byte[] bytes = null;
+
+            IContent content = null;
+            // Check the module class path.
+            for (int i = 0;
+                (bytes == null) &&
+                (i < m_module.getClassPath().length); i++)
+            {
+                bytes = m_module.getClassPath()[i].getEntryAsBytes(actual);
+                content = m_module.getClassPath()[i];
+            }
+
+            if (bytes != null)
+            {
+                // Before we actually attempt to define the class, grab
+                // the lock for this class loader and make sure than no
+                // other thread has defined this class in the meantime.
+                synchronized (this)
+                {
+                    clazz = findLoadedClass(name);
+
+                    if (clazz == null)
+                    {
+                        // We need to try to define a Package object for the class
+                        // before we call defineClass(). Get the package name and
+                        // see if we have already created the package.
+                        String pkgName = Util.getClassPackage(name);
+                        if (pkgName.length() > 0)
+                        {
+                            if (getPackage(pkgName) == null)
+                            {
+                                Object[] params = definePackage(pkgName);
+                                if (params != null)
+                                {
+                                    definePackage(
+                                        pkgName,
+                                        (String) params[0],
+                                        (String) params[1],
+                                        (String) params[2],
+                                        (String) params[3],
+                                        (String) params[4],
+                                        (String) params[5],
+                                        null);
+                                }
+                                else
+                                {
+                                    definePackage(pkgName, null, null,
+                                        null, null, null, null, null);
+                                }
+                            }
+                        }
+
+                        // If we can load the class from a dex file do so
+                        if (content instanceof JarContent)
+                        {
+                            try
+                            {
+                                clazz = getDexFileClass((JarContent) content, name, this);
+                            }
+                            catch (Exception ex)
+                            {
+                                // Looks like we can't
+                            }
+                        }
+
+                        if (clazz == null)
+                        {
+                            // If we have a security context, then use it to
+                            // define the class with it for security purposes,
+                            // otherwise define the class without a protection domain.
+                            if (m_protectionDomain != null)
+                            {
+                                clazz = defineClass(name, bytes, 0, bytes.length,
+                                    m_protectionDomain);
+                            }
+                            else
+                            {
+                                clazz = defineClass(name, bytes, 0, bytes.length);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return clazz;
+    }
+
+    private Object[] definePackage(String pkgName)
+    {
+        Map headerMap = m_module.getHeaders();
+        String spectitle = (String) headerMap.get("Specification-Title");
+        String specversion = (String) headerMap.get("Specification-Version");
+        String specvendor = (String) headerMap.get("Specification-Vendor");
+        String impltitle = (String) headerMap.get("Implementation-Title");
+        String implversion = (String) headerMap.get("Implementation-Version");
+        String implvendor = (String) headerMap.get("Implementation-Vendor");
+        if ((spectitle != null)
+            || (specversion != null)
+            || (specvendor != null)
+            || (impltitle != null)
+            || (implversion != null)
+            || (implvendor != null))
+        {
+            return new Object[] {
+                spectitle, specversion, specvendor, impltitle, implversion, implvendor
+            };
+        }
+        return null;
+    }
+
+    private Class getDexFileClass(JarContent content, String name, ClassLoader loader)
+        throws Exception
+    {
+        if (m_jarContentToDexFile == null)
+        {
+            return null;
+        }
+
+        Object dexFile = null;
+
+        if (!m_jarContentToDexFile.containsKey(content))
+        {
+            try
+            {
+                dexFile = m_dexFileClassConstructor.newInstance(
+                    new Object[] { content.getFile() });
+            }
+            finally
+            {
+                m_jarContentToDexFile.put(content, dexFile);
+            }
+        }
+        else
+        {
+            dexFile = m_jarContentToDexFile.get(content);
+        }
+
+        if (dexFile != null)
+        {
+            return (Class) m_dexFileClassLoadClass.invoke(dexFile,
+                new Object[] { name.replace('.','/'), loader });
+        }
+        return null;
+    }
+
+    public URL getResource(String name)
+    {
+        try
+        {
+            return (URL) m_module.findClassOrResourceByDelegation(name, false);
+        }
+        catch (ClassNotFoundException ex)
+        {
+            // This should never happen, so just ignore it.
+        }
+        catch (ResourceNotFoundException ex)
+        {
+            // Not much we can do here since getResource() does not throw any
+            // exceptions, so just ignore it too.
+        }
+        return null;
+    }
+
+    protected URL findResource(String name)
+    {
+        return m_module.getResourceFromModule(name);
+    }
+
+    // This should actually be findResources(), but it can't be for the
+    // reason described below for the actual findResources() method.
+    Enumeration findResourcesFromModule(String name)
+    {
+        return m_module.getResourcesFromModule(name);
+    }
+
+    // The findResources() method should only look at the module itself, but
+    // instead it tries to delegate because in Java version prior to 1.5 the
+    // getResources() method was final and could not be overridden. We should
+    // override getResources() like getResource() to make it delegate, but we
+    // can't. As a workaround, we make findResources() delegate instead.
+    protected Enumeration findResources(String name)
+    {
+        return m_module.getResourcesByDelegation(name);
+    }
+
+    protected String findLibrary(String name)
+    {
+        // Remove leading slash, if present.
+        if (name.startsWith("/"))
+        {
+            name = name.substring(1);
+        }
+
+        R4Library[] libs = m_module.getNativeLibraries();
+        for (int i = 0; (libs != null) && (i < libs.length); i++)
+        {
+            if (libs[i].match(name))
+            {
+                return m_module.getContent()
+                    .getEntryAsNativeLibrary(libs[i].getEntryName());
+            }
+        }
+
+        return null;
+    }
+
+    public String toString()
+    {
+        return m_module.toString();
+    }
+
+    private static String diagnoseClassLoadError(ModuleImpl module, String name)
+    {
+        // We will try to do some diagnostics here to help the developer
+        // deal with this exception.
+
+        // Get package name.
+        String pkgName = Util.getClassPackage(name);
+
+        // First, get the bundle ID of the module doing the class loader.
+        long impId = Util.getBundleIdFromModuleId(module.getId());
+
+        // Next, check to see if the module imports the package.
+        IWire[] wires = module.getWires();
+        for (int i = 0; (wires != null) && (i < wires.length); i++)
+        {
+            if (wires[i].getCapability().getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
+                wires[i].getCapability().getProperties().get(ICapability.PACKAGE_PROPERTY).equals(pkgName))
+            {
+                long expId = Util.getBundleIdFromModuleId(wires[i].getExporter().getId());
+
+                StringBuffer sb = new StringBuffer("*** Package '");
+                sb.append(pkgName);
+                sb.append("' is imported by bundle ");
+                sb.append(impId);
+                sb.append(" from bundle ");
+                sb.append(expId);
+                sb.append(", but the exported package from bundle ");
+                sb.append(expId);
+                sb.append(" does not contain the requested class '");
+                sb.append(name);
+                sb.append("'. Please verify that the class name is correct in the importing bundle ");
+                sb.append(impId);
+                sb.append(" and/or that the exported package is correctly bundled in ");
+                sb.append(expId);
+                sb.append(". ***");
+
+                return sb.toString();
+            }
+        }
+
+        // Next, check to see if the package was optionally imported and
+        // whether or not there is an exporter available.
+        IRequirement[] reqs = module.getRequirements();
+/*
+ * TODO: RB - Fix diagnostic message for optional imports.
+        for (int i = 0; (reqs != null) && (i < reqs.length); i++)
+        {
+            if (reqs[i].getName().equals(pkgName) && reqs[i].isOptional())
+            {
+                // Try to see if there is an exporter available.
+                IModule[] exporters = getResolvedExporters(reqs[i], true);
+                exporters = (exporters.length == 0)
+                    ? getUnresolvedExporters(reqs[i], true) : exporters;
+
+                // An exporter might be available, but it may have attributes
+                // that do not match the importer's required attributes, so
+                // check that case by simply looking for an exporter of the
+                // desired package without any attributes.
+                if (exporters.length == 0)
+                {
+                    IRequirement pkgReq = new Requirement(
+                        ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
+                    exporters = getResolvedExporters(pkgReq, true);
+                    exporters = (exporters.length == 0)
+                        ? getUnresolvedExporters(pkgReq, true) : exporters;
+                }
+
+                long expId = (exporters.length == 0)
+                    ? -1 : Util.getBundleIdFromModuleId(exporters[0].getId());
+
+                StringBuffer sb = new StringBuffer("*** Class '");
+                sb.append(name);
+                sb.append("' was not found, but this is likely normal since package '");
+                sb.append(pkgName);
+                sb.append("' is optionally imported by bundle ");
+                sb.append(impId);
+                sb.append(".");
+                if (exporters.length > 0)
+                {
+                    sb.append(" However, bundle ");
+                    sb.append(expId);
+                    if (reqs[i].isSatisfied(
+                        Util.getExportPackage(exporters[0], reqs[i].getName())))
+                    {
+                        sb.append(" does export this package. Bundle ");
+                        sb.append(expId);
+                        sb.append(" must be installed before bundle ");
+                        sb.append(impId);
+                        sb.append(" is resolved or else the optional import will be ignored.");
+                    }
+                    else
+                    {
+                        sb.append(" does export this package with attributes that do not match.");
+                    }
+                }
+                sb.append(" ***");
+
+                return sb.toString();
+            }
+        }
+*/
+        // Next, check to see if the package is dynamically imported by the module.
+/* TODO: RESOLVER: Need to fix this too.
+        IRequirement[] dynamics = module.getDefinition().getDynamicRequirements();
+        for (int dynIdx = 0; dynIdx < dynamics.length; dynIdx++)
+        {
+            IRequirement target = createDynamicRequirement(dynamics[dynIdx], pkgName);
+            if (target != null)
+            {
+                // Try to see if there is an exporter available.
+                PackageSource[] exporters = getResolvedCandidates(target);
+                exporters = (exporters.length == 0)
+                    ? getUnresolvedCandidates(target) : exporters;
+
+                // An exporter might be available, but it may have attributes
+                // that do not match the importer's required attributes, so
+                // check that case by simply looking for an exporter of the
+                // desired package without any attributes.
+                if (exporters.length == 0)
+                {
+                    try
+                    {
+                        IRequirement pkgReq = new Requirement(
+                            ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
+                        exporters = getResolvedCandidates(pkgReq);
+                        exporters = (exporters.length == 0)
+                            ? getUnresolvedCandidates(pkgReq) : exporters;
+                    }
+                    catch (InvalidSyntaxException ex)
+                    {
+                        // This should never happen.
+                    }
+                }
+
+                long expId = (exporters.length == 0)
+                    ? -1 : Util.getBundleIdFromModuleId(exporters[0].m_module.getId());
+
+                StringBuffer sb = new StringBuffer("*** Class '");
+                sb.append(name);
+                sb.append("' was not found, but this is likely normal since package '");
+                sb.append(pkgName);
+                sb.append("' is dynamically imported by bundle ");
+                sb.append(impId);
+                sb.append(".");
+                if (exporters.length > 0)
+                {
+                    try
+                    {
+                        if (!target.isSatisfied(
+                            Util.getSatisfyingCapability(exporters[0].m_module,
+                                new Requirement(ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")"))))
+                        {
+                            sb.append(" However, bundle ");
+                            sb.append(expId);
+                            sb.append(" does export this package with attributes that do not match.");
+                        }
+                    }
+                    catch (InvalidSyntaxException ex)
+                    {
+                        // This should never happen.
+                    }
+                }
+                sb.append(" ***");
+
+                return sb.toString();
+            }
+        }
+*/
+        IRequirement pkgReq = null;
+        try
+        {
+            pkgReq = new Requirement(ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
+        }
+        catch (InvalidSyntaxException ex)
+        {
+            // This should never happen.
+        }
+        PackageSource[] exporters =
+            module.getResolver().getResolvedCandidates(pkgReq);
+        exporters = (exporters.length == 0)
+            ? module.getResolver().getUnresolvedCandidates(pkgReq)
+            : exporters;
+        if (exporters.length > 0)
+        {
+            boolean classpath = false;
+            try
+            {
+                ModuleClassLoader.class.getClassLoader().loadClass(name);
+                classpath = true;
+            }
+            catch (NoClassDefFoundError err)
+            {
+                // Ignore
+            }
+            catch (Exception ex)
+            {
+                // Ignore
+            }
+
+            long expId = Util.getBundleIdFromModuleId(exporters[0].m_module.getId());
+
+            StringBuffer sb = new StringBuffer("*** Class '");
+            sb.append(name);
+            sb.append("' was not found because bundle ");
+            sb.append(impId);
+            sb.append(" does not import '");
+            sb.append(pkgName);
+            sb.append("' even though bundle ");
+            sb.append(expId);
+            sb.append(" does export it.");
+            if (classpath)
+            {
+                sb.append(" Additionally, the class is also available from the system class loader. There are two fixes: 1) Add an import for '");
+                sb.append(pkgName);
+                sb.append("' to bundle ");
+                sb.append(impId);
+                sb.append("; imports are necessary for each class directly touched by bundle code or indirectly touched, such as super classes if their methods are used. ");
+                sb.append("2) Add package '");
+                sb.append(pkgName);
+                sb.append("' to the '");
+                sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
+                sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
+            }
+            else
+            {
+                sb.append(" To resolve this issue, add an import for '");
+                sb.append(pkgName);
+                sb.append("' to bundle ");
+                sb.append(impId);
+                sb.append(".");
+            }
+            sb.append(" ***");
+
+            return sb.toString();
+        }
+
+        // Next, try to see if the class is available from the system
+        // class loader.
+        try
+        {
+            ModuleClassLoader.class.getClassLoader().loadClass(name);
+
+            StringBuffer sb = new StringBuffer("*** Package '");
+            sb.append(pkgName);
+            sb.append("' is not imported by bundle ");
+            sb.append(impId);
+            sb.append(", nor is there any bundle that exports package '");
+            sb.append(pkgName);
+            sb.append("'. However, the class '");
+            sb.append(name);
+            sb.append("' is available from the system class loader. There are two fixes: 1) Add package '");
+            sb.append(pkgName);
+            sb.append("' to the '");
+            sb.append(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
+            sb.append("' property and modify bundle ");
+            sb.append(impId);
+            sb.append(" to import this package; this causes the system bundle to export class path packages. 2) Add package '");
+            sb.append(pkgName);
+            sb.append("' to the '");
+            sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
+            sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
+            sb.append(" ***");
+
+            return sb.toString();
+        }
+        catch (Exception ex2)
+        {
+        }
+
+        // Finally, if there are no imports or exports for the package
+        // and it is not available on the system class path, simply
+        // log a message saying so.
+        StringBuffer sb = new StringBuffer("*** Class '");
+        sb.append(name);
+        sb.append("' was not found. Bundle ");
+        sb.append(impId);
+        sb.append(" does not import package '");
+        sb.append(pkgName);
+        sb.append("', nor is the package exported by any other bundle or available from the system class loader.");
+        sb.append(" ***");
+
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleDefinition.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleDefinition.java
deleted file mode 100644
index 8774ea5..0000000
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleDefinition.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.searchpolicy;
-
-import java.util.Map;
-import org.apache.felix.framework.util.manifestparser.R4Library;
-import org.apache.felix.moduleloader.*;
-
-public class ModuleDefinition implements IModuleDefinition
-{
-    private Map m_headerMap = null;
-    private ICapability[] m_capabilities = null;
-    private IRequirement[] m_requirements = null;
-    private IRequirement[] m_dynamicRequirements = null;
-    private R4Library[] m_libraries = null;
-
-    public ModuleDefinition(
-        Map headerMap, ICapability[] capabilities, IRequirement[] requirements,
-        IRequirement[] dynamicRequirements, R4Library[] libraries)
-    {
-        m_headerMap = headerMap;
-        m_capabilities = capabilities;
-        m_requirements = requirements;
-        m_dynamicRequirements = dynamicRequirements;
-        m_libraries = libraries;
-    }
-
-    public Map getHeaders()
-    {
-        return m_headerMap;
-    }
-
-    public ICapability[] getCapabilities()
-    {
-// TODO: RB - These should probably all return copies of the array.
-        return m_capabilities;
-    }
-
-    public IRequirement[] getRequirements()
-    {
-        return m_requirements;
-    }
-
-    public IRequirement[] getDynamicRequirements()
-    {
-        return m_dynamicRequirements;
-    }
-
-    public R4Library[] getLibraries()
-    {
-        return m_libraries;
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java
new file mode 100644
index 0000000..51aec37
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java
@@ -0,0 +1,1191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework.searchpolicy;
+
+import org.apache.felix.moduleloader.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Proxy;
+import java.net.URL;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import org.apache.felix.framework.Felix.FelixResolver;
+import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.util.CompoundEnumeration;
+import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.framework.util.SecureAction;
+import org.apache.felix.framework.util.SecurityManagerEx;
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.framework.util.manifestparser.ManifestParser;
+import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+public class ModuleImpl implements IModule
+{
+    private final Logger m_logger;
+
+    private Bundle m_bundle = null;
+
+    private final Map m_headerMap;
+    private final ICapability[] m_capabilities;
+    private final IRequirement[] m_requirements;
+    private final IRequirement[] m_dynamicRequirements;
+    private final R4Library[] m_nativeLibraries;
+
+    private final String m_id;
+    private volatile String m_symbolicName = null;
+    private IModule[] m_fragments = null;
+    private IWire[] m_wires = null;
+    private IModule[] m_dependentHosts = new IModule[0];
+    private IModule[] m_dependentImporters = new IModule[0];
+    private IModule[] m_dependentRequirers = new IModule[0];
+    private volatile boolean m_isResolved = false;
+
+    // TODO: REFACTOR - Fields below are from ContentLoaderImpl
+    private final Map m_configMap;
+    private final FelixResolver m_resolver;
+    private final IContent m_content;
+    private IContent[] m_contentPath;
+    private IContent[] m_fragmentContents = null;
+    private IURLPolicy m_urlPolicy = null;
+    private ModuleClassLoader m_classLoader;
+    private ProtectionDomain m_protectionDomain = null;
+    private static SecureAction m_secureAction = new SecureAction();
+
+    // Boot delegation packages.
+    private final String[] m_bootPkgs;
+    private final boolean[] m_bootPkgWildcards;
+
+    // Re-usable security manager for accessing class context.
+    private static SecurityManagerEx m_sm = new SecurityManagerEx();
+
+// TODO: REFACTOR - Should the module constructor parse the manifest?
+    public ModuleImpl(Logger logger, Map configMap, FelixResolver resolver,
+        String id, IContent content, Map headerMap,
+        ICapability[] caps, IRequirement[] reqs, IRequirement[] dynReqs,
+        R4Library[] nativeLibs)
+    {
+        m_logger = logger;
+        m_configMap = configMap;
+        m_resolver = resolver;
+        m_id = id;
+        m_content = content;
+        m_headerMap = headerMap;
+        m_capabilities = caps;
+        m_requirements = reqs;
+        m_dynamicRequirements = dynReqs;
+        m_nativeLibraries = nativeLibs;
+
+        // Read the boot delegation property and parse it.
+// TODO: REFACTOR - This used to be per framework, now it is per module
+//       which doesn't really make sense.
+        String s = (m_configMap == null)
+            ? null
+            : (String) m_configMap.get(Constants.FRAMEWORK_BOOTDELEGATION);
+        s = (s == null) ? "java.*" : s + ",java.*";
+        StringTokenizer st = new StringTokenizer(s, " ,");
+        m_bootPkgs = new String[st.countTokens()];
+        m_bootPkgWildcards = new boolean[m_bootPkgs.length];
+        for (int i = 0; i < m_bootPkgs.length; i++)
+        {
+            s = st.nextToken();
+            if (s.endsWith("*"))
+            {
+                m_bootPkgWildcards[i] = true;
+                s = s.substring(0, s.length() - 1);
+            }
+            m_bootPkgs[i] = s;
+        }
+   }
+
+    public synchronized Bundle getBundle()
+    {
+        return m_bundle;
+    }
+
+    public synchronized void setBundle(Bundle bundle)
+    {
+        if (m_bundle == null)
+        {
+            m_bundle = bundle;
+        }
+    }
+
+    public String getId()
+    {
+        return m_id;
+    }
+
+    public String getSymbolicName()
+    {
+        if (m_symbolicName == null)
+        {
+            for (int capIdx = 0;
+                (m_symbolicName == null) && (m_capabilities != null) && (capIdx < m_capabilities.length);
+                capIdx++)
+            {
+                if (m_capabilities[capIdx].getNamespace().equals(ICapability.MODULE_NAMESPACE))
+                {
+                    m_symbolicName = (String) m_capabilities[capIdx].getProperties().get(
+                        Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
+                }
+            }
+        }
+        return m_symbolicName;
+    }
+
+    public Map getHeaders()
+    {
+        return m_headerMap;
+    }
+
+    public ICapability[] getCapabilities()
+    {
+        return m_capabilities;
+    }
+
+    public IRequirement[] getRequirements()
+    {
+        return m_requirements;
+    }
+
+    public IRequirement[] getDynamicRequirements()
+    {
+        return m_dynamicRequirements;
+    }
+
+    public R4Library[] getNativeLibraries()
+    {
+        return m_nativeLibraries;
+    }
+
+    public synchronized IModule[] getFragments()
+    {
+        return m_fragments;
+    }
+
+    public synchronized void attachFragments(IModule[] fragments) throws Exception
+    {
+        // Remove module from old fragment dependencies.
+        // We will generally only remove module fragment
+        // dependencies when we are uninstalling the module.
+        for (int i = 0; (m_fragments != null) && (i < m_fragments.length); i++)
+        {
+            ((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)
+        {
+            IContent[] fragmentContents = new IContent[m_fragments.length];
+            for (int i = 0; (m_fragments != null) && (i < m_fragments.length); i++)
+            {
+                ((ModuleImpl) m_fragments[i]).addDependentHost(this);
+                fragmentContents[i] =
+                    m_fragments[i].getContent()
+                        .getEntryAsContent(FelixConstants.CLASS_PATH_DOT);
+            }
+            // Now attach the fragment contents to our content loader.
+            attachFragmentContents(fragmentContents);
+        }
+    }
+
+    private void attachFragmentContents(IContent[] fragmentContents)
+        throws Exception
+    {
+        // Close existing fragment contents.
+        if (m_fragmentContents != null)
+        {
+            for (int i = 0; i < m_fragmentContents.length; i++)
+            {
+                m_fragmentContents[i].close();
+            }
+        }
+        m_fragmentContents = fragmentContents;
+
+        if (m_contentPath != null)
+        {
+            for (int i = 0; i < m_contentPath.length; i++)
+            {
+                m_contentPath[i].close();
+            }
+        }
+        m_contentPath = initializeContentPath();
+    }
+
+    public synchronized IWire[] getWires()
+    {
+        return m_wires;
+    }
+
+    public synchronized void setWires(IWire[] wires)
+    {
+        // 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++)
+        {
+            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 ourself as a dependent to the new wires' modules.
+        for (int i = 0; (m_wires != null) && (i < m_wires.length); i++)
+        {
+            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);
+            }
+        }
+    }
+
+    public synchronized IModule[] getDependentHosts()
+    {
+        return m_dependentHosts;
+    }
+
+    public synchronized void addDependentHost(IModule module)
+    {
+        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()
+    {
+        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 getClassByDelegation(String name) throws ClassNotFoundException
+    {
+        try
+        {
+            return getClassLoader().loadClass(name);
+        }
+        catch (ClassNotFoundException ex)
+        {
+// TODO: REFACTOR - Should this log?
+            m_logger.log(
+                Logger.LOG_WARNING,
+                ex.getMessage(),
+                ex);
+            throw ex;
+        }
+    }
+
+    public URL getResourceByDelegation(String name)
+    {
+        return getClassLoader().getResource(name);
+    }
+
+    public Enumeration getResourcesByDelegation(String name)
+    {
+        Enumeration urls = null;
+        List enums = new ArrayList();
+
+        // First, try to resolve the originating module.
+// TODO: FRAMEWORK - Consider opimizing this call to resolve, since it is called
+// for each class load.
+        try
+        {
+            m_resolver.resolve(this);
+        }
+        catch (ResolveException ex)
+        {
+            // The spec states that if the bundle cannot be resolved, then
+            // only the local bundle's resources should be searched. So we
+            // will ask the module's own class path.
+            urls = getResourcesFromModule(name);
+            return urls;
+        }
+
+        // Get the package of the target class/resource.
+        String pkgName = Util.getResourcePackage(name);
+
+        // Delegate any packages listed in the boot delegation
+        // property to the parent class loader.
+        // NOTE for the default package:
+        // Only consider delegation if we have a package name, since
+        // we don't want to promote the default package. The spec does
+        // not take a stand on this issue.
+        if (pkgName.length() > 0)
+        {
+            for (int i = 0; i < m_bootPkgs.length; i++)
+            {
+                // A wildcarded boot delegation package will be in the form of
+                // "foo.", so if the package is wildcarded do a startsWith() or a
+                // regionMatches() to ignore the trailing "." to determine if the
+                // request should be delegated to the parent class loader. If the
+                // package is not wildcarded, then simply do an equals() test to
+                // see if the request should be delegated to the parent class loader.
+                if ((m_bootPkgWildcards[i] &&
+                    (pkgName.startsWith(m_bootPkgs[i]) ||
+                    m_bootPkgs[i].regionMatches(0, pkgName, 0, pkgName.length())))
+                    || (!m_bootPkgWildcards[i] && m_bootPkgs[i].equals(pkgName)))
+                {
+                    try
+                    {
+                        urls = getClass().getClassLoader().getResources(name);
+                    }
+                    catch (IOException ex)
+                    {
+                        // This shouldn't happen and even if it does, there
+                        // is nothing we can do, so just ignore it.
+                    }
+                    // If this is a java.* package, then always terminate the
+                    // search; otherwise, continue to look locally.
+                    if (m_bootPkgs[i].startsWith("java."))
+                    {
+                        return urls;
+                    }
+
+                    enums.add(urls);
+                    break;
+                }
+            }
+        }
+
+        // Look in the module's imports.
+        // We delegate to the module's wires for the resources.
+        // If any resources are found, this means that the package of these
+        // resources is imported, we must not keep looking since we do not
+        // support split-packages.
+
+        // Note that the search may be aborted if this method throws an
+        // exception, otherwise it continues if a null is returned.
+        IWire[] wires = getWires();
+        for (int i = 0; (wires != null) && (i < wires.length); i++)
+        {
+            if (wires[i] instanceof R4Wire)
+            {
+                try
+                {
+                    // If we find the class or resource, then return it.
+                    urls = wires[i].getResources(name);
+                }
+                catch (ResourceNotFoundException ex)
+                {
+                    urls = null;
+                }
+                if (urls != null)
+                {
+                    enums.add(urls);
+                    return new CompoundEnumeration((Enumeration[])
+                        enums.toArray(new Enumeration[enums.size()]));
+                }
+            }
+        }
+
+        // See whether we can get the resource from the required bundles and
+        // regardless of whether or not this is the case continue to the next
+        // step potentially passing on the result of this search (if any).
+        for (int i = 0; (wires != null) && (i < wires.length); i++)
+        {
+            if (wires[i] instanceof R4WireModule)
+            {
+                try
+                {
+                    // If we find the class or resource, then add it.
+                    urls = wires[i].getResources(name);
+                }
+                catch (ResourceNotFoundException ex)
+                {
+                    urls = null;
+                }
+                if (urls != null)
+                {
+                    enums.add(urls);
+                }
+            }
+        }
+
+        // Try the module's own class path. If we can find the resource then
+        // return it together with the results from the other searches else
+        // try to look into the dynamic imports.
+        urls = getResourcesFromModule(name);
+        if (urls != null)
+        {
+            enums.add(urls);
+        }
+        else
+        {
+            // If not found, then try the module's dynamic imports.
+            // At this point, the module's imports were searched and so was the
+            // the module's content. Now we make an attempt to load the
+            // class/resource via a dynamic import, if possible.
+            IWire wire = null;
+            try
+            {
+                wire = m_resolver.resolveDynamicImport(this, pkgName);
+            }
+            catch (ResolveException ex)
+            {
+                // Ignore this since it is likely normal.
+            }
+            if (wire != null)
+            {
+                try
+                {
+                    urls = wire.getResources(name);
+                }
+                catch (ResourceNotFoundException ex)
+                {
+                    urls = null;
+                }
+                if (urls != null)
+                {
+                    enums.add(urls);
+                }
+            }
+        }
+
+        return new CompoundEnumeration((Enumeration[])
+            enums.toArray(new Enumeration[enums.size()]));
+    }
+
+    public boolean isResolved()
+    {
+        return m_isResolved;
+    }
+
+    public void setResolved()
+    {
+        m_isResolved = true;
+    }
+
+    public String toString()
+    {
+        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 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;
+    }
+
+    // TODO: REFACTOR - Below are from ContentLoaderImpl
+
+    Logger getLogger()
+    {
+        return m_logger;
+    }
+
+    FelixResolver getResolver()
+    {
+        return m_resolver;
+    }
+
+    public synchronized void close()
+    {
+        m_content.close();
+        for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
+        {
+            m_contentPath[i].close();
+        }
+        for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
+        {
+            m_fragmentContents[i].close();
+        }
+        synchronized (this)
+        {
+            m_classLoader = null;
+        }
+    }
+
+    public IContent getContent()
+    {
+        return m_content;
+    }
+
+    synchronized IContent[] getClassPath()
+    {
+        if (m_contentPath == null)
+        {
+            try
+            {
+                m_contentPath = initializeContentPath();
+            }
+            catch (Exception ex)
+            {
+                m_logger.log(Logger.LOG_ERROR, "Unable to get module class path.", ex);
+            }
+        }
+        return m_contentPath;
+    }
+
+    public synchronized void setURLPolicy(IURLPolicy urlPolicy)
+    {
+        m_urlPolicy = urlPolicy;
+    }
+
+    public synchronized IURLPolicy getURLPolicy()
+    {
+        return m_urlPolicy;
+    }
+
+    public synchronized void setSecurityContext(Object securityContext)
+    {
+        m_protectionDomain = (ProtectionDomain) securityContext;
+    }
+
+    public synchronized Object getSecurityContext()
+    {
+        return m_protectionDomain;
+    }
+
+    public Class getClassFromModule(String name) throws ClassNotFoundException
+    {
+        try
+        {
+            return getClassLoader().findClass(name);
+        }
+        catch (ClassNotFoundException ex)
+        {
+            m_logger.log(
+                Logger.LOG_WARNING,
+                ex.getMessage(),
+                ex);
+            throw ex;
+        }
+    }
+
+// TODO: REFACTOR - This previously didn't cause the class loader to be created.
+    public URL getResourceFromModule(String name)
+    {
+        URL url = null;
+
+        // Remove leading slash, if present, but special case
+        // "/" so that it returns a root URL...this isn't very
+        // clean or meaninful, but the Spring guys want it.
+        if (name.equals("/"))
+        {
+            // Just pick a class path index since it doesn't really matter.
+            url = getURLPolicy().createURL(1, name);
+        }
+        else if (name.startsWith("/"))
+        {
+            name = name.substring(1);
+        }
+
+        // Check the module class path.
+        IContent[] contentPath = getClassPath();
+        for (int i = 0;
+            (url == null) &&
+            (i < contentPath.length); i++)
+        {
+            if (contentPath[i].hasEntry(name))
+            {
+                url = getURLPolicy().createURL(i + 1, name);
+            }
+        }
+
+        return url;
+    }
+
+// TODO: REFACTOR - This previously didn't cause the class loader to be created.
+    public Enumeration getResourcesFromModule(String name)
+    {
+        Vector v = new Vector();
+
+        // Special case "/" so that it returns a root URLs for
+        // each bundle class path entry...this isn't very
+        // clean or meaningful, but the Spring guys want it.
+        if (name.equals("/"))
+        {
+            for (int i = 0; i < getClassPath().length; i++)
+            {
+                v.addElement(getURLPolicy().createURL(i + 1, name));
+            }
+        }
+        else
+        {
+            // Remove leading slash, if present.
+            if (name.startsWith("/"))
+            {
+                name = name.substring(1);
+            }
+
+            // Check the module class path.
+            IContent[] contentPath = getClassPath();
+            for (int i = 0; i < contentPath.length; i++)
+            {
+                if (contentPath[i].hasEntry(name))
+                {
+                    // Use the class path index + 1 for creating the path so
+                    // that we can differentiate between module content URLs
+                    // (where the path will start with 0) and module class
+                    // path URLs.
+                    v.addElement(getURLPolicy().createURL(i + 1, name));
+                }
+            }
+        }
+
+        return v.elements();
+    }
+
+    // TODO: API: Investigate how to handle this better, perhaps we need
+    // multiple URL policies, one for content -- one for class path.
+    public URL getResourceFromContent(String name)
+    {
+        URL url = null;
+
+        // Check for the special case of "/", which represents
+        // the root of the bundle according to the spec.
+        if (name.equals("/"))
+        {
+            url = getURLPolicy().createURL(0, "/");
+        }
+
+        if (url == null)
+        {
+            // Remove leading slash, if present.
+            if (name.startsWith("/"))
+            {
+                name = name.substring(1);
+            }
+
+            // Check the module content.
+            if (getContent().hasEntry(name))
+            {
+                // Module content URLs start with 0, whereas module
+                // class path URLs start with the index into the class
+                // path + 1.
+                url = getURLPolicy().createURL(0, name);
+            }
+        }
+
+        return url;
+    }
+
+    public boolean hasInputStream(int index, String urlPath)
+    {
+        if (urlPath.startsWith("/"))
+        {
+            urlPath = urlPath.substring(1);
+        }
+        if (index == 0)
+        {
+            return m_content.hasEntry(urlPath);
+        }
+        return getClassPath()[index - 1].hasEntry(urlPath);
+    }
+
+    public InputStream getInputStream(int index, String urlPath)
+        throws IOException
+    {
+        if (urlPath.startsWith("/"))
+        {
+            urlPath = urlPath.substring(1);
+        }
+        if (index == 0)
+        {
+            return m_content.getEntryAsStream(urlPath);
+        }
+        return getClassPath()[index - 1].getEntryAsStream(urlPath);
+    }
+
+    private ModuleClassLoader getClassLoader()
+    {
+        synchronized (this)
+        {
+            if (m_classLoader == null)
+            {
+                m_classLoader = m_secureAction.createModuleClassLoader(
+                    this, m_protectionDomain);
+            }
+        }
+        return m_classLoader;
+    }
+
+    private IContent[] initializeContentPath() throws Exception
+    {
+        List contentList = new ArrayList();
+        calculateContentPath(m_content, contentList, true);
+        for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
+        {
+            calculateContentPath(m_fragmentContents[i], contentList, false);
+        }
+        return (IContent[]) contentList.toArray(new IContent[contentList.size()]);
+    }
+
+    private List calculateContentPath(IContent content, List contentList, boolean searchFragments)
+        throws Exception
+    {
+        // Creating the content path entails examining the bundle's
+        // class path to determine whether the bundle JAR file itself
+        // is on the bundle's class path and then creating content
+        // objects for everything on the class path.
+
+        // Create a list to contain the content path for the specified content.
+        List localContentList = new ArrayList();
+
+        // Find class path meta-data.
+        String classPath = (String) m_headerMap.get(FelixConstants.BUNDLE_CLASSPATH);
+        // Parse the class path into strings.
+        String[] classPathStrings = ManifestParser.parseDelimitedString(
+            classPath, FelixConstants.CLASS_PATH_SEPARATOR);
+
+        if (classPathStrings == null)
+        {
+            classPathStrings = new String[0];
+        }
+
+        // Create the bundles class path.
+        for (int i = 0; i < classPathStrings.length; i++)
+        {
+            // Remove any leading slash, since all bundle class path
+            // entries are relative to the root of the bundle.
+            classPathStrings[i] = (classPathStrings[i].startsWith("/"))
+                ? classPathStrings[i].substring(1)
+                : classPathStrings[i];
+
+            // Check for the bundle itself on the class path.
+            if (classPathStrings[i].equals(FelixConstants.CLASS_PATH_DOT))
+            {
+                localContentList.add(content);
+            }
+            else
+            {
+                // Try to find the embedded class path entry in the current
+                // content.
+                IContent embeddedContent = content.getEntryAsContent(classPathStrings[i]);
+                // If the embedded class path entry was not found, it might be
+                // in one of the fragments if the current content is the bundle,
+                // so try to search the fragments if necessary.
+                for (int fragIdx = 0;
+                    searchFragments && (embeddedContent == null)
+                        && (m_fragmentContents != null) && (fragIdx < m_fragmentContents.length);
+                    fragIdx++)
+                {
+                    embeddedContent = m_fragmentContents[fragIdx].getEntryAsContent(classPathStrings[i]);
+                }
+                // If we found the embedded content, then add it to the
+                // class path content list.
+                if (embeddedContent != null)
+                {
+                    localContentList.add(embeddedContent);
+                }
+                else
+                {
+// TODO: FRAMEWORK - Per the spec, this should fire a FrameworkEvent.INFO event;
+//       need to create an "Eventer" class like "Logger" perhaps.
+                    m_logger.log(Logger.LOG_INFO,
+                        "Class path entry not found: "
+                        + classPathStrings[i]);
+                }
+            }
+        }
+
+        // If there is nothing on the class path, then include
+        // "." by default, as per the spec.
+        if (localContentList.size() == 0)
+        {
+            localContentList.add(content);
+        }
+
+        // Now add the local contents to the global content list and return it.
+        contentList.addAll(localContentList);
+        return contentList;
+    }
+
+// From ModuleClassLoader
+
+    Object findClassOrResourceByDelegation(String name, boolean isClass)
+        throws ClassNotFoundException, ResourceNotFoundException
+    {
+        // First, try to resolve the originating module.
+// TODO: FRAMEWORK - Consider opimizing this call to resolve, since it is called
+// for each class load.
+        try
+        {
+            m_resolver.resolve(this);
+        }
+        catch (ResolveException ex)
+        {
+            if (isClass)
+            {
+                // We do not use the resolve exception as the
+                // cause of the exception, since this would
+                // potentially leak internal module information.
+                throw new ClassNotFoundException(
+                    name + ": cannot resolve package "
+                    + ex.getRequirement());
+            }
+            else
+            {
+                // The spec states that if the bundle cannot be resolved, then
+                // only the local bundle's resources should be searched. So we
+                // will ask the module's own class path.
+                URL url = getResourceFromModule(name);
+                if (url != null)
+                {
+                    return url;
+                }
+
+                // We need to throw a resource not found exception.
+                throw new ResourceNotFoundException(
+                    name + ": cannot resolve package "
+                    + ex.getRequirement());
+            }
+        }
+
+        // Get the package of the target class/resource.
+        String pkgName = (isClass)
+            ? Util.getClassPackage(name)
+            : Util.getResourcePackage(name);
+
+        // Delegate any packages listed in the boot delegation
+        // property to the parent class loader.
+        Object result = null;
+        for (int i = 0; i < m_bootPkgs.length; i++)
+        {
+            // A wildcarded boot delegation package will be in the form of "foo.",
+            // so if the package is wildcarded do a startsWith() or a regionMatches()
+            // to ignore the trailing "." to determine if the request should be
+            // delegated to the parent class loader. If the package is not wildcarded,
+            // then simply do an equals() test to see if the request should be
+            // delegated to the parent class loader.
+            if (pkgName.length() > 0)
+            {
+                // Only consider delegation if we have a package name, since
+                // we don't want to promote the default package. The spec does
+                // not take a stand on this issue.
+                if ((m_bootPkgWildcards[i] &&
+                    (pkgName.startsWith(m_bootPkgs[i]) ||
+                    m_bootPkgs[i].regionMatches(0, pkgName, 0, pkgName.length())))
+                    || (!m_bootPkgWildcards[i] && m_bootPkgs[i].equals(pkgName)))
+                {
+                    try
+                    {
+                        result = (isClass)
+                            ? (Object) getClass().getClassLoader().loadClass(name)
+                            : (Object) getClass().getClassLoader().getResource(name);
+                        // If this is a java.* package, then always terminate the
+                        // search; otherwise, continue to look locally if not found.
+                        if (m_bootPkgs[i].startsWith("java.") || (result != null))
+                        {
+                            return result;
+                        }
+                    }
+                    catch (ClassNotFoundException ex)
+                    {
+                        // If this is a java.* package, then always terminate the
+                        // search; otherwise, continue to look locally if not found.
+                        if (m_bootPkgs[i].startsWith("java."))
+                        {
+                            throw ex;
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        // Look in the module's imports. Note that the search may
+        // be aborted if this method throws an exception, otherwise
+        // it continues if a null is returned.
+        result = searchImports(name, isClass);
+
+        // If not found, try the module's own class path.
+        if (result == null)
+        {
+            result = (isClass)
+                ? (Object) getClassFromModule(name)
+                : (Object) getResourceFromModule(name);
+
+            // If still not found, then try the module's dynamic imports.
+            if (result == null)
+            {
+                result = searchDynamicImports(name, pkgName, isClass);
+            }
+        }
+
+        if (result == null)
+        {
+            if (isClass)
+            {
+                throw new ClassNotFoundException(name);
+            }
+            else
+            {
+                throw new ResourceNotFoundException(name);
+            }
+        }
+
+        return result;
+    }
+
+    private Object searchImports(String name, boolean isClass)
+        throws ClassNotFoundException, ResourceNotFoundException
+    {
+        // We delegate to the module's wires to find the class or resource.
+        IWire[] wires = getWires();
+        for (int i = 0; (wires != null) && (i < wires.length); i++)
+        {
+            // If we find the class or resource, then return it.
+            Object result = (isClass)
+                ? (Object) wires[i].getClass(name)
+                : (Object) wires[i].getResource(name);
+            if (result != null)
+            {
+                return result;
+            }
+        }
+
+        return null;
+    }
+
+    private Object searchDynamicImports(
+        String name, String pkgName, boolean isClass)
+        throws ClassNotFoundException, ResourceNotFoundException
+    {
+        // At this point, the module's imports were searched and so was the
+        // the module's content. Now we make an attempt to load the
+        // class/resource via a dynamic import, if possible.
+        IWire wire = null;
+        try
+        {
+            wire = m_resolver.resolveDynamicImport(this, pkgName);
+        }
+        catch (ResolveException ex)
+        {
+            // Ignore this since it is likely normal.
+        }
+
+        // If the dynamic import was successful, then this initial
+        // time we must directly return the result from dynamically
+        // created wire, but subsequent requests for classes/resources
+        // in the associated package will be processed as part of
+        // normal static imports.
+        if (wire != null)
+        {
+            // Return the class or resource.
+            return (isClass)
+                ? (Object) wire.getClass(name)
+                : (Object) wire.getResource(name);
+        }
+
+        // At this point, the class/resource could not be found by the bundle's
+        // static or dynamic imports, nor its own content. Before we throw
+        // an exception, we will try to determine if the instigator of the
+        // class/resource load was a class from a bundle or not. This is necessary
+        // because the specification mandates that classes on the class path
+        // should be hidden (except for java.*), but it does allow for these
+        // classes/resources to be exposed by the system bundle as an export.
+        // However, in some situations classes on the class path make the faulty
+        // assumption that they can access everything on the class path from
+        // every other class loader that they come in contact with. This is
+        // not true if the class loader in question is from a bundle. Thus,
+        // this code tries to detect that situation. If the class
+        // instigating the load request was NOT from a bundle, then we will
+        // make the assumption that the caller actually wanted to use the
+        // parent class loader and we will delegate to it. If the class was
+        // from a bundle, then we will enforce strict class loading rules
+        // for the bundle and throw an exception.
+
+        // Get the class context to see the classes on the stack.
+        Class[] classes = m_sm.getClassContext();
+        // Start from 1 to skip security manager class.
+        for (int i = 1; i < classes.length; i++)
+        {
+            // Find the first class on the call stack that is not from
+            // the class loader that loaded the Felix classes or is not
+            // a class loader or class itself, because we want to ignore
+            // calls to ClassLoader.loadClass() and Class.forName() since
+            // we are trying to find out who instigated the class load.
+            // Also since Felix uses threads for changing the start level
+            // and refreshing packages, it is possible that there is no
+            // module classes on the call stack; therefore, as soon as we
+            // see Thread on the call stack we exit this loop. Other cases
+            // where modules actually use threads are not an issue because
+            // the module classes will be on the call stack before the
+            // Thread class.
+// TODO: FRAMEWORK - This check is a hack and we should see if we can think
+// of another way to do it, since it won't necessarily work in all situations.
+            if (Thread.class.equals(classes[i]))
+            {
+                break;
+            }
+            else if ((this.getClass().getClassLoader() != classes[i].getClassLoader())
+                && !ClassLoader.class.isAssignableFrom(classes[i])
+                && !Class.class.equals(classes[i])
+                && !Proxy.class.equals(classes[i]))
+            {
+                // If there are no bundles providing exports for this
+                // package and if the instigating class was not from a
+                // bundle, then delegate to the parent class loader.
+                // Otherwise, break out of loop and return null.
+                boolean delegate = true;
+                for (ClassLoader cl = classes[i].getClassLoader(); cl != null; cl = cl.getClass().getClassLoader())
+                {
+                    if (ModuleClassLoader.class.isInstance(cl))
+                    {
+                        delegate = false;
+                        break;
+                    }
+                }
+                // If delegate is true then there are no bundles
+                // providing exports for this package and the instigating
+                // class was not from a bundle. Therefore,
+                // delegate to the parent class loader in case
+                // that this is not due to outside code calling a method
+                // on the bundle interface (e.g., Bundle.loadClass()).
+                if (delegate && !Bundle.class.isInstance(classes[i - 1]))
+                {
+                    try
+                    {
+                        // Return the class or resource from the parent class loader.
+                        return (isClass)
+                            ? (Object) this.getClass().getClassLoader().loadClass(name)
+                            : (Object) this.getClass().getClassLoader().getResource(name);
+                    }
+                    catch (NoClassDefFoundError ex)
+                    {
+                        // Ignore, will return null
+                    }
+                }
+                break;
+            }
+        }
+
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicy.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicy.java
deleted file mode 100644
index d928dfd..0000000
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicy.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.searchpolicy;
-
-import java.net.URL;
-import java.util.Enumeration;
-
-import org.apache.felix.moduleloader.*;
-
-public class R4SearchPolicy implements ISearchPolicy
-{
-    private R4SearchPolicyCore m_policyCore = null;
-    private IModule m_module = null;
-
-    public R4SearchPolicy(R4SearchPolicyCore policyCore, IModule module)
-    {
-        m_policyCore = policyCore;
-        m_module = module;
-    }
-
-    public Object[] definePackage(String name)
-    {
-        return m_policyCore.definePackage(m_module, name);
-    }
-
-    public Class findClass(String name)
-        throws ClassNotFoundException
-    {
-        return m_policyCore.findClass(m_module, name);
-    }
-
-    public URL findResource(String name)
-        throws ResourceNotFoundException
-    {
-        return m_policyCore.findResource(m_module, name);
-    }
-
-    public Enumeration findResources(String name)
-        throws ResourceNotFoundException
-    {
-        return m_policyCore.findResources(m_module, name);
-    }
-
-    public String findLibrary(String name)
-    {
-        return m_policyCore.findLibrary(m_module, name);
-    }
-
-    public String toString()
-    {
-        return m_module.toString();
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
deleted file mode 100755
index e7299e0..0000000
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
+++ /dev/null
@@ -1,924 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.searchpolicy;
-
-import java.io.IOException;
-import java.lang.reflect.Proxy;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-import org.apache.felix.framework.Felix.FelixResolver;
-import org.apache.felix.framework.Logger;
-import org.apache.felix.framework.util.CompoundEnumeration;
-import org.apache.felix.framework.util.SecurityManagerEx;
-import org.apache.felix.framework.util.Util;
-import org.apache.felix.framework.util.manifestparser.R4Library;
-import org.apache.felix.framework.util.manifestparser.Requirement;
-import org.apache.felix.moduleloader.ICapability;
-import org.apache.felix.moduleloader.IModule;
-import org.apache.felix.moduleloader.IRequirement;
-import org.apache.felix.moduleloader.IWire;
-import org.apache.felix.moduleloader.ResourceNotFoundException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.Bundle;
-
-public class R4SearchPolicyCore
-{
-    private final Logger m_logger;
-    private final Map m_configMap;
-    private final FelixResolver m_resolver;
-
-    // Boot delegation packages.
-    private String[] m_bootPkgs = null;
-    private boolean[] m_bootPkgWildcards = null;
-
-    // Reusable empty array.
-    public static final ICapability[] m_emptyCapabilities = new ICapability[0];
-
-    // Re-usable security manager for accessing class context.
-    private static SecurityManagerEx m_sm = new SecurityManagerEx();
-
-    public R4SearchPolicyCore(
-        Logger logger, Map configMap, FelixResolver resolver)
-    {
-        m_logger = logger;
-        m_configMap = configMap;
-        m_resolver = resolver;
-
-        // Read the boot delegation property and parse it.
-        String s = (String) m_configMap.get(Constants.FRAMEWORK_BOOTDELEGATION);
-        s = (s == null) ? "java.*" : s + ",java.*";
-        StringTokenizer st = new StringTokenizer(s, " ,");
-        m_bootPkgs = new String[st.countTokens()];
-        m_bootPkgWildcards = new boolean[m_bootPkgs.length];
-        for (int i = 0; i < m_bootPkgs.length; i++)
-        {
-            s = st.nextToken();
-            if (s.endsWith("*"))
-            {
-                m_bootPkgWildcards[i] = true;
-                s = s.substring(0, s.length() - 1);
-            }
-            m_bootPkgs[i] = s;
-        }
-    }
-
-    public Object[] definePackage(IModule module, String pkgName)
-    {
-        Map headerMap = ((ModuleDefinition) module.getDefinition()).getHeaders();
-        String spectitle = (String) headerMap.get("Specification-Title");
-        String specversion = (String) headerMap.get("Specification-Version");
-        String specvendor = (String) headerMap.get("Specification-Vendor");
-        String impltitle = (String) headerMap.get("Implementation-Title");
-        String implversion = (String) headerMap.get("Implementation-Version");
-        String implvendor = (String) headerMap.get("Implementation-Vendor");
-        if ((spectitle != null)
-            || (specversion != null)
-            || (specvendor != null)
-            || (impltitle != null)
-            || (implversion != null)
-            || (implvendor != null))
-        {
-            return new Object[] {
-                spectitle, specversion, specvendor, impltitle, implversion, implvendor
-            };
-        }
-        return null;
-    }
-
-    public Class findClass(IModule module, String name)
-        throws ClassNotFoundException
-    {
-        try
-        {
-            return (Class) findClassOrResource(module, name, true);
-        }
-        catch (ResourceNotFoundException ex)
-        {
-            // This should never happen, so just ignore it.
-        }
-        catch (ClassNotFoundException ex)
-        {
-            String msg = name;
-            if (m_logger.getLogLevel() >= Logger.LOG_DEBUG)
-            {
-                msg = diagnoseClassLoadError(module, name);
-            }
-            throw new ClassNotFoundException(msg, ex);
-        }
-
-        // We should never reach this point.
-        return null;
-    }
-
-    public URL findResource(IModule module, String name)
-        throws ResourceNotFoundException
-    {
-        try
-        {
-            return (URL) findClassOrResource(module, name, false);
-        }
-        catch (ClassNotFoundException ex)
-        {
-            // This should never happen, so just ignore it.
-        }
-        catch (ResourceNotFoundException ex)
-        {
-            throw ex;
-        }
-
-        // We should never reach this point.
-        return null;
-    }
-
-    public Enumeration findResources(IModule module, String name)
-        throws ResourceNotFoundException
-    {
-        Enumeration urls = null;
-        List enums = new ArrayList();
-
-        // First, try to resolve the originating module.
-// TODO: FRAMEWORK - Consider opimizing this call to resolve, since it is called
-// for each class load.
-        try
-        {
-            m_resolver.resolve(module);
-        }
-        catch (ResolveException ex)
-        {
-            // The spec states that if the bundle cannot be resolved, then
-            // only the local bundle's resources should be searched. So we
-            // will ask the module's own class path.
-            urls = module.getContentLoader().getResources(name);
-            if (urls != null)
-            {
-                return urls;
-            }
-            // We need to throw a resource not found exception.
-            throw new ResourceNotFoundException(name
-                + ": cannot resolve requirement " + ex.getRequirement());
-        }
-
-        // Get the package of the target class/resource.
-        String pkgName = Util.getResourcePackage(name);
-
-        // Delegate any packages listed in the boot delegation
-        // property to the parent class loader.
-        // NOTE for the default package:
-        // Only consider delegation if we have a package name, since
-        // we don't want to promote the default package. The spec does
-        // not take a stand on this issue.
-        if (pkgName.length() > 0)
-        {
-            for (int i = 0; i < m_bootPkgs.length; i++)
-            {
-                // A wildcarded boot delegation package will be in the form of
-                // "foo.", so if the package is wildcarded do a startsWith() or a
-                // regionMatches() to ignore the trailing "." to determine if the
-                // request should be delegated to the parent class loader. If the
-                // package is not wildcarded, then simply do an equals() test to
-                // see if the request should be delegated to the parent class loader.
-                if ((m_bootPkgWildcards[i] &&
-                    (pkgName.startsWith(m_bootPkgs[i]) ||
-                    m_bootPkgs[i].regionMatches(0, pkgName, 0, pkgName.length())))
-                    || (!m_bootPkgWildcards[i] && m_bootPkgs[i].equals(pkgName)))
-                {
-                    try
-                    {
-                        urls = getClass().getClassLoader().getResources(name);
-                    }
-                    catch (IOException ex)
-                    {
-                        // This shouldn't happen and even if it does, there
-                        // is nothing we can do, so just ignore it.
-                    }
-                    // If this is a java.* package, then always terminate the
-                    // search; otherwise, continue to look locally.
-                    if (m_bootPkgs[i].startsWith("java."))
-                    {
-                        return urls;
-                    }
-
-                    enums.add(urls);
-                    break;
-                }
-            }
-        }
-
-        // Look in the module's imports.
-        // We delegate to the module's wires for the resources.
-        // If any resources are found, this means that the package of these
-        // resources is imported, we must not keep looking since we do not
-        // support split-packages.
-
-        // Note that the search may be aborted if this method throws an
-        // exception, otherwise it continues if a null is returned.
-        IWire[] wires = module.getWires();
-        for (int i = 0; (wires != null) && (i < wires.length); i++)
-        {
-            if (wires[i] instanceof R4Wire)
-            {
-                // If we find the class or resource, then return it.
-                urls = wires[i].getResources(name);
-                if (urls != null)
-                {
-                    enums.add(urls);
-                    return new CompoundEnumeration((Enumeration[])
-                        enums.toArray(new Enumeration[enums.size()]));
-                }
-            }
-        }
-
-        // See whether we can get the resource from the required bundles and
-        // regardless of whether or not this is the case continue to the next
-        // step potentially passing on the result of this search (if any).
-        for (int i = 0; (wires != null) && (i < wires.length); i++)
-        {
-            if (wires[i] instanceof R4WireModule)
-            {
-                // If we find the class or resource, then add it.
-                urls = wires[i].getResources(name);
-                if (urls != null)
-                {
-                    enums.add(urls);
-                }
-            }
-        }
-
-        // Try the module's own class path. If we can find the resource then
-        // return it together with the results from the other searches else
-        // try to look into the dynamic imports.
-        urls = module.getContentLoader().getResources(name);
-        if (urls != null)
-        {
-            enums.add(urls);
-        }
-        else
-        {
-            // If not found, then try the module's dynamic imports.
-            // At this point, the module's imports were searched and so was the
-            // the module's content. Now we make an attempt to load the
-            // class/resource via a dynamic import, if possible.
-            IWire wire = null;
-            try
-            {
-                wire = m_resolver.resolveDynamicImport(module, pkgName);
-            }
-            catch (ResolveException ex)
-            {
-                // Ignore this since it is likely normal.
-            }
-            if (wire != null)
-            {
-                urls = wire.getResources(name);
-
-                if (urls != null)
-                {
-                    enums.add(urls);
-                }
-            }
-        }
-
-        return new CompoundEnumeration((Enumeration[])
-            enums.toArray(new Enumeration[enums.size()]));
-    }
-
-    private Object findClassOrResource(IModule module, String name, boolean isClass)
-        throws ClassNotFoundException, ResourceNotFoundException
-    {
-        // First, try to resolve the originating module.
-// TODO: FRAMEWORK - Consider opimizing this call to resolve, since it is called
-// for each class load.
-        try
-        {
-            m_resolver.resolve(module);
-        }
-        catch (ResolveException ex)
-        {
-            if (isClass)
-            {
-                // We do not use the resolve exception as the
-                // cause of the exception, since this would
-                // potentially leak internal module information.
-                throw new ClassNotFoundException(
-                    name + ": cannot resolve package "
-                    + ex.getRequirement());
-            }
-            else
-            {
-                // The spec states that if the bundle cannot be resolved, then
-                // only the local bundle's resources should be searched. So we
-                // will ask the module's own class path.
-                URL url = module.getContentLoader().getResource(name);
-                if (url != null)
-                {
-                    return url;
-                }
-
-                // We need to throw a resource not found exception.
-                throw new ResourceNotFoundException(
-                    name + ": cannot resolve package "
-                    + ex.getRequirement());
-            }
-        }
-
-        // Get the package of the target class/resource.
-        String pkgName = (isClass)
-            ? Util.getClassPackage(name)
-            : Util.getResourcePackage(name);
-
-        // Delegate any packages listed in the boot delegation
-        // property to the parent class loader.
-        Object result = null;
-        for (int i = 0; i < m_bootPkgs.length; i++)
-        {
-            // A wildcarded boot delegation package will be in the form of "foo.",
-            // so if the package is wildcarded do a startsWith() or a regionMatches()
-            // to ignore the trailing "." to determine if the request should be
-            // delegated to the parent class loader. If the package is not wildcarded,
-            // then simply do an equals() test to see if the request should be
-            // delegated to the parent class loader.
-            if (pkgName.length() > 0)
-            {
-                // Only consider delegation if we have a package name, since
-                // we don't want to promote the default package. The spec does
-                // not take a stand on this issue.
-                if ((m_bootPkgWildcards[i] &&
-                    (pkgName.startsWith(m_bootPkgs[i]) ||
-                    m_bootPkgs[i].regionMatches(0, pkgName, 0, pkgName.length())))
-                    || (!m_bootPkgWildcards[i] && m_bootPkgs[i].equals(pkgName)))
-                {
-                    try
-                    {
-                        result = (isClass)
-                            ? (Object) getClass().getClassLoader().loadClass(name)
-                            : (Object) getClass().getClassLoader().getResource(name);
-                        // If this is a java.* package, then always terminate the
-                        // search; otherwise, continue to look locally if not found.
-                        if (m_bootPkgs[i].startsWith("java.") || (result != null))
-                        {
-                            return result;
-                        }
-                    }
-                    catch (ClassNotFoundException ex)
-                    {
-                        // If this is a java.* package, then always terminate the
-                        // search; otherwise, continue to look locally if not found.
-                        if (m_bootPkgs[i].startsWith("java."))
-                        {
-                            throw ex;
-                        }
-                        else
-                        {
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        // Look in the module's imports. Note that the search may
-        // be aborted if this method throws an exception, otherwise
-        // it continues if a null is returned.
-        result = searchImports(module, name, isClass);
-
-        // If not found, try the module's own class path.
-        if (result == null)
-        {
-            result = (isClass)
-                ? (Object) module.getContentLoader().getClass(name)
-                : (Object) module.getContentLoader().getResource(name);
-
-            // If still not found, then try the module's dynamic imports.
-            if (result == null)
-            {
-                result = searchDynamicImports(module, name, pkgName, isClass);
-            }
-        }
-
-        if (result == null)
-        {
-            if (isClass)
-            {
-                throw new ClassNotFoundException(name);
-            }
-            else
-            {
-                throw new ResourceNotFoundException(name);
-            }
-        }
-
-        return result;
-    }
-
-    private Object searchImports(IModule module, String name, boolean isClass)
-        throws ClassNotFoundException, ResourceNotFoundException
-    {
-        // We delegate to the module's wires to find the class or resource.
-        IWire[] wires = module.getWires();
-        for (int i = 0; (wires != null) && (i < wires.length); i++)
-        {
-            // If we find the class or resource, then return it.
-            Object result = (isClass)
-                ? (Object) wires[i].getClass(name)
-                : (Object) wires[i].getResource(name);
-            if (result != null)
-            {
-                return result;
-            }
-        }
-
-        return null;
-    }
-
-    private Object searchDynamicImports(
-        IModule module, String name, String pkgName, boolean isClass)
-        throws ClassNotFoundException, ResourceNotFoundException
-    {
-        // At this point, the module's imports were searched and so was the
-        // the module's content. Now we make an attempt to load the
-        // class/resource via a dynamic import, if possible.
-        IWire wire = null;
-        try
-        {
-            wire = m_resolver.resolveDynamicImport(module, pkgName);
-        }
-        catch (ResolveException ex)
-        {
-            // Ignore this since it is likely normal.
-        }
-
-        // If the dynamic import was successful, then this initial
-        // time we must directly return the result from dynamically
-        // created wire, but subsequent requests for classes/resources
-        // in the associated package will be processed as part of
-        // normal static imports.
-        if (wire != null)
-        {
-            // Return the class or resource.
-            return (isClass)
-                ? (Object) wire.getClass(name)
-                : (Object) wire.getResource(name);
-        }
-
-        // At this point, the class/resource could not be found by the bundle's
-        // static or dynamic imports, nor its own content. Before we throw
-        // an exception, we will try to determine if the instigator of the
-        // class/resource load was a class from a bundle or not. This is necessary
-        // because the specification mandates that classes on the class path
-        // should be hidden (except for java.*), but it does allow for these
-        // classes/resources to be exposed by the system bundle as an export.
-        // However, in some situations classes on the class path make the faulty
-        // assumption that they can access everything on the class path from
-        // every other class loader that they come in contact with. This is
-        // not true if the class loader in question is from a bundle. Thus,
-        // this code tries to detect that situation. If the class
-        // instigating the load request was NOT from a bundle, then we will
-        // make the assumption that the caller actually wanted to use the
-        // parent class loader and we will delegate to it. If the class was
-        // from a bundle, then we will enforce strict class loading rules
-        // for the bundle and throw an exception.
-
-        // Get the class context to see the classes on the stack.
-        Class[] classes = m_sm.getClassContext();
-        // Start from 1 to skip security manager class.
-        for (int i = 1; i < classes.length; i++)
-        {
-            // Find the first class on the call stack that is not from
-            // the class loader that loaded the Felix classes or is not
-            // a class loader or class itself, because we want to ignore
-            // calls to ClassLoader.loadClass() and Class.forName() since
-            // we are trying to find out who instigated the class load.
-            // Also since Felix uses threads for changing the start level
-            // and refreshing packages, it is possible that there is no
-            // module classes on the call stack; therefore, as soon as we
-            // see Thread on the call stack we exit this loop. Other cases
-            // where modules actually use threads are not an issue because
-            // the module classes will be on the call stack before the
-            // Thread class.
-// TODO: FRAMEWORK - This check is a hack and we should see if we can think
-// of another way to do it, since it won't necessarily work in all situations.
-            if (Thread.class.equals(classes[i]))
-            {
-                break;
-            }
-            else if ((this.getClass().getClassLoader() != classes[i].getClassLoader())
-                && !ClassLoader.class.isAssignableFrom(classes[i])
-                && !Class.class.equals(classes[i])
-                && !Proxy.class.equals(classes[i]))
-            {
-                // If there are no bundles providing exports for this
-                // package and if the instigating class was not from a
-                // bundle, then delegate to the parent class loader.
-                // Otherwise, break out of loop and return null.
-                boolean delegate = true;
-                for (ClassLoader cl = classes[i].getClassLoader(); cl != null; cl = cl.getClass().getClassLoader())
-                {
-                    if (ContentClassLoader.class.isInstance(cl))
-                    {
-                        delegate = false;
-                        break;
-                    }
-                }
-                // If delegate is true then there are no bundles
-                // providing exports for this package and the instigating
-                // class was not from a bundle. Therefore,
-                // delegate to the parent class loader in case
-                // that this is not due to outside code calling a method
-                // on the bundle interface (e.g., Bundle.loadClass()).
-                if (delegate && !Bundle.class.isInstance(classes[i - 1]))
-                {
-                    try
-                    {
-                        // Return the class or resource from the parent class loader.
-                        return (isClass)
-                            ? (Object) this.getClass().getClassLoader().loadClass(name)
-                            : (Object) this.getClass().getClassLoader().getResource(name);
-                    }
-                    catch (NoClassDefFoundError ex)
-                    {
-                        // Ignore, will return null
-                    }
-                }
-                break;
-            }
-        }
-
-        return null;
-    }
-
-    public String findLibrary(IModule module, String name)
-    {
-        // Remove leading slash, if present.
-        if (name.startsWith("/"))
-        {
-            name = name.substring(1);
-        }
-
-        R4Library[] libs = module.getDefinition().getLibraries();
-        for (int i = 0; (libs != null) && (i < libs.length); i++)
-        {
-            if (libs[i].match(name))
-            {
-                return module.getContentLoader().getContent()
-                    .getEntryAsNativeLibrary(libs[i].getEntryName());
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * This is an experimental method that is likely to change or go
-     * away - so don't use it for now.
-     *
-     * Note to self, we need to think about what the implications of
-     * this are and whether we are fine with them.
-     */
-    /*
-     * This method is used by the framework to let us know that we need to re-read
-     * the system bundle capabilities which have been extended by an extension bundle.
-     *
-     * For now we assume that capabilities have been added only. We might need to
-     * enforce that at one point of time.
-     */
-/* TODO: RESOLVER - We need to figure out what to do with this.
-    public void moduleRefreshed(ModuleEvent event)
-    {
-        synchronized (m_factory)
-        {
-            IModule module = event.getModule();
-            // Remove exports from package maps.
-            ICapability[] caps = event.getModule().getDefinition().getCapabilities();
-            // Add exports to unresolved package map.
-            for (int i = 0; (caps != null) && (i < caps.length); i++)
-            {
-                ICapability[] resolvedCaps = (ICapability[]) m_resolvedCapMap.get(module);
-                resolvedCaps = addCapabilityToArray(resolvedCaps, caps[i]);
-                m_resolvedCapMap.put(module, resolvedCaps);
-
-                // If the capability is a package, then add the exporter module
-                // of the wire to the "resolved" package index and remove it
-                // from the "unresolved" package index.
-                if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
-                {
-                    // Get package name.
-                    String pkgName = (String)
-                        caps[i].getProperties().get(ICapability.PACKAGE_PROPERTY);
-                    // Add to "resolved" package index.
-                    indexPackageCapability(
-                        m_resolvedPkgIndexMap,
-                        module,
-                        caps[i]);
-                }
-            }
-        }
-    }
-*/
-    //
-    // Diagnostics.
-    //
-
-    private String diagnoseClassLoadError(IModule module, String name)
-    {
-        // We will try to do some diagnostics here to help the developer
-        // deal with this exception.
-
-        // Get package name.
-        String pkgName = Util.getClassPackage(name);
-
-        // First, get the bundle ID of the module doing the class loader.
-        long impId = Util.getBundleIdFromModuleId(module.getId());
-
-        // Next, check to see if the module imports the package.
-        IWire[] wires = module.getWires();
-        for (int i = 0; (wires != null) && (i < wires.length); i++)
-        {
-            if (wires[i].getCapability().getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
-                wires[i].getCapability().getProperties().get(ICapability.PACKAGE_PROPERTY).equals(pkgName))
-            {
-                long expId = Util.getBundleIdFromModuleId(
-                    wires[i].getExporter().getId());
-
-                StringBuffer sb = new StringBuffer("*** Package '");
-                sb.append(pkgName);
-                sb.append("' is imported by bundle ");
-                sb.append(impId);
-                sb.append(" from bundle ");
-                sb.append(expId);
-                sb.append(", but the exported package from bundle ");
-                sb.append(expId);
-                sb.append(" does not contain the requested class '");
-                sb.append(name);
-                sb.append("'. Please verify that the class name is correct in the importing bundle ");
-                sb.append(impId);
-                sb.append(" and/or that the exported package is correctly bundled in ");
-                sb.append(expId);
-                sb.append(". ***");
-
-                return sb.toString();
-            }
-        }
-
-        // Next, check to see if the package was optionally imported and
-        // whether or not there is an exporter available.
-        IRequirement[] reqs = module.getDefinition().getRequirements();
-/*
- * TODO: RB - Fix diagnostic message for optional imports.
-        for (int i = 0; (reqs != null) && (i < reqs.length); i++)
-        {
-            if (reqs[i].getName().equals(pkgName) && reqs[i].isOptional())
-            {
-                // Try to see if there is an exporter available.
-                IModule[] exporters = getResolvedExporters(reqs[i], true);
-                exporters = (exporters.length == 0)
-                    ? getUnresolvedExporters(reqs[i], true) : exporters;
-
-                // An exporter might be available, but it may have attributes
-                // that do not match the importer's required attributes, so
-                // check that case by simply looking for an exporter of the
-                // desired package without any attributes.
-                if (exporters.length == 0)
-                {
-                    IRequirement pkgReq = new Requirement(
-                        ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
-                    exporters = getResolvedExporters(pkgReq, true);
-                    exporters = (exporters.length == 0)
-                        ? getUnresolvedExporters(pkgReq, true) : exporters;
-                }
-
-                long expId = (exporters.length == 0)
-                    ? -1 : Util.getBundleIdFromModuleId(exporters[0].getId());
-
-                StringBuffer sb = new StringBuffer("*** Class '");
-                sb.append(name);
-                sb.append("' was not found, but this is likely normal since package '");
-                sb.append(pkgName);
-                sb.append("' is optionally imported by bundle ");
-                sb.append(impId);
-                sb.append(".");
-                if (exporters.length > 0)
-                {
-                    sb.append(" However, bundle ");
-                    sb.append(expId);
-                    if (reqs[i].isSatisfied(
-                        Util.getExportPackage(exporters[0], reqs[i].getName())))
-                    {
-                        sb.append(" does export this package. Bundle ");
-                        sb.append(expId);
-                        sb.append(" must be installed before bundle ");
-                        sb.append(impId);
-                        sb.append(" is resolved or else the optional import will be ignored.");
-                    }
-                    else
-                    {
-                        sb.append(" does export this package with attributes that do not match.");
-                    }
-                }
-                sb.append(" ***");
-
-                return sb.toString();
-            }
-        }
-*/
-        // Next, check to see if the package is dynamically imported by the module.
-/* TODO: RESOLVER: Need to fix this too.
-        IRequirement[] dynamics = module.getDefinition().getDynamicRequirements();
-        for (int dynIdx = 0; dynIdx < dynamics.length; dynIdx++)
-        {
-            IRequirement target = createDynamicRequirement(dynamics[dynIdx], pkgName);
-            if (target != null)
-            {
-                // Try to see if there is an exporter available.
-                PackageSource[] exporters = getResolvedCandidates(target);
-                exporters = (exporters.length == 0)
-                    ? getUnresolvedCandidates(target) : exporters;
-
-                // An exporter might be available, but it may have attributes
-                // that do not match the importer's required attributes, so
-                // check that case by simply looking for an exporter of the
-                // desired package without any attributes.
-                if (exporters.length == 0)
-                {
-                    try
-                    {
-                        IRequirement pkgReq = new Requirement(
-                            ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
-                        exporters = getResolvedCandidates(pkgReq);
-                        exporters = (exporters.length == 0)
-                            ? getUnresolvedCandidates(pkgReq) : exporters;
-                    }
-                    catch (InvalidSyntaxException ex)
-                    {
-                        // This should never happen.
-                    }
-                }
-
-                long expId = (exporters.length == 0)
-                    ? -1 : Util.getBundleIdFromModuleId(exporters[0].m_module.getId());
-
-                StringBuffer sb = new StringBuffer("*** Class '");
-                sb.append(name);
-                sb.append("' was not found, but this is likely normal since package '");
-                sb.append(pkgName);
-                sb.append("' is dynamically imported by bundle ");
-                sb.append(impId);
-                sb.append(".");
-                if (exporters.length > 0)
-                {
-                    try
-                    {
-                        if (!target.isSatisfied(
-                            Util.getSatisfyingCapability(exporters[0].m_module,
-                                new Requirement(ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")"))))
-                        {
-                            sb.append(" However, bundle ");
-                            sb.append(expId);
-                            sb.append(" does export this package with attributes that do not match.");
-                        }
-                    }
-                    catch (InvalidSyntaxException ex)
-                    {
-                        // This should never happen.
-                    }
-                }
-                sb.append(" ***");
-
-                return sb.toString();
-            }
-        }
-*/
-        IRequirement pkgReq = null;
-        try
-        {
-            pkgReq = new Requirement(ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
-        }
-        catch (InvalidSyntaxException ex)
-        {
-            // This should never happen.
-        }
-        PackageSource[] exporters = m_resolver.getResolvedCandidates(pkgReq);
-        exporters = (exporters.length == 0) ? m_resolver.getUnresolvedCandidates(pkgReq) : exporters;
-        if (exporters.length > 0)
-        {
-            boolean classpath = false;
-            try
-            {
-                getClass().getClassLoader().loadClass(name);
-                classpath = true;
-            }
-            catch (NoClassDefFoundError err)
-            {
-                // Ignore
-            }
-            catch (Exception ex)
-            {
-                // Ignore
-            }
-
-            long expId = Util.getBundleIdFromModuleId(exporters[0].m_module.getId());
-
-            StringBuffer sb = new StringBuffer("*** Class '");
-            sb.append(name);
-            sb.append("' was not found because bundle ");
-            sb.append(impId);
-            sb.append(" does not import '");
-            sb.append(pkgName);
-            sb.append("' even though bundle ");
-            sb.append(expId);
-            sb.append(" does export it.");
-            if (classpath)
-            {
-                sb.append(" Additionally, the class is also available from the system class loader. There are two fixes: 1) Add an import for '");
-                sb.append(pkgName);
-                sb.append("' to bundle ");
-                sb.append(impId);
-                sb.append("; imports are necessary for each class directly touched by bundle code or indirectly touched, such as super classes if their methods are used. ");
-                sb.append("2) Add package '");
-                sb.append(pkgName);
-                sb.append("' to the '");
-                sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
-                sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
-            }
-            else
-            {
-                sb.append(" To resolve this issue, add an import for '");
-                sb.append(pkgName);
-                sb.append("' to bundle ");
-                sb.append(impId);
-                sb.append(".");
-            }
-            sb.append(" ***");
-
-            return sb.toString();
-        }
-
-        // Next, try to see if the class is available from the system
-        // class loader.
-        try
-        {
-            getClass().getClassLoader().loadClass(name);
-
-            StringBuffer sb = new StringBuffer("*** Package '");
-            sb.append(pkgName);
-            sb.append("' is not imported by bundle ");
-            sb.append(impId);
-            sb.append(", nor is there any bundle that exports package '");
-            sb.append(pkgName);
-            sb.append("'. However, the class '");
-            sb.append(name);
-            sb.append("' is available from the system class loader. There are two fixes: 1) Add package '");
-            sb.append(pkgName);
-            sb.append("' to the '");
-            sb.append(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
-            sb.append("' property and modify bundle ");
-            sb.append(impId);
-            sb.append(" to import this package; this causes the system bundle to export class path packages. 2) Add package '");
-            sb.append(pkgName);
-            sb.append("' to the '");
-            sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
-            sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
-            sb.append(" ***");
-
-            return sb.toString();
-        }
-        catch (Exception ex2)
-        {
-        }
-
-        // Finally, if there are no imports or exports for the package
-        // and it is not available on the system class path, simply
-        // log a message saying so.
-        StringBuffer sb = new StringBuffer("*** Class '");
-        sb.append(name);
-        sb.append("' was not found. Bundle ");
-        sb.append(impId);
-        sb.append(" does not import package '");
-        sb.append(pkgName);
-        sb.append("', nor is the package exported by any other bundle or available from the system class loader.");
-        sb.append(" ***");
-
-        return sb.toString();
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java
index ac1c74e..0eb232b 100755
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java
@@ -97,23 +97,15 @@
         if (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
             m_capability.getProperties().get(ICapability.PACKAGE_PROPERTY).equals(pkgName))
         {
-            // If the importer and the exporter are the same, then
-            // just ask for the class from the exporting module's
-            // content directly.
-            if (m_exporter == m_importer)
-            {
-                clazz = m_exporter.getContentLoader().getClass(name);
-            }
-            // Otherwise, check the include/exclude filters from the target
-            // package to make sure that the class is actually visible. In
-            // this case since the importing and exporting modules are different,
-            // we delegate to the exporting module, rather than its content,
-            // so that it can follow any internal wires it may have (e.g.,
-            // if the package has multiple sources).
-            else if (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
+            // Check the include/exclude filters from the target package
+            // to make sure that the class is actually visible. We delegate
+            // to the exporting module, rather than its content, so it can
+            // it can follow any internal wires it may have (e.g., if the
+            // package has multiple sources).
+            if (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
                 && ((Capability) m_capability).isIncluded(name))
             {
-                clazz = m_exporter.getClass(name);
+                clazz = m_exporter.getClassByDelegation(name);
             }
 
             // If no class was found, then we must throw an exception
@@ -143,20 +135,10 @@
         if (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
             m_capability.getProperties().get(ICapability.PACKAGE_PROPERTY).equals(pkgName))
         {
-            // If the importer and the exporter are the same, then
-            // just ask for the resource from the exporting module's
-            // content directly.
-            if (m_exporter == m_importer)
-            {
-                url = m_exporter.getContentLoader().getResource(name);
-            }
-            // Otherwise, delegate to the exporting module, rather than its
+            // Delegate to the exporting module, rather than its
             // content, so that it can follow any internal wires it may have
             // (e.g., if the package has multiple sources).
-            else
-            {
-                url = m_exporter.getResource(name);
-            }
+            url = m_exporter.getResourceByDelegation(name);
 
             // If no resource was found, then we must throw an exception
             // since the exporter for this package did not contain the
@@ -185,7 +167,7 @@
         if (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
             m_capability.getProperties().get(ICapability.PACKAGE_PROPERTY).equals(pkgName))
         {
-            urls = m_exporter.getContentLoader().getResources(name);
+            urls = m_exporter.getResourcesByDelegation(name);
 
             // If no resource was found, then we must throw an exception
             // since the exporter for this package did not contain the
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java
index 31c606c..0ddaa93 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java
@@ -100,14 +100,26 @@
             for (int srcIdx = 0; srcIdx < rp.m_sourceList.size(); srcIdx++)
             {
                 PackageSource ps = (PackageSource) rp.m_sourceList.get(srcIdx);
+// TODO: REFACTOR - Module's shouldn't depend on themself.
                 if ((ps.m_module == m_importer) ||
                     ((ps.m_capability instanceof Capability) &&
                     ((Capability) ps.m_capability).isIncluded(name)))
                 {
-                    Class clazz = ps.m_module.getContentLoader().getClass(name);
-                    if (clazz != null)
+// TODO: REFACTOR - It seems like we should be able to use getClassByDelegation()
+//       here once we don't allow modules to require themself above.
+                    try
                     {
-                        return clazz;
+                        Class clazz = ps.m_module.getClassFromModule(name);
+                        if (clazz != null)
+                        {
+                            return clazz;
+                        }
+                    }
+                    catch (ClassNotFoundException ex)
+                    {
+                        // Do not throw the exception here, since we want
+                        // to continue search other package sources and
+                        // ultimately the module's own content.
                     }
                 }
             }
@@ -130,7 +142,9 @@
             for (int srcIdx = 0; srcIdx < rp.m_sourceList.size(); srcIdx++)
             {
                 PackageSource ps = (PackageSource) rp.m_sourceList.get(srcIdx);
-                URL url = ps.m_module.getContentLoader().getResource(name);
+// TODO: REFACTOR - It seems like we should be able to use getClassByDelegation()
+//       here once we don't allow modules to require themself above.
+                URL url = ps.m_module.getResourceFromModule(name);
                 if (url != null)
                 {
                     return url;
@@ -164,7 +178,9 @@
             for (int srcIdx = 0; srcIdx < rp.m_sourceList.size(); srcIdx++)
             {
                 PackageSource ps = (PackageSource) rp.m_sourceList.get(srcIdx);
-                Enumeration urls = ps.m_module.getContentLoader().getResources(name);
+// TODO: REFACTOR - It seems like we should be able to use getClassByDelegation()
+//       here once we don't allow modules to require themself above.
+                Enumeration urls = ps.m_module.getResourcesFromModule(name);
                 if (urls != null)
                 {
                     enums.add(urls);
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
index 55930d4..2d1a811 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
@@ -40,6 +40,7 @@
     private final Logger m_logger;
 
     // Reusable empty array.
+    private static final IWire[] m_emptyWires = new IWire[0];
     private static final IModule[] m_emptyModules = new IModule[0];
     private static final PackageSource[] m_emptySources = new PackageSource[0];
 
@@ -55,7 +56,7 @@
     public Map resolve(ResolverState state, IModule rootModule) throws ResolveException
     {
         // If the module is already resolved, then we can just return.
-        if (state.isResolved(rootModule))
+        if (rootModule.isResolved())
         {
             return null;
         }
@@ -119,7 +120,7 @@
             // 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.
-            IRequirement[] dynamics = importer.getDefinition().getDynamicRequirements();
+            IRequirement[] dynamics = importer.getDynamicRequirements();
             for (int dynIdx = 0; (dynamics != null) && (dynIdx < dynamics.length); dynIdx++)
             {
                 IRequirement target =
@@ -186,7 +187,7 @@
     {
         // If any of the module exports this package, then we cannot
         // attempt to dynamically import it.
-        ICapability[] caps = importer.getDefinition().getCapabilities();
+        ICapability[] caps = importer.getCapabilities();
         for (int i = 0; (caps != null) && (i < caps.length); i++)
         {
             if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
@@ -258,7 +259,7 @@
         // provider. If there is no consistent class space, then a resolve
         // exception is thrown.
         Map candidatesMap = new HashMap();
-        if (!state.isResolved(provider))
+        if (!provider.isResolved())
         {
             populateCandidatesMap(state, candidatesMap, provider);
             findConsistentClassSpace(state, candidatesMap, provider);
@@ -403,7 +404,7 @@
 
         // Loop through each requirement and calculate its resolving
         // set of candidates.
-        IRequirement[] reqs = targetModule.getDefinition().getRequirements();
+        IRequirement[] reqs = targetModule.getRequirements();
         for (int reqIdx = 0; (reqs != null) && (reqIdx < reqs.length); reqIdx++)
         {
             if (reqs[reqIdx].getNamespace().equals(ICapability.HOST_NAMESPACE))
@@ -421,7 +422,7 @@
                         {
                             // Only populate the resolver map with hosts that
                             // are not already resolved.
-                            if (!state.isResolved(hosts[hostIdx]))
+                            if (!hosts[hostIdx].isResolved())
                             {
                                 populateCandidatesMap(state, candidatesMap, hosts[hostIdx]);
                             }
@@ -489,7 +490,7 @@
                         {
                             // Only populate the resolver map with modules that
                             // are not already resolved.
-                            if (!state.isResolved(candidates[candIdx].m_module))
+                            if (!candidates[candIdx].m_module.isResolved())
                             {
                                 populateCandidatesMap(state, candidatesMap, candidates[candIdx].m_module);
                             }
@@ -606,9 +607,9 @@
         IModule[] modules = state.getModules();
         for (int i = 0; (modules != null) && (i < modules.length); i++)
         {
-            if (state.isResolved(modules[i]) && isSingleton(modules[i]))
+            if (modules[i].isResolved() && isSingleton(modules[i]))
             {
-                String symName = state.getBundleSymbolicName(modules[i]);
+                String symName = modules[i].getSymbolicName();
                 singletonMap.put(symName, symName);
             }
         }
@@ -648,7 +649,7 @@
         // Check to see if the targetModule violates a singleton.
         // If not and it is a singleton, then add it to the singleton
         // map since it will constrain other singletons.
-        String symName = state.getBundleSymbolicName(targetModule);
+        String symName = targetModule.getSymbolicName();
         boolean isSingleton = isSingleton(targetModule);
         if (isSingleton && singletonMap.containsKey(symName))
         {
@@ -689,7 +690,7 @@
                 // we have to see if resolving it would violate a singleton
                 // constraint.
                 PackageSource ps = (PackageSource) rp.m_sourceList.get(srcIdx);
-                if (!state.isResolved(ps.m_module))
+                if (!ps.m_module.isResolved())
                 {
                     return areCandidatesSingletonConsistent(state, ps.m_module, singletonMap, moduleMap, cycleMap, candidatesMap);
                 }
@@ -1099,7 +1100,7 @@
 
         // Loop through the target module's capabilities that represent
         // exported packages and add them to the exported package map.
-        ICapability[] caps = targetModule.getDefinition().getCapabilities();
+        ICapability[] caps = targetModule.getCapabilities();
         for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
         {
             if (caps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
@@ -1354,7 +1355,7 @@
 
         // Now loop through the target module's export package capabilities and
         // add the target module as a package source for any exported packages.
-        ICapability[] candCaps = psTarget.m_module.getDefinition().getCapabilities();
+        ICapability[] candCaps = psTarget.m_module.getCapabilities();
         for (int capIdx = 0; (candCaps != null) && (capIdx < candCaps.length); capIdx++)
         {
             if (candCaps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
@@ -1470,7 +1471,7 @@
 
         // Now loop through the target module's export package capabilities and
         // add the target module as a package source for any exported packages.
-        ICapability[] caps = targetModule.getDefinition().getCapabilities();
+        ICapability[] caps = targetModule.getCapabilities();
         for (int i = 0; (caps != null) && (i < caps.length); i++)
         {
             if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
@@ -1529,7 +1530,7 @@
     {
         // If the module is already resolved or it is part of
         // a cycle, then just return the wire map.
-        if (state.isResolved(importer) || (wireMap.get(importer) != null))
+        if (importer.isResolved() || (wireMap.get(importer) != null))
         {
             return wireMap;
         }
@@ -1585,11 +1586,10 @@
 
         List moduleWires = new ArrayList();
         List packageWires = new ArrayList();
-        IWire[] wires = new IWire[candSetList.size()];
 
         // Put the module in the wireMap with an empty wire array;
         // we do this early so we can use it to detect cycles.
-        wireMap.put(importer, wires);
+        wireMap.put(importer, m_emptyModules);
 
         // Loop through each candidate Set and create a wire
         // for the selected candidate for the associated import.
@@ -1606,6 +1606,7 @@
             }
             else
             {
+                // Create a module wire for module dependencies.
                 if (cs.m_requirement.getNamespace().equals(ICapability.MODULE_NAMESPACE))
                 {
                     moduleWires.add(new R4WireModule(
@@ -1615,7 +1616,11 @@
                         cs.m_candidates[cs.m_idx].m_capability,
                         calculateCandidateRequiredPackages(importer, cs.m_candidates[cs.m_idx], candidatesMap)));
                 }
-                else
+                // Create a package wire for package dependencies.
+                // Filter out the case where a module imports from
+                // itself, since the module should simply load from
+                // its internal class path in this case.
+                else if (importer != cs.m_candidates[cs.m_idx].m_module)
                 {
                     // Add wire for imported package.
                     packageWires.add(new R4Wire(
@@ -1632,7 +1637,7 @@
         }
 
         packageWires.addAll(moduleWires);
-        wireMap.put(importer, packageWires.toArray(wires));
+        wireMap.put(importer, packageWires.toArray(new IWire[packageWires.size()]));
 
         return wireMap;
     }
@@ -1705,9 +1710,6 @@
     {
         IModule[] getModules();
         // TODO: RESOLVER - This should be on module.
-        String getBundleSymbolicName(IModule module);
-        // TODO: RESOLVER - This should be on module.
-        boolean isResolved(IModule module);
         Map getPotentialFragments(IModule module);
         List getPotentialHosts(IModule module);
         PackageSource[] getResolvedCandidates(IRequirement req);
diff --git a/framework/src/main/java/org/apache/felix/framework/util/ObjectInputStreamX.java b/framework/src/main/java/org/apache/felix/framework/util/ObjectInputStreamX.java
deleted file mode 100644
index 8d70130..0000000
--- a/framework/src/main/java/org/apache/felix/framework/util/ObjectInputStreamX.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.util;
-
-import java.io.*;
-
-import org.apache.felix.moduleloader.IModule;
-
-/**
- * The ObjectInputStreamX class is a simple extension to the ObjectInputStream
- * class.  The purpose of ObjectInputStreamX is to allow objects to be deserialized
- * when their classes are not in the CLASSPATH (e.g., in a JAR file).
- */
-public class ObjectInputStreamX extends ObjectInputStream
-{
-    private IModule m_module = null;
-
-    /**
-     * Construct an ObjectInputStreamX for the specified InputStream and the specified
-     * ClassLoader.
-     * @param in the input stream to read.
-     * @param loader the class loader used to resolve classes.
-     */
-    public ObjectInputStreamX(InputStream in, IModule module)
-        throws IOException, StreamCorruptedException
-    {
-        super(in);
-        m_module = module;
-    }
-
-    /**
-     * By overloading this method, the ObjectInputStreamX can resolve a class
-     * from the class loader that was passed into it at construction time.
-     */
-    protected Class resolveClass(ObjectStreamClass v)
-        throws IOException, ClassNotFoundException
-    {
-        return m_module.getClass(v.getName());
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java b/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
index ac524fc..a495394 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
@@ -25,8 +25,8 @@
 import java.util.Hashtable;
 import java.util.jar.JarFile;
 
-import org.apache.felix.framework.searchpolicy.ContentClassLoader;
-import org.apache.felix.framework.searchpolicy.ContentLoaderImpl;
+import org.apache.felix.framework.searchpolicy.ModuleClassLoader;
+import org.apache.felix.framework.searchpolicy.ModuleImpl;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
@@ -541,12 +541,12 @@
         }
     }
 
-    public ContentClassLoader createContentClassLoader(ContentLoaderImpl impl)
+    public ModuleClassLoader createModuleClassLoader(ModuleImpl impl)
     {
-        return createContentClassLoader(impl, null);
+        return createModuleClassLoader(impl, null);
     }
 
-    public ContentClassLoader createContentClassLoader(ContentLoaderImpl impl,
+    public ModuleClassLoader createModuleClassLoader(ModuleImpl impl,
         ProtectionDomain protectionDomain)
     {
         if (System.getSecurityManager() != null)
@@ -554,8 +554,8 @@
             try
             {
                 Actions actions = (Actions) m_actions.get();
-                actions.set(Actions.CREATE_CONTENTCLASSLOADER_ACTION, impl, protectionDomain);
-                return (ContentClassLoader) AccessController.doPrivileged(actions, m_acc);
+                actions.set(Actions.CREATE_MODULECLASSLOADER_ACTION, impl, protectionDomain);
+                return (ModuleClassLoader) AccessController.doPrivileged(actions, m_acc);
             }
             catch (PrivilegedActionException ex)
             {
@@ -564,7 +564,7 @@
         }
         else
         {
-            return new ContentClassLoader(impl, protectionDomain);
+            return new ModuleClassLoader(impl, protectionDomain);
         }
     }
 
@@ -943,7 +943,7 @@
         public static final int DELETE_FILE_ACTION = 13;
         public static final int OPEN_JARX_ACTION = 14;
         public static final int GET_URL_INPUT_ACTION = 15;
-        public static final int CREATE_CONTENTCLASSLOADER_ACTION = 16;
+        public static final int CREATE_MODULECLASSLOADER_ACTION = 16;
         public static final int START_ACTIVATOR_ACTION = 17;
         public static final int STOP_ACTIVATOR_ACTION = 18;
         public static final int SYSTEM_EXIT_ACTION = 19;
@@ -1104,10 +1104,9 @@
             {
                 return ((URLConnection) arg1).getInputStream();
             }
-            else if (action == CREATE_CONTENTCLASSLOADER_ACTION)
+            else if (action == CREATE_MODULECLASSLOADER_ACTION)
             {
-                return new ContentClassLoader((ContentLoaderImpl) arg1,
-                    (ProtectionDomain) arg2);
+                return new ModuleClassLoader((ModuleImpl) arg1, (ProtectionDomain) arg2);
             }
             else if (action == START_ACTIVATOR_ACTION)
             {
diff --git a/framework/src/main/java/org/apache/felix/framework/util/Util.java b/framework/src/main/java/org/apache/felix/framework/util/Util.java
index 285231b..685ddba 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/Util.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/Util.java
@@ -26,7 +26,6 @@
 import java.util.Map;
 import java.util.Properties;
 
-import org.apache.felix.framework.searchpolicy.ModuleDefinition;
 import org.apache.felix.framework.util.manifestparser.Capability;
 import org.apache.felix.moduleloader.*;
 import org.osgi.framework.Bundle;
@@ -232,7 +231,7 @@
 
     public static ICapability getSatisfyingCapability(IModule m, IRequirement req)
     {
-        ICapability[] caps = m.getDefinition().getCapabilities();
+        ICapability[] caps = m.getCapabilities();
         for (int i = 0; (caps != null) && (i < caps.length); i++)
         {
             if (caps[i].getNamespace().equals(req.getNamespace()) &&
@@ -254,7 +253,7 @@
     public static ICapability[] getCapabilityByNamespace(IModule module, String namespace)
     {
         final List matching = new ArrayList();
-        final ICapability[] caps = module.getDefinition().getCapabilities();
+        final ICapability[] caps = module.getCapabilities();
         for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
         {
             if (caps[capIdx].getNamespace().equals(namespace))
@@ -525,11 +524,7 @@
      */
     public static boolean isFragment(IModule module)
     {
-        if (module.getDefinition() instanceof ModuleDefinition)
-        {
-            Map headerMap = ((ModuleDefinition) module.getDefinition()).getHeaders();
-            return headerMap.containsKey(Constants.FRAGMENT_HOST);
-        }
-        return false;
+        Map headerMap = module.getHeaders();
+        return headerMap.containsKey(Constants.FRAGMENT_HOST);
     }
 }
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/IContentLoader.java b/framework/src/main/java/org/apache/felix/moduleloader/IContentLoader.java
deleted file mode 100644
index f416e3a..0000000
--- a/framework/src/main/java/org/apache/felix/moduleloader/IContentLoader.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.moduleloader;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Enumeration;
-
-public interface IContentLoader
-{
-    public void close();
-
-    public IContent getContent();
-
-    public void setSearchPolicy(ISearchPolicy searchPolicy);
-    public ISearchPolicy getSearchPolicy();
-
-    public void setURLPolicy(IURLPolicy urlPolicy);
-    public IURLPolicy getURLPolicy();
-
-    public void setSecurityContext(Object securityContext);
-    public Object getSecurityContext();
-
-    public Class getClass(String name);
-    public URL getResource(String name);
-    public Enumeration getResources(String name);
-    public URL getResourceFromContent(String name);
-
-    // TODO: ML - For expediency, the index argument was added to these methods
-    // but it is not clear that this makes sense in the long run. This needs to
-    // be readdressed in the future, perhaps by the spec to clearly indicate
-    // how resources on the bundle class path are searched, which is why we
-    // need the index number in the first place -- to differentiate among
-    // resources with the same name on the bundle class path. This was previously
-    // handled as part of the resource path, but that approach is not spec
-    // compliant.
-    public boolean hasInputStream(int index, String urlPath)
-        throws IOException;
-    public InputStream getInputStream(int index, String urlPath)
-        throws IOException;
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/IModule.java b/framework/src/main/java/org/apache/felix/moduleloader/IModule.java
index fc6c8dd..b6e5e6f 100644
--- a/framework/src/main/java/org/apache/felix/moduleloader/IModule.java
+++ b/framework/src/main/java/org/apache/felix/moduleloader/IModule.java
@@ -18,27 +18,56 @@
  */
 package org.apache.felix.moduleloader;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
 import java.util.Enumeration;
+import java.util.Map;
+import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.osgi.framework.Bundle;
 
 public interface IModule
 {
-    public String getId();
-    public IModuleDefinition getDefinition();
-    public IContentLoader getContentLoader();
-    public IWire[] getWires();
+    Bundle getBundle();
 
-    public Class getClass(String name) throws ClassNotFoundException;
-    public URL getResource(String name);
-    public Enumeration getResources(String name);
+    void setURLPolicy(IURLPolicy urlPolicy);
+    IURLPolicy getURLPolicy();
+    void setSecurityContext(Object securityContext);
+    Object getSecurityContext();
 
+    // Metadata access
+    Map getHeaders();
+    ICapability[] getCapabilities();
+    IRequirement[] getRequirements();
+    IRequirement[] getDynamicRequirements();
+    R4Library[] getNativeLibraries();
 
-    /**
-     * Returns whether the module is associated with an uninstalled bundle.
-     * If so, then it should not be used when resolving fragments or fragment
-     * hosts. However, it still can be used for resolving imported packages.
-     * @return <tt>true</tt> if the module's bundle is uninstalled, otherwise
-     *         <tt>false</tt>.
-    **/
-    public boolean isStale();
-}
+    // Run-time data access.
+    String getId();
+    String getSymbolicName();
+    IWire[] getWires();
+    boolean isResolved();
+
+    // Content access.
+    IContent getContent();
+    Class getClassByDelegation(String name) throws ClassNotFoundException;
+    URL getResourceByDelegation(String name);
+    Enumeration getResourcesByDelegation(String name);
+    Class getClassFromModule(String name) throws ClassNotFoundException;
+    URL getResourceFromModule(String name);
+    Enumeration getResourcesFromModule(String name);
+    URL getResourceFromContent(String name);
+
+    // TODO: ML - For expediency, the index argument was added to these methods
+    // but it is not clear that this makes sense in the long run. This needs to
+    // be readdressed in the future, perhaps by the spec to clearly indicate
+    // how resources on the bundle class path are searched, which is why we
+    // need the index number in the first place -- to differentiate among
+    // resources with the same name on the bundle class path. This was previously
+    // handled as part of the resource path, but that approach is not spec
+    // compliant.
+    boolean hasInputStream(int index, String urlPath)
+        throws IOException;
+    InputStream getInputStream(int index, String urlPath)
+        throws IOException;
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/IModuleDefinition.java b/framework/src/main/java/org/apache/felix/moduleloader/IModuleDefinition.java
deleted file mode 100644
index 1c50e67..0000000
--- a/framework/src/main/java/org/apache/felix/moduleloader/IModuleDefinition.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.moduleloader;
-
-import org.apache.felix.framework.util.manifestparser.R4Library;
-
-public interface IModuleDefinition
-{
-    public ICapability[] getCapabilities();
-    public IRequirement[] getRequirements();
-    public IRequirement[] getDynamicRequirements();
-    public R4Library[] getLibraries();
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/IModuleFactory.java b/framework/src/main/java/org/apache/felix/moduleloader/IModuleFactory.java
deleted file mode 100644
index 2bb3b3d..0000000
--- a/framework/src/main/java/org/apache/felix/moduleloader/IModuleFactory.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.moduleloader;
-
-public interface IModuleFactory
-{
-    public IModule[] getModules();
-    public IModule getModule(String id);
-
-    public IModule createModule(String id, IModuleDefinition md);
-    public void removeModule(IModule module);
-
-    public void setContentLoader(IModule module, IContentLoader contentLoader);
-
-    public void addModuleListener(ModuleListener l);
-    public void removeModuleListener(ModuleListener l);
-
-    /**
-     * This is an experimental method that is likely to change or go
-     * away - so don't use it for now.
-     *
-     * Note to self, we need to think about what the implications of
-     * this are and whether we are fine with them.
-     */
-    public void refreshModule(IModule currentModule);
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/ISearchPolicy.java b/framework/src/main/java/org/apache/felix/moduleloader/ISearchPolicy.java
deleted file mode 100644
index de269e1..0000000
--- a/framework/src/main/java/org/apache/felix/moduleloader/ISearchPolicy.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.moduleloader;
-
-import java.net.URL;
-import java.util.Enumeration;
-
-public interface ISearchPolicy
-{
-    public Object[] definePackage(String name);
-    public Class findClass(String name) throws ClassNotFoundException;
-    public URL findResource(String name) throws ResourceNotFoundException;
-    public Enumeration findResources(String name) throws ResourceNotFoundException;
-    public String findLibrary(String name);
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java b/framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java
index bdc3f37..407616e 100644
--- a/framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java
+++ b/framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java
@@ -44,9 +44,9 @@
      * @param mgr the source of the event.
      * @param module the subject of the event.
     **/
-    public ModuleEvent(IModuleFactory factory, IModule module)
+    public ModuleEvent(IModule module)
     {
-        super(factory);
+        super(module);
         m_module = module;
     }
 
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/ModuleFactoryImpl.java b/framework/src/main/java/org/apache/felix/moduleloader/ModuleFactoryImpl.java
deleted file mode 100644
index 649cc61..0000000
--- a/framework/src/main/java/org/apache/felix/moduleloader/ModuleFactoryImpl.java
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.moduleloader;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.felix.framework.Logger;
-
-public class ModuleFactoryImpl implements IModuleFactory
-{
-    private Logger m_logger = null;
-    private Map m_moduleMap = new HashMap();
-
-    private ModuleListener[] m_listeners = null;
-    private static final ModuleListener[] m_noListeners = new ModuleListener[0];
-
-    public ModuleFactoryImpl(Logger logger)
-    {
-        m_logger = logger;
-        m_listeners = m_noListeners;
-    }
-
-    public synchronized IModule[] getModules()
-    {
-        return (IModule[]) m_moduleMap.values().toArray(new IModule[m_moduleMap.size()]);
-    }
-
-    public synchronized IModule getModule(String id)
-    {
-        return (IModule) m_moduleMap.get(id);
-    }
-
-    public IModule createModule(String id, IModuleDefinition md)
-    {
-        IModule module = null;
-
-        // Use a synchronized block instead of synchronizing the
-        // method, so we can fire our event outside of the block.
-        synchronized (this)
-        {
-            if (m_moduleMap.get(id) == null)
-            {
-                module = new ModuleImpl(m_logger, id, md);
-                m_moduleMap.put(id, module);
-            }
-            else
-            {
-                throw new IllegalArgumentException("Module ID must be unique.");
-            }
-        }
-
-        // Fire event here instead of inside synchronized block.
-        fireModuleAdded(module);
-
-        return module;
-    }
-
-    /**
-     * This is an experimental method that is likely to change or go
-     * away - so don't use it for now.
-     *
-     * Note to self, we need to think about what the implications of
-     * this are and whether we are fine with them.
-     */
-    public void refreshModule(IModule module)
-    {
-        boolean fire = false;
-
-        synchronized (this)
-        {
-            fire = (m_moduleMap.get(module.getId()) != null);
-        }
-
-        if (fire)
-        {
-            fireModuleRefreshed(module);
-        }
-    }
-
-    public void removeModule(IModule module)
-    {
-        // Use a synchronized block instead of synchronizing the
-        // method, so we can fire our event outside of the block.
-        synchronized (this)
-        {
-            if (m_moduleMap.get(module.getId()) != null)
-            {
-                // Remove from data structures.
-                m_moduleMap.remove(module.getId());
-                // Close the module's content loader to deinitialize it.
-                // TODO: This is not really the best place for this, but at
-                // least it is centralized with the call to IContentLoader.open()
-                // when a module's content loader is set below.
-                ((ModuleImpl) module).getContentLoader().close();
-            }
-            else
-            {
-                // Don't fire event.
-                return;
-            }
-        }
-
-        // Fire event here instead of inside synchronized block.
-        fireModuleRemoved(module);
-    }
-
-    public void setContentLoader(IModule module, IContentLoader contentLoader)
-    {
-        synchronized (this)
-        {
-            ((ModuleImpl) module).setContentLoader(contentLoader);
-        }
-    }
-
-    /**
-     * <p>
-     * Adds a listener to the <tt>IModuleFactory</tt> to listen for
-     * module added and removed events.
-     * </p>
-     * @param l the <tt>ModuleListener</tt> to add.
-    **/
-    public void addModuleListener(ModuleListener l)
-    {
-        // Verify listener.
-        if (l == null)
-        {
-            throw new IllegalArgumentException("Listener is null");
-        }
-
-        // Use the m_noListeners object as a lock.
-        synchronized (m_noListeners)
-        {
-            // If we have no listeners, then just add the new listener.
-            if (m_listeners == m_noListeners)
-            {
-                m_listeners = new ModuleListener[] { l };
-            }
-            // Otherwise, we need to do some array copying.
-            // Notice, the old array is always valid, so if
-            // the dispatch thread is in the middle of a dispatch,
-            // then it has a reference to the old listener array
-            // and is not affected by the new value.
-            else
-            {
-                ModuleListener[] newList = new ModuleListener[m_listeners.length + 1];
-                System.arraycopy(m_listeners, 0, newList, 0, m_listeners.length);
-                newList[m_listeners.length] = l;
-                m_listeners = newList;
-            }
-        }
-    }
-
-    /**
-     * <p>
-     * Removes a listener from the <tt>IModuleFactory</tt>.
-     * </p>
-     * @param l the <tt>ModuleListener</tt> to remove.
-    **/
-    public void removeModuleListener(ModuleListener l)
-    {
-        // Verify listener.
-        if (l == null)
-        {
-            throw new IllegalArgumentException("Listener is null");
-        }
-
-        // Use the m_noListeners object as a lock.
-        synchronized (m_noListeners)
-        {
-            // Try to find the instance in our list.
-            int idx = -1;
-            for (int i = 0; i < m_listeners.length; i++)
-            {
-                if (m_listeners[i].equals(l))
-                {
-                    idx = i;
-                    break;
-                }
-            }
-
-            // If we have the instance, then remove it.
-            if (idx >= 0)
-            {
-                // If this is the last listener, then point to empty list.
-                if (m_listeners.length == 1)
-                {
-                    m_listeners = m_noListeners;
-                }
-                // Otherwise, we need to do some array copying.
-                // Notice, the old array is always valid, so if
-                // the dispatch thread is in the middle of a dispatch,
-                // then it has a reference to the old listener array
-                // and is not affected by the new value.
-                else
-                {
-                    ModuleListener[] newList = new ModuleListener[m_listeners.length - 1];
-                    System.arraycopy(m_listeners, 0, newList, 0, idx);
-                    if (idx < newList.length)
-                    {
-                        System.arraycopy(m_listeners, idx + 1, newList, idx,
-                            newList.length - idx);
-                    }
-                    m_listeners = newList;
-                }
-            }
-        }
-    }
-
-    /**
-     * <p>
-     * Fires an event indicating that the specified module was added
-     * to the <tt>IModuleFactory</tt>.
-     * </p>
-     * @param module the module that was added.
-    **/
-    protected void fireModuleAdded(IModule module)
-    {
-        // Event holder.
-        ModuleEvent event = null;
-
-        // Get a copy of the listener array, which is guaranteed
-        // to not be null.
-        ModuleListener[] listeners = m_listeners;
-
-        // Loop through listeners and fire events.
-        for (int i = 0; i < listeners.length; i++)
-        {
-            // Lazily create event.
-            if (event == null)
-            {
-                event = new ModuleEvent(this, module);
-            }
-            listeners[i].moduleAdded(event);
-        }
-    }
-
-    /**
-     * <p>
-     * Fires an event indicating that the specified module was removed
-     * from the <tt>IModuleFactory</tt>.
-     * </p>
-     * @param module the module that was removed.
-    **/
-    protected void fireModuleRemoved(IModule module)
-    {
-        // Event holder.
-        ModuleEvent event = null;
-
-        // Get a copy of the listener array, which is guaranteed
-        // to not be null.
-        ModuleListener[] listeners = m_listeners;
-
-        // Loop through listeners and fire events.
-        for (int i = 0; i < listeners.length; i++)
-        {
-            // Lazily create event.
-            if (event == null)
-            {
-                event = new ModuleEvent(this, module);
-            }
-            listeners[i].moduleRemoved(event);
-        }
-    }
-
-    /**
-     * This is an experimental method that is likely to change or go
-     * away - so don't use it for now.
-     *
-     * Note to self, we need to think about what the implications of
-     * this are and whether we are fine with them.
-     */
-    protected void fireModuleRefreshed(IModule module)
-    {
-     // Event holder.
-        ModuleEvent event = null;
-
-        // Get a copy of the listener array, which is guaranteed
-        // to not be null.
-        ModuleListener[] listeners = m_listeners;
-
-        // Loop through listeners and fire events.
-        for (int i = 0; i < listeners.length; i++)
-        {
-            // Lazily create event.
-            if (event == null)
-            {
-                event = new ModuleEvent(this, module);
-            }
-            listeners[i].moduleRefreshed(event);
-        }
-    }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/ModuleImpl.java b/framework/src/main/java/org/apache/felix/moduleloader/ModuleImpl.java
deleted file mode 100644
index 8963cf8..0000000
--- a/framework/src/main/java/org/apache/felix/moduleloader/ModuleImpl.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.moduleloader;
-
-import java.net.URL;
-import java.util.Enumeration;
-
-import org.apache.felix.framework.Logger;
-import org.apache.felix.framework.searchpolicy.ContentLoaderImpl;
-import org.apache.felix.framework.util.FelixConstants;
-
-public class ModuleImpl implements IModule
-{
-    private Logger m_logger = null;
-    private String m_id = null;
-    private IModuleDefinition m_md = null;
-    private IContentLoader m_contentLoader = null;
-    private IModule[] m_fragments = null;
-    private IWire[] m_wires = null;
-    private IModule[] m_dependentHosts = new IModule[0];
-    private IModule[] m_dependentImporters = new IModule[0];
-    private IModule[] m_dependentRequirers = new IModule[0];
-    private volatile boolean m_isStale = false;
-
-    ModuleImpl(Logger logger, String id, IModuleDefinition md)
-    {
-        m_logger = logger;
-        m_id = id;
-        m_md = md;
-    }
-
-    public String getId()
-    {
-        return m_id;
-    }
-
-    public IModuleDefinition getDefinition()
-    {
-        return m_md;
-    }
-
-    public IContentLoader getContentLoader()
-    {
-        return m_contentLoader;
-    }
-
-    protected void setContentLoader(IContentLoader contentLoader)
-    {
-        m_contentLoader = contentLoader;
-    }
-
-    public synchronized IModule[] getFragments()
-    {
-        return m_fragments;
-    }
-
-    public synchronized void attachFragments(IModule[] fragments) throws Exception
-    {
-        // Remove module from old fragment dependencies.
-        // We will generally only remove module fragment
-        // dependencies when we are uninstalling the module.
-        for (int i = 0; (m_fragments != null) && (i < m_fragments.length); i++)
-        {
-            ((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)
-        {
-            IContent[] fragmentContents = new IContent[m_fragments.length];
-            for (int i = 0; (m_fragments != null) && (i < m_fragments.length); i++)
-            {
-                ((ModuleImpl) m_fragments[i]).addDependentHost(this);
-                fragmentContents[i] =
-                    m_fragments[i].getContentLoader().getContent()
-                        .getEntryAsContent(FelixConstants.CLASS_PATH_DOT);
-            }
-            // Now attach the fragment contents to our content loader.
-            ((ContentLoaderImpl) m_contentLoader).attachFragmentContents(fragmentContents);
-        }
-    }
-
-    public synchronized IWire[] getWires()
-    {
-        return m_wires;
-    }
-
-    public synchronized void setWires(IWire[] wires)
-    {
-        // 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++)
-        {
-            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 ourself as a dependent to the new wires' modules.
-        for (int i = 0; (m_wires != null) && (i < m_wires.length); i++)
-        {
-            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);
-            }
-        }
-    }
-
-    public synchronized IModule[] getDependentHosts()
-    {
-        return m_dependentHosts;
-    }
-
-    public synchronized void addDependentHost(IModule module)
-    {
-        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()
-    {
-        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
-    {
-        try
-        {
-            return m_contentLoader.getSearchPolicy().findClass(name);
-        }
-        catch (ClassNotFoundException ex)
-        {
-            m_logger.log(
-                Logger.LOG_WARNING,
-                ex.getMessage(),
-                ex);
-            throw ex;
-        }
-    }
-
-    public URL getResource(String name)
-    {
-        try
-        {
-            return m_contentLoader.getSearchPolicy().findResource(name);
-        }
-        catch (ResourceNotFoundException ex)
-        {
-            m_logger.log(
-                Logger.LOG_WARNING,
-                ex.getMessage(),
-                ex);
-        }
-        return null;
-    }
-
-    public Enumeration getResources(String name)
-    {
-        try
-        {
-           return m_contentLoader.getSearchPolicy().findResources(name);
-        }
-        catch (ResourceNotFoundException ex)
-        {
-            m_logger.log(
-                Logger.LOG_WARNING,
-                ex.getMessage(),
-                ex);
-        }
-        return null;
-    }
-
-    public boolean isStale()
-    {
-        return m_isStale;
-    }
-
-    public void setStale()
-    {
-        m_isStale = true;
-    }
-
-    public String toString()
-    {
-        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;
-    }
-}
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/ModuleListener.java b/framework/src/main/java/org/apache/felix/moduleloader/ModuleListener.java
deleted file mode 100644
index 775787d..0000000
--- a/framework/src/main/java/org/apache/felix/moduleloader/ModuleListener.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.moduleloader;
-
-import java.util.EventListener;
-
-/**
- * <p>
- * This interface is an event listener for <tt>ModuleEvent</tt> events.
- * To receive events, an implementation of this listener must be added
- * to the <tt>IModuleFactory</tt> instance.
- * </p>
- * @see org.apache.felix.moduleloader.IModuleFactory
- * @see org.apache.felix.moduleloader.ModuleEvent
-**/
-public interface ModuleListener extends EventListener
-{
-    /**
-     * <p>
-     * This method is called after a module is added to the
-     * <tt>IModuleFactory</tt>.
-     * </p>
-     * @param event the event object containing the event details.
-    **/
-    public void moduleAdded(ModuleEvent event);
-
-    /**
-     * <p>
-     * This method is called after a module is remove from the
-     * <tt>IModuleFactory</tt>.
-     * </p>
-     * @param event the event object containing the event details.
-    **/
-    public void moduleRemoved(ModuleEvent event);
-
-    /**
-     * This is an experimental method that is likely to change or go
-     * away - so don't use it for now.
-     *
-     * Note to self, we need to think about what the implications of
-     * this are and whether we are fine with them.
-     */
-    public void moduleRefreshed(ModuleEvent event);
-}
\ No newline at end of file