Merged sandbox/rickhall/framework-branch changes r370894:374616 into trunk.
These changes represent a refactoring of the Module Loader layer to provide
better abstractions for modules and search policy to more cleanly support
some R4 features, like Bundle.getEntry(), and future experimental features.


git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@374660 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
index 4613fd4..b613648 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
@@ -156,7 +156,7 @@
         }
         catch (InvalidSyntaxException ex)
         {
-            m_felix.getLogger().log(LogWrapper.LOG_ERROR, "BundleContextImpl: " + ex);
+            m_felix.getLogger().log(Logger.LOG_ERROR, "BundleContextImpl: " + ex);
         }
         return null;
     }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/BundleInfo.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/BundleInfo.java
index 2ab1823..1d059a5 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/BundleInfo.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/BundleInfo.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -19,14 +19,14 @@
 import java.util.Map;
 
 import org.apache.felix.framework.cache.BundleArchive;
-import org.apache.felix.moduleloader.Module;
+import org.apache.felix.moduleloader.IModule;
 import org.osgi.framework.*;
 
 class BundleInfo
 {
-    private LogWrapper m_logger = null;
+    private Logger m_logger = null;
     private BundleArchive m_archive = null;
-    private Module[] m_modules = null;
+    private IModule[] m_modules = null;
     private int m_state = 0;
     private long m_modified = 0;
     private BundleActivator m_activator = null;
@@ -39,12 +39,12 @@
     private int m_lockCount = 0;
     private Thread m_lockThread = null;
 
-    protected BundleInfo(LogWrapper logger, BundleArchive archive, Module module)
+    protected BundleInfo(Logger logger, BundleArchive archive, IModule module)
         throws Exception
     {
         m_logger = logger;
         m_archive = archive;
-        m_modules = (module == null) ? new Module[0] : new Module[] { module };
+        m_modules = (module == null) ? new IModule[0] : new IModule[] { module };
 
         m_state = Bundle.INSTALLED;
         m_removalPending = false;
@@ -73,7 +73,7 @@
      * no limit on the potential number of bundle JAR file revisions.
      * @return array of modules corresponding to the bundle JAR file revisions.
     **/
-    public Module[] getModules()
+    public IModule[] getModules()
     {
         return m_modules;
     }
@@ -84,7 +84,7 @@
      * @return <tt>true</tt> if the specified module is in the array of modules
      *         associated with this bundle, <tt>false</tt> otherwise.
     **/
-    public boolean hasModule(Module module)
+    public boolean hasModule(IModule module)
     {
         for (int i = 0; i < m_modules.length; i++)
         {
@@ -101,7 +101,7 @@
      * in the module array.
      * @return the newest module.
     **/
-    public Module getCurrentModule()
+    public IModule getCurrentModule()
     {
         return m_modules[m_modules.length - 1];
     }
@@ -111,9 +111,9 @@
      * the bundle associated with this <tt>BundleInfo</tt> object.
      * @param module the module to add.
     **/
-    public void addModule(Module module)
+    public void addModule(IModule module)
     {
-        Module[] dest = new Module[m_modules.length + 1];
+        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;
@@ -133,7 +133,7 @@
         catch (Exception ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "Error reading location from bundle archive.",
                 ex);
             return null;
@@ -149,7 +149,7 @@
         catch (Exception ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "Error reading start level from bundle archive.",
                 ex);
             return defaultLevel;
@@ -165,7 +165,7 @@
         catch (Exception ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "Error writing start level to bundle archive.",
                 ex);
         }
@@ -182,7 +182,7 @@
         catch (Exception ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "Error reading manifest from bundle archive.",
                 ex);
             return null;
@@ -218,7 +218,7 @@
         catch (Exception ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "Error reading persistent state from bundle archive.",
                 ex);
             return Bundle.INSTALLED;
@@ -233,7 +233,7 @@
         }
         catch (Exception ex)
         {
-            m_logger.log(LogWrapper.LOG_ERROR,
+            m_logger.log(Logger.LOG_ERROR,
                 "Error writing persistent state to bundle archive.",
                 ex);
         }
@@ -248,7 +248,7 @@
         catch (Exception ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "Error writing persistent state to bundle archive.",
                 ex);
         }
@@ -263,7 +263,7 @@
         catch (Exception ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "Error writing persistent state to bundle archive.",
                 ex);
         }
@@ -342,42 +342,4 @@
         m_lockCount = info.m_lockCount;
         m_lockThread = info.m_lockThread;
     }
-
-    /**
-     * Converts a module identifier to a bundle identifier. Module IDs
-     * are typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this
-     * method returns only the portion corresponding to the bundle ID.
-    **/
-    protected static long getBundleIdFromModuleId(String id)
-    {
-        try
-        {
-            String bundleId = (id.indexOf('.') >= 0)
-                ? id.substring(0, id.indexOf('.')) : id;
-            return Long.parseLong(bundleId);
-        }
-        catch (NumberFormatException ex)
-        {
-            return -1;
-        }
-    }
-
-    /**
-     * Converts a module identifier to a bundle identifier. Module IDs
-     * are typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this
-     * method returns only the portion corresponding to the revision.
-    **/
-    protected static int getModuleRevisionFromModuleId(String id)
-    {
-        try
-        {
-            String rev = (id.indexOf('.') >= 0)
-                ? id.substring(id.indexOf('.') + 1) : id;
-            return Integer.parseInt(rev);
-        }
-        catch (NumberFormatException ex)
-        {
-            return -1;
-        }
-    }
 }
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ExportedPackageImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ExportedPackageImpl.java
index f853fe1..b952a8f 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ExportedPackageImpl.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ExportedPackageImpl.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -16,8 +16,8 @@
  */
 package org.apache.felix.framework;
 
-import org.apache.felix.framework.searchpolicy.R4Version;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
 import org.osgi.service.packageadmin.ExportedPackage;
 
 class ExportedPackageImpl implements ExportedPackage
@@ -25,12 +25,12 @@
     private Felix m_felix = null;
     private BundleImpl m_exporter = null;
     private String m_name = null;
-    private R4Version m_version = null;
+    private Version m_version = null;
     private String m_toString = null;
     private String m_versionString = null;
 
     public ExportedPackageImpl(
-        Felix felix, BundleImpl exporter, String name, R4Version version)
+        Felix felix, BundleImpl exporter, String name, Version version)
     {
         m_felix = felix;
         m_exporter = exporter;
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
index cf0b317..cdf8871 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -27,22 +27,21 @@
 import org.apache.felix.framework.util.*;
 import org.apache.felix.framework.util.Util;
 import org.apache.felix.moduleloader.*;
-import org.apache.felix.moduleloader.search.ResolveException;
-import org.apache.felix.moduleloader.search.ResolveListener;
 import org.osgi.framework.*;
 import org.osgi.service.packageadmin.ExportedPackage;
 
 public class Felix
 {
     // Logging related member variables.
-    private LogWrapper m_logger = new LogWrapper();
+    private Logger m_logger = new Logger();
     // Config properties.
     private PropertyResolver m_config = new ConfigImpl();
     // Configuration properties passed into constructor.
     private MutablePropertyResolver m_configMutable = null;
 
-    // MODULE MANAGER.
-    private ModuleManager m_mgr = null;
+    // MODULE FACTORY.
+    private IModuleFactory m_factory = null;
+    private R4SearchPolicyCore m_policyCore = null;
 
     // Object used as a lock when calculating which bundles
     // when performing an operation on one or more bundles.
@@ -97,6 +96,9 @@
     // Service registry.
     private ServiceRegistry m_registry = null;
 
+    // Reusable bundle URL stream handler.
+    private URLStreamHandler m_bundleStreamHandler = null;
+
     // Reusable admin permission object for all instances
     // of the BundleImpl.
     private static AdminPermission m_adminPerm = new AdminPermission();
@@ -215,7 +217,7 @@
         m_frameworkStatus = STARTING_STATUS;
 
         // Initialize member variables.
-        m_mgr = null;
+        m_factory = null;
         m_configMutable = (configMutable == null)
             ? new MutablePropertyResolverImpl(new StringMap(false)) : configMutable;
         m_activeStartLevel = FelixConstants.FRAMEWORK_INACTIVE_STARTLEVEL;
@@ -225,6 +227,7 @@
         m_cache = null;
         m_nextId = 1L;
         m_dispatchQueue = null;
+        m_bundleStreamHandler = new URLHandlersBundleStreamHandler(this);
         m_registry = new ServiceRegistry(m_logger);
 
         // Add a listener to the service registry; this is
@@ -272,18 +275,18 @@
         }
 
         // Create search policy for module loader.
-        R4SearchPolicy searchPolicy = new R4SearchPolicy(m_logger);
+        m_policyCore = new R4SearchPolicyCore(m_logger);
 
         // Add a resolver listener to the search policy
         // so that we will be notified when modules are resolved
         // in order to update the bundle state.
-        searchPolicy.addResolverListener(new ResolveListener() {
+        m_policyCore.addResolverListener(new ResolveListener() {
             public void moduleResolved(ModuleEvent event)
             {
                 BundleImpl bundle = null;
                 try
                 {
-                    long id = BundleInfo.getBundleIdFromModuleId(
+                    long id = Util.getBundleIdFromModuleId(
                         event.getModule().getId());
                     if (id >= 0)
                     {
@@ -331,7 +334,8 @@
             }
         });
 
-        m_mgr = new ModuleManager(searchPolicy, new OSGiURLPolicy(this));
+        m_factory = new ModuleFactoryImpl(m_logger);
+        m_policyCore.setModuleFactory(m_factory);
 
         // Initialize dispatch queue.
         m_dispatchQueue = new FelixDispatchQueue(m_logger);
@@ -349,13 +353,16 @@
             BundleInfo info = new BundleInfo(
                 m_logger, new SystemBundleArchive(), null);
             systembundle = new SystemBundle(this, info, activatorList);
-            systembundle.getInfo().addModule(
-                m_mgr.addModule(
-                    "0", systembundle.getAttributes(),
-                    systembundle.getResourceSources(),
-                    systembundle.getLibrarySources(),
-                    true)); // HACK ALERT! This flag indicates that we will
-                            // use the parent class loader as a resource source.
+            systembundle.getInfo().addModule(m_factory.createModule("0"));
+            systembundle.getContentLoader().setSearchPolicy(
+                new R4SearchPolicy(
+                    m_policyCore, systembundle.getInfo().getCurrentModule()));
+            m_factory.setContentLoader(
+                systembundle.getInfo().getCurrentModule(),
+                systembundle.getContentLoader());
+            m_policyCore.setExports(
+                systembundle.getInfo().getCurrentModule(), systembundle.getExports());
+
             m_installedBundleMap.put(
                 systembundle.getInfo().getLocation(), systembundle);
 
@@ -363,7 +370,7 @@
             // state to be set to RESOLVED.
             try
             {
-                searchPolicy.resolve(systembundle.getInfo().getCurrentModule());
+                m_policyCore.resolve(systembundle.getInfo().getCurrentModule());
             }
             catch (ResolveException ex)
             {
@@ -380,9 +387,9 @@
         }
         catch (Exception ex)
         {
-            m_mgr = null;
+            m_factory = null;
             DispatchQueue.shutdown();
-            m_logger.log(LogWrapper.LOG_ERROR, "Unable to start system bundle.", ex);
+            m_logger.log(Logger.LOG_ERROR, "Unable to start system bundle.", ex);
             throw new RuntimeException("Unable to start system bundle.");
         }
         
@@ -397,7 +404,7 @@
         catch (Exception ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "Unable to list saved bundles: " + ex, ex);
             archives = null;
         }
@@ -437,14 +444,14 @@
                 try
                 {
                     m_logger.log(
-                        LogWrapper.LOG_ERROR,
+                        Logger.LOG_ERROR,
                         "Unable to re-install " + archives[i].getLocation(),
                         ex);
                 }
                 catch (Exception ex2)
                 {
                     m_logger.log(
-                        LogWrapper.LOG_ERROR,
+                        Logger.LOG_ERROR,
                         "Unable to re-install bundle " + archives[i].getId(),
                         ex);
                 }
@@ -521,7 +528,7 @@
         catch (Exception ex)
         {
             fireFrameworkEvent(FrameworkEvent.ERROR, getBundle(0), ex);
-            m_logger.log(LogWrapper.LOG_ERROR, "Error stopping system bundle.", ex);
+            m_logger.log(Logger.LOG_ERROR, "Error stopping system bundle.", ex);
         }
 
         // Loop through all bundles and update any updated bundles.
@@ -538,7 +545,7 @@
                 catch (Exception ex)
                 {
                     fireFrameworkEvent(FrameworkEvent.ERROR, bundle, ex);
-                    m_logger.log(LogWrapper.LOG_ERROR, "Unable to purge bundle "
+                    m_logger.log(Logger.LOG_ERROR, "Unable to purge bundle "
                         + bundle.getInfo().getLocation(), ex);
                 }
             }
@@ -556,7 +563,7 @@
             catch (Exception ex)
             {
                 m_logger.log(
-                    LogWrapper.LOG_ERROR,
+                    Logger.LOG_ERROR,
                     "Unable to remove "
                     + m_uninstalledBundles[i].getInfo().getLocation(), ex);
             }
@@ -682,7 +689,7 @@
                 {
                     fireFrameworkEvent(FrameworkEvent.ERROR, impl, th);
                     m_logger.log(
-                        LogWrapper.LOG_ERROR,
+                        Logger.LOG_ERROR,
                         "Error starting " + impl.getInfo().getLocation(), th);
                 }
             }
@@ -698,7 +705,7 @@
                 {
                     fireFrameworkEvent(FrameworkEvent.ERROR, impl, th);
                     m_logger.log(
-                        LogWrapper.LOG_ERROR,
+                        Logger.LOG_ERROR,
                         "Error stopping " + impl.getInfo().getLocation(), th);
                 }
             }
@@ -810,7 +817,7 @@
         }
         catch (BundleException ex)
         {
-            m_logger.log(LogWrapper.LOG_ERROR, "Unable to acquire lock to set start level.", ex);
+            m_logger.log(Logger.LOG_ERROR, "Unable to acquire lock to set start level.", ex);
             return;
         }
         
@@ -847,12 +854,12 @@
                 catch (Throwable th)
                 {
                     rethrow = th;
-                    m_logger.log(LogWrapper.LOG_ERROR, "Error starting/stopping bundle.", th);
+                    m_logger.log(Logger.LOG_ERROR, "Error starting/stopping bundle.", th);
                 }
             }
             else
             {
-                m_logger.log(LogWrapper.LOG_WARNING, "Bundle start level must be greater than zero.");
+                m_logger.log(Logger.LOG_WARNING, "Bundle start level must be greater than zero.");
             }
         }
         finally
@@ -899,9 +906,18 @@
     **/
     protected boolean isBundleClass(Class clazz)
     {
-        if (clazz.getClassLoader() instanceof ModuleClassLoader)
+        if (clazz.getClassLoader() instanceof ContentClassLoader)
         {
-            return ((ModuleClassLoader) clazz.getClassLoader()).isModuleManagerEqual(m_mgr);
+            IContentLoader contentLoader =
+                ((ContentClassLoader) clazz.getClassLoader()).getContentLoader();
+            IModule[] modules = m_factory.getModules();
+            for (int i = 0; i < modules.length; i++)
+            {
+                if (modules[i].getContentLoader() == contentLoader)
+                {
+                    return true;
+                }
+            }
         }
         return false;
     }
@@ -916,13 +932,16 @@
      * @return an input stream to the bundle resource.
      * @throws IOException if the input stream could not be created.
     **/
+/*
+ This might note be needed due to changes in URLHandlersBundleURLConnection
+
     protected InputStream getBundleResourceInputStream(URL url)
         throws IOException
     {
         // The URL is constructed like this:
         // bundle://<module-id>/<source-idx>/<resource-path>
     
-        Module module = m_mgr.getModule(url.getHost());
+        IModule module = m_factory.getModule(url.getHost());
         if (module == null)
         {
             throw new IOException("Unable to find bundle's module.");
@@ -933,38 +952,22 @@
         {
             throw new IOException("Unable to find resource: " + url.toString());
         }
+
+        // Remove any leading slash.
         if (resource.startsWith("/"))
         {
             resource = resource.substring(1);
         }
-        int rsIdx = -1;
-        try
-        {
-            rsIdx = Integer.parseInt(resource.substring(0, resource.indexOf("/")));
-        }
-        catch (NumberFormatException ex)
-        {
-            new IOException("Error parsing resource index.");
-        }
-        resource = resource.substring(resource.indexOf("/") + 1);
 
         // Get the resource bytes from the resource source.
-        byte[] bytes = null;
-        ResourceSource[] resSources = module.getResourceSources();
-        if ((resSources != null) && (rsIdx < resSources.length))
-        {
-            if (resSources[rsIdx].hasResource(resource))
-            {
-                bytes = resSources[rsIdx].getBytes(resource);
-            }
-        }
+        byte[] bytes = module.getContentLoader().getResourceBytes(resource);
         if (bytes == null)
         {
             throw new IOException("Unable to find resource: " + url.toString());
         }
         return new ByteArrayInputStream(bytes);
     }
-
+*/
     //
     // Implementation of Bundle interface methods.
     //
@@ -1006,7 +1009,7 @@
         {
             AccessController.checkPermission(m_adminPerm);
         }
-        return bundle.getInfo().getCurrentModule().getClassLoader().getResource(name);
+        return bundle.getInfo().getCurrentModule().getContentLoader().getResource(name);
     }
 
     protected ServiceReference[] getBundleRegisteredServices(BundleImpl bundle)
@@ -1150,7 +1153,7 @@
             catch (Exception ex)
             {
                 m_logger.log(
-                    LogWrapper.LOG_WARNING,
+                    Logger.LOG_WARNING,
                     "Exception while evaluating the permission.",
                     ex);
                 return false; 
@@ -1165,18 +1168,20 @@
     **/
     protected Class loadBundleClass(BundleImpl bundle, String name) throws ClassNotFoundException
     {
-        try
+        Class clazz = bundle.getInfo().getCurrentModule().getContentLoader().getClass(name);
+        if (clazz == null)
         {
-            return bundle.getInfo().getCurrentModule().getClassLoader().loadClass(name);
-        }
-        catch (ClassNotFoundException ex)
-        {
+            // Throw exception.
+            ClassNotFoundException ex = new ClassNotFoundException(name);
+
             // The spec says we must fire a framework error.
             fireFrameworkEvent(
                 FrameworkEvent.ERROR, bundle,
                 new BundleException(ex.getMessage()));
+
             throw ex;
         }
+        return clazz;
     }
 
     /**
@@ -1366,13 +1371,10 @@
 //            }
         }
 
-        // Get the import search policy.
-        R4SearchPolicy search = (R4SearchPolicy) m_mgr.getSearchPolicy();
-
-        Module module = bundle.getInfo().getCurrentModule();
+        IModule module = bundle.getInfo().getCurrentModule();
         try
         {
-            search.resolve(module);
+            m_policyCore.resolve(module);
         }
         catch (ResolveException ex)
         {
@@ -1380,7 +1382,7 @@
             {
                 throw new BundleException(
                     "Unresolved package in bundle "
-                    + BundleInfo.getBundleIdFromModuleId(ex.getModule().getId())
+                    + Util.getBundleIdFromModuleId(ex.getModule().getId())
                     + ": " + ex.getPackage());
             }
             else
@@ -1478,7 +1480,7 @@
                 // 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.
-                Module module = createModule(
+                IModule module = createModule(
                     info.getBundleId(),
                     archive.getRevisionCount() - 1,
                     info.getCurrentHeader());
@@ -1487,7 +1489,7 @@
             }
             catch (Exception ex)
             {
-                m_logger.log(LogWrapper.LOG_ERROR, "Unable to update the bundle.", ex);
+                m_logger.log(Logger.LOG_ERROR, "Unable to update the bundle.", ex);
                 rethrow = ex;
             }
 
@@ -1522,7 +1524,7 @@
             }
             catch (IOException ex)
             {
-                m_logger.log(LogWrapper.LOG_ERROR, "Unable to close input stream.", ex);
+                m_logger.log(Logger.LOG_ERROR, "Unable to close input stream.", ex);
             }
         }
     }
@@ -1614,7 +1616,7 @@
         }
         catch (Throwable th)
         {
-            m_logger.log(LogWrapper.LOG_ERROR, "Error stopping bundle.", th);
+            m_logger.log(Logger.LOG_ERROR, "Error stopping bundle.", th);
             rethrow = th;
         }
                   
@@ -1725,7 +1727,7 @@
         else
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR, "Unable to remove bundle from installed map!");
+                Logger.LOG_ERROR, "Unable to remove bundle from installed map!");
         }
 
         // Set state to uninstalled.
@@ -1846,7 +1848,7 @@
                     catch (IOException ex)
                     {
                         m_logger.log(
-                            LogWrapper.LOG_ERROR,
+                            Logger.LOG_ERROR,
                             "Unable to close input stream.", ex);
                     }
                 }
@@ -1867,9 +1869,8 @@
                 }
                 catch (Exception ex)
                 {
-                    ex.printStackTrace();
                     m_logger.log(
-                        LogWrapper.LOG_ERROR,
+                        Logger.LOG_ERROR,
                         "Could not purge bundle.", ex);
                 }
             }
@@ -1892,10 +1893,11 @@
                     catch (Exception ex1)
                     {
                         m_logger.log(
-                            LogWrapper.LOG_ERROR,
+                            Logger.LOG_ERROR,
                             "Could not remove from cache.", ex1);
                     }
                 }
+ex.printStackTrace();
                 throw new BundleException("Could not create bundle object.", ex);
             }
 
@@ -1926,7 +1928,7 @@
             catch (IOException ex)
             {
                 m_logger.log(
-                    LogWrapper.LOG_ERROR,
+                    Logger.LOG_ERROR,
                     "Unable to close input stream.", ex);
                 // Not much else we can do.
             }
@@ -2367,7 +2369,7 @@
                         // We do not throw this exception since the bundle
                         // is not supposed to know about the service at all
                         // if it does not have permission.
-                        m_logger.log(LogWrapper.LOG_ERROR, ex.getMessage());
+                        m_logger.log(Logger.LOG_ERROR, ex.getMessage());
                     }
                 }
                 
@@ -2496,7 +2498,7 @@
         }
         catch (Exception ex)
         {
-            m_logger.log(LogWrapper.LOG_ERROR, ex.getMessage());
+            m_logger.log(Logger.LOG_ERROR, ex.getMessage());
             return null;
         }
     }
@@ -2517,14 +2519,13 @@
     {
         // First, find the bundle exporting the package.
         BundleImpl bundle = null;
-        R4SearchPolicy search = (R4SearchPolicy) m_mgr.getSearchPolicy();
-        Module[] exporters = search.getInUseExporters(new R4Package(pkgName, null, null));
+        IModule[] exporters = m_policyCore.getInUseExporters(new R4Import(pkgName, null, null));
         if (exporters != null)
         {
             // Since OSGi R4 there may be more than one exporting, so just
             // take the first one.
             bundle = (BundleImpl) getBundle(
-                BundleInfo.getBundleIdFromModuleId(exporters[0].getId()));
+                Util.getBundleIdFromModuleId(exporters[0].getId()));
         }
 
         // If we have found the exporting bundle, then return the
@@ -2541,13 +2542,13 @@
             // 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.
-            Module[] modules = bundle.getInfo().getModules();
+            IModule[] modules = bundle.getInfo().getModules();
             for (int modIdx = 0; modIdx < modules.length; modIdx++)
             {
-                R4Package pkg = R4SearchPolicy.getExportPackage(modules[modIdx], pkgName);
-                if (pkg != null)
+                R4Export export = Util.getExportPackage(modules[modIdx], pkgName);
+                if (export != null)
                 {
-                    return new ExportedPackageImpl(this, bundle, pkgName, pkg.getVersionLow());
+                    return new ExportedPackageImpl(this, bundle, pkgName, export.getVersion());
                 }
             }
         }
@@ -2619,26 +2620,32 @@
     **/
     private void getExportedPackages(BundleImpl bundle, List list)
     {
-        R4SearchPolicy policy = (R4SearchPolicy) m_mgr.getSearchPolicy();
-
         // 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.
-        Module[] modules = bundle.getInfo().getModules();
+        IModule[] modules = bundle.getInfo().getModules();
         for (int modIdx = 0; modIdx < modules.length; modIdx++)
         {
-            R4Package[] exports = R4SearchPolicy.getExportsAttr(modules[modIdx]);
-            if (exports.length > 0)
+            R4Export[] exports = m_policyCore.getExports(modules[modIdx]);
+            if ((exports != null) && (exports.length > 0))
             {
                 for (int expIdx = 0; expIdx < exports.length; expIdx++)
                 {
                     // See if the target bundle's module is one of the
                     // "in use" exporters of the package.
-                    Module[] inUseModules = policy.getInUseExporters(exports[expIdx]);
-                    if (R4SearchPolicy.isModuleInArray(inUseModules, modules[modIdx]))
+                    IModule[] inUseModules =
+                        m_policyCore.getInUseExporters(
+                            new R4Import(exports[expIdx].getName(), null, null));
+                    // Search through the current providers to find the target
+                    // module.
+                    for (int i = 0; (inUseModules != null) && (i < inUseModules.length); i++)
                     {
-                        list.add(new ExportedPackageImpl(
-                            this, bundle, exports[expIdx].getId(), exports[expIdx].getVersionLow()));
+                        if (inUseModules[i] == modules[modIdx])
+                        {
+                            list.add(new ExportedPackageImpl(
+                                this, bundle, exports[expIdx].getName(),
+                                exports[expIdx].getVersion()));
+                        }
                     }
                 }
             }
@@ -2667,15 +2674,15 @@
             if (exporter != importer)
             {
                 // Check the import wires of all modules for all bundles.
-                Module[] modules = importer.getInfo().getModules();
+                IModule[] modules = importer.getInfo().getModules();
                 for (int modIdx = 0; modIdx < modules.length; modIdx++)
                 {
-                    R4Wire wire = R4SearchPolicy.getWire(modules[modIdx], ep.getName());
+                    R4Wire wire = Util.getWire(modules[modIdx], ep.getName());
     
                     // If the resolving module is associated with the
                     // exporting bundle, then add current bundle to
                     // import list.
-                    if ((wire != null) && exporterInfo.hasModule(wire.m_module))
+                    if ((wire != null) && exporterInfo.hasModule(wire.getExportingModule()))
                     {
                         // Add the bundle to the list of importers.
                         list.add(bundles[bundleIdx]);
@@ -2808,7 +2815,7 @@
         // 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.
-        Module module = createModule(
+        IModule module = createModule(
             archive.getId(), archive.getRevisionCount() - 1, headerMap);
 
         // Finally, create an return the bundle info.
@@ -2824,7 +2831,7 @@
      * @param headers The headers map associated with the bundle.
      * @return The initialized and/or newly created module.
     **/
-    private Module createModule(long id, int revision, Map headerMap)
+    private IModule createModule(long id, int revision, Map headerMap)
         throws Exception
     {
         // Get the manifest version.
@@ -2835,31 +2842,14 @@
             throw new BundleException("Unknown 'Bundle-ManifestVersion' value: " + version);
         }
 
-        // Create the resource sources for the bundle. The resource sources
-        // are comprised of the bundle's class path values (as JarResourceSources).
-        ResourceSource[] resSources = null;
-        try
-        {
-            // Get bundle class path for the specified revision from cache.
-            String[] classPath = m_cache.getArchive(id).getClassPath(revision);
-
-            // Create resource sources for everything.
-            resSources = new ResourceSource[classPath.length];
-            for (int i = 0; i < classPath.length; i++)
-            {
-                resSources[i] = new JarResourceSource(classPath[i]);
-            }
-        }
-        catch (Exception ex)
-        {
-            ex.printStackTrace();
-            throw new BundleException("Error in class path: " + ex);
-        }
-
         // Get import packages from bundle manifest.
-        R4Package[] imports = R4Package.parseImportOrExportHeader(
+        R4Package[] pkgs = R4Package.parseImportOrExportHeader(
             (String) headerMap.get(Constants.IMPORT_PACKAGE));
-
+        R4Import[] imports = new R4Import[pkgs.length];
+        for (int i = 0; i < pkgs.length; i++)
+        {
+            imports[i] = new R4Import(pkgs[i]);
+        }
 
         // Check to make sure that R3 bundles have only specified
         // the 'specification-version' attribute and no directives.
@@ -2887,8 +2877,13 @@
         }
 
         // Get export packages from bundle manifest.
-        R4Package[] exports = R4Package.parseImportOrExportHeader(
+        pkgs = R4Package.parseImportOrExportHeader(
             (String) headerMap.get(Constants.EXPORT_PACKAGE));
+        R4Export[] exports = new R4Export[pkgs.length];
+        for (int i = 0; i < pkgs.length; i++)
+        {
+            exports[i] = new R4Export(pkgs[i]);
+        }
 
         // Check to make sure that R3 bundles have only specified
         // the 'specification-version' attribute and no directives.
@@ -2915,9 +2910,12 @@
                 }
             }
             
-            R4Package[] newImports = new R4Package[imports.length + exports.length];
+            R4Import[] newImports = new R4Import[imports.length + exports.length];
             System.arraycopy(imports, 0, newImports, 0, imports.length);
-            System.arraycopy(exports, 0, newImports, imports.length, exports.length);
+            for (int i = 0; i < exports.length; i++)
+            {
+                newImports[i + imports.length] = new R4Import(exports[i]);
+            }
             imports = newImports;
         }
 
@@ -2933,24 +2931,28 @@
             {
                 usesValue = usesValue
                     + ((usesValue.length() > 0) ? "," : "")
-                    + imports[i].getId();
+                    + imports[i].getName();
             }
             R4Directive uses = new R4Directive(
                 FelixConstants.USES_DIRECTIVE, usesValue);
             for (int i = 0; (exports != null) && (i < exports.length); i++)
             {
-                exports[i] = new R4Package(
-                    exports[i].getId(),
+                exports[i] = new R4Export(
+                    exports[i].getName(),
                     new R4Directive[] { uses },
                     exports[i].getAttributes());
             }
         }
 
 // TODO: CHECK FOR DUPLICATE IMPORTS/EXPORTS HERE.
-
         // Get dynamic import packages from bundle manifest.
-        R4Package[] dynamics = R4Package.parseImportOrExportHeader(
+        pkgs = R4Package.parseImportOrExportHeader(
             (String) headerMap.get(Constants.DYNAMICIMPORT_PACKAGE));
+        R4Import[] dynamics = new R4Import[pkgs.length];
+        for (int i = 0; i < pkgs.length; i++)
+        {
+            dynamics[i] = new R4Import(pkgs[i]);
+        }
 
         // Check to make sure that R3 bundles have no attributes or
         // directives.
@@ -2969,30 +2971,56 @@
             }
         }
 
-        Object[][] attributes = {
-            new Object[] { R4SearchPolicy.EXPORTS_ATTR, exports },
-            new Object[] { R4SearchPolicy.IMPORTS_ATTR, imports },
-            new Object[] { R4SearchPolicy.DYNAMICIMPORTS_ATTR, dynamics }
-        };
-
         // Get native library entry names for module library sources.
-        LibraryInfo[] libraries =
+        R4LibraryHeader[] libraryHeaders =
             Util.parseLibraryStrings(
+                m_logger,
                 Util.parseDelimitedString(
                     (String) headerMap.get(Constants.BUNDLE_NATIVECODE), ","));
-        LibrarySource[] libSources = {
-            new OSGiLibrarySource(
+        R4Library[] libraries = new R4Library[libraryHeaders.length];
+        for (int i = 0; i < libraries.length; i++)
+        {
+            libraries[i] = new R4Library(
                 m_logger, m_cache, id, revision,
                 getProperty(Constants.FRAMEWORK_OS_NAME),
                 getProperty(Constants.FRAMEWORK_PROCESSOR),
-                libraries)
-        };
+                libraryHeaders[i]);
+        }
 
-        Module module =
-            m_mgr.addModule(
-                Long.toString(id) + "." + Integer.toString(revision),
-                attributes, resSources, libSources);
+        // 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., content loader, search policy,
+        // url policy). We need to create all of these pieces and bind
+        // them together.
 
+        // First, create the module.
+        IModule module = m_factory.createModule(
+            Long.toString(id) + "." + Integer.toString(revision));
+        // Attach the R4 search policy metadata to the module.
+        m_policyCore.setExports(module, exports);
+        m_policyCore.setImports(module, imports);
+        m_policyCore.setDynamicImports(module, dynamics);
+        m_policyCore.setLibraries(module, libraries);
+
+        // Create the content loader associated with the module archive.
+        IContentLoader contentLoader = new ContentLoaderImpl(
+                m_logger,
+                m_cache.getArchive(id).getContent(revision),
+                m_cache.getArchive(id).getContentPath(revision));
+        // Set the content loader's search policy.
+        contentLoader.setSearchPolicy(
+                new R4SearchPolicy(m_policyCore, module));
+        // Set the content loader's URL policy.
+        contentLoader.setURLPolicy(
+// TODO: FIX - NEED 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);
+
+        // Done, so return the module.
         return module;
     }
 
@@ -3013,7 +3041,7 @@
             {
                 activator =
                     m_cache.getArchive(info.getBundleId())
-                        .getActivator(info.getCurrentModule().getClassLoader());
+                        .getActivator(info.getCurrentModule().getContentLoader());
             }
             catch (Exception ex)
             {
@@ -3037,7 +3065,7 @@
             if (className != null)
             {
                 className = className.trim();
-                Class clazz = info.getCurrentModule().getClassLoader().loadClass(className);
+                Class clazz = info.getCurrentModule().getContentLoader().getClass(className);
                 if (clazz == null)
                 {
                     throw new BundleException("Not found: "
@@ -3070,10 +3098,10 @@
             // 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.
-            Module[] modules = info.getModules();
+            IModule[] modules = info.getModules();
             for (int i = 0; i < modules.length; i++)
             {
-                m_mgr.removeModule(modules[i]);
+                m_factory.removeModule(modules[i]);
             }
 
             // Purge all bundle revisions, but the current one.
@@ -3094,10 +3122,10 @@
 
         // Remove the bundle's associated modules from
         // the module manager.
-        Module[] modules = bundle.getInfo().getModules();
+        IModule[] modules = bundle.getInfo().getModules();
         for (int i = 0; i < modules.length; i++)
         {
-            m_mgr.removeModule(modules[i]);
+            m_factory.removeModule(modules[i]);
         }
 
         // Remove the bundle from the cache.
@@ -3209,11 +3237,11 @@
             System.getProperty("os.version"));
 
         String s = null;
-        s = OSGiLibrarySource.normalizePropertyValue(
+        s = R4Library.normalizePropertyValue(
             FelixConstants.FRAMEWORK_OS_NAME,
             System.getProperty("os.name"));
         m_configMutable.put(FelixConstants.FRAMEWORK_OS_NAME, s);
-        s = OSGiLibrarySource.normalizePropertyValue(
+        s = R4Library.normalizePropertyValue(
             FelixConstants.FRAMEWORK_PROCESSOR,
             System.getProperty("os.arch"));
         m_configMutable.put(FelixConstants.FRAMEWORK_PROCESSOR, s);
@@ -3243,7 +3271,7 @@
                 }
                 catch (NumberFormatException ex)
                 {
-                    m_logger.log(LogWrapper.LOG_ERROR, "Invalid property: " + keys[i]);
+                    m_logger.log(Logger.LOG_ERROR, "Invalid property: " + keys[i]);
                 }
                 StringTokenizer st = new StringTokenizer(m_config.get(keys[i]), "\" ",true);
                 if (st.countTokens() > 0)
@@ -3262,7 +3290,7 @@
                             catch (Exception ex)
                             {
                                 m_logger.log(
-                                    LogWrapper.LOG_ERROR, "Auto-properties install.", ex);
+                                    Logger.LOG_ERROR, "Auto-properties install.", ex);
                             }
                         }
                     }
@@ -3289,7 +3317,7 @@
                 }
                 catch (NumberFormatException ex)
                 {
-                    m_logger.log(LogWrapper.LOG_ERROR, "Invalid property: " + keys[i]);
+                    m_logger.log(Logger.LOG_ERROR, "Invalid property: " + keys[i]);
                 }
                 StringTokenizer st = new StringTokenizer(m_config.get(keys[i]), "\" ",true);
                 if (st.countTokens() > 0)
@@ -3307,7 +3335,7 @@
                             }
                             catch (Exception ex)
                             {
-                                m_logger.log(LogWrapper.LOG_ERROR, "Auto-properties install.", ex);
+                                m_logger.log(Logger.LOG_ERROR, "Auto-properties install.", ex);
                             }
                         }
                     }
@@ -3342,7 +3370,7 @@
                             catch (Exception ex)
                             {
                                 m_logger.log(
-                                    LogWrapper.LOG_ERROR, "Auto-properties start.", ex);
+                                    Logger.LOG_ERROR, "Auto-properties start.", ex);
                             }
                         }
                     }
@@ -3446,7 +3474,7 @@
     // Logging methods and inner classes.
     //
 
-    public LogWrapper getLogger()
+    public Logger getLogger()
     {
         return m_logger;
     }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/FilterImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/FilterImpl.java
index 280d265..c41aeea 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/FilterImpl.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/FilterImpl.java
@@ -32,7 +32,7 @@
 **/
 public class FilterImpl implements Filter
 {
-    private LogWrapper m_logger = null;
+    private Logger m_logger = null;
     private String m_toString = null;
     private Evaluator m_evaluator = null;
     private SimpleMapper m_mapper = null;
@@ -47,7 +47,7 @@
      * Construct a filter for a given filter expression string.
      * @param expr the filter expression string for the filter.
     **/
-    public FilterImpl(LogWrapper logger, String expr) throws InvalidSyntaxException
+    public FilterImpl(Logger logger, String expr) throws InvalidSyntaxException
     {
         m_logger = logger;
         if (expr == null)
@@ -132,11 +132,11 @@
         }
         catch (AttributeNotFoundException ex)
         {
-            m_logger.log(LogWrapper.LOG_DEBUG, "FilterImpl: " + ex);
+            m_logger.log(Logger.LOG_DEBUG, "FilterImpl: " + ex);
         }
         catch (EvaluationException ex)
         {
-            m_logger.log(LogWrapper.LOG_ERROR, "FilterImpl: " + toString(), ex);
+            m_logger.log(Logger.LOG_ERROR, "FilterImpl: " + toString(), ex);
         }
         return false;
     }
@@ -158,11 +158,11 @@
         }
         catch (AttributeNotFoundException ex)
         {
-            m_logger.log(LogWrapper.LOG_DEBUG, "FilterImpl: " + ex);
+            m_logger.log(Logger.LOG_DEBUG, "FilterImpl: " + ex);
         }
         catch (EvaluationException ex)
         {
-            m_logger.log(LogWrapper.LOG_ERROR, "FilterImpl: " + toString(), ex);
+            m_logger.log(Logger.LOG_ERROR, "FilterImpl: " + toString(), ex);
         }
         return false;
     }
@@ -176,11 +176,11 @@
         }
         catch (AttributeNotFoundException ex)
         {
-            m_logger.log(LogWrapper.LOG_DEBUG, "FilterImpl: " + ex);
+            m_logger.log(Logger.LOG_DEBUG, "FilterImpl: " + ex);
         }
         catch (EvaluationException ex)
         {
-            m_logger.log(LogWrapper.LOG_ERROR, "FilterImpl: " + toString(), ex);        }
+            m_logger.log(Logger.LOG_ERROR, "FilterImpl: " + toString(), ex);        }
         return false;
     }
 
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/LogWrapper.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Logger.java
similarity index 98%
rename from org.apache.felix.framework/src/main/java/org/apache/felix/framework/LogWrapper.java
rename to org.apache.felix.framework/src/main/java/org/apache/felix/framework/Logger.java
index e128f49..6266c10 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/LogWrapper.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Logger.java
@@ -31,7 +31,7 @@
  * </p>
 **/
 // TODO: Modify LogWrapper to get LogService service object and invoke with reflection.
-public class LogWrapper
+public class Logger
 {
     public static final int LOG_ERROR = 1;
     public static final int LOG_WARNING = 2;
@@ -40,7 +40,7 @@
 
     private Object m_logObj = null;
 
-    public LogWrapper()
+    public Logger()
     {
     }
 
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/OSGiURLPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/OSGiURLPolicy.java
deleted file mode 100644
index 5c9c299..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/OSGiURLPolicy.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedExceptionAction;
-
-import org.apache.felix.framework.util.FelixConstants;
-import org.apache.felix.moduleloader.*;
-
-public class OSGiURLPolicy implements URLPolicy
-{
-    private Felix m_framework = null;
-    private URLHandlersBundleStreamHandler m_bundleHandler = null;
-    private FakeURLStreamHandler m_fakeHandler = null;
-
-    public OSGiURLPolicy(Felix framework)
-    {
-        m_framework = framework;
-    }
-
-    public URL createCodeSourceURL(ModuleManager mgr, Module module)
-    {
-        URL url = null;
-/*
-        BundleImpl bundle = null;
-        try
-        {
-            bundle = (BundleImpl)
-                m_felix.getBundle(BundleInfo.getBundleIdFromModuleId(module.getId()));
-            if (bundle != null)
-            {
-                url = new URL(bundle.getInfo().getLocation());
-            }
-        }
-        catch (NumberFormatException ex)
-        {
-            url = null;
-        }
-        catch (MalformedURLException ex)
-        {
-            if (m_fakeHandler == null)
-            {
-                m_fakeHandler = new FakeURLStreamHandler();
-            }
-            try
-            {
-                url = new URL(null,
-                    FelixConstants.FAKE_URL_PROTOCOL_VALUE
-                    + "//" + bundle.getLocation(), m_fakeHandler);
-            }
-            catch (Exception ex2)
-            {
-                url = null;
-            }
-        }
-*/
-        return url;
-    }
-
-    public URL createResourceURL(ModuleManager mgr, Module module, int rsIdx, String name)
-    {
-        if (m_bundleHandler == null)
-        {
-            m_bundleHandler = new URLHandlersBundleStreamHandler(m_framework);
-        }
-
-        // Add a slash if there is one already, otherwise
-        // the is no slash separating the host from the file
-        // in the resulting URL.
-        if (!name.startsWith("/"))
-        {
-            name = "/" + name;
-        }
-
-        try
-        {
-            if (System.getSecurityManager() != null)
-            {
-                return (URL) AccessController.doPrivileged(
-                    new CreateURLPrivileged(module.getId(), rsIdx, name));
-            }
-            else
-            {
-                return new URL(FelixConstants.BUNDLE_URL_PROTOCOL,
-                    module.getId(), -1, "/" + rsIdx + name, m_bundleHandler);
-            }
-        }
-        catch (Exception ex)
-        {
-            System.err.println("OSGiURLPolicy: " + ex);
-            return null;
-        }
-    }
-
-    /**
-     * This simple class is used to perform the privileged action of
-     * creating a URL using the "bundle:" protocol stream handler.
-    **/
-    private class CreateURLPrivileged implements PrivilegedExceptionAction
-    {
-        private String m_id = null;
-        private int m_rsIdx = 0;
-        private String m_name = null;
-
-        public CreateURLPrivileged(String id, int rsIdx, String name)
-        {
-            m_id = id;
-            m_rsIdx = rsIdx;
-            m_name = name;
-        }
-
-        public Object run() throws Exception
-        {
-            return new URL(FelixConstants.BUNDLE_URL_PROTOCOL,
-                m_id, -1, "/" + m_rsIdx + m_name, m_bundleHandler);
-        }
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java
index 72c5b7d..3b4eb7c 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceReferenceImpl.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -16,8 +16,8 @@
  */
 package org.apache.felix.framework;
 
-import org.apache.felix.framework.searchpolicy.R4SearchPolicy;
 import org.apache.felix.framework.searchpolicy.R4Wire;
+import org.apache.felix.framework.util.Util;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceReference;
 
@@ -31,7 +31,7 @@
         m_registration = reg;
         m_bundle = bundle;
     }
-
+    
     protected ServiceRegistrationImpl getServiceRegistration()
     {
         return m_registration;
@@ -117,11 +117,12 @@
         boolean allow = true;
         // Get the package.
         String pkgName =
-            org.apache.felix.moduleloader.Util.getClassPackage(className);
-        // Get package wiring from service provider and requester.
-        R4Wire requesterWire = R4SearchPolicy.getWire(
+            Util.getClassPackage(className);
+        // Get package wiring from service requester.
+        R4Wire requesterWire = Util.getWire(
             ((BundleImpl) requester).getInfo().getCurrentModule(), pkgName);
-        R4Wire providerWire = R4SearchPolicy.getWire(
+        // Get package wiring from service provider.
+        R4Wire providerWire = Util.getWire(
             ((BundleImpl) m_bundle).getInfo().getCurrentModule(), pkgName);
 
         // There are three situations that may occur here:
@@ -151,8 +152,8 @@
             {
                 // Load the class from the requesting bundle.
                 Class requestClass =
-                    ((BundleImpl) requester).getInfo().getCurrentModule().getClassLoader()
-                        .loadClass(className);
+                    ((BundleImpl) requester).getInfo().getCurrentModule().getContentLoader()
+                        .getClass(className);
                 // Get the service registration and ask it to check
                 // if the service object is assignable to the requesting
                 // bundle's class.
@@ -168,7 +169,7 @@
         // same source module.
         else
         {
-            allow = providerWire.m_module.equals(requesterWire.m_module);
+            allow = providerWire.getExportingModule().equals(requesterWire.getExportingModule());
         }
 
         return allow;
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
index 5f52889..f8a15a0 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
@@ -174,7 +174,7 @@
             catch (Exception ex)
             {
                 m_registry.getLogger().log(
-                    LogWrapper.LOG_ERROR, "ServiceRegistrationImpl: Error getting service.", ex);
+                    Logger.LOG_ERROR, "ServiceRegistrationImpl: Error getting service.", ex);
                 return null;
             }
         }
@@ -205,7 +205,7 @@
             catch (Exception ex)
             {
                 m_registry.getLogger().log(
-                    LogWrapper.LOG_ERROR, "ServiceRegistrationImpl: Error ungetting service.", ex);
+                    Logger.LOG_ERROR, "ServiceRegistrationImpl: Error ungetting service.", ex);
             }
         }
     }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
index ccf3d40..f65e9be 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
@@ -23,7 +23,7 @@
 
 public class ServiceRegistry
 {
-    private LogWrapper m_logger = null;
+    private Logger m_logger = null;
     private long m_currentServiceId = 1L;
     // Maps bundle to an array of service registrations.
     private Map m_serviceRegsMap = new HashMap();
@@ -32,7 +32,7 @@
 
     private ServiceListener m_serviceListener = null;
 
-    public ServiceRegistry(LogWrapper logger)
+    public ServiceRegistry(Logger logger)
     {
         m_logger = logger;
     }
@@ -337,7 +337,7 @@
         fireServiceChanged(new ServiceEvent(ServiceEvent.MODIFIED, reg.getReference()));
     }
 
-    public LogWrapper getLogger()
+    public Logger getLogger()
     {
         return m_logger;
     }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundle.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundle.java
index 8718142..b089de8 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundle.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundle.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -24,19 +24,16 @@
 import org.apache.felix.framework.searchpolicy.*;
 import org.apache.felix.framework.util.FelixConstants;
 import org.apache.felix.framework.util.StringMap;
-import org.apache.felix.moduleloader.LibrarySource;
-import org.apache.felix.moduleloader.ResourceSource;
+import org.apache.felix.moduleloader.IContentLoader;
 import org.osgi.framework.*;
 
-
 class SystemBundle extends BundleImpl
 {
     private List m_activatorList = null;
     private BundleActivator m_activator = null;
     private Thread m_shutdownThread = null;
-    private Object[][] m_attributes = null;
-    private ResourceSource[] m_resSources = null;
-    private LibrarySource[] m_libSources = null;
+    private R4Export[] m_exports = null;
+    private IContentLoader m_contentLoader = null;
 
     protected SystemBundle(Felix felix, BundleInfo info, List activatorList)
         throws BundleException
@@ -74,62 +71,59 @@
         }
         catch (Exception ex)
         {
+            classPathPkgs = new R4Package[0];
             getFelix().getLogger().log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "Error parsing system bundle export statement.", ex);
         }
 
         // Now, create the list of standard framework exports for
         // the system bundle.
-        R4Package[] exports = new R4Package[classPathPkgs.length + 4];
+        m_exports = new R4Export[classPathPkgs.length + 4];
 
-        exports[0] = new R4Package(
+        m_exports[0] = new R4Export(
             "org.osgi.framework",
             new R4Directive[0],
             new R4Attribute[] { new R4Attribute("version", "1.3.0", false) });
 
-        exports[1] = new R4Package(
+        m_exports[1] = new R4Export(
             "org.osgi.service.packageadmin",
             new R4Directive[0],
             new R4Attribute[] { new R4Attribute("version", "1.2.0", false) });
 
-        exports[2] = new R4Package(
+        m_exports[2] = new R4Export(
                 "org.osgi.service.startlevel",
                 new R4Directive[0],
                 new R4Attribute[] { new R4Attribute("version", "1.0.0", false) });
 
-        exports[3] = new R4Package(
+        m_exports[3] = new R4Export(
                 "org.osgi.service.url",
                 new R4Directive[0],
                 new R4Attribute[] { new R4Attribute("version", "1.0.0", false) });
 
         // Copy the class path exported packages.
-        System.arraycopy(classPathPkgs, 0, exports, 4, classPathPkgs.length);
+        for (int i = 0; i < classPathPkgs.length; i++)
+        {
+            m_exports[i + 4] = new R4Export(classPathPkgs[i]);
+        }
 
-        m_attributes = new Object[][] {
-            new Object[] { R4SearchPolicy.EXPORTS_ATTR, exports },
-            new Object[] { R4SearchPolicy.IMPORTS_ATTR, new R4Package[0] }
-        };
-
-        m_resSources = new ResourceSource[0];
-
-        m_libSources = null;
+        m_contentLoader = new SystemBundleContentLoader(getFelix().getLogger());
 
         String exportString = "";
-        for (int i = 0; i < exports.length; i++)
+        for (int i = 0; i < m_exports.length; i++)
         {
             exportString = exportString +
-            exports[i].getId()
+            m_exports[i].getName()
             + "; specification-version=\""
-            + exports[i].getVersionLow().toString() + "\"";
+            + m_exports[i].getVersion().toString() + "\"";
 
-            if (i < (exports.length - 1))
+            if (i < (m_exports.length - 1))
             {
                 exportString = exportString + ", ";
                 exportString = exportString +
-                    exports[i].getId()
+                    m_exports[i].getName()
                     + "; specification-version=\""
-                    + exports[i].getVersionLow().toString() + "\", ";
+                    + m_exports[i].getVersion().toString() + "\", ";
             }
         }
 
@@ -143,19 +137,14 @@
         ((SystemBundleArchive) getInfo().getArchive()).setManifestHeader(map);
     }
 
-    public Object[][] getAttributes()
+    public R4Export[] getExports()
     {
-        return m_attributes;
+        return m_exports;
     }
 
-    public ResourceSource[] getResourceSources()
+    public IContentLoader getContentLoader()
     {
-        return m_resSources;
-    }
-
-    public LibrarySource[] getLibrarySources()
-    {
-        return m_libSources;
+        return m_contentLoader;
     }
 
     public synchronized void start() throws BundleException
@@ -173,7 +162,6 @@
             getInfo().setContext(new BundleContextImpl(getFelix(), this));
             getActivator().start(getInfo().getContext());
         } catch (Throwable throwable) {
-throwable.printStackTrace();
             throw new BundleException(
                 "Unable to start system bundle.", throwable);
         }
@@ -205,7 +193,7 @@
                     catch (Exception ex)
                     {
                         getFelix().getLogger().log(
-                            LogWrapper.LOG_ERROR,
+                            Logger.LOG_ERROR,
                             "SystemBundle: Error while shutting down.", ex);
                     }
 
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundleArchive.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundleArchive.java
index 8e70fd3..0547655 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundleArchive.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundleArchive.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@
 
 import org.apache.felix.framework.cache.BundleArchive;
 import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.moduleloader.IContent;
+import org.apache.felix.moduleloader.IContentLoader;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 
@@ -67,7 +69,7 @@
         return null;
     }
 
-    public BundleActivator getActivator(ClassLoader loader)
+    public BundleActivator getActivator(IContentLoader contentLoader)
         throws Exception
     {
         return null;
@@ -95,7 +97,13 @@
         m_headerMap = headerMap;
     }
 
-    public String[] getClassPath(int revision)
+    public IContent getContent(int revision)
+        throws Exception
+    {
+        return null;
+    }
+
+    public IContent[] getContentPath(int revision)
         throws Exception
     {
         return null;
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundleContentLoader.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundleContentLoader.java
new file mode 100644
index 0000000..aa20c2f
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/SystemBundleContentLoader.java
@@ -0,0 +1,102 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.io.InputStream;
+import java.net.URL;
+
+import org.apache.felix.moduleloader.*;
+
+public class SystemBundleContentLoader implements IContentLoader
+{
+    private Logger m_logger = null;
+    private ISearchPolicy m_searchPolicy = null;
+    private IURLPolicy m_urlPolicy = null;
+
+    public SystemBundleContentLoader(Logger logger)
+    {
+        m_logger = logger;
+    }
+
+    public void open()
+    {
+        // Nothing needed here.
+    }
+
+    public void close()
+    {
+        // Nothing needed here.
+    }
+
+    public IContent getContent()
+    {
+        return null;
+    }
+
+    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)
+    {
+        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 InputStream getResourceAsStream(String name) throws IOException
+    {
+        return getClass().getClassLoader().getResourceAsStream(name);
+    }
+
+    public String findLibrary(String name)
+    {
+        // No native libs associated with the system bundle.
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlers.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlers.java
index e7536ee..4fcb8e0 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlers.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlers.java
@@ -19,8 +19,8 @@
 import java.net.*;
 import java.util.*;
 
+import org.apache.felix.framework.searchpolicy.ContentClassLoader;
 import org.apache.felix.framework.util.*;
-import org.apache.felix.moduleloader.ModuleClassLoader;
 import org.osgi.framework.BundleContext;
 
 /**
@@ -345,7 +345,7 @@
                 Class targetClass = null;
                 for (int i = 0; i < stack.length; i++)
                 {
-                    if (stack[i].getClassLoader() instanceof ModuleClassLoader)
+                    if (stack[i].getClassLoader() instanceof ContentClassLoader)
                     {
                         targetClass = stack[i];
                         break;
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
index 551373e..9c5b05e 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@
 import java.net.URLConnection;
 import java.security.Permission;
 
+import org.apache.felix.framework.util.Util;
+
 class URLHandlersBundleURLConnection extends URLConnection
 {
     private Felix m_framework;
@@ -54,8 +56,18 @@
                 throw new IOException("Unable to find framework instance from context.");
             }
 
-            m_is = m_framework.getBundleResourceInputStream(url);
-            m_contentLength = m_is.available();
+            // The URL is constructed like this:
+            //     bundle://<module-id>/<resource-path>
+            // Where <module-id> = <bundle-id>.<revision>
+            long bundleId = Util.getBundleIdFromModuleId(url.getHost());
+            BundleImpl bundle = (BundleImpl) m_framework.getBundle(bundleId);
+            if (bundle == null)
+            {
+                throw new IOException("Unable to find bundle.");
+            }
+            int revision = Util.getModuleRevisionFromModuleId(url.getHost());
+            m_is = bundle.getInfo().getModules()[revision].getContentLoader().getResourceAsStream(url.getPath());
+            m_contentLength = (m_is == null) ? 0 : m_is.available();
             m_contentTime = 0L;
             m_contentType = URLConnection.guessContentTypeFromName(url.getFile());
             connected = true;
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java
index 85dc382..b0f6aec 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/BundleArchive.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@
 import java.io.File;
 import java.util.Map;
 
+import org.apache.felix.moduleloader.IContent;
+import org.apache.felix.moduleloader.IContentLoader;
 import org.osgi.framework.BundleActivator;
 
 /**
@@ -117,7 +119,7 @@
      *         this archive.
      * @throws java.lang.Exception if any error occurs.
     **/
-    public BundleActivator getActivator(ClassLoader loader)
+    public BundleActivator getActivator(IContentLoader contentLoader)
         throws Exception;
 
     /**
@@ -162,19 +164,27 @@
 
     /**
      * <p>
-     * Returns an array of <tt>String</tt>s that represent the class path of
-     * the specified revision of the bundle associated with this archive.
-     * Currently, these values are restricted to absolute paths in the file
-     * system, but this may be lifted in the future (perhaps they should be
-     * <tt>ResourceSource</tt>s from the Module Loader.
+     * Returns a content object that is associated with the specified bundle
+     * revision's JAR file.
      * </p>
      * @param revision the specified revision.
-     * @return a <tt>String</tt> array of the absolute path names that
-     *         comprise the class path of the specified revision of the
-     *         bundle associated with this archive.
+     * @return A content object for the specified bundle revision's JAR file.
      * @throws java.lang.Exception if any error occurs.
     **/
-    public String[] getClassPath(int revision)
+    public IContent getContent(int revision)
+        throws Exception;
+
+    /**
+     * <p>
+     * Returns an array of content objects that are associated with the
+     * specified bundle revision's class path.
+     * </p>
+     * @param revision the specified revision.
+     * @return An array of content objects for the specified bundle revision's
+     *         class path.
+     * @throws java.lang.Exception if any error occurs.
+    **/
+    public IContent[] getContentPath(int revision)
         throws Exception;
 
     /**
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/BundleCache.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/BundleCache.java
index 33b4a35..a1ddc76 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/BundleCache.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/BundleCache.java
@@ -18,7 +18,7 @@
 
 import java.io.InputStream;
 
-import org.apache.felix.framework.LogWrapper;
+import org.apache.felix.framework.Logger;
 import org.apache.felix.framework.util.PropertyResolver;
 
 /**
@@ -58,7 +58,7 @@
      * @param logger the logger to use for reporting errors.
      * @throws Exception if any error occurs.
     **/
-    public void initialize(PropertyResolver cfg, LogWrapper logger)
+    public void initialize(PropertyResolver cfg, Logger logger)
         throws Exception;
 
     /**
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/DefaultBundleArchive.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/DefaultBundleArchive.java
index d449099..101f067 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/DefaultBundleArchive.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/DefaultBundleArchive.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -23,8 +23,10 @@
 import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 
-import org.apache.felix.framework.LogWrapper;
+import org.apache.felix.framework.Logger;
 import org.apache.felix.framework.util.*;
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.moduleloader.*;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 
@@ -53,7 +55,7 @@
     private static final transient String INSTALLED_STATE = "installed";
     private static final transient String UNINSTALLED_STATE = "uninstalled";
 
-    private LogWrapper m_logger = null;
+    private Logger m_logger = null;
     private long m_id = -1;
     private File m_dir = null;
     private String m_location = null;
@@ -64,7 +66,8 @@
     private long m_refreshCount = -1;
     private int m_revisionCount = -1;
 
-    public DefaultBundleArchive(LogWrapper logger, File dir, long id, String location, InputStream is)    
+    public DefaultBundleArchive(
+        Logger logger, File dir, long id, String location, InputStream is)    
         throws Exception
     {
         this(logger, dir, id);
@@ -80,14 +83,14 @@
             if (!deleteDirectoryTree(dir))
             {
                 m_logger.log(
-                    LogWrapper.LOG_ERROR,
+                    Logger.LOG_ERROR,
                     "Unable to delete the archive directory: " + id);
             }
             throw ex;
         }
     }
 
-    public DefaultBundleArchive(LogWrapper logger, File dir, long id)
+    public DefaultBundleArchive(Logger logger, File dir, long id)
     {
         m_logger = logger;
         m_dir = dir;
@@ -133,7 +136,7 @@
             if (!m_dir.mkdir())
             {
                 m_logger.log(
-                    LogWrapper.LOG_ERROR,
+                    Logger.LOG_ERROR,
                     "DefaultBundleArchive: Unable to create archive directory.");
                 throw new IOException("Unable to create archive directory.");
             }
@@ -152,7 +155,7 @@
             if (!revisionDir.mkdir())
             {
                 m_logger.log(
-                    LogWrapper.LOG_ERROR,
+                    Logger.LOG_ERROR,
                     "DefaultBundleArchive: Unable to create revision directory.");
                 throw new IOException("Unable to create revision directory.");
             }
@@ -354,7 +357,7 @@
         catch (IOException ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "DefaultBundleArchive: Unable to record state: " + ex);
             throw ex;
         }
@@ -463,7 +466,7 @@
         catch (IOException ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "DefaultBundleArchive: Unable to record start leel: " + ex);
             throw ex;
         }
@@ -521,7 +524,7 @@
         }
     }
 
-    public BundleActivator getActivator(ClassLoader loader)
+    public BundleActivator getActivator(IContentLoader contentLoader)
         throws Exception
     {
         if (System.getSecurityManager() != null)
@@ -530,7 +533,7 @@
             {
                 return (BundleActivator) AccessController.doPrivileged(
                     new PrivilegedAction(
-                        PrivilegedAction.GET_ACTIVATOR_ACTION, this, loader));
+                        PrivilegedAction.GET_ACTIVATOR_ACTION, this, contentLoader));
             }
             catch (PrivilegedActionException ex)
             {
@@ -539,11 +542,11 @@
         }
         else
         {
-            return getActivatorUnchecked(loader);
+            return getActivatorUnchecked(contentLoader);
         }
     }
 
-    private BundleActivator getActivatorUnchecked(ClassLoader loader)
+    private BundleActivator getActivatorUnchecked(IContentLoader contentLoader)
         throws Exception
     {
         // Get bundle activator file.
@@ -559,14 +562,14 @@
         try
         {
             is = new FileInputStream(activatorFile);
-            ois = new ObjectInputStreamX(is, loader);
+            ois = new ObjectInputStreamX(is, contentLoader);
             Object o = ois.readObject();
             return (BundleActivator) o;
         }
         catch (Exception ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "DefaultBundleArchive: Trying to deserialize - " + ex);
         }
         finally
@@ -623,7 +626,7 @@
         catch (IOException ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "DefaultBundleArchive: Unable to serialize activator - " + ex);
             throw ex;
         }
@@ -741,16 +744,28 @@
         return new JarFile(bundleJar);
     }
 
-    public String[] getClassPath(int revision)
+    private IContent getContentUnchecked(int revision)
         throws Exception
     {
+        // Get the revision directory.
+        File revisionDir = new File(
+            m_dir, REVISION_DIRECTORY + getRefreshCount() + "." + revision);
+        // Return a content object for the bundle itself.
+        return new JarContent(new File(revisionDir, BUNDLE_JAR_FILE));
+    }
+
+    public IContent getContent(int revision)
+        throws Exception
+    {
+        IContent content = null;
+    
         if (System.getSecurityManager() != null)
         {
             try
             {
-                return (String []) AccessController.doPrivileged(
+                content = (IContent) AccessController.doPrivileged(
                     new PrivilegedAction(
-                        PrivilegedAction.GET_CLASS_PATH_ACTION, this, revision));
+                        PrivilegedAction.GET_CONTENT_ACTION, this, revision));
             }
             catch (PrivilegedActionException ex)
             {
@@ -759,16 +774,24 @@
         }
         else
         {
-            return getClassPathUnchecked(revision);
+            content = getContentUnchecked(revision);
         }
+    
+        return content;
     }
 
-    private String[] getClassPathUnchecked(int revision)
+    private IContent[] getContentPathUnchecked(int revision)
         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.
+
         // Get the revision directory.
         File revisionDir = new File(
             m_dir, REVISION_DIRECTORY + getRefreshCount() + "." + revision);
+        File embedDir = new File(revisionDir, EMBEDDED_DIRECTORY);
 
         // Get the bundle's manifest header.
         Map map = getManifestHeader(revision);
@@ -778,75 +801,79 @@
         }
 
         // Find class path meta-data.
-        String classPath = null;
+        String classPathString = null;
         Iterator iter = map.entrySet().iterator();
-        while ((classPath == null) && iter.hasNext())
+        while ((classPathString == null) && iter.hasNext())
         {
             Map.Entry entry = (Map.Entry) iter.next();
             if (entry.getKey().toString().toLowerCase().equals(
                 FelixConstants.BUNDLE_CLASSPATH.toLowerCase()))
             {
-                classPath = entry.getValue().toString();
+                classPathString = entry.getValue().toString();
             }
         }
 
         // Parse the class path into strings.
         String[] classPathStrings = Util.parseDelimitedString(
-            classPath, FelixConstants.CLASS_PATH_SEPARATOR);
+            classPathString, FelixConstants.CLASS_PATH_SEPARATOR);
 
         if (classPathStrings == null)
         {
             classPathStrings = new String[0];
         }
 
-        // Now, check for "." in the class path.
-        boolean includeDot = false;
-        for (int i = 0; !includeDot && (i < classPathStrings.length); i++)
+        // Create the bundles class path.
+        IContent self = new JarContent(new File(revisionDir, BUNDLE_JAR_FILE));
+        IContent[] classPath = new IContent[classPathStrings.length];
+        for (int i = 0; i < classPathStrings.length; i++)
         {
             if (classPathStrings[i].equals(FelixConstants.CLASS_PATH_DOT))
             {
-                includeDot = true;
+                classPath[i] = self;
             }
-        }
-
-        // Include all JARs in the embedded jar directory, since they
-        // were extracted when the bundle was initially saved.
-        File embedDir = new File(revisionDir, EMBEDDED_DIRECTORY);
-        String[] paths = null;
-        if (embedDir.exists())
-        {
-            // The size of the paths array is the number of
-            // embedded JAR files plus one, if we need to include
-            // ".", otherwise it is just the number of JAR files.
-            // If "." is included, then it will be added to the
-            // first place in the path array below.
-            File[] children = embedDir.listFiles();
-            int size = (children == null) ? 0 : children.length;
-            size = (includeDot) ? size + 1 : size;
-            paths = new String[size];
-            for (int i = 0; i < children.length; i++)
+            else
             {
-                // If we are including "." then skip the first slot,
-                // because this is where we will put the bundle JAR file.
-                paths[(includeDot) ? i + 1 : i] = children[i].getPath();
+                String jarName = (classPathStrings[i].lastIndexOf('/') >= 0)
+                    ? classPathStrings[i].substring(classPathStrings[i].lastIndexOf('/') + 1)
+                    : classPathStrings[i];
+                classPath[i] = new JarContent(new File(embedDir, jarName));
             }
         }
 
         // If there is nothing on the class path, then include
         // "." by default, as per the spec.
-        if ((paths == null) || (paths.length == 0))
+        if (classPath.length == 0)
         {
-            includeDot = true;
-            paths = new String[1];
+            classPath = new IContent[] { self };
         }
 
-        // Put the bundle jar file first, if included.
-        if (includeDot)
+        return classPath;
+    }
+
+    public IContent[] getContentPath(int revision)
+        throws Exception
+    {
+        IContent[] contents = null;
+
+        if (System.getSecurityManager() != null)
         {
-            paths[0] = revisionDir + File.separator + BUNDLE_JAR_FILE;
+            try
+            {
+                contents = (IContent[]) AccessController.doPrivileged(
+                    new PrivilegedAction(
+                        PrivilegedAction.GET_CONTENT_PATH_ACTION, this, revision));
+            }
+            catch (PrivilegedActionException ex)
+            {
+                throw ((PrivilegedActionException) ex).getException();
+            }
+        }
+        else
+        {
+            contents = getContentPathUnchecked(revision);
         }
 
-        return paths;
+        return contents;
     }
 
 //  TODO: This will need to consider security.
@@ -999,7 +1026,7 @@
         catch (IOException ex)
         {
             m_logger.log(
-                LogWrapper.LOG_ERROR,
+                Logger.LOG_ERROR,
                 "DefaultBundleArchive: Unable to write counter: " + ex);
             throw ex;
         }
@@ -1159,6 +1186,8 @@
         // Remove leading slash if present.
         jarPath = (jarPath.charAt(0) == '/') ? jarPath.substring(1) : jarPath;
         // Get only the JAR file name.
+// TODO: FIX THIS SO THAT IT CREATES DIRECTORIES TO AVOID NAME CLASHES,
+// DOING SO WILL IMPACT getContentLoaderUnchecked() METHOD ABOVE.
         String jarName = (jarPath.lastIndexOf('/') >= 0)
             ? jarPath.substring(jarPath.lastIndexOf('/') + 1) : jarPath;
 
@@ -1254,7 +1283,7 @@
                 {
                     // There is very little we can do here.
                     m_logger.log(
-                        LogWrapper.LOG_ERROR,
+                        Logger.LOG_ERROR,
                         "Unable to remove partial revision directory.", ex2);
                 }
             }
@@ -1368,16 +1397,17 @@
         private static final int SET_START_LEVEL_ACTION = 9;
         private static final int OPEN_BUNDLE_JAR_ACTION = 10;
         private static final int CREATE_DATA_DIR_ACTION = 11;
-        private static final int GET_CLASS_PATH_ACTION = 12;
-        private static final int GET_ACTIVATOR_ACTION = 13;
-        private static final int SET_ACTIVATOR_ACTION = 14;
+        private static final int GET_CONTENT_ACTION = 12;
+        private static final int GET_CONTENT_PATH_ACTION = 13;
+        private static final int GET_ACTIVATOR_ACTION = 14;
+        private static final int SET_ACTIVATOR_ACTION = 15;
 
         private int m_action = 0;
         private DefaultBundleArchive m_archive = null;
         private InputStream m_isArg = null;
         private int m_intArg = 0;
         private File m_fileArg = null;
-        private ClassLoader m_loaderArg = null;
+        private IContentLoader m_contentLoaderArg = null;
         private Object m_objArg = null;
 
         public PrivilegedAction(int action, DefaultBundleArchive archive)
@@ -1407,11 +1437,11 @@
             m_fileArg = fileArg;
         }
 
-        public PrivilegedAction(int action, DefaultBundleArchive archive, ClassLoader loaderArg)
+        public PrivilegedAction(int action, DefaultBundleArchive archive, IContentLoader contentLoaderArg)
         {
             m_action = action;
             m_archive = archive;
-            m_loaderArg = loaderArg;
+            m_contentLoaderArg = contentLoaderArg;
         }
 
         public PrivilegedAction(int action, DefaultBundleArchive archive, Object objArg)
@@ -1456,10 +1486,12 @@
                 case CREATE_DATA_DIR_ACTION:
                     m_archive.createDataDirectoryUnchecked(m_fileArg);
                     return null;
-                case GET_CLASS_PATH_ACTION:
-                    return m_archive.getClassPathUnchecked(m_intArg);
+                case GET_CONTENT_ACTION:
+                    return m_archive.getContentUnchecked(m_intArg);
+                case GET_CONTENT_PATH_ACTION:
+                    return m_archive.getContentPathUnchecked(m_intArg);
                 case GET_ACTIVATOR_ACTION:
-                    return m_archive.getActivatorUnchecked(m_loaderArg);
+                    return m_archive.getActivatorUnchecked(m_contentLoaderArg);
                 case SET_ACTIVATOR_ACTION:
                     m_archive.setActivatorUnchecked(m_objArg);
                     return null;
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/DefaultBundleCache.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/DefaultBundleCache.java
index c1568a6..eb0499d 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/DefaultBundleCache.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/cache/DefaultBundleCache.java
@@ -18,7 +18,7 @@
 
 import java.io.*;
 
-import org.apache.felix.framework.LogWrapper;
+import org.apache.felix.framework.Logger;
 import org.apache.felix.framework.util.PropertyResolver;
 
 /**
@@ -77,7 +77,7 @@
     protected static transient final String BUNDLE_DIR_PREFIX = "bundle";
 
     private PropertyResolver m_cfg = null;
-    private LogWrapper m_logger = null;
+    private Logger m_logger = null;
     private File m_profileDir = null;
     private BundleArchive[] m_archives = null;
 
@@ -85,7 +85,7 @@
     {
     }
 
-    public void initialize(PropertyResolver cfg, LogWrapper logger) throws Exception
+    public void initialize(PropertyResolver cfg, Logger logger) throws Exception
     {
         // Save Properties reference.
         m_cfg = cfg;
@@ -154,7 +154,7 @@
             if (!m_profileDir.mkdirs())
             {
                 m_logger.log(
-                    LogWrapper.LOG_ERROR,
+                    Logger.LOG_ERROR,
                     "Unable to create directory: " + m_profileDir);
                 throw new RuntimeException("Unable to create profile directory.");
             }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java
new file mode 100644
index 0000000..8c73300
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java
@@ -0,0 +1,249 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.security.CodeSource;
+import java.security.SecureClassLoader;
+import java.security.cert.Certificate;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.moduleloader.IContentLoader;
+import org.apache.felix.moduleloader.ResourceNotFoundException;
+
+public class ContentClassLoader extends SecureClassLoader
+{
+    private ContentLoaderImpl m_contentLoader = null;
+
+    ContentClassLoader(ContentLoaderImpl contentLoader)
+    {
+        m_contentLoader = contentLoader;
+    }
+
+    public IContentLoader getContentLoader()
+    {
+        return m_contentLoader;
+    }
+
+    public 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);
+        }
+        resolveClass(clazz);
+        return clazz;
+    }
+
+    protected Class loadClass(String name, boolean resolve)
+        throws ClassNotFoundException
+    {
+        // Make sure the class was not already loaded.
+        Class 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
+    {
+        Class clazz = findLoadedClass(name);
+
+        // Search for class in module.
+        if (clazz == null)
+        {
+            String actual = name.replace('.', '/') + ".class";
+            byte[] bytes = null;
+
+            // Check the module class path.
+            for (int i = 0;
+                (bytes == null) &&
+                (i < m_contentLoader.getClassPath().length); i++)
+            {
+                bytes = m_contentLoader.getClassPath()[i].getEntry(actual);
+            }
+
+            if (bytes != 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);
+                        }
+                    }
+                }
+
+                // Get the code source URL for this class. For concurrency
+                // purposes, we are performing this call outside of the
+                // synchronized block below since we call out to application
+                // code, which might in turn need to call back into the
+                // module loader code. Because of this, it is better to
+                // not be holding any locks before making the call.
+                URL url = null;
+// TODO: FIX CODE SOURCE URL
+//                URL url = m_mgr.getURLPolicy().createCodeSourceURL(
+//                    m_mgr, m_module);
+
+                // If we have a valid code source URL, then use it to
+                // define the class for security purposes, otherwise
+                // define the class without a code source.
+                if (url != null)
+                {
+                    CodeSource cs = new CodeSource(url, (Certificate[]) null);
+                    clazz = defineClass(name, bytes, 0, bytes.length, cs);
+                }
+                else
+                {
+                    clazz = defineClass(name, bytes, 0, bytes.length);
+                }
+            }
+        }
+
+        if (clazz != null)
+        {
+            return clazz;
+        }
+
+        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)
+        {
+            m_contentLoader.getLogger().log(
+                Logger.LOG_WARNING,
+                ex.getMessage(),
+                ex);
+        }
+        return null;
+    }
+
+    protected URL findResource(String name)
+    {
+        URL url = null;
+
+        // Remove leading slash, if present.
+        if (name.startsWith("/"))
+        {
+            name = name.substring(1);
+        }
+
+        // Check the module class path.
+        for (int i = 0;
+            (url == null) &&
+            (i < m_contentLoader.getClassPath().length); i++)
+        {
+            if (m_contentLoader.getClassPath()[i].hasEntry(name))
+            {
+                url = m_contentLoader.getURLPolicy().createURL(i + "/" + name);
+            }
+        }
+
+        return url;
+    }
+
+    protected Enumeration findResources(String name)
+    {
+        Vector v = new Vector();
+
+        // Remove leading slash, if present.
+        if (name.startsWith("/"))
+        {
+            name = name.substring(1);
+        }
+
+        // Check the module class path.
+        for (int i = 0; i < m_contentLoader.getClassPath().length; i++)
+        {
+            if (m_contentLoader.getClassPath()[i].hasEntry(name))
+            {
+                v.addElement(m_contentLoader.getURLPolicy().createURL(i + "/" + name));
+            }
+        }
+
+        return v.elements();
+    }
+
+    protected String findLibrary(String name)
+    {
+        return m_contentLoader.getSearchPolicy().findLibrary(name);
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentLoaderImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentLoaderImpl.java
new file mode 100644
index 0000000..2abd263
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentLoaderImpl.java
@@ -0,0 +1,140 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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 org.apache.felix.framework.Logger;
+import org.apache.felix.moduleloader.*;
+
+public class ContentLoaderImpl implements IContentLoader
+{
+    private Logger m_logger = null;
+    private IContent m_content = null;
+    private IContent[] m_contentPath = null;
+    private ISearchPolicy m_searchPolicy = null;
+    private IURLPolicy m_urlPolicy = null;
+    private ContentClassLoader m_classLoader = null;
+
+    public ContentLoaderImpl(Logger logger, IContent content, IContent[] contentPath)
+    {
+        m_logger = logger;
+        m_content = content;
+        m_contentPath = contentPath;
+    }
+
+    public Logger getLogger()
+    {
+        return m_logger;
+    }
+
+    public void open()
+    {
+        m_content.open();
+        for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
+        {
+            m_contentPath[i].open();
+        }
+    }
+
+    public void close()
+    {
+        m_content.close();
+        for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
+        {
+            m_contentPath[i].close();
+        }
+    }
+
+    public IContent getContent()
+    {
+        return m_content;
+    }
+
+    public IContent[] getClassPath()
+    {
+        return m_contentPath;
+    }
+
+    public void setSearchPolicy(ISearchPolicy searchPolicy)
+    {
+        m_searchPolicy = searchPolicy;
+    }
+
+    public ISearchPolicy getSearchPolicy()
+    {
+        return m_searchPolicy;
+    }
+
+    public void setURLPolicy(IURLPolicy urlPolicy)
+    {
+        m_urlPolicy = urlPolicy;
+    }
+
+    public IURLPolicy getURLPolicy()
+    {
+        return m_urlPolicy;
+    }
+
+    public Class getClass(String name)
+    {
+        if (m_classLoader == null)
+        {
+            m_classLoader = new ContentClassLoader(this);
+        }
+
+        try
+        {
+            return m_classLoader.loadClassFromModule(name);
+        }
+        catch (ClassNotFoundException ex)
+        {
+            return null;
+        }
+    }
+
+    public URL getResource(String name)
+    {
+        if (m_classLoader == null)
+        {
+            m_classLoader = new ContentClassLoader(this);
+        }
+
+        return m_classLoader.getResourceFromModule(name);
+    }
+
+    public InputStream getResourceAsStream(String name)
+        throws IOException
+    {
+        if (name.startsWith("/"))
+        {
+            name = name.substring(1);
+        }
+        // The name is the path contructed like this:
+        // <class-path-index> / <relative-resource-path>
+        int idx = Integer.parseInt(name.substring(0, name.indexOf('/')));
+        name = name.substring(name.indexOf('/') + 1);
+        return m_contentPath[idx].getEntryAsStream(name);
+    }
+
+    public String toString()
+    {
+        return m_searchPolicy.toString();
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/IR4SearchPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/IR4SearchPolicy.java
new file mode 100644
index 0000000..0a36b98
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/IR4SearchPolicy.java
@@ -0,0 +1,55 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.ISearchPolicy;
+
+/**
+ * <p>
+ * This interface extends the search policy interface with specific
+ * methods related to implementing an R4 search policy. For the most
+ * part, this interface is really implementation specific and should
+ * not be used by any except the R4 search policy implementation or
+ * those that are very sure they know what they are doing. For example,
+ * just blindly calling the various setter methods will likely not
+ * provide the desired results.
+ * </p>
+**/
+public interface IR4SearchPolicy extends ISearchPolicy
+{
+    public R4Export[] getExports();
+    public void setExports(R4Export[] exports);
+
+    public R4Import[] getImports();
+    public void setImports(R4Import[] imports);
+
+    public R4Import[] getDynamicImports();
+    public void setDynamicImports(R4Import[] imports);
+
+    public R4Library[] getLibraries();
+    public void setLibraries(R4Library[] libraries);
+
+    public R4Wire[] getWires();
+    public void setWires(R4Wire[] wires);
+
+    public boolean isResolved();
+    public void setResolved(boolean resolved);
+    public void resolve() throws ResolveException;
+
+    public void addResolverListener(ResolveListener l);
+    public void removeResolverListener(ResolveListener l);
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Export.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Export.java
new file mode 100644
index 0000000..9378d9a
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Export.java
@@ -0,0 +1,301 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.*;
+
+import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.framework.util.Util;
+
+public class R4Export extends R4Package
+{
+    private String[] m_uses = null;
+    private String[][] m_includeFilter = null;
+    private String[][] m_excludeFilter = null;
+
+    public R4Export(R4Package pkg)
+    {
+        this(pkg.getName(), pkg.getDirectives(), pkg.getAttributes());
+    }
+
+    public R4Export(String name, R4Directive[] directives, R4Attribute[] attrs)
+    {
+        super(name, directives, attrs);
+
+        // Find all export directives: uses, mandatory, include, and exclude.
+        String mandatory = "", uses = "";
+        for (int i = 0; i < m_directives.length; i++)
+        {
+            if (m_directives[i].getName().equals(FelixConstants.USES_DIRECTIVE))
+            {
+                uses = m_directives[i].getValue();
+            }
+            else if (m_directives[i].getName().equals(FelixConstants.MANDATORY_DIRECTIVE))
+            {
+                mandatory = m_directives[i].getValue();
+            }
+            else if (m_directives[i].getName().equals(FelixConstants.INCLUDE_DIRECTIVE))
+            {
+                String[] ss = Util.parseDelimitedString(m_directives[i].getValue(), ",");
+                m_includeFilter = new String[ss.length][];
+                for (int filterIdx = 0; filterIdx < ss.length; filterIdx++)
+                {
+                    m_includeFilter[filterIdx] = parseSubstring(ss[filterIdx]);
+                }
+            }
+            else if (m_directives[i].getName().equals(FelixConstants.EXCLUDE_DIRECTIVE))
+            {
+                String[] ss = Util.parseDelimitedString(m_directives[i].getValue(), ",");
+                m_excludeFilter = new String[ss.length][];
+                for (int filterIdx = 0; filterIdx < ss.length; filterIdx++)
+                {
+                    m_excludeFilter[filterIdx] = parseSubstring(ss[filterIdx]);
+                }
+            }
+        }
+
+        // Parse these uses directive.
+        StringTokenizer tok = new StringTokenizer(uses, ",");
+        m_uses = new String[tok.countTokens()];
+        for (int i = 0; i < m_uses.length; i++)
+        {
+            m_uses[i] = tok.nextToken().trim();
+        }
+
+        // Parse mandatory directive and mark specified
+        // attributes as mandatory.
+        tok = new StringTokenizer(mandatory, ",");
+        while (tok.hasMoreTokens())
+        {
+            // Get attribute name.
+            String attrName = tok.nextToken().trim();
+            // Find attribute and mark it as mandatory.
+            boolean found = false;
+            for (int i = 0; (!found) && (i < m_attrs.length); i++)
+            {
+                if (m_attrs[i].getName().equals(attrName))
+                {
+                    m_attrs[i] = new R4Attribute(
+                        m_attrs[i].getName(),
+                        m_attrs[i].getValue(), true);
+                    found = true;
+                }
+            }
+            // If a specified mandatory attribute was not found,
+            // then error.
+            if (!found)
+            {
+                throw new IllegalArgumentException(
+                    "Mandatory attribute '" + attrName + "' does not exist.");
+            }
+        }
+
+        // Find and parse version attribute, if present.
+        String rangeStr = "0.0.0";
+        for (int i = 0; i < m_attrs.length; i++)
+        {
+            if (m_attrs[i].getName().equals(FelixConstants.VERSION_ATTRIBUTE) ||
+                m_attrs[i].getName().equals(FelixConstants.PACKAGE_SPECIFICATION_VERSION))
+            {
+                // Normalize version attribute name.
+                m_attrs[i] = new R4Attribute(
+                    FelixConstants.VERSION_ATTRIBUTE, m_attrs[i].getValue(),
+                    m_attrs[i].isMandatory());
+                rangeStr = m_attrs[i].getValue();
+                break;
+            }
+        }
+        
+        VersionRange range = VersionRange.parse(rangeStr);
+        // For now, ignore if we have a version range.
+        m_version = range.getLow();
+    }
+
+    public String[] getUses()
+    {
+        return m_uses;
+    }
+
+    public boolean isIncluded(String name)
+    {
+        if ((m_includeFilter == null) && (m_excludeFilter == null))
+        {
+            return true;
+        }
+
+        // Get the class name portion of the target class.
+        String className = Util.getClassName(name);
+
+        // If there are no include filters then all classes are included
+        // by default, otherwise try to find one match.
+        boolean included = (m_includeFilter == null);
+        for (int i = 0;
+            (!included) && (m_includeFilter != null) && (i < m_includeFilter.length);
+            i++)
+        {
+            included = checkSubstring(m_includeFilter[i], className);
+        }
+
+        // If there are no exclude filters then no classes are excluded
+        // by default, otherwise try to find one match.
+        boolean excluded = false;
+        for (int i = 0;
+            (!excluded) && (m_excludeFilter != null) && (i < m_excludeFilter.length);
+            i++)
+        {
+            excluded = checkSubstring(m_excludeFilter[i], className);
+        }
+        return included && !excluded;
+    }
+
+    //
+    // The following substring-related code was lifted and modified
+    // from the LDAP parser code.
+    //
+
+    private static String[] parseSubstring(String target)
+    {
+        List pieces = new ArrayList();
+        StringBuffer ss = new StringBuffer();
+        // int kind = SIMPLE; // assume until proven otherwise
+        boolean wasStar = false; // indicates last piece was a star
+        boolean leftstar = false; // track if the initial piece is a star
+        boolean rightstar = false; // track if the final piece is a star
+
+        int idx = 0;
+
+        // We assume (sub)strings can contain leading and trailing blanks
+loop:   for (;;)
+        {
+            if (idx >= target.length())
+            {
+                if (wasStar)
+                {
+                    // insert last piece as "" to handle trailing star
+                    rightstar = true;
+                }
+                else
+                {
+                    pieces.add(ss.toString());
+                    // accumulate the last piece
+                    // note that in the case of
+                    // (cn=); this might be
+                    // the string "" (!=null)
+                }
+                ss.setLength(0);
+                break loop;
+            }
+
+            char c = target.charAt(idx++);
+            if (c == '*')
+            {
+                if (wasStar)
+                {
+                    // encountered two successive stars;
+                    // I assume this is illegal
+                    throw new IllegalArgumentException("Invalid filter string: " + target);
+                }
+                if (ss.length() > 0)
+                {
+                    pieces.add(ss.toString()); // accumulate the pieces
+                    // between '*' occurrences
+                }
+                ss.setLength(0);
+                // if this is a leading star, then track it
+                if (pieces.size() == 0)
+                {
+                    leftstar = true;
+                }
+                ss.setLength(0);
+                wasStar = true;
+            }
+            else
+            {
+                wasStar = false;
+                ss.append(c);
+            }
+        }
+        if (leftstar || rightstar || pieces.size() > 1)
+        {
+            // insert leading and/or trailing "" to anchor ends
+            if (rightstar)
+            {
+                pieces.add("");
+            }
+            if (leftstar)
+            {
+                pieces.add(0, "");
+            }
+        }
+        return (String[]) pieces.toArray(new String[pieces.size()]);
+    }
+
+    private static boolean checkSubstring(String[] pieces, String s)
+    {
+        // Walk the pieces to match the string
+        // There are implicit stars between each piece,
+        // and the first and last pieces might be "" to anchor the match.
+        // assert (pieces.length > 1)
+        // minimal case is <string>*<string>
+
+        boolean result = false;
+        int len = pieces.length;
+
+loop:   for (int i = 0; i < len; i++)
+        {
+            String piece = (String) pieces[i];
+            int index = 0;
+            if (i == len - 1)
+            {
+                // this is the last piece
+                if (s.endsWith(piece))
+                {
+                    result = true;
+                }
+                else
+                {
+                    result = false;
+                }
+                break loop;
+            }
+            // initial non-star; assert index == 0
+            else if (i == 0)
+            {
+                if (!s.startsWith(piece))
+                {
+                    result = false;
+                    break loop;
+                }
+            }
+            // assert i > 0 && i < len-1
+            else
+            {
+                // Sure wish stringbuffer supported e.g. indexOf
+                index = s.indexOf(piece, index);
+                if (index < 0)
+                {
+                    result = false;
+                    break loop;
+                }
+            }
+            // start beyond the matching piece
+            index += piece.length();
+        }
+
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Import.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Import.java
new file mode 100644
index 0000000..6b56936
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Import.java
@@ -0,0 +1,183 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.framework.util.FelixConstants;
+import org.osgi.framework.Version;
+
+public class R4Import extends R4Package
+{
+    private VersionRange m_versionRange = null;
+    private boolean m_isOptional = false;
+
+    public R4Import(R4Package pkg)
+    {
+        this(pkg.getName(), pkg.getDirectives(), pkg.getAttributes());
+    }
+
+    public R4Import(String name, R4Directive[] directives, R4Attribute[] attrs)
+    {
+        super(name, directives, attrs);
+
+        // Find all import directives: resolution.
+        for (int i = 0; i < m_directives.length; i++)
+        {
+            if (m_directives[i].getName().equals(FelixConstants.RESOLUTION_DIRECTIVE))
+            {
+                m_isOptional = m_directives[i].getValue().equals(FelixConstants.RESOLUTION_OPTIONAL);
+            }
+        }
+
+        // Find and parse version attribute, if present.
+        String rangeStr = "0.0.0";
+        for (int i = 0; i < m_attrs.length; i++)
+        {
+            if (m_attrs[i].getName().equals(FelixConstants.VERSION_ATTRIBUTE) ||
+                m_attrs[i].getName().equals(FelixConstants.PACKAGE_SPECIFICATION_VERSION))
+            {
+                // Normalize version attribute name.
+                m_attrs[i] = new R4Attribute(
+                    FelixConstants.VERSION_ATTRIBUTE, m_attrs[i].getValue(),
+                    m_attrs[i].isMandatory());
+                rangeStr = m_attrs[i].getValue();
+                break;
+            }
+        }
+        
+        m_versionRange = VersionRange.parse(rangeStr);
+        m_version = m_versionRange.getLow();
+    }
+
+    public Version getVersionHigh()
+    {
+        return m_versionRange.getHigh();
+    }
+
+    public boolean isLowInclusive()
+    {
+        return m_versionRange.isLowInclusive();
+    }
+
+    public boolean isHighInclusive()
+    {
+        return m_versionRange.isHighInclusive();
+    }
+
+    public boolean isOptional()
+    {
+        return m_isOptional;
+    }
+
+    public boolean isSatisfied(R4Export export)
+    {
+        // For packages to be compatible, they must have the
+        // same name.
+        if (!getName().equals(export.getName()))
+        {
+            return false;
+        }
+        
+        return m_versionRange.isInRange(export.getVersion())
+            && doAttributesMatch(export);
+    }
+
+    private boolean doAttributesMatch(R4Export export)
+    {
+        // Cycle through all attributes of this import package
+        // and make sure its values match the attribute values
+        // of the specified export package.
+        for (int impAttrIdx = 0; impAttrIdx < getAttributes().length; impAttrIdx++)
+        {
+            // Get current attribute from this import package.
+            R4Attribute impAttr = getAttributes()[impAttrIdx];
+
+            // Ignore version attribute, since it is a special case that
+            // has already been compared using isVersionInRange() before
+            // the call to this method was made.
+            if (impAttr.getName().equals(FelixConstants.VERSION_ATTRIBUTE))
+            {
+                continue;
+            }
+
+            // Check if the export package has the same attribute.
+            boolean found = false;
+            for (int expAttrIdx = 0;
+                (!found) && (expAttrIdx < export.getAttributes().length);
+                expAttrIdx++)
+            {
+                // Get current attribute for the export package.
+                R4Attribute expAttr = export.getAttributes()[expAttrIdx];
+                // Check if the attribute names are equal.
+                if (impAttr.getName().equals(expAttr.getName()))
+                {
+                    // If the values are not equal, then return false immediately.
+                    // We should not compare version values here, since they are
+                    // a special case and have already been compared by a call to
+                    // isVersionInRange() before getting here; however, it is
+                    // possible for version to be mandatory, so make sure it is
+                    // present below.
+                    if (!impAttr.getValue().equals(expAttr.getValue()))
+                    {
+                        return false;
+                    }
+                    found = true;
+                }
+            }
+            // If the attribute was not found, then return false.
+            if (!found)
+            {
+                return false;
+            }
+        }
+
+        // Now, cycle through all attributes of the export package and verify that
+        // all mandatory attributes are present in this import package.
+        for (int expAttrIdx = 0; expAttrIdx < export.getAttributes().length; expAttrIdx++)
+        {
+            // Get current attribute for this package.
+            R4Attribute expAttr = export.getAttributes()[expAttrIdx];
+            
+            // If the export attribute is mandatory, then make sure
+            // this import package has the attribute.
+            if (expAttr.isMandatory())
+            {
+                boolean found = false;
+                for (int impAttrIdx = 0;
+                    (!found) && (impAttrIdx < getAttributes().length);
+                    impAttrIdx++)
+                {
+                    // Get current attribute from specified package.
+                    R4Attribute impAttr = getAttributes()[impAttrIdx];
+        
+                    // Check if the attribute names are equal
+                    // and set found flag.
+                    if (expAttr.getName().equals(impAttr.getName()))
+                    {
+                        found = true;
+                    }
+                }
+                // If not found, then return false.
+                if (!found)
+                {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/OSGiLibrarySource.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Library.java
similarity index 67%
rename from org.apache.felix.framework/src/main/java/org/apache/felix/framework/OSGiLibrarySource.java
rename to org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Library.java
index 4546d61..80bdada 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/OSGiLibrarySource.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Library.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -14,27 +14,25 @@
  *   limitations under the License.
  *
  */
-package org.apache.felix.framework;
+package org.apache.felix.framework.searchpolicy;
 
+import org.apache.felix.framework.Logger;
 import org.apache.felix.framework.cache.BundleCache;
-import org.apache.felix.framework.util.LibraryInfo;
-import org.apache.felix.moduleloader.LibrarySource;
 import org.osgi.framework.Constants;
 
-public class OSGiLibrarySource implements LibrarySource
+public class R4Library
 {
-    private LogWrapper m_logger = null;
-    private boolean m_opened = false;
+    private Logger m_logger = null;
     private BundleCache m_cache = null;
     private long m_bundleId = -1;
     private int m_revision = -1;
     private String m_os = null;
     private String m_processor = null;
-    private LibraryInfo[] m_libraries = null;
+    private R4LibraryHeader m_header = null;
 
-    public OSGiLibrarySource(
-        LogWrapper logger, BundleCache cache, long bundleId, int revision,
-        String os, String processor, LibraryInfo[] libraries)
+    public R4Library(
+        Logger logger, BundleCache cache, long bundleId, int revision,
+        String os, String processor, R4LibraryHeader header)
     {
         m_logger = logger;
         m_cache = cache;
@@ -42,51 +40,32 @@
         m_revision = revision;
         m_os = normalizePropertyValue(Constants.FRAMEWORK_OS_NAME, os);
         m_processor = normalizePropertyValue(Constants.FRAMEWORK_PROCESSOR, processor);
-        m_libraries = libraries;
+        m_header = header;
     }
 
-    public void open()
+    /**
+     * <p>
+     * Returns a file system path to the specified library.
+     * </p>
+     * @param name the name of the library that is being requested.
+     * @return a file system path to the specified library.
+    **/
+    public String getPath(String name)
     {
-        m_opened = true;
-    }
-
-    public void close()
-    {
-        m_opened = false;
-    }
-
-    public String getPath(String name) throws IllegalStateException
-    {
-        if (!m_opened)
-        {
-            throw new IllegalStateException("OSGiLibrarySource is not open");
-        }
-
-        if (m_libraries != null)
+        if (m_header != null)
         {
             String libname = System.mapLibraryName(name);
 
-            // Check to see if we have a matching library.
-            // TODO: This "matching" algorithm does not fully
-            // match the spec and should be improved.
-            LibraryInfo library = null;
-            for (int i = 0; (library == null) && (i < m_libraries.length); i++)
-            {
-                boolean osOkay = checkOS(m_libraries[i].getOSNames());
-                boolean procOkay = checkProcessor(m_libraries[i].getProcessors());
-                if (m_libraries[i].getName().endsWith(libname) && osOkay && procOkay)
-                {
-                    library = m_libraries[i];
-                }
-            }
-
-            if (library != null)
+            // Check to see if the library matches.
+            boolean osOkay = checkOS(m_header.getOSNames());
+            boolean procOkay = checkProcessor(m_header.getProcessors());
+            if (m_header.getName().endsWith(libname) && osOkay && procOkay)
             {
                 try {
                     return m_cache.getArchive(m_bundleId)
-                        .findLibrary(m_revision, library.getName());
+                        .findLibrary(m_revision, m_header.getName());
                 } catch (Exception ex) {
-                    m_logger.log(LogWrapper.LOG_ERROR, "OSGiLibrarySource: Error finding library.", ex);
+                    m_logger.log(Logger.LOG_ERROR, "R4Library: Error finding library.", ex);
                 }
             }
         }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/LibraryInfo.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4LibraryHeader.java
similarity index 89%
rename from org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/LibraryInfo.java
rename to org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4LibraryHeader.java
index b6171e9..28fde9b 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/LibraryInfo.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4LibraryHeader.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
  *   limitations under the License.
  *
  */
-package org.apache.felix.framework.util;
+package org.apache.felix.framework.searchpolicy;
 
 import java.util.*;
 
+import org.apache.felix.framework.Logger;
 import org.osgi.framework.Constants;
 
-public class LibraryInfo
+public class R4LibraryHeader
 {
     private String m_name = null;
     private String[] m_osnames = null;
@@ -28,7 +29,7 @@
     private String[] m_processors = null;
     private String[] m_languages = null;
 
-    public LibraryInfo(String name, String[] osnames, String[] osversions,
+    public R4LibraryHeader(String name, String[] osnames, String[] osversions,
         String[] processors, String[] languages)
     {
         m_name = name;
@@ -38,7 +39,7 @@
         m_languages = languages;
     }
 
-    public LibraryInfo(LibraryInfo library)
+    public R4LibraryHeader(R4LibraryHeader library)
     {
         m_name = library.m_name;
         m_osnames = library.m_osnames;
@@ -67,7 +68,7 @@
         return m_processors;
     }
 
-    public static LibraryInfo[] parse(String s)
+    public static R4LibraryHeader[] parse(Logger logger, String s)
     {
         try
         {
@@ -150,11 +151,11 @@
                 return null;
             }
 
-            LibraryInfo[] libraries = new LibraryInfo[libCount];
+            R4LibraryHeader[] libraries = new R4LibraryHeader[libCount];
             for (int i = 0; i < libCount; i++)
             {
                 libraries[i] =
-                    new LibraryInfo(
+                    new R4LibraryHeader(
                         libs[i],
                         (String[]) osNameList.toArray(new String[0]),
                         (String[]) osVersionList.toArray(new String[0]),
@@ -167,7 +168,10 @@
         }
         catch (RuntimeException ex)
         {
-            ex.printStackTrace();
+            logger.log(
+                Logger.LOG_ERROR,
+                "Error parsing native library header.",
+                ex);
             throw ex;
         }
     }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Package.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Package.java
index a46e17f..b826760 100755
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Package.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Package.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -16,140 +16,30 @@
  */
 package org.apache.felix.framework.searchpolicy;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.felix.framework.util.FelixConstants;
 import org.apache.felix.framework.util.Util;
+import org.osgi.framework.Version;
 
 public class R4Package
 {
-    private String m_id = "";
-    private R4Directive[] m_directives = null;
-    private R4Attribute[] m_attrs = null;
-    private R4Version m_versionLow = null;
-    private R4Version m_versionHigh = null;
-    private String[] m_uses = null;
-    private boolean m_isOptional = false;
-    private String[][] m_includeFilter = null;
-    private String[][] m_excludeFilter = null;
+    private String m_name = "";
+    protected R4Directive[] m_directives = null;
+    protected R4Attribute[] m_attrs = null;
+    protected Version m_version = null;
 
-    protected R4Package(R4Package pkg)
+    public R4Package(String name, R4Directive[] directives, R4Attribute[] attrs)
     {
-        m_id = pkg.m_id;
-        m_directives = pkg.m_directives;
-        m_attrs = pkg.m_attrs;
-        m_versionLow = pkg.m_versionLow;
-        m_versionHigh = pkg.m_versionHigh;
-        m_uses = pkg.m_uses;
-        m_isOptional = pkg.m_isOptional;
-        m_includeFilter = pkg.m_includeFilter;
-        m_excludeFilter = pkg.m_excludeFilter;
-    }
-
-    public R4Package(String id, R4Directive[] directives, R4Attribute[] attrs)
-    {
-        m_id = id;
+        m_name = name;
         m_directives = (directives == null) ? new R4Directive[0] : directives;
         m_attrs = (attrs == null) ? new R4Attribute[0] : attrs;
-
-        // Find all directives: uses, mandatory, resolution, include, and exclude.
-        String mandatory = "", uses = "";
-        for (int i = 0; i < m_directives.length; i++)
-        {
-            if (m_directives[i].getName().equals(FelixConstants.USES_DIRECTIVE))
-            {
-                uses = m_directives[i].getValue();
-            }
-            else if (m_directives[i].getName().equals(FelixConstants.MANDATORY_DIRECTIVE))
-            {
-                mandatory = m_directives[i].getValue();
-            }
-            else if (m_directives[i].getName().equals(FelixConstants.RESOLUTION_DIRECTIVE))
-            {
-                m_isOptional = m_directives[i].getValue().equals(FelixConstants.RESOLUTION_OPTIONAL);
-            }
-            else if (m_directives[i].getName().equals(FelixConstants.INCLUDE_DIRECTIVE))
-            {
-                String[] ss = Util.parseDelimitedString(m_directives[i].getValue(), ",");
-                m_includeFilter = new String[ss.length][];
-                for (int filterIdx = 0; filterIdx < ss.length; filterIdx++)
-                {
-                    m_includeFilter[filterIdx] = parseSubstring(ss[filterIdx]);
-                }
-            }
-            else if (m_directives[i].getName().equals(FelixConstants.EXCLUDE_DIRECTIVE))
-            {
-                String[] ss = Util.parseDelimitedString(m_directives[i].getValue(), ",");
-                m_excludeFilter = new String[ss.length][];
-                for (int filterIdx = 0; filterIdx < ss.length; filterIdx++)
-                {
-                    m_excludeFilter[filterIdx] = parseSubstring(ss[filterIdx]);
-                }
-            }
-        }
-
-        // Parse these uses directive.
-        StringTokenizer tok = new StringTokenizer(uses, ",");
-        m_uses = new String[tok.countTokens()];
-        for (int i = 0; i < m_uses.length; i++)
-        {
-            m_uses[i] = tok.nextToken().trim();
-        }
-
-        // Parse mandatory directive and mark specified
-        // attributes as mandatory.
-        tok = new StringTokenizer(mandatory, ",");
-        while (tok.hasMoreTokens())
-        {
-            // Get attribute name.
-            String attrName = tok.nextToken().trim();
-            // Find attribute and mark it as mandatory.
-            boolean found = false;
-            for (int i = 0; (!found) && (i < m_attrs.length); i++)
-            {
-                if (m_attrs[i].getName().equals(attrName))
-                {
-                    m_attrs[i] = new R4Attribute(
-                        m_attrs[i].getName(), m_attrs[i].getValue(), true);
-                    found = true;
-                }
-            }
-            // If a specified mandatory attribute was not found,
-            // then error.
-            if (!found)
-            {
-                throw new IllegalArgumentException(
-                    "Mandatory attribute '" + attrName + "' does not exist.");
-            }
-        }
-
-        // Find and parse version attribute, if present.
-        String versionInterval = "0.0.0";
-        for (int i = 0; i < m_attrs.length; i++)
-        {
-            if (m_attrs[i].getName().equals(FelixConstants.VERSION_ATTRIBUTE) ||
-                m_attrs[i].getName().equals(FelixConstants.PACKAGE_SPECIFICATION_VERSION))
-            {
-                // Normalize version attribute name.
-                m_attrs[i] = new R4Attribute(
-                    FelixConstants.VERSION_ATTRIBUTE, m_attrs[i].getValue(),
-                    m_attrs[i].isMandatory());
-                versionInterval = m_attrs[i].getValue();
-                break;
-            }
-        }
-        
-        R4Version[] versions = parseVersionInterval(versionInterval);
-        m_versionLow = versions[0];
-        if (versions.length == 2)
-        {
-            m_versionHigh = versions[1];
-        }
     }
 
-    public String getId()
+    public String getName()
     {
-        return m_id;
+        return m_name;
     }
 
     public R4Directive[] getDirectives()
@@ -162,185 +52,15 @@
         return m_attrs;
     }
 
-    public R4Version getVersionLow()
+    public Version getVersion()
     {
-        return m_versionLow;
+        return m_version;
     }
 
-    public R4Version getVersionHigh()
-    {
-        return m_versionHigh;
-    }
-
-    public String[] getUses()
-    {
-        return m_uses;
-    }
-
-    public boolean isOptional()
-    {
-        return m_isOptional;
-    }
-
-    public boolean isIncluded(String name)
-    {
-        if ((m_includeFilter == null) && (m_excludeFilter == null))
-        {
-            return true;
-        }
-
-        // Get the class name portion of the target class.
-        String className = org.apache.felix.moduleloader.Util.getClassName(name);
-
-        // If there are no include filters then all classes are included
-        // by default, otherwise try to find one match.
-        boolean included = (m_includeFilter == null);
-        for (int i = 0;
-            (!included) && (m_includeFilter != null) && (i < m_includeFilter.length);
-            i++)
-        {
-            included = checkSubstring(m_includeFilter[i], className);
-        }
-
-        // If there are no exclude filters then no classes are excluded
-        // by default, otherwise try to find one match.
-        boolean excluded = false;
-        for (int i = 0;
-            (!excluded) && (m_excludeFilter != null) && (i < m_excludeFilter.length);
-            i++)
-        {
-            excluded = checkSubstring(m_excludeFilter[i], className);
-        }
-        return included && !excluded;
-    }
-
-    // PREVIOUSLY PART OF COMPATIBILITY POLICY.
-    public boolean doesSatisfy(R4Package pkg)
-    {
-        // For packages to be compatible, they must have the
-        // same name.
-        if (!m_id.equals(pkg.m_id))
-        {
-            return false;
-        }
-        
-        return isVersionInRange(m_versionLow, pkg.m_versionLow, pkg.m_versionHigh)
-            && doAttributesMatch(pkg);
-    }
-
-    // PREVIOUSLY PART OF COMPATIBILITY POLICY.
-    public static boolean isVersionInRange(R4Version version, R4Version low, R4Version high)
-    {
-        // We might not have an upper end to the range.
-        if (high == null)
-        {
-            return (version.compareTo(low) >= 0);
-        }
-        else if (low.isInclusive() && high.isInclusive())
-        {
-            return (version.compareTo(low) >= 0) && (version.compareTo(high) <= 0);
-        }
-        else if (high.isInclusive())
-        {
-            return (version.compareTo(low) > 0) && (version.compareTo(high) <= 0);
-        }
-        else if (low.isInclusive())
-        {
-            return (version.compareTo(low) >= 0) && (version.compareTo(high) < 0);
-        }
-
-        return (version.compareTo(low) > 0) && (version.compareTo(high) < 0);
-    }
-
-    private boolean doAttributesMatch(R4Package pkg)
-    {
-        // Cycle through all attributes of the specified package
-        // and make sure their values match the attribute values
-        // of this package.
-        for (int attrIdx = 0; attrIdx < pkg.m_attrs.length; attrIdx++)
-        {
-            // Get current attribute from specified package.
-            R4Attribute attr = pkg.m_attrs[attrIdx];
-
-            // Ignore version attribute, since it is a special case that
-            // has already been compared using isVersionInRange() before
-            // the call to this method was made.
-            if (attr.getName().equals(FelixConstants.VERSION_ATTRIBUTE))
-            {
-                continue;
-            }
-
-            // Check if this package has the same attribute.
-            boolean found = false;
-            for (int thisAttrIdx = 0;
-                (!found) && (thisAttrIdx < m_attrs.length);
-                thisAttrIdx++)
-            {
-                // Get current attribute for this package.
-                R4Attribute thisAttr = m_attrs[thisAttrIdx];
-                // Check if the attribute names are equal.
-                if (attr.getName().equals(thisAttr.getName()))
-                {
-                    // If the values are not equal, then return false immediately.
-                    // We should not compare version values here, since they are
-                    // a special case and have already been compared by a call to
-                    // isVersionInRange() before getting here; however, it is
-                    // possible for version to be mandatory, so make sure it is
-                    // present below.
-                    if (!attr.getValue().equals(thisAttr.getValue()))
-                    {
-                        return false;
-                    }
-                    found = true;
-                }
-            }
-            // If the attribute was not found, then return false.
-            if (!found)
-            {
-                return false;
-            }
-        }
-
-        // Now, cycle through all attributes of this package and verify that
-        // all mandatory attributes are present in the speceified package.
-        for (int thisAttrIdx = 0; thisAttrIdx < m_attrs.length; thisAttrIdx++)
-        {
-            // Get current attribute for this package.
-            R4Attribute thisAttr = m_attrs[thisAttrIdx];
-            
-            // If the attribute is mandatory, then make sure
-            // the specified package has the attribute.
-            if (thisAttr.isMandatory())
-            {
-                boolean found = false;
-                for (int attrIdx = 0;
-                    (!found) && (attrIdx < pkg.m_attrs.length);
-                    attrIdx++)
-                {
-                    // Get current attribute from specified package.
-                    R4Attribute attr = pkg.m_attrs[attrIdx];
-        
-                    // Check if the attribute names are equal
-                    // and set found flag.
-                    if (thisAttr.getName().equals(attr.getName()))
-                    {
-                        found = true;
-                    }
-                }
-                // If not found, then return false.
-                if (!found)
-                {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
 
     public String toString()
     {
-        String msg = getId();
+        String msg = getName();
         for (int i = 0; (m_directives != null) && (i < m_directives.length); i++)
         {
             msg = msg + " [" + m_directives[i].getName() + ":="+ m_directives[i].getValue() + "]";
@@ -471,164 +191,8 @@
             }
         }
     
-        R4Package[] ips = (R4Package[])
+        R4Package[] pkgs = (R4Package[])
             completeList.toArray(new R4Package[completeList.size()]);
-        return ips;
-    }
-
-    public static R4Version[] parseVersionInterval(String interval)
-    {
-        // Check if the version is an interval.
-        if (interval.indexOf(',') >= 0)
-        {
-            String s = interval.substring(1, interval.length() - 1);
-            String vlo = s.substring(0, s.indexOf(','));
-            String vhi = s.substring(s.indexOf(',') + 1, s.length());
-            return new R4Version[] {
-                new R4Version(vlo, (interval.charAt(0) == '[')),
-                new R4Version(vhi, (interval.charAt(interval.length() - 1) == ']'))
-            };
-        }
-        else
-        {
-            return new R4Version[] { new R4Version(interval, true) };
-        }
-    }
-
-    //
-    // The following substring-related code was lifted and modified
-    // from the LDAP parser code.
-    //
-
-    private static String[] parseSubstring(String target)
-    {
-        List pieces = new ArrayList();
-        StringBuffer ss = new StringBuffer();
-        // int kind = SIMPLE; // assume until proven otherwise
-        boolean wasStar = false; // indicates last piece was a star
-        boolean leftstar = false; // track if the initial piece is a star
-        boolean rightstar = false; // track if the final piece is a star
-
-        int idx = 0;
-
-        // We assume (sub)strings can contain leading and trailing blanks
-loop:   for (;;)
-        {
-            if (idx >= target.length())
-            {
-                if (wasStar)
-                {
-                    // insert last piece as "" to handle trailing star
-                    rightstar = true;
-                }
-                else
-                {
-                    pieces.add(ss.toString());
-                    // accumulate the last piece
-                    // note that in the case of
-                    // (cn=); this might be
-                    // the string "" (!=null)
-                }
-                ss.setLength(0);
-                break loop;
-            }
-
-            char c = target.charAt(idx++);
-            if (c == '*')
-            {
-                if (wasStar)
-                {
-                    // encountered two successive stars;
-                    // I assume this is illegal
-                    throw new IllegalArgumentException("Invalid filter string: " + target);
-                }
-                if (ss.length() > 0)
-                {
-                    pieces.add(ss.toString()); // accumulate the pieces
-                    // between '*' occurrences
-                }
-                ss.setLength(0);
-                // if this is a leading star, then track it
-                if (pieces.size() == 0)
-                {
-                    leftstar = true;
-                }
-                ss.setLength(0);
-                wasStar = true;
-            }
-            else
-            {
-                wasStar = false;
-                ss.append(c);
-            }
-        }
-        if (leftstar || rightstar || pieces.size() > 1)
-        {
-            // insert leading and/or trailing "" to anchor ends
-            if (rightstar)
-            {
-                pieces.add("");
-            }
-            if (leftstar)
-            {
-                pieces.add(0, "");
-            }
-        }
-        return (String[]) pieces.toArray(new String[pieces.size()]);
-    }
-
-    private static boolean checkSubstring(String[] pieces, String s)
-    {
-        // Walk the pieces to match the string
-        // There are implicit stars between each piece,
-        // and the first and last pieces might be "" to anchor the match.
-        // assert (pieces.length > 1)
-        // minimal case is <string>*<string>
-
-        boolean result = false;
-        int len = pieces.length;
-
-loop:   for (int i = 0; i < len; i++)
-        {
-            String piece = (String) pieces[i];
-            int index = 0;
-            if (i == len - 1)
-            {
-                // this is the last piece
-                if (s.endsWith(piece))
-                {
-                    result = true;
-                }
-                else
-                {
-                    result = false;
-                }
-                break loop;
-            }
-            // initial non-star; assert index == 0
-            else if (i == 0)
-            {
-                if (!s.startsWith(piece))
-                {
-                    result = false;
-                    break loop;
-                }
-            }
-            // assert i > 0 && i < len-1
-            else
-            {
-                // Sure wish stringbuffer supported e.g. indexOf
-                index = s.indexOf(piece, index);
-                if (index < 0)
-                {
-                    result = false;
-                    break loop;
-                }
-            }
-            // start beyond the matching piece
-            index += piece.length();
-        }
-
-        return result;
+        return pkgs;
     }
 }
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicy.java
old mode 100755
new mode 100644
index 7c22675..ef6bfef
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicy.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicy.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -17,1619 +17,119 @@
 package org.apache.felix.framework.searchpolicy;
 
 import java.net.URL;
-import java.util.*;
 
-import org.apache.felix.framework.LogWrapper;
-import org.apache.felix.framework.util.SecurityManagerEx;
 import org.apache.felix.moduleloader.*;
-import org.apache.felix.moduleloader.search.ResolveException;
-import org.apache.felix.moduleloader.search.ResolveListener;
 
-public class R4SearchPolicy implements SearchPolicy, ModuleListener
+public class R4SearchPolicy implements IR4SearchPolicy
 {
-    // Array of R4Package.
-    public static final String EXPORTS_ATTR = "exports";
-    // Array of R4Package.
-    public static final String IMPORTS_ATTR = "imports";
-    // Array of R4Package.
-    public static final String DYNAMICIMPORTS_ATTR = "dynamicimports";
-    // Array of R4Wire.
-    public static final String WIRING_ATTR = "wiring";
-    // Boolean.
-    public static final String RESOLVED_ATTR = "resolved";
+    private R4SearchPolicyCore m_policyCore = null;
+    private IModule m_module = null;
 
-    private LogWrapper m_logger = null;
-    private ModuleManager m_mgr = null;
-    private Map m_availPkgMap = new HashMap();
-    private Map m_inUsePkgMap = new HashMap();
-
-    // Listener-related instance variables.
-    private static final ResolveListener[] m_emptyListeners = new ResolveListener[0];
-    private ResolveListener[] m_listeners = m_emptyListeners;
-
-    // Reusable empty arrays.
-    public static final Module[] m_emptyModules = new Module[0];
-    public static final R4Package[] m_emptyPackages = new R4Package[0];
-    public static final R4Wire[] m_emptyWires = new R4Wire[0];
-
-    // Re-usable security manager for accessing class context.
-    private static SecurityManagerEx m_sm = new SecurityManagerEx();
-
-    public R4SearchPolicy(LogWrapper logger)
+    public R4SearchPolicy(R4SearchPolicyCore policyCore, IModule module)
     {
-        m_logger = logger;
+        m_policyCore = policyCore;
+        m_module = module;
     }
 
-    public void setModuleManager(ModuleManager mgr)
-        throws IllegalStateException
+    public Object[] definePackage(String name)
     {
-        if (m_mgr == null)
-        {
-            m_mgr = mgr;
-            m_mgr.addModuleListener(this);
-        }
-        else
-        {
-            throw new IllegalStateException("Module manager is already initialized");
-        }
+        return m_policyCore.definePackage(m_module, name);
     }
 
-    public Object[] definePackage(Module module, String pkgName)
-    {
-        R4Package pkg = R4SearchPolicy.getExportPackage(module, pkgName);
-        if (pkg != null)
-        {
-            return new Object[]  {
-                pkgName, // Spec title.
-                pkg.getVersionLow().toString(), // Spec version.
-                "", // Spec vendor.
-                "", // Impl title.
-                "", // Impl version.
-                ""  // Impl vendor.
-            };
-        }
-        return null;
-    }
-
-    public Class findClassBeforeModule(ClassLoader parent, Module module, String name)
+    public Class findClass(String name)
         throws ClassNotFoundException
     {
-        // First, try to resolve the originating module.
-        try
-        {
-            resolve(module);
-        }
-        catch (ResolveException ex)
-        {
-            // 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.getPackage() + ".");
-        }
-
-        // Get the package of the target class.
-        String pkgName = Util.getClassPackage(name);
-
-        // Load all "java.*" classes from parent class loader;
-        // these packages cannot be provided by other bundles.
-        if (pkgName.startsWith("java."))
-        {
-            return (parent == null) ? null : parent.loadClass(name);
-        }
-
-        // We delegate to the module's wires to find the class.
-        R4Wire[] wires = getWiringAttr(module);
-        for (int i = 0; i < wires.length; i++)
-        {
-            // Only check when the package of the class is
-            // the same as the import package.
-            if (wires[i].m_pkg.getId().equals(pkgName))
-            {
-                // Before delegating to the module class loader to satisfy
-                // the class load, we must check the include/exclude filters
-                // from the target package to make sure that the class is
-                // actually visible. If the exporting module is the same as
-                // the requesting module, then filtering is not performed
-                // since a module has complete access to itself.
-// TODO: Determine if it is possible to modify Module Loader somehow
-// so that this check is done within the target module itself; it
-// doesn't totally make sense to do this check in the importing module.
-                if (wires[i].m_module != module)
-                {
-                    if (!wires[i].m_pkg.isIncluded(name))
-                    {
-                        throw new ClassNotFoundException(name);
-                    }
-                }
-
-                // Since the class is included, delegate to the exporting module.
-                try
-                {
-                    Class clazz = wires[i].m_module.getClassLoader().loadClassFromModule(name);
-                    if (clazz != null)
-                    {
-                        return clazz;
-                    }
-                }
-                catch (Throwable th)
-                {
-                    // Not much we can do here.
-                }
-                throw new ClassNotFoundException(name);
-            }
-        }
-
-        return null;
+        return m_policyCore.findClass(m_module, name);
     }
 
-    public Class findClassAfterModule(ClassLoader parent, Module module, String name)
-        throws ClassNotFoundException
-    {
-        // At this point, the module's imports were searched and so was the
-        // the module's own resources. Now we make an attempt to load the
-        // class via a dynamic import, if possible.
-        String pkgName = Util.getClassPackage(name);
-        Module candidate = attemptDynamicImport(module, pkgName);
-        // If the dynamic import was successful, then this initial
-        // time we must directly return the result from dynamically
-        // selected candidate's class loader, but for subsequent
-        // requests for classes in the associated package will be
-        // processed as part of normal static imports.
-        if (candidate != null)
-        {
-            return candidate.getClassLoader().loadClass(name);
-        }
-
-        // At this point, the class could not be found by the bundle's static
-        // or dynamic imports, nor its own resources. Before we throw
-        // an exception, we will try to determine if the instigator of the
-        // class 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 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 class load 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 a class not found exception.
-
-        // Get the class context to see the classes on the stack.
-        Class[] classes = m_sm.getClassContext();
-        // Start from 1 to skip inner class.
-        for (int i = 1; i < classes.length; i++)
-        {
-            // Find the first class on the call stack that is neither
-            // a class loader or Class itself, because we want to ignore
-            // the calls to ClassLoader.loadClass() and Class.forName().
-            if (!ClassLoader.class.isAssignableFrom(classes[i]) &&
-                !Class.class.isAssignableFrom(classes[i]))
-            {
-                // If the instigating class was not from a bundle, then
-                // delegate to the parent class loader. Otherwise, break
-                // out of loop and throw an exception.
-                if (!ModuleClassLoader.class.isInstance(classes[i].getClassLoader()))
-                {
-                    return parent.loadClass(name);
-                }
-                break;
-            }
-        }
-        
-        throw new ClassNotFoundException(name);
-    }
-
-    public URL findResource(ClassLoader parent, Module module, String name)
+    public URL findResource(String name)
         throws ResourceNotFoundException
     {
-        // First, try to resolve the originating module.
-        try
-        {
-            resolve(module);
-        }
-        catch (ResolveException ex)
-        {
-            return null;
-        }
-
-        // Get the package of the target resource.
-        String pkgName = Util.getResourcePackage(name);
-
-        // Load all "java.*" resources from parent class loader;
-        // these packages cannot be provided by other bundles.
-        if (pkgName.startsWith("java."))
-        {
-            return (parent == null) ? null : parent.getResource(name);
-        }
-
-        // We delegate to the module's wires to find the resource.
-        R4Wire[] wires = getWiringAttr(module);
-        for (int i = 0; i < wires.length; i++)
-        {
-            // Only check when the package of the resource is
-            // the same as the import package.
-            if (wires[i].m_pkg.getId().equals(pkgName))
-            {
-                try
-                {
-                    URL url = wires[i].m_module.getClassLoader().getResourceFromModule(name);
-                    if (url != null)
-                    {
-                        return url;
-                    }
-                }
-                catch (Throwable th)
-                {
-                    // Not much we can do here.
-                }
-                throw new ResourceNotFoundException(name);
-            }
-        }
-
-        // Check dynamic imports.
-// TODO: Dynamic imports should be searched after local sources.
-        Module candidate = attemptDynamicImport(module, pkgName);
-        // This initial time we must directly return the result from
-        // the candidate's class loaders, but since the candidate was
-        // added to the module's wiring attribute, subsequent class
-        // loads from the same package will be handled in the normal
-        // fashion for statically imported packaes.
-        return (candidate == null)
-            ? null : candidate.getClassLoader().getResource(name);
+        return m_policyCore.findResource(m_module, name);
     }
 
-    private Module attemptDynamicImport(Module module, String pkgName)
+    public String findLibrary(String name)
     {
-        Module candidate = null;
-
-        // There is an overriding assumption here that a package is
-        // never split across bundles. If a package can be split
-        // across bundles, then this will fail.
-
-        try
-        {
-            // Check the dynamic import specs for a match of
-            // the target package.
-            R4Package[] dynamics = getDynamicImportsAttr(module);
-            R4Package pkgMatch = null;
-            for (int i = 0; (pkgMatch == null) && (i < dynamics.length); i++)
-            {
-                // Star matches everything.
-                if (dynamics[i].getId().equals("*"))
-                {
-                    // Create a package instance without wildcard.
-                    pkgMatch = new R4Package(
-                        pkgName,
-                        dynamics[i].getDirectives(),
-                        dynamics[i].getAttributes());
-                }
-                // Packages ending in ".*" must match starting strings.
-                else if (dynamics[i].getId().endsWith(".*"))
-                {
-                    if (pkgName.regionMatches(
-                        0, dynamics[i].getId(), 0, dynamics[i].getId().length() - 2))
-                    {
-                        // Create a package instance without wildcard.
-                        pkgMatch = new R4Package(
-                            pkgName,
-                            dynamics[i].getDirectives(),
-                            dynamics[i].getAttributes());
-                    }
-                }
-                // Or we can have a precise match.
-                else
-                {
-                    if (pkgName.equals(dynamics[i].getId()))
-                    {
-                        pkgMatch = dynamics[i];
-                    }
-                }
-            }
-
-            // If the target package does not match any dynamically imported
-            // packages or if the module is already wired for the target package,
-            // then just return null. The module may be already wired to the target
-            // package if the class being searched for does not actually exist.
-            if ((pkgMatch == null) || (getWire(module, pkgMatch.getId()) != null))
-            {
-                return null;
-            }
-
-            // At this point, the target package has matched a dynamically
-            // imported package spec. Now we must try to find a candidate
-            // exporter for target package and add it to the module's set
-            // of wires.
-
-            // Lock module manager instance to ensure that nothing changes.
-            synchronized (m_mgr)
-            {
-                // Try to add a new entry to the module's import attribute.
-                // Select the first candidate that successfully resolves.
-
-                // First check already resolved exports for a match.
-                Module[] candidates = getCompatibleExporters(
-                    (Module[]) m_inUsePkgMap.get(pkgMatch.getId()), pkgMatch);
-                // If there is an "in use" candidate, just take the first one.
-                if (candidates.length > 0)
-                {
-                    candidate = candidates[0];
-                }
-
-                // If there were no "in use" candidates, then try "available"
-                // candidates.
-                if (candidate == null)
-                {
-                    candidates = getCompatibleExporters(
-                        (Module[]) m_availPkgMap.get(pkgMatch.getId()), pkgMatch);
-                    for (int candIdx = 0;
-                        (candidate == null) && (candIdx < candidates.length);
-                        candIdx++)
-                    {
-                        try
-                        {
-                            resolve(module);
-                            candidate = candidates[candIdx];
-                        }
-                        catch (ResolveException ex)
-                        {
-                        }
-                    }
-                }
-
-                // If we found a candidate, then add it to the module's
-                // wiring attribute.
-                if (candidate != null)
-                {
-                    R4Wire[] wires = getWiringAttr(module);
-                    R4Wire[] newWires = new R4Wire[wires.length + 1];
-                    System.arraycopy(wires, 0, newWires, 0, wires.length);
-                    // Find the candidate's export package object and
-                    // use that for creating the wire; this is necessary
-                    // since it contains "uses" dependency information.
-                    newWires[wires.length] = new R4Wire(
-                        getExportPackage(candidate, pkgMatch.getId()), candidate);
-                    module.setAttribute(WIRING_ATTR, newWires);
-m_logger.log(LogWrapper.LOG_DEBUG, "WIRE: [" + module + "] " + newWires[wires.length]);
-                }
-            }
-        }
-        catch (Exception ex)
-        {
-            m_logger.log(LogWrapper.LOG_ERROR, "Unable to dynamically import package.", ex);
-        }
-
-        return candidate;
+        return m_policyCore.findLibrary(m_module, name);
     }
 
-    public Module[] getAvailableExporters(R4Package pkg)
+    public R4Export[] getExports()
     {
-        // Synchronized on the module manager to make sure that no
-        // modules are added, removed, or resolved.
-        synchronized (m_mgr)
-        {
-            return getCompatibleExporters((Module[]) m_availPkgMap.get(pkg.getId()), pkg);
-        }
+        return m_policyCore.getExports(m_module);
     }
 
-    public Module[] getInUseExporters(R4Package pkg)
+    public void setExports(R4Export[] exports)
     {
-        // Synchronized on the module manager to make sure that no
-        // modules are added, removed, or resolved.
-        synchronized (m_mgr)
-        {
-            return getCompatibleExporters((Module[]) m_inUsePkgMap.get(pkg.getId()), pkg);
-        }
+        m_policyCore.setExports(m_module, exports);
     }
 
-    public void resolve(Module rootModule)
-        throws ResolveException
+    public R4Import[] getImports()
     {
-        // If the module is already resolved, then we can just return.
-        if (getResolvedAttr(rootModule).booleanValue())
-        {
-            return;
-        }
-
-        // This variable maps an unresolved module to a list of resolver
-        // nodes, where there is one resolver node for each import that
-        // must be resolved. A resolver node contains the potential
-        // candidates to resolve the import and the current selected
-        // candidate index.
-        Map resolverMap = new HashMap();
-
-        // This map will be used to hold the final wires for all
-        // resolved modules, which can then be used to fire resolved
-        // events outside of the synchronized block.
-        Map resolvedModuleWireMap = null;
-    
-        // Synchronize on the module manager, because we don't want
-        // any modules being added or removed while we are in the
-        // middle of this operation.
-        synchronized (m_mgr)
-        {
-            // The first step is to populate the resolver map. This
-            // will use the target module to populate the resolver map
-            // with all potential modules that need to be resolved as a
-            // result of resolving the target module. The key of the
-            // map is a potential module to be resolved and the value is
-            // a list of resolver nodes, one for each of the module's
-            // imports, where each resolver node contains the potential
-            // candidates for resolving the import. Not all modules in
-            // this map will be resolved, only the target module and
-            // any candidates selected to resolve its imports and the
-            // transitive imports this implies.
-            populateResolverMap(resolverMap, rootModule);
-
-//dumpResolverMap();
-
-            // The next step is to use the resolver map to determine if
-            // the class space for the root module is consistent. This
-            // is an iterative process that transitively walks the "uses"
-            // relationships of all currently selected potential candidates
-            // for resolving import packages checking for conflicts. If a
-            // conflict is found, it "increments" the configuration of
-            // currently selected potential candidates and tests them again.
-            // If this method returns, then it has found a consistent set
-            // of candidates; otherwise, a resolve exception is thrown if
-            // it exhausts all possible combinations and could not find a
-            // consistent class space.
-            findConsistentClassSpace(resolverMap, rootModule);
-
-            // The final step is to create the wires for the root module and
-            // transitively all modules that are to be resolved from the
-            // selected candidates for resolving the root module's imports.
-            // When this call returns, each module's wiring and resolved
-            // attributes are set. The resulting wiring map is used below
-            // to fire resolved events outside of the synchronized block.
-            // The resolved module wire map maps a module to its array of
-            // wires.
-            resolvedModuleWireMap = createWires(resolverMap, rootModule);
-            
-//dumpAvailablePackages();
-//dumpUsedPackages();
-
-        } // End of synchronized block on module manager.
-
-        // Fire resolved events for all resolved modules;
-        // the resolved modules array will only be set if the resolve
-        // was successful after the root module was resolved.
-        if (resolvedModuleWireMap != null)
-        {
-            Iterator iter = resolvedModuleWireMap.entrySet().iterator();
-            while (iter.hasNext())
-            {
-                fireModuleResolved((Module) ((Map.Entry) iter.next()).getKey());
-            }
-        }
+        return m_policyCore.getImports(m_module);
     }
 
-    private void populateResolverMap(Map resolverMap, Module module)
-        throws ResolveException
+    public void setImports(R4Import[] imports)
     {
-        // Detect cycles.
-        if (resolverMap.get(module) != null)
-        {
-            return;
-        }
-
-        // Map to hold the bundle's import packages
-        // and their respective resolving candidates.
-        List nodeList = new ArrayList();
-
-        // Even though the node list is currently emptry, we
-        // record it in the resolver map early so we can use
-        // it to detect cycles.
-        resolverMap.put(module, nodeList);
-
-        // Loop through each import and calculate its resolving
-        // set of candidates.
-        R4Package[] imports = getImportsAttr(module);
-        for (int impIdx = 0; impIdx < imports.length; impIdx++)
-        {
-            // Get the candidates from the "in use" and "available"
-            // package maps. Candidates "in use" have higher priority
-            // than "available" ones, so put the "in use" candidates
-            // at the front of the list of candidates.
-            Module[] inuse = getCompatibleExporters(
-                (Module[]) m_inUsePkgMap.get(
-                    imports[impIdx].getId()), imports[impIdx]);
-            Module[] available = getCompatibleExporters(
-                (Module[]) m_availPkgMap.get(
-                    imports[impIdx].getId()), imports[impIdx]);
-            Module[] candidates = new Module[inuse.length + available.length];
-            System.arraycopy(inuse, 0, candidates, 0, inuse.length);
-            System.arraycopy(available, 0, candidates, inuse.length, available.length);
-
-            // If we have candidates, then we need to recursively populate
-            // the resolver map with each of them.
-            ResolveException rethrow = null;
-            if (candidates.length > 0)
-            {
-                for (int candIdx = 0; candIdx < candidates.length; candIdx++)
-                {
-                    try
-                    {
-                        // Only populate the resolver map with modules that
-                        // are not already resolved.
-                        if (!getResolvedAttr(candidates[candIdx]).booleanValue())
-                        {
-                            populateResolverMap(resolverMap, candidates[candIdx]);
-                        }
-                    }
-                    catch (ResolveException ex)
-                    {
-                        // If we received a resolve exception, then the
-                        // current candidate is not resolvable for some
-                        // reason and should be removed from the list of
-                        // candidates. For now, just null it.
-                        candidates[candIdx] = null;
-                        rethrow = ex;
-                    }
-                }
-
-                // Remove any nulled candidates to create the final list
-                // of available candidates.
-                candidates = shrinkModuleArray(candidates);
-            }
-
-            // If no candidates exist at this point, then throw a
-            // resolve exception unless the import is optional.
-            if ((candidates.length == 0) && !imports[impIdx].isOptional())
-            {
-                // If we have received an exception while trying to populate
-                // the resolver map, rethrow that exception since it might
-                // be useful. NOTE: This is not necessarily the "only"
-                // correct exception, since it is possible that multiple
-                // candidates were not resolvable, but it is better than
-                // nothing.
-                if (rethrow != null)
-                {
-                    throw rethrow;
-                }
-                else
-                {
-                    throw new ResolveException(
-                        "Unable to resolve.", module, imports[impIdx]);
-                }
-            }
-            else if (candidates.length > 0)
-            {
-                nodeList.add(
-                    new ResolverNode(module, imports[impIdx], candidates));
-            }
-        }
+        m_policyCore.setImports(m_module, imports);
     }
 
-    /**
-     * <p>
-     * This method searches the resolver solution space for a consistent
-     * set of modules to resolve all transitive imports that must be resolved
-     * as a result of resolving the root module. A consistent set of modules
-     * is one where the "uses" relationships of the exported packages for
-     * the selected provider modules do not conflict with each other. A
-     * conflict can occur when the constraints on two or more modules result
-     * in multiple providers for the same package in the same class space.
-     * </p>
-     * @param resolverMap a map containing all potential modules that may need
-     *        to be resolved and the candidates to resolve them.
-     * @param rootModule the module that is the root of the resolve operation.
-     * @throws ResolveException if no consistent set of candidates can be
-     *         found to resolve the root module.
-    **/
-    private void findConsistentClassSpace(Map resolverMap, Module rootModule)
-        throws ResolveException
+    public R4Import[] getDynamicImports()
     {
-        List resolverList = null;
-
-        // Test the current set of candidates to determine if they
-        // are consistent. Keep looping until we find a consistent
-        // set or an exception is thrown.
-        Map cycleMap = new HashMap();
-        while (!isClassSpaceConsistent(resolverMap, rootModule, cycleMap))
-        {
-m_logger.log(
-    LogWrapper.LOG_DEBUG,
-    "Constraint violation detected, will try to repair.");
-
-            // The incrementCandidateConfiguration() method requires a
-            // ordered access to the resolver map, so we will create
-            // a reusable list once right here.
-            if (resolverList == null)
-            {
-                resolverList = new ArrayList();
-                for (Iterator iter = resolverMap.entrySet().iterator();
-                    iter.hasNext(); )
-                {
-                    resolverList.add((List) ((Map.Entry) iter.next()).getValue());
-                }
-            }
-
-            // Increment the candidate configuration so we can test again.
-            incrementCandidateConfiguration(resolverList);
-
-            // Clear the cycle map.
-            cycleMap.clear();
-        }
+        return m_policyCore.getDynamicImports(m_module);
     }
 
-    private boolean isClassSpaceConsistent(
-        Map resolverMap, Module rootModule, Map cycleMap)
+    public void setDynamicImports(R4Import[] imports)
     {
-        // We do not need to verify that already resolved modules
-        // have consistent class spaces because they should be
-        // consistent by definition. Also, if the root module is
-        // part of a cycle, then just assume it is true.
-        if (getResolvedAttr(rootModule).booleanValue() ||
-            (cycleMap.get(rootModule) != null))
-        {
-            return true;
-        }
-
-        // Add to cycle map for future reference.
-        cycleMap.put(rootModule, rootModule);
-
-        // Create an implicit "uses" constraint for every exported package
-        // of the root module that is not also imported; uses constraints
-        // for exported packages that are also imported will be taken
-        // care of as part of normal import package processing.
-        R4Package[] exports = (R4Package[]) getExportsAttr(rootModule);
-        Map usesMap = new HashMap();
-        for (int i = 0; i < exports.length; i++)
-        {
-            // Ignore exports that are also imported, since they
-            // will be taken care of when verifying import constraints.
-            if (getImportPackage(rootModule, exports[i].getId()) == null)
-            {
-                usesMap.put(exports[i].getId(), rootModule);
-            }
-        }
-
-        // Loop through the current candidates for the module's imports
-        // (available in the resolver node list of the resolver map) and
-        // calculate the uses constraints for each of the currently
-        // selected candidates for resolving the imports. Compare each
-        // candidate's constraints to the existing constraints to check
-        // for conflicts.
-        List nodeList = (List) resolverMap.get(rootModule);
-        for (int nodeIdx = 0; nodeIdx < nodeList.size(); nodeIdx++)
-        {
-            // Verify that the current candidate does not violate
-            // any "uses" constraints of existing candidates by
-            // calculating the candidate's transitive "uses" constraints
-            // for the provided package and testing whether they
-            // overlap with existing constraints.
-
-            // First, get the resolver node.
-            ResolverNode node = (ResolverNode) nodeList.get(nodeIdx);
-
-            // Verify that the current candidate itself has a consistent
-            // class space.
-            if (!isClassSpaceConsistent(
-                resolverMap, node.m_candidates[node.m_idx], cycleMap))
-            {
-                return false;
-            }
-
-            // Get the exported package from the current candidate that
-            // will be used to resolve the root module's import.
-            R4Package candidatePkg = getExportPackage(
-                node.m_candidates[node.m_idx], node.m_pkg.getId());
-
-            // Calculate the "uses" dependencies implied by the candidate's
-            // exported package with respect to the currently selected
-            // candidates in the resolver map.
-            Map candUsesMap = calculateUsesDependencies(
-                resolverMap,
-                node.m_candidates[node.m_idx],
-                candidatePkg,
-                new HashMap());
-//System.out.println("MODULE " + rootModule + " USES    " + usesMap);
-//System.out.println("CANDIDATE " + node.m_candidates[node.m_idx] + " USES " + candUsesMap);
-
-            // Iterate through the root module's current set of transitive
-            // "uses" constraints and compare them with the candidate's
-            // transitive set of constraints.
-            Iterator usesIter = candUsesMap.entrySet().iterator();
-            while (usesIter.hasNext())
-            {
-                // If the candidate's uses constraints overlap with
-                // the existing uses constraints, but refer to a
-                // different provider, then the class space is not
-                // consistent; thus, return false.
-                Map.Entry entry = (Map.Entry) usesIter.next();
-                if ((usesMap.get(entry.getKey()) != null) &&
-                    (usesMap.get(entry.getKey()) != entry.getValue()))
-                {
-                    return false;
-                }
-            }
-
-            // Since the current candidate's uses constraints did not
-            // conflict with existing constraints, merge all constraints
-            // and keep testing the remaining candidates for the other
-            // imports of the root module.
-            usesMap.putAll(candUsesMap);
-        }
-
-        return true;
+        m_policyCore.setDynamicImports(m_module, imports);
     }
 
-    private Map calculateUsesDependencies(
-        Map resolverMap, Module module, R4Package exportPkg, Map usesMap)
+    public R4Library[] getLibraries()
     {
-// TODO: CAN THIS BE OPTIMIZED?
-// TODO: IS THIS CYCLE CHECK CORRECT??
-// TODO: WHAT HAPPENS THERE ARE OVERLAPS WHEN CALCULATING USES??
-//       MAKE AN EXAMPLE WHERE TWO DEPENDENCIES PROVIDE SAME PACKAGE.
-        // Make sure we are not in a cycle.
-        if (usesMap.get(exportPkg.getId()) != null)
-        {
-            return usesMap;
-        }
-
-        // The target package at least uses itself,
-        // so add it to the uses map.
-        usesMap.put(exportPkg.getId(), module);
-
-        // Get the "uses" constraints for the target export
-        // package and calculate the transitive uses constraints
-        // of any used packages.
-        String[] uses = exportPkg.getUses();
-        List nodeList = (List) resolverMap.get(module);
-
-        // We need to walk the transitive closure of "uses" relationships
-        // for the current export package to calculate the entire set of
-        // "uses" constraints.
-        for (int usesIdx = 0; usesIdx < uses.length; usesIdx++)
-        {
-            // There are two possibilities at this point: 1) we are dealing
-            // with an already resolved bundle or 2) we are dealing with a
-            // bundle that has not yet been resolved. In case 1, there will
-            // be no resolver node in the resolver map, so we just need to
-            // examine the bundle directly to determine its exact constraints.
-            // In case 2, there will be a resolver node in the resolver map,
-            // so we will use that to determine the potential constraints of
-            // potential candidate for resolving the import.
-
-            // This is case 1, described in the comment above.
-            if (nodeList == null)
-            {
-                // Get the actual exporter from the wire or if there
-                // is no wire, then get the export is from the module
-                // itself.
-                R4Wire wire = getWire(module, uses[usesIdx]);
-                if (wire != null)
-                {
-                    usesMap = calculateUsesDependencies(
-                        resolverMap, wire.m_module, wire.m_pkg, usesMap);
-                }
-                else
-                {
-                    exportPkg = getExportPackage(module, uses[usesIdx]);
-                    if (exportPkg != null)
-                    {
-                        usesMap = calculateUsesDependencies(
-                            resolverMap, module, exportPkg, usesMap);
-                    }
-                }
-            }
-            // This is case 2, described in the comment above.
-            else
-            {
-                // First, get the resolver node for the "used" package.
-                ResolverNode node = null;
-                for (int nodeIdx = 0;
-                    (node == null) && (nodeIdx < nodeList.size());
-                    nodeIdx++)
-                {
-                    node = (ResolverNode) nodeList.get(nodeIdx);
-                    if (!node.m_pkg.getId().equals(uses[usesIdx]))
-                    {
-                        node = null;
-                    }
-                }
-    
-                // If there is a resolver node for the "used" package,
-                // then this means that the module imports the package
-                // and we need to recursively add the constraints of
-                // the potential exporting module.
-                if (node != null)
-                {
-                    usesMap = calculateUsesDependencies(
-                        resolverMap,
-                        node.m_candidates[node.m_idx],
-                        getExportPackage(node.m_candidates[node.m_idx], node.m_pkg.getId()),
-                        usesMap);
-                }
-                // If there was no resolver node for the "used" package,
-                // then this means that the module exports the package
-                // and we need to recursively add the constraints of this
-                // other exported package of this module.
-                else if (getExportPackage(module, uses[usesIdx]) != null)
-                {
-                    usesMap = calculateUsesDependencies(
-                        resolverMap,
-                        module,
-                        getExportPackage(module, uses[usesIdx]),
-                        usesMap);
-                }
-            }
-        }
-
-        return usesMap;
+        return m_policyCore.getLibraries(m_module);
     }
 
-    /**
-     * <p>
-     * This method <i>increments</i> the current candidate configuration
-     * in the specified resolver list, which contains resolver node lists
-     * for all of the candidates for all of the imports that need to be
-     * resolved. This method performs its function by treating the current
-     * candidate index variable in each resolver node as part of a big
-     * counter. In other words, it increments the least significant index.
-     * If the index overflows it sets it back to zero and carries the
-     * overflow to the next significant index and so on. Using this approach
-     * it checks every possible combination for a solution.
-     * </p>
-     * <p>
-     * This method is inefficient and a better approach is necessary. For
-     * example, it does not take into account which imports are actually
-     * being used, it just increments starting at the beginning of the list.
-     * This means that it could be modifying candidates that are not relevant
-     * to the current configuration and re-testing even though nothing has
-     * really changed. It needs to be smarter.
-     * </p>
-     * @param resolverList an ordered list of resolver node lists for all
-     *        the candidates of the potential imports that need to be
-     *        resolved.
-     * @throws ResolveException if the increment overflows the entire list,
-     *         signifying no consistent configurations exist.
-    **/
-    private void incrementCandidateConfiguration(List resolverList)
-        throws ResolveException
+    public void setLibraries(R4Library[] libraries)
     {
-        for (int i = 0; i < resolverList.size(); i++)
-        {
-            List nodeList = (List) resolverList.get(i);
-            for (int j = 0; j < nodeList.size(); j++)
-            {
-                ResolverNode node = (ResolverNode) nodeList.get(j);
-                // See if we can increment the node, without overflowing
-                // the candidate array bounds.
-                if ((node.m_idx + 1) < node.m_candidates.length)
-                {
-                    node.m_idx++;
-                    return;
-                }
-                // If the index will overflow the candidate array bounds,
-                // then set the index back to zero and try to increment
-                // the next candidate.
-                else
-                {
-                    node.m_idx = 0;
-                }
-            }
-        }
-        throw new ResolveException(
-            "Unable to resolve due to constraint violation.", null, null);
+        m_policyCore.setLibraries(m_module, libraries);
     }
 
-    private Map createWires(Map resolverMap, Module rootModule)
+    public R4Wire[] getWires()
     {
-        Map resolvedModuleWireMap =
-            populateWireMap(resolverMap, rootModule, new HashMap());
-        Iterator iter = resolvedModuleWireMap.entrySet().iterator();
-        while (iter.hasNext())
-        {
-            Map.Entry entry = (Map.Entry) iter.next();
-            Module module = (Module) entry.getKey();
-            R4Wire[] wires = (R4Wire[]) entry.getValue();
-
-            // Set the module's resolved and wiring attribute.
-            module.setAttribute(RESOLVED_ATTR, Boolean.TRUE);
-            // Only add wires attribute if some exist; export
-            // only modules may not have wires.
-            if (wires.length > 0)
-            {
-                module.setAttribute(WIRING_ATTR, wires);
-            }
-
-            // Remove the wire's exporting module from the "available"
-            // package map and put it into the "in use" package map;
-            // these steps may be a no-op.
-            for (int wireIdx = 0;
-                (wires != null) && (wireIdx < wires.length);
-                wireIdx++)
-            {
-m_logger.log(LogWrapper.LOG_DEBUG, "WIRE: [" + module + "] " + wires[wireIdx]);
-                // First remove the wire module from "available" package map.
-                Module[] modules = (Module[]) m_availPkgMap.get(wires[wireIdx].m_pkg.getId());
-                modules = removeModuleFromArray(modules, wires[wireIdx].m_module);
-                m_availPkgMap.put(wires[wireIdx].m_pkg.getId(), modules);
-
-                // Also remove any exported packages from the "available"
-                // package map that are from the module associated with
-                // the current wires where the exported packages were not
-                // actually exported; an export may not be exported if
-                // the module also imports the same package and was wired
-                // to a different module. If the exported package is not
-                // actually exported, then we just want to remove it
-                // completely, since it cannot be used.
-                if (wires[wireIdx].m_module != module)
-                {
-                    modules = (Module[]) m_availPkgMap.get(wires[wireIdx].m_pkg.getId());
-                    modules = removeModuleFromArray(modules, module);
-                    m_availPkgMap.put(wires[wireIdx].m_pkg.getId(), modules);
-                }
-
-                // Add the module of the wire to the "in use" package map.
-                modules = (Module[]) m_inUsePkgMap.get(wires[wireIdx].m_pkg.getId());
-                modules = addModuleToArray(modules, wires[wireIdx].m_module);
-                m_inUsePkgMap.put(wires[wireIdx].m_pkg.getId(), modules);
-            }
-        }
-        return resolvedModuleWireMap;
+        return m_policyCore.getWires(m_module);
     }
 
-    private Map populateWireMap(Map resolverMap, Module module, Map wireMap)
+    public void setWires(R4Wire[] wires)
     {
-        // If the module is already resolved or it is part of
-        // a cycle, then just return the wire map.
-        if (getResolvedAttr(module).booleanValue() ||
-            (wireMap.get(module) != null))
-        {
-            return wireMap;
-        }
-
-        List nodeList = (List) resolverMap.get(module);
-        R4Wire[] wires = new R4Wire[nodeList.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(module, wires);
-
-        // Loop through each resolver node and create a wire
-        // for the selected candidate for the associated import.
-        for (int nodeIdx = 0; nodeIdx < nodeList.size(); nodeIdx++)
-        {
-            // Get the import's associated resolver node.
-            ResolverNode node = (ResolverNode) nodeList.get(nodeIdx);
-
-            // Add the candidate to the list of wires.
-            R4Package exportPkg =
-                getExportPackage(node.m_candidates[node.m_idx], node.m_pkg.getId());
-            wires[nodeIdx] = new R4Wire(exportPkg, node.m_candidates[node.m_idx]);
-
-            // Create the wires for the selected candidate module.
-            wireMap = populateWireMap(resolverMap, node.m_candidates[node.m_idx], wireMap);
-        }
-
-        return wireMap;
+        m_policyCore.setWires(m_module, wires);
     }
 
-// TODO: REMOVE THESE DEBUG METHODS.
-    private void dumpResolverMap(Map resolverMap)
+    public boolean isResolved()
     {
-        Iterator iter = resolverMap.entrySet().iterator();
-        while (iter.hasNext())
-        {
-            Map.Entry entry = (Map.Entry) iter.next();
-            ResolverNode node = (ResolverNode) entry.getValue();
-            System.out.println("MODULE " + node.m_module + " IMPORT " + node.m_pkg);
-            for (int i = 0; i < node.m_candidates.length; i++)
-            {
-                System.out.println("--> " + node.m_candidates[i]);
-            }
-        }
+        return m_policyCore.isResolved(m_module);
     }
 
-    private void dumpAvailablePackages()
+    public void setResolved(boolean resolved)
     {
-        synchronized (m_mgr)
-        {
-            System.out.println("AVAILABLE PACKAGES:");
-            for (Iterator i = m_availPkgMap.entrySet().iterator(); i.hasNext(); )
-            {
-                Map.Entry entry = (Map.Entry) i.next();
-                System.out.println("  " + entry.getKey());
-                Module[] modules = (Module[]) entry.getValue();
-                for (int j = 0; j < modules.length; j++)
-                {
-                    System.out.println("    " + modules[j]);
-                }
-            }
-        }
+        m_policyCore.setResolved(m_module, resolved);
     }
 
-    private void dumpUsedPackages()
+    public void resolve() throws ResolveException
     {
-        synchronized (m_mgr)
-        {
-            System.out.println("USED PACKAGES:");
-            for (Iterator i = m_inUsePkgMap.entrySet().iterator(); i.hasNext(); )
-            {
-                Map.Entry entry = (Map.Entry) i.next();
-                System.out.println("  " + entry.getKey());
-                Module[] modules = (Module[]) entry.getValue();
-                for (int j = 0; j < modules.length; j++)
-                {
-                    System.out.println("    " + modules[j]);
-                }
-            }
-        }
+        m_policyCore.resolve(m_module);
     }
 
-    /**
-     * This method returns a list of modules that have an export
-     * that is compatible with the given import identifier and version.
-     * @param pkgMap a map of export packages to exporting modules.
-     * @param target the target import package.
-     * @return an array of modules that have compatible exports or <tt>null</tt>
-     *         if none are found.
-    **/
-    protected Module[] getCompatibleExporters(Module[] modules, R4Package target)
-    {
-        // Create list of compatible exporters.
-        Module[] candidates = null;
-        for (int modIdx = 0; (modules != null) && (modIdx < modules.length); modIdx++)
-        {
-            // Get the modules export package for the target package.
-            R4Package exportPkg = getExportPackage(modules[modIdx], target.getId());
-            // If compatible, then add the candidate to the list.
-            if ((exportPkg != null) && (exportPkg.doesSatisfy(target)))
-            {
-                candidates = addModuleToArray(candidates, modules[modIdx]);
-            }
-        }
-
-        if (candidates == null)
-        {
-            return m_emptyModules;
-        }
-
-        return candidates;
-    }
-
-    public void moduleAdded(ModuleEvent event)
-    {
-        // When a module is added to the system, we need to initialize
-        // its resolved and wiring attributes and add its exports to
-        // the map of available exports.
-
-        // Synchronize on the module manager, since we don't want any
-        // bundles to be installed or removed.
-        synchronized (m_mgr)
-        {
-            // Add wiring attribute.
-            event.getModule().setAttribute(WIRING_ATTR, null);
-            // Add resolved attribute.
-            event.getModule().setAttribute(RESOLVED_ATTR, Boolean.FALSE);
-            // Add exports to available package map.
-            R4Package[] exports = getExportsAttr(event.getModule());
-            for (int i = 0; i < exports.length; i++)
-            {
-                Module[] modules = (Module[]) m_availPkgMap.get(exports[i].getId());
-
-                // We want to add the module into the list of available
-                // exporters in sorted order (descending version and
-                // ascending bundle identifier). Insert using a simple
-                // binary search algorithm.
-                if (modules == null)
-                {
-                    modules = new Module[] { event.getModule() };
-                }
-                else
-                {
-                    int top = 0, bottom = modules.length - 1, middle = 0;
-                    R4Version middleVersion = null;
-                    while (top <= bottom)
-                    {
-                        middle = (bottom - top) / 2 + top;
-                        middleVersion = getExportPackage(
-                            modules[middle], exports[i].getId()).getVersionLow();
-                        // Sort in reverse version order.
-                        int cmp = middleVersion.compareTo(exports[i].getVersionLow());
-                        if (cmp < 0)
-                        {
-                            bottom = middle - 1;
-                        }
-                        else if (cmp == 0)
-                        {
-                            // Sort further by ascending bundle ID.
-                            long middleId = getBundleIdFromModuleId(modules[middle].getId());
-                            long exportId = getBundleIdFromModuleId(event.getModule().getId());
-                            if (middleId < exportId)
-                            {
-                                top = middle + 1;
-                            }
-                            else
-                            {
-                                bottom = middle - 1;
-                            }
-                        }
-                        else
-                        {
-                            top = middle + 1;
-                        }
-                    }
-
-                    Module[] newMods = new Module[modules.length + 1];
-                    System.arraycopy(modules, 0, newMods, 0, top);
-                    System.arraycopy(modules, top, newMods, top + 1, modules.length - top);
-                    newMods[top] = event.getModule();
-                    modules = newMods;
-                }
-
-                m_availPkgMap.put(exports[i].getId(), modules);
-            }
-        }
-    }
-
-    public void moduleReset(ModuleEvent event)
-    {
-        moduleRemoved(event);
-    }
-
-    public void moduleRemoved(ModuleEvent event)
-    {
-        // When a module is removed from the system, we need remove
-        // its exports from the "in use" and "available" package maps.
-
-        // Synchronize on the module manager, since we don't want any
-        // bundles to be installed or removed.
-        synchronized (m_mgr)
-        {
-            // Remove exports from package maps.
-            R4Package[] pkgs = getExportsAttr(event.getModule());
-            for (int i = 0; i < pkgs.length; i++)
-            {
-                // Remove from "available" package map.
-                Module[] modules = (Module[]) m_availPkgMap.get(pkgs[i].getId());
-                if (modules != null)
-                {
-                    modules = removeModuleFromArray(modules, event.getModule());
-                    m_availPkgMap.put(pkgs[i].getId(), modules);
-                }
-                // Remove from "in use" package map.
-                modules = (Module[]) m_inUsePkgMap.get(pkgs[i].getId());
-                if (modules != null)
-                {
-                    modules = removeModuleFromArray(modules, event.getModule());
-                    m_inUsePkgMap.put(pkgs[i].getId(), modules);
-                }
-            }
-        }
-    }
-
-    // This is duplicated from BundleInfo and probably shouldn't be,
-    // but its functionality is needed by the moduleAdded() callback.
-    protected static long getBundleIdFromModuleId(String id)
-    {
-        try
-        {
-            String bundleId = (id.indexOf('.') >= 0)
-                ? id.substring(0, id.indexOf('.')) : id;
-            return Long.parseLong(bundleId);
-        }
-        catch (NumberFormatException ex)
-        {
-            return -1;
-        }
-    }
-
-    //
-    // Event handling methods for validation events.
-    //
-
-    /**
-     * Adds a resolver listener to the search policy. Resolver
-     * listeners are notified when a module is resolve and/or unresolved
-     * by the search policy.
-     * @param l the resolver listener to add.
-    **/
     public void addResolverListener(ResolveListener l)
     {
-        // Verify listener.
-        if (l == null)
-        {
-            throw new IllegalArgumentException("Listener is null");
-        }
-
-        // Use the m_noListeners object as a lock.
-        synchronized (m_emptyListeners)
-        {
-            // If we have no listeners, then just add the new listener.
-            if (m_listeners == m_emptyListeners)
-            {
-                m_listeners = new ResolveListener[] { 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
-            {
-                ResolveListener[] newList = new ResolveListener[m_listeners.length + 1];
-                System.arraycopy(m_listeners, 0, newList, 0, m_listeners.length);
-                newList[m_listeners.length] = l;
-                m_listeners = newList;
-            }
-        }
+        m_policyCore.addResolverListener(l);
     }
 
-    /**
-     * Removes a resolver listener to this search policy.
-     * @param l the resolver listener to remove.
-    **/
     public void removeResolverListener(ResolveListener l)
     {
-        // Verify listener.
-        if (l == null)
-        {
-            throw new IllegalArgumentException("Listener is null");
-        }
-
-        // Use the m_emptyListeners object as a lock.
-        synchronized (m_emptyListeners)
-        {
-            // 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_emptyListeners;
-                }
-                // 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
-                {
-                    ResolveListener[] newList = new ResolveListener[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;
-                }
-            }
-        }
+        m_policyCore.removeResolverListener(l);
     }
 
-    /**
-     * Fires a validation event for the specified module.
-     * @param module the module that was resolved.
-    **/
-    protected void fireModuleResolved(Module module)
+    public String toString()
     {
-        // Event holder.
-        ModuleEvent event = null;
-
-        // Get a copy of the listener array, which is guaranteed
-        // to not be null.
-        ResolveListener[] 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(m_mgr, module);
-            }
-            listeners[i].moduleResolved(event);
-        }
-    }
-
-    /**
-     * Fires an unresolved event for the specified module.
-     * @param module the module that was unresolved.
-    **/
-    protected void fireModuleUnresolved(Module module)
-    {
-        // Event holder.
-        ModuleEvent event = null;
-
-        // Get a copy of the listener array, which is guaranteed
-        // to not be null.
-        ResolveListener[] 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(m_mgr, module);
-            }
-            listeners[i].moduleUnresolved(event);
-        }
-    }
-
-    //
-    // Static utility methods.
-    //
-
-    public static Boolean getResolvedAttr(Module m)
-    {
-        Boolean b =
-            (Boolean) m.getAttribute(RESOLVED_ATTR);
-        if (b == null)
-        {
-            b = Boolean.FALSE;
-        }
-        return b;
-    }
-
-    public static R4Package[] getExportsAttr(Module m)
-    {
-        R4Package[] attr =
-            (R4Package[]) m.getAttribute(EXPORTS_ATTR);
-        return (attr == null) ? m_emptyPackages : attr;
-    }
-
-    public static R4Package getExportPackage(Module m, String id)
-    {
-        R4Package[] pkgs = getExportsAttr(m);
-        for (int i = 0; (pkgs != null) && (i < pkgs.length); i++)
-        {
-            if (pkgs[i].getId().equals(id))
-            {
-                return pkgs[i];
-            }
-        }
-        return null;
-    }
-
-    public static R4Package[] getImportsAttr(Module m)
-    {
-        R4Package[] attr =
-            (R4Package[]) m.getAttribute(IMPORTS_ATTR);
-        return (attr == null) ? m_emptyPackages: attr;
-    }
-
-    public static R4Package getImportPackage(Module m, String id)
-    {
-        R4Package[] pkgs = getImportsAttr(m);
-        for (int i = 0; (pkgs != null) && (i < pkgs.length); i++)
-        {
-            if (pkgs[i].getId().equals(id))
-            {
-                return pkgs[i];
-            }
-        }
-        return null;
-    }
-
-    public static R4Package[] getDynamicImportsAttr(Module m)
-    {
-        R4Package[] attr =
-            (R4Package[]) m.getAttribute(DYNAMICIMPORTS_ATTR);
-        return (attr == null) ? m_emptyPackages: attr;
-    }
-
-    public static R4Package getDynamicImportPackage(Module m, String id)
-    {
-        R4Package[] pkgs = getDynamicImportsAttr(m);
-        for (int i = 0; (pkgs != null) && (i < pkgs.length); i++)
-        {
-            if (pkgs[i].getId().equals(id))
-            {
-                return pkgs[i];
-            }
-        }
-        return null;
-    }
-
-    public static R4Wire[] getWiringAttr(Module m)
-    {
-        R4Wire[] attr =
-            (R4Wire[]) m.getAttribute(WIRING_ATTR);
-        if (attr == null)
-        {
-            attr = m_emptyWires;
-        }
-        return attr;
-    }
-
-    public static R4Wire getWire(Module m, String id)
-    {
-        R4Wire[] wires = getWiringAttr(m);
-        for (int i = 0; (wires != null) && (i < wires.length); i++)
-        {
-            if (wires[i].m_pkg.getId().equals(id))
-            {
-                return wires[i];
-            }
-        }
-        return null;
-    }
-
-    public static boolean isModuleInArray(Module[] modules, Module m)
-    {
-        // Verify that the module is not already in the array.
-        for (int i = 0; (modules != null) && (i < modules.length); i++)
-        {
-            if (modules[i] == m)
-            {
-                return true;
-            }
-        }
-        
-        return false;
-    }
-
-    public static Module[] addModuleToArray(Module[] modules, Module m)
-    {
-        // Verify that the module is not already in the array.
-        for (int i = 0; (modules != null) && (i < modules.length); i++)
-        {
-            if (modules[i] == m)
-            {
-                return modules;
-            }
-        }
-
-        if (modules != null)
-        {
-            Module[] newModules = new Module[modules.length + 1];
-            System.arraycopy(modules, 0, newModules, 0, modules.length);
-            newModules[modules.length] = m;
-            modules = newModules;
-        }
-        else
-        {
-            modules = new Module[] { m };
-        }
-
-        return modules;
-    }
-
-    public static Module[] removeModuleFromArray(Module[] modules, Module m)
-    {
-        if (modules == null)
-        {
-            return m_emptyModules;
-        }
-
-        int idx = -1;
-        for (int i = 0; i < modules.length; i++)
-        {
-            if (modules[i] == m)
-            {
-                idx = i;
-                break;
-            }
-        }
-
-        if (idx >= 0)
-        {
-            // If this is the module, then point to empty list.
-            if ((modules.length - 1) == 0)
-            {
-                modules = m_emptyModules;
-            }
-            // Otherwise, we need to do some array copying.
-            else
-            {
-                Module[] newModules= new Module[modules.length - 1];
-                System.arraycopy(modules, 0, newModules, 0, idx);
-                if (idx < newModules.length)
-                {
-                    System.arraycopy(
-                        modules, idx + 1, newModules, idx, newModules.length - idx);
-                }
-                modules = newModules;
-            }
-        }
-        return modules;
-    }
-
-// TODO: INVESTIGATE GENERIC ARRAY GROWING/SHRINKING.
-    private static R4Wire[] shrinkWireArray(R4Wire[] wires)
-    {
-        if (wires == null)
-        {
-            return m_emptyWires;
-        }
-
-        int count = 0;
-        for (int i = 0; i < wires.length; i++)
-        {
-            if (wires[i] == null)
-            {
-                count++;
-            }
-        }
-
-        if (count > 0)
-        {
-            R4Wire[] newWires = new R4Wire[wires.length - count];
-            count = 0;
-            for (int i = 0; i < wires.length; i++)
-            {
-                if (wires[i] != null)
-                {
-                    newWires[count++] = wires[i];
-                }
-            }
-            wires = newWires;
-        }
-
-        return wires;
-    }
-
-    private static Module[] shrinkModuleArray(Module[] modules)
-    {
-        if (modules == null)
-        {
-            return m_emptyModules;
-        }
-
-        int count = 0;
-        for (int i = 0; i < modules.length; i++)
-        {
-            if (modules[i] == null)
-            {
-                count++;
-            }
-        }
-
-        if (count > 0)
-        {
-            Module[] newModules = new Module[modules.length - count];
-            count = 0;
-            for (int i = 0; i < modules.length; i++)
-            {
-                if (modules[i] != null)
-                {
-                    newModules[count++] = modules[i];
-                }
-            }
-            modules = newModules;
-        }
-
-        return modules;
-    }
-
-    private static class ResolverNode
-    {
-        public Module m_module = null;
-        public R4Package m_pkg = null;
-        public Module[] m_candidates = null;
-        public int m_idx = 0;
-        public boolean m_visited = false;
-        public ResolverNode(Module module, R4Package pkg, Module[] candidates)
-        {
-            m_module = module;
-            m_pkg = pkg;
-            m_candidates = candidates;
-            if (getResolvedAttr(m_module).booleanValue())
-            {
-                m_visited = true;
-            }
-        }
+        return m_module.toString();
     }
 }
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
new file mode 100755
index 0000000..e6d0d83
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
@@ -0,0 +1,1645 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.*;
+
+import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.util.SecurityManagerEx;
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.moduleloader.*;
+import org.osgi.framework.Version;
+
+public class R4SearchPolicyCore implements ModuleListener
+{
+    private Logger m_logger = null;
+    private IModuleFactory m_factory = null;
+    private Map m_availPkgMap = new HashMap();
+    private Map m_inUsePkgMap = new HashMap();
+    private Map m_moduleDataMap = new HashMap();
+
+    // Listener-related instance variables.
+    private static final ResolveListener[] m_emptyListeners = new ResolveListener[0];
+    private ResolveListener[] m_listeners = m_emptyListeners;
+
+    // Reusable empty array.
+    public static final IModule[] m_emptyModules = new IModule[0];
+
+    // Re-usable security manager for accessing class context.
+    private static SecurityManagerEx m_sm = new SecurityManagerEx();
+
+    public R4SearchPolicyCore(Logger logger)
+    {
+        m_logger = logger;
+    }
+
+    public IModuleFactory getModuleFactory()
+    {
+        return m_factory;
+    }
+
+    public void setModuleFactory(IModuleFactory factory)
+        throws IllegalStateException
+    {
+        if (m_factory == null)
+        {
+            m_factory = factory;
+            m_factory.addModuleListener(this);
+        }
+        else
+        {
+            throw new IllegalStateException("Module manager is already initialized");
+        }
+    }
+
+    public synchronized R4Export[] getExports(IModule module)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        return (data == null) ? null : data.m_exports;
+    }
+
+    public synchronized void setExports(IModule module, R4Export[] exports)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        if (data == null)
+        {
+            data = new ModuleData(module);
+            m_moduleDataMap.put(module, data);
+        }
+        data.m_exports = exports;
+
+        // When a module is added and its exports are set, create an
+        // aggregated list of available exports to simplify later
+        // processing when resolving bundles.
+
+        // Add exports to available package map.
+        for (int i = 0; (exports != null) && (i < exports.length); i++)
+        {
+            IModule[] modules = (IModule[]) m_availPkgMap.get(exports[i].getName());
+
+            // We want to add the module into the list of available
+            // exporters in sorted order (descending version and
+            // ascending bundle identifier). Insert using a simple
+            // binary search algorithm.
+            if (modules == null)
+            {
+                modules = new IModule[] { module };
+            }
+            else
+            {
+                int top = 0, bottom = modules.length - 1, middle = 0;
+                Version middleVersion = null;
+                while (top <= bottom)
+                {
+                    middle = (bottom - top) / 2 + top;
+                    middleVersion = Util.getExportPackage(
+                        modules[middle], exports[i].getName()).getVersion();
+                    // Sort in reverse version order.
+                    int cmp = middleVersion.compareTo(exports[i].getVersion());
+                    if (cmp < 0)
+                    {
+                        bottom = middle - 1;
+                    }
+                    else if (cmp == 0)
+                    {
+                        // Sort further by ascending bundle ID.
+                        long middleId = Util.getBundleIdFromModuleId(modules[middle].getId());
+                        long exportId = Util.getBundleIdFromModuleId(module.getId());
+                        if (middleId < exportId)
+                        {
+                            top = middle + 1;
+                        }
+                        else
+                        {
+                            bottom = middle - 1;
+                        }
+                    }
+                    else
+                    {
+                        top = middle + 1;
+                    }
+                }
+
+                IModule[] newMods = new IModule[modules.length + 1];
+                System.arraycopy(modules, 0, newMods, 0, top);
+                System.arraycopy(modules, top, newMods, top + 1, modules.length - top);
+                newMods[top] = module;
+                modules = newMods;
+            }
+
+            m_availPkgMap.put(exports[i].getName(), modules);
+        }
+    }
+
+    public synchronized R4Import[] getImports(IModule module)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        return (data == null) ? null : data.m_imports;
+    }
+
+    public synchronized void setImports(IModule module, R4Import[] imports)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        if (data == null)
+        {
+            data = new ModuleData(module);
+            m_moduleDataMap.put(module, data);
+        }
+        data.m_imports = imports;
+    }
+
+    public synchronized R4Import[] getDynamicImports(IModule module)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        return (data == null) ? null : data.m_dynamicImports;
+    }
+
+    public synchronized void setDynamicImports(IModule module, R4Import[] imports)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        if (data == null)
+        {
+            data = new ModuleData(module);
+            m_moduleDataMap.put(module, data);
+        }
+        data.m_dynamicImports = imports;
+    }
+
+    public synchronized R4Library[] getLibraries(IModule module)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        return (data == null) ? null : data.m_libraries;
+    }
+
+    public synchronized void setLibraries(IModule module, R4Library[] libraries)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        if (data == null)
+        {
+            data = new ModuleData(module);
+            m_moduleDataMap.put(module, data);
+        }
+        data.m_libraries = libraries;
+    }
+
+    public synchronized R4Wire[] getWires(IModule module)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        return (data == null) ? null : data.m_wires;
+    }
+
+    public synchronized void setWires(IModule module, R4Wire[] wires)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        if (data == null)
+        {
+            data = new ModuleData(module);
+            m_moduleDataMap.put(module, data);
+        }
+        data.m_wires = wires;
+    }
+
+    public synchronized boolean isResolved(IModule module)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        return (data == null) ? false : data.m_resolved;
+    }
+
+    public synchronized void setResolved(IModule module, boolean resolved)
+    {
+        ModuleData data = (ModuleData) m_moduleDataMap.get(module);
+        if (data == null)
+        {
+            data = new ModuleData(module);
+            m_moduleDataMap.put(module, data);
+        }
+        data.m_resolved = resolved;
+    }
+
+    public Object[] definePackage(IModule module, String pkgName)
+    {
+        R4Package pkg = Util.getExportPackage(module, pkgName);
+        if (pkg != null)
+        {
+            return new Object[]  {
+                pkgName, // Spec title.
+                pkg.getVersion().toString(), // Spec version.
+                "", // Spec vendor.
+                "", // Impl title.
+                "", // Impl version.
+                ""  // Impl vendor.
+            };
+        }
+        return null;
+    }
+
+    public Class findClass(IModule module, String name)
+        throws ClassNotFoundException
+    {
+        // First, try to resolve the originating module.
+// TODO: Consider opimizing this call to resolve, since it is called
+// for each class load.
+        try
+        {
+            resolve(module);
+        }
+        catch (ResolveException ex)
+        {
+            // 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.getPackage());
+        }
+
+        // Get the package of the target class.
+        String pkgName = Util.getClassPackage(name);
+
+        // Load all "java.*" classes from parent class loader;
+        // these packages cannot be provided by other bundles.
+        if (pkgName.startsWith("java."))
+        {
+            return this.getClass().getClassLoader().loadClass(name);
+        }
+
+        // Look in the module's imports.
+        Class clazz = findImportedClass(module, name, pkgName);
+
+        // If not found, try the module's own content.
+        if (clazz == null)
+        {
+            clazz = module.getContentLoader().getClass(name);
+
+            // If still not found, then try the module's dynamic imports.
+            if (clazz == null)
+            {
+                clazz = findDynamicallyImportedClass(module, name, pkgName);
+            }
+        }
+
+        if (clazz == null)
+        {
+            throw new ClassNotFoundException(name);
+        }
+
+        return clazz;
+    }
+
+    private Class findImportedClass(IModule module, String name, String pkgName)
+        throws ClassNotFoundException
+    {
+        // We delegate to the module's wires to find the class.
+        R4Wire[] wires = getWires(module);
+        for (int i = 0; (wires != null) && (i < wires.length); i++)
+        {
+            // If we find the class, then return it.
+            Class clazz = wires[i].getClass(name);
+            if (clazz != null)
+            {
+                return clazz;
+            }
+        }
+
+        return null;
+    }
+
+    private Class findDynamicallyImportedClass(
+        IModule module, String name, String pkgName)
+        throws ClassNotFoundException
+    {
+        // 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 via a dynamic import, if possible.
+        R4Wire wire = attemptDynamicImport(module, pkgName);
+
+        // 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 in
+        // the associated package will be processed as part of
+        // normal static imports.
+        if (wire != null)
+        {
+            // If we find the class, then return it. Otherwise,
+            // throw an exception since the provider of the
+            // package did not have the class.
+            Class clazz = wire.getClass(name);
+            if (clazz != null)
+            {
+                return clazz;
+            }
+            else
+            {
+                throw new ClassNotFoundException(name);
+            }
+        }
+
+        // At this point, the class could not be found by the bundle's static
+        // or dynamic imports, nor its own resources. Before we throw
+        // an exception, we will try to determine if the instigator of the
+        // class 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 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 class load 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 a class not found 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 neither
+            // a class loader or Class itself, because we want to ignore
+            // the calls to ClassLoader.loadClass() and Class.forName().
+            if (!ClassLoader.class.isAssignableFrom(classes[i]) &&
+                !Class.class.isAssignableFrom(classes[i]))
+            {
+                // If the instigating class was not from a bundle, then
+                // delegate to the parent class loader. Otherwise, break
+                // out of loop and throw an exception.
+                if (!ContentClassLoader.class.isInstance(classes[i].getClassLoader()))
+                {
+                    return this.getClass().getClassLoader().loadClass(name);
+                }
+                break;
+            }
+        }
+        
+        throw new ClassNotFoundException(name);
+    }
+
+    public URL findResource(IModule module, String name)
+        throws ResourceNotFoundException
+    {
+        // First, try to resolve the originating module.
+// TODO: Consider opimizing this call to resolve, since it is called
+// for each class load.
+        try
+        {
+            resolve(module);
+        }
+        catch (ResolveException ex)
+        {
+            // We do not use the resolve exception as the
+            // cause of the exception, since this would
+            // potentially leak internal module information.
+            throw new ResourceNotFoundException(
+                name + ": cannot resolve package "
+                + ex.getPackage());
+        }
+
+        // Get the package of the target class.
+        String pkgName = Util.getResourcePackage(name);
+
+        // Load all "java.*" classes from parent class loader;
+        // these packages cannot be provided by other bundles.
+        if (pkgName.startsWith("java."))
+        {
+            return this.getClass().getClassLoader().getResource(name);
+        }
+
+        // Look in the module's imports.
+        URL url = findImportedResource(module, name);
+
+        // If not found, try the module's own content.
+        if (url == null)
+        {
+            url = module.getContentLoader().getResource(name);
+
+            // If still not found, then try the module's dynamic imports.
+            if (url == null)
+            {
+                url = findDynamicallyImportedResource(module, name, pkgName);
+            }
+        }
+
+        if (url == null)
+        {
+            throw new ResourceNotFoundException(name);
+        }
+
+        return url;
+    }
+
+    private URL findImportedResource(IModule module, String name)
+        throws ResourceNotFoundException
+    {
+        // We delegate to the module's wires to find the class.
+        R4Wire[] wires = getWires(module);
+        for (int i = 0; (wires != null) && (i < wires.length); i++)
+        {
+            // If we find the resource, then return it.
+            URL url = wires[i].getResource(name);
+            if (url != null)
+            {
+                return url;
+            }
+        }
+    
+        return null;
+    }
+
+    private URL findDynamicallyImportedResource(
+        IModule module, String name, String pkgName)
+        throws 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 via a dynamic import, if possible.
+        R4Wire wire = attemptDynamicImport(module, pkgName);
+        
+        // If the dynamic import was successful, then this initial
+        // time we must directly return the result from dynamically
+        // created wire, but subsequent requests for resources in
+        // the associated package will be processed as part of
+        // normal static imports.
+        if (wire != null)
+        {
+            // If we find the class, then return it. Otherwise,
+            // throw an exception since the provider of the
+            // package did not have the class.
+            URL url = wire.getResource(name);
+            if (url != null)
+            {
+                return url;
+            }
+            else
+            {
+                throw new ResourceNotFoundException(name);
+            }
+        }
+    
+        // At this point, the resource could not be found by the bundle's static
+        // or dynamic imports, nor its own resources. Before we throw
+        // an exception, we will try to determine if the instigator of the
+        // 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 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 resource load 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 a resource not found 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 neither
+            // a class loader or Class itself, because we want to ignore
+            // the calls to ClassLoader.loadClass() and Class.forName().
+            if (!ClassLoader.class.isAssignableFrom(classes[i]) &&
+                !Class.class.isAssignableFrom(classes[i]))
+            {
+                // If the instigating class was not from a bundle, then
+                // delegate to the parent class loader. Otherwise, break
+                // out of loop and throw an exception.
+                if (!ContentClassLoader.class.isInstance(classes[i].getClassLoader()))
+                {
+                    return this.getClass().getClassLoader().getResource(name);
+                }
+                break;
+            }
+        }
+        
+        throw new ResourceNotFoundException(name);
+    }
+
+    private R4Wire attemptDynamicImport(IModule module, String pkgName)
+    {
+        R4Wire wire = null;
+        IModule candidate = null;
+
+        // There is an overriding assumption here that a package is
+        // never split across bundles. If a package can be split
+        // across bundles, then this will fail.
+
+        try
+        {
+            // Check the dynamic import specs for a match of
+            // the target package.
+            R4Import[] dynamics = getDynamicImports(module);
+            R4Import impMatch = null;
+            for (int i = 0;
+                (impMatch == null) && (dynamics != null) && (i < dynamics.length);
+                i++)
+            {
+                // Star matches everything.
+                if (dynamics[i].getName().equals("*"))
+                {
+                    // Create a package instance without wildcard.
+                    impMatch = new R4Import(
+                        pkgName,
+                        dynamics[i].getDirectives(),
+                        dynamics[i].getAttributes());
+                }
+                // Packages ending in ".*" must match starting strings.
+                else if (dynamics[i].getName().endsWith(".*"))
+                {
+                    if (pkgName.regionMatches(
+                        0, dynamics[i].getName(), 0, dynamics[i].getName().length() - 2))
+                    {
+                        // Create a package instance without wildcard.
+                        impMatch = new R4Import(
+                            pkgName,
+                            dynamics[i].getDirectives(),
+                            dynamics[i].getAttributes());
+                    }
+                }
+                // Or we can have a precise match.
+                else
+                {
+                    if (pkgName.equals(dynamics[i].getName()))
+                    {
+                        impMatch = dynamics[i];
+                    }
+                }
+            }
+
+            // If the target package does not match any dynamically imported
+            // packages or if the module is already wired for the target package,
+            // then just return null. The module may be already wired to the target
+            // package if the class being searched for does not actually exist.
+            if ((impMatch == null) || (Util.getWire(module, impMatch.getName()) != null))
+            {
+                return null;
+            }
+
+            // At this point, the target package has matched a dynamically
+            // imported package spec. Now we must try to find a candidate
+            // exporter for target package and add it to the module's set
+            // of wires.
+
+            // Lock module manager instance to ensure that nothing changes.
+            synchronized (m_factory)
+            {
+                // Try to add a new entry to the module's import attribute.
+                // Select the first candidate that successfully resolves.
+
+                // First check already resolved exports for a match.
+                IModule[] candidates = getCompatibleExporters(
+                    (IModule[]) m_inUsePkgMap.get(impMatch.getName()), impMatch);
+                // If there is an "in use" candidate, just take the first one.
+                if (candidates.length > 0)
+                {
+                    candidate = candidates[0];
+                }
+
+                // If there were no "in use" candidates, then try "available"
+                // candidates.
+                if (candidate == null)
+                {
+                    candidates = getCompatibleExporters(
+                        (IModule[]) m_availPkgMap.get(impMatch.getName()), impMatch);
+                    for (int candIdx = 0;
+                        (candidate == null) && (candIdx < candidates.length);
+                        candIdx++)
+                    {
+                        try
+                        {
+                            resolve(module);
+                            candidate = candidates[candIdx];
+                        }
+                        catch (ResolveException ex)
+                        {
+                        }
+                    }
+                }
+
+                // If we found a candidate, then add it to the module's
+                // wiring attribute.
+                if (candidate != null)
+                {
+                    R4Wire[] wires = getWires(module);
+                    R4Wire[] newWires = null;
+                    if (wires == null)
+                    {
+                        newWires = new R4Wire[1];
+                    }
+                    else
+                    {
+                        newWires = new R4Wire[wires.length + 1];
+                        System.arraycopy(wires, 0, newWires, 0, wires.length);
+                    }
+                    // Find the candidate's export package object and
+                    // use that for creating the wire; this is necessary
+                    // since it contains "uses" dependency information.
+                    wire = new R4Wire(
+                        module, candidate,
+                        Util.getExportPackage(candidate, impMatch.getName()));
+                    newWires[wires.length] = wire;
+                    setWires(module, newWires);
+m_logger.log(Logger.LOG_DEBUG, "WIRE: [" + module + "] " + newWires[wires.length]);
+                }
+            }
+        }
+        catch (Exception ex)
+        {
+            m_logger.log(Logger.LOG_ERROR, "Unable to dynamically import package.", ex);
+        }
+
+        return wire;
+    }
+
+    public String findLibrary(IModule module, String name)
+    {
+        // Remove leading slash, if present.
+        if (name.startsWith("/"))
+        {
+            name = name.substring(1);
+        }
+
+        // TODO: This "matching" algorithm does not fully
+        // match the spec and should be improved.
+        R4Library[] libs = getLibraries(module);
+        for (int i = 0; (libs != null) && (i < libs.length); i++)
+        {
+            String path = libs[i].getPath(name);
+            if (path != null)
+            {
+                return path;
+            }
+        }
+
+        return null;
+    }
+
+    public IModule[] getAvailableExporters(R4Import pkg)
+    {
+        // Synchronized on the module manager to make sure that no
+        // modules are added, removed, or resolved.
+        synchronized (m_factory)
+        {
+            return getCompatibleExporters((IModule[]) m_availPkgMap.get(pkg.getName()), pkg);
+        }
+    }
+
+    public IModule[] getInUseExporters(R4Import pkg)
+    {
+        // Synchronized on the module manager to make sure that no
+        // modules are added, removed, or resolved.
+        synchronized (m_factory)
+        {
+            return getCompatibleExporters((IModule[]) m_inUsePkgMap.get(pkg.getName()), pkg);
+        }
+    }
+
+    public void resolve(IModule rootModule)
+        throws ResolveException
+    {
+        // If the module is already resolved, then we can just return.
+        if (isResolved(rootModule))
+        {
+            return;
+        }
+
+        // This variable maps an unresolved module to a list of resolver
+        // nodes, where there is one resolver node for each import that
+        // must be resolved. A resolver node contains the potential
+        // candidates to resolve the import and the current selected
+        // candidate index.
+        Map resolverMap = new HashMap();
+    
+        // This map will be used to hold the final wires for all
+        // resolved modules, which can then be used to fire resolved
+        // events outside of the synchronized block.
+        Map resolvedModuleWireMap = null;
+    
+        // Synchronize on the module manager, because we don't want
+        // any modules being added or removed while we are in the
+        // middle of this operation.
+        synchronized (m_factory)
+        {
+            // The first step is to populate the resolver map. This
+            // will use the target module to populate the resolver map
+            // with all potential modules that need to be resolved as a
+            // result of resolving the target module. The key of the
+            // map is a potential module to be resolved and the value is
+            // a list of resolver nodes, one for each of the module's
+            // imports, where each resolver node contains the potential
+            // candidates for resolving the import. Not all modules in
+            // this map will be resolved, only the target module and
+            // any candidates selected to resolve its imports and the
+            // transitive imports this implies.
+            populateResolverMap(resolverMap, rootModule);
+
+            // The next step is to use the resolver map to determine if
+            // the class space for the root module is consistent. This
+            // is an iterative process that transitively walks the "uses"
+            // relationships of all currently selected potential candidates
+            // for resolving import packages checking for conflicts. If a
+            // conflict is found, it "increments" the configuration of
+            // currently selected potential candidates and tests them again.
+            // If this method returns, then it has found a consistent set
+            // of candidates; otherwise, a resolve exception is thrown if
+            // it exhausts all possible combinations and could not find a
+            // consistent class space.
+            findConsistentClassSpace(resolverMap, rootModule);
+    
+            // The final step is to create the wires for the root module and
+            // transitively all modules that are to be resolved from the
+            // selected candidates for resolving the root module's imports.
+            // When this call returns, each module's wiring and resolved
+            // attributes are set. The resulting wiring map is used below
+            // to fire resolved events outside of the synchronized block.
+            // The resolved module wire map maps a module to its array of
+            // wires.
+            resolvedModuleWireMap = createWires(resolverMap, rootModule);
+        
+//dumpAvailablePackages();
+//dumpUsedPackages();
+
+        } // End of synchronized block on module manager.
+
+        // Fire resolved events for all resolved modules;
+        // the resolved modules array will only be set if the resolve
+        // was successful after the root module was resolved.
+        if (resolvedModuleWireMap != null)
+        {
+            Iterator iter = resolvedModuleWireMap.entrySet().iterator();
+            while (iter.hasNext())
+            {
+                fireModuleResolved((IModule) ((Map.Entry) iter.next()).getKey());
+            }
+        }
+    }
+
+    private void populateResolverMap(Map resolverMap, IModule module)
+        throws ResolveException
+    {
+        // Detect cycles.
+        if (resolverMap.get(module) != null)
+        {
+            return;
+        }
+        // Map to hold the module's import packages
+        // and their respective resolving candidates.
+        List nodeList = new ArrayList();
+
+        // Even though the node list is currently empty, we
+        // record it in the resolver map early so we can use
+        // it to detect cycles.
+        resolverMap.put(module, nodeList);
+
+        // Loop through each import and calculate its resolving
+        // set of candidates.
+        R4Import[] imports = getImports(module);
+        for (int impIdx = 0; (imports != null) && (impIdx < imports.length); impIdx++)
+        {
+            // Get the candidates from the "in use" and "available"
+            // package maps. Candidates "in use" have higher priority
+            // than "available" ones, so put the "in use" candidates
+            // at the front of the list of candidates.
+            IModule[] inuse = getCompatibleExporters(
+                (IModule[]) m_inUsePkgMap.get(
+                    imports[impIdx].getName()), imports[impIdx]);
+            IModule[] available = getCompatibleExporters(
+                (IModule[]) m_availPkgMap.get(
+                    imports[impIdx].getName()), imports[impIdx]);
+            IModule[] candidates = new IModule[inuse.length + available.length];
+            System.arraycopy(inuse, 0, candidates, 0, inuse.length);
+            System.arraycopy(available, 0, candidates, inuse.length, available.length);
+
+            // If we have candidates, then we need to recursively populate
+            // the resolver map with each of them.
+            ResolveException rethrow = null;
+            if (candidates.length > 0)
+            {
+                for (int candIdx = 0; candIdx < candidates.length; candIdx++)
+                {
+                    try
+                    {
+                        // Only populate the resolver map with modules that
+                        // are not already resolved.
+                        if (!isResolved(candidates[candIdx]))
+                        {
+                            populateResolverMap(resolverMap, candidates[candIdx]);
+                        }
+                    }
+                    catch (ResolveException ex)
+                    {
+                        // If we received a resolve exception, then the
+                        // current candidate is not resolvable for some
+                        // reason and should be removed from the list of
+                        // candidates. For now, just null it.
+                        candidates[candIdx] = null;
+                        rethrow = ex;
+                    }
+                }
+
+                // Remove any nulled candidates to create the final list
+                // of available candidates.
+                candidates = shrinkModuleArray(candidates);
+            }
+
+            // If no candidates exist at this point, then throw a
+            // resolve exception unless the import is optional.
+            if ((candidates.length == 0) && !imports[impIdx].isOptional())
+            {
+                // If we have received an exception while trying to populate
+                // the resolver map, rethrow that exception since it might
+                // be useful. NOTE: This is not necessarily the "only"
+                // correct exception, since it is possible that multiple
+                // candidates were not resolvable, but it is better than
+                // nothing.
+                if (rethrow != null)
+                {
+                    throw rethrow;
+                }
+                else
+                {
+                    throw new ResolveException(
+                        "Unable to resolve.", module, imports[impIdx]);
+                }
+            }
+            else if (candidates.length > 0)
+            {
+                nodeList.add(
+                    new ResolverNode(module, imports[impIdx], candidates));
+            }
+        }
+    }
+
+
+//  TODO: REMOVE THESE DEBUG METHODS.
+    private void dumpAvailablePackages()
+    {
+        synchronized (this)
+        {
+            System.out.println("AVAILABLE PACKAGES:");
+            for (Iterator i = m_availPkgMap.entrySet().iterator(); i.hasNext(); )
+            {
+                Map.Entry entry = (Map.Entry) i.next();
+                System.out.println("  " + entry.getKey());
+                IModule[] modules = (IModule[]) entry.getValue();
+                for (int j = 0; j < modules.length; j++)
+                {
+                    System.out.println("    " + modules[j]);
+                }
+            }
+        }
+    }
+
+    private void dumpUsedPackages()
+    {
+        synchronized (this)
+        {
+            System.out.println("USED PACKAGES:");
+            for (Iterator i = m_inUsePkgMap.entrySet().iterator(); i.hasNext(); )
+            {
+                Map.Entry entry = (Map.Entry) i.next();
+                System.out.println("  " + entry.getKey());
+                IModule[] modules = (IModule[]) entry.getValue();
+                for (int j = 0; j < modules.length; j++)
+                {
+                    System.out.println("    " + modules[j]);
+                }
+            }
+        }
+    }
+
+    private IModule[] getCompatibleExporters(IModule[] modules, R4Import target)
+    {
+        // Create list of compatible exporters.
+        IModule[] candidates = null;
+        for (int modIdx = 0; (modules != null) && (modIdx < modules.length); modIdx++)
+        {
+            // Get the modules export package for the target package.
+            R4Export export = Util.getExportPackage(modules[modIdx], target.getName());
+            // If compatible, then add the candidate to the list.
+            if ((export != null) && (target.isSatisfied(export)))
+            {
+                candidates = addModuleToArray(candidates, modules[modIdx]);
+            }
+        }
+        if (candidates == null)
+        {
+            return m_emptyModules;
+        }
+        return candidates;
+    }
+
+    private void findConsistentClassSpace(Map resolverMap, IModule rootModule)
+        throws ResolveException
+    {
+        List resolverList = null;
+    
+        // Test the current set of candidates to determine if they
+        // are consistent. Keep looping until we find a consistent
+        // set or an exception is thrown.
+        Map cycleMap = new HashMap();
+        while (!isClassSpaceConsistent(resolverMap, rootModule, cycleMap))
+        {
+m_logger.log(
+    Logger.LOG_DEBUG,
+    "Constraint violation detected, will try to repair.");
+
+            // The incrementCandidateConfiguration() method requires an
+            // ordered access to the resolver map, so we will create
+            // a reusable list once right here.
+            if (resolverList == null)
+            {
+                resolverList = new ArrayList();
+                for (Iterator iter = resolverMap.entrySet().iterator();
+                    iter.hasNext(); )
+                {
+                    resolverList.add((List) ((Map.Entry) iter.next()).getValue());
+                }
+            }
+    
+            // Increment the candidate configuration so we can test again.
+            incrementCandidateConfiguration(resolverList);
+    
+            // Clear the cycle map.
+            cycleMap.clear();
+        }
+    }
+
+    private boolean isClassSpaceConsistent(
+        Map resolverMap, IModule rootModule, Map cycleMap)
+    {
+        // We do not need to verify that already resolved modules
+        // have consistent class spaces because they should be
+        // consistent by definition. Also, if the root module is
+        // part of a cycle, then just assume it is true.
+        if (isResolved(rootModule) || (cycleMap.get(rootModule) != null))
+        {
+            return true;
+        }
+    
+        // Add to cycle map for future reference.
+        cycleMap.put(rootModule, rootModule);
+    
+        // Create an implicit "uses" constraint for every exported package
+        // of the root module that is not also imported; uses constraints
+        // for exported packages that are also imported will be taken
+        // care of as part of normal import package processing.
+        R4Export[] exports = getExports(rootModule);
+        Map usesMap = new HashMap();
+        for (int i = 0; (exports != null) && (i < exports.length); i++)
+        {
+            // Ignore exports that are also imported, since they
+            // will be taken care of when verifying import constraints.
+            if (Util.getImportPackage(rootModule, exports[i].getName()) == null)
+            {
+                usesMap.put(exports[i].getName(), rootModule);
+            }
+        }
+    
+        // Loop through the current candidates for the module's imports
+        // (available in the resolver node list of the resolver map) and
+        // calculate the uses constraints for each of the currently
+        // selected candidates for resolving the imports. Compare each
+        // candidate's constraints to the existing constraints to check
+        // for conflicts.
+        List nodeList = (List) resolverMap.get(rootModule);
+        for (int nodeIdx = 0; nodeIdx < nodeList.size(); nodeIdx++)
+        {
+            // Verify that the current candidate does not violate
+            // any "uses" constraints of existing candidates by
+            // calculating the candidate's transitive "uses" constraints
+            // for the provided package and testing whether they
+            // overlap with existing constraints.
+    
+            // First, get the resolver node.
+            ResolverNode node = (ResolverNode) nodeList.get(nodeIdx);
+    
+            // Verify that the current candidate itself has a consistent
+            // class space.
+            if (!isClassSpaceConsistent(
+                resolverMap, node.m_candidates[node.m_idx], cycleMap))
+            {
+                return false;
+            }
+    
+            // Get the exported package from the current candidate that
+            // will be used to resolve the root module's import.
+            R4Export candidatePkg = Util.getExportPackage(
+                node.m_candidates[node.m_idx], node.m_import.getName());
+    
+            // Calculate the "uses" dependencies implied by the candidate's
+            // exported package with respect to the currently selected
+            // candidates in the resolver map.
+            Map candUsesMap = calculateUsesDependencies(
+                resolverMap,
+                node.m_candidates[node.m_idx],
+                candidatePkg,
+                new HashMap());
+//System.out.println("MODULE " + rootModule + " USES    " + usesMap);
+//System.out.println("CANDIDATE " + node.m_candidates[node.m_idx] + " USES " + candUsesMap);
+
+            // Iterate through the root module's current set of transitive
+            // "uses" constraints and compare them with the candidate's
+            // transitive set of constraints.
+            Iterator usesIter = candUsesMap.entrySet().iterator();
+            while (usesIter.hasNext())
+            {
+                // If the candidate's uses constraints overlap with
+                // the existing uses constraints, but refer to a
+                // different provider, then the class space is not
+                // consistent; thus, return false.
+                Map.Entry entry = (Map.Entry) usesIter.next();
+                if ((usesMap.get(entry.getKey()) != null) &&
+                    (usesMap.get(entry.getKey()) != entry.getValue()))
+                {
+                    return false;
+                }
+            }
+    
+            // Since the current candidate's uses constraints did not
+            // conflict with existing constraints, merge all constraints
+            // and keep testing the remaining candidates for the other
+            // imports of the root module.
+            usesMap.putAll(candUsesMap);
+        }
+    
+        return true;
+    }
+
+    private Map calculateUsesDependencies(
+        Map resolverMap, IModule module, R4Export export, Map usesMap)
+    {
+// TODO: CAN THIS BE OPTIMIZED?
+// TODO: IS THIS CYCLE CHECK CORRECT??
+// TODO: WHAT HAPPENS THERE ARE OVERLAPS WHEN CALCULATING USES??
+//       MAKE AN EXAMPLE WHERE TWO DEPENDENCIES PROVIDE SAME PACKAGE.
+        // Make sure we are not in a cycle.
+        if (usesMap.get(export.getName()) != null)
+        {
+            return usesMap;
+        }
+
+        // The target package at least uses itself,
+        // so add it to the uses map.
+        usesMap.put(export.getName(), module);
+
+        // Get the "uses" constraints for the target export
+        // package and calculate the transitive uses constraints
+        // of any used packages.
+        String[] uses = export.getUses();
+        List nodeList = (List) resolverMap.get(module);
+
+        // We need to walk the transitive closure of "uses" relationships
+        // for the current export package to calculate the entire set of
+        // "uses" constraints.
+        for (int usesIdx = 0; usesIdx < uses.length; usesIdx++)
+        {
+            // There are two possibilities at this point: 1) we are dealing
+            // with an already resolved bundle or 2) we are dealing with a
+            // bundle that has not yet been resolved. In case 1, there will
+            // be no resolver node in the resolver map, so we just need to
+            // examine the bundle directly to determine its exact constraints.
+            // In case 2, there will be a resolver node in the resolver map,
+            // so we will use that to determine the potential constraints of
+            // potential candidate for resolving the import.
+
+            // This is case 1, described in the comment above.
+            if (nodeList == null)
+            {
+                // Get the actual exporter from the wire or if there
+                // is no wire, then get the export is from the module
+                // itself.
+                R4Wire wire = Util.getWire(module, uses[usesIdx]);
+                if (wire != null)
+                {
+                    usesMap = calculateUsesDependencies(
+                        resolverMap, wire.getExportingModule(), wire.getExport(), usesMap);
+                }
+                else
+                {
+                    export = Util.getExportPackage(module, uses[usesIdx]);
+                    if (export != null)
+                    {
+                        usesMap = calculateUsesDependencies(
+                            resolverMap, module, export, usesMap);
+                    }
+                }
+            }
+            // This is case 2, described in the comment above.
+            else
+            {
+                // First, get the resolver node for the "used" package.
+                ResolverNode node = null;
+                for (int nodeIdx = 0;
+                    (node == null) && (nodeIdx < nodeList.size());
+                    nodeIdx++)
+                {
+                    node = (ResolverNode) nodeList.get(nodeIdx);
+                    if (!node.m_import.getName().equals(uses[usesIdx]))
+                    {
+                        node = null;
+                    }
+                }
+    
+                // If there is a resolver node for the "used" package,
+                // then this means that the module imports the package
+                // and we need to recursively add the constraints of
+                // the potential exporting module.
+                if (node != null)
+                {
+                    usesMap = calculateUsesDependencies(
+                        resolverMap,
+                        node.m_candidates[node.m_idx],
+                        Util.getExportPackage(node.m_candidates[node.m_idx], node.m_import.getName()),
+                        usesMap);
+                }
+                // If there was no resolver node for the "used" package,
+                // then this means that the module exports the package
+                // and we need to recursively add the constraints of this
+                // other exported package of this module.
+                else if (Util.getExportPackage(module, uses[usesIdx]) != null)
+                {
+                    usesMap = calculateUsesDependencies(
+                        resolverMap,
+                        module,
+                        Util.getExportPackage(module, uses[usesIdx]),
+                        usesMap);
+                }
+            }
+        }
+
+        return usesMap;
+    }
+
+    private void incrementCandidateConfiguration(List resolverList)
+        throws ResolveException
+    {
+        for (int i = 0; i < resolverList.size(); i++)
+        {
+            List nodeList = (List) resolverList.get(i);
+            for (int j = 0; j < nodeList.size(); j++)
+            {
+                ResolverNode node = (ResolverNode) nodeList.get(j);
+                // See if we can increment the node, without overflowing
+                // the candidate array bounds.
+                if ((node.m_idx + 1) < node.m_candidates.length)
+                {
+                    node.m_idx++;
+                    return;
+                }
+                // If the index will overflow the candidate array bounds,
+                // then set the index back to zero and try to increment
+                // the next candidate.
+                else
+                {
+                    node.m_idx = 0;
+                }
+            }
+        }
+        throw new ResolveException(
+            "Unable to resolve due to constraint violation.", null, null);
+    }
+
+    private Map createWires(Map resolverMap, IModule rootModule)
+    {
+        Map resolvedModuleWireMap =
+            populateWireMap(resolverMap, rootModule, new HashMap());
+        Iterator iter = resolvedModuleWireMap.entrySet().iterator();
+        while (iter.hasNext())
+        {
+            Map.Entry entry = (Map.Entry) iter.next();
+            IModule module = (IModule) entry.getKey();
+            R4Wire[] wires = (R4Wire[]) entry.getValue();
+    
+            // Set the module's resolved and wiring attribute.
+            setResolved(module, true);
+            // Only add wires attribute if some exist; export
+            // only modules may not have wires.
+            if (wires.length > 0)
+            {
+                setWires(module, wires);
+            }
+    
+            // Remove the wire's exporting module from the "available"
+            // package map and put it into the "in use" package map;
+            // these steps may be a no-op.
+            for (int wireIdx = 0;
+                (wires != null) && (wireIdx < wires.length);
+                wireIdx++)
+            {
+m_logger.log(Logger.LOG_DEBUG, "WIRE: [" + module + "] " + wires[wireIdx]);
+                // First remove the wire module from "available" package map.
+                IModule[] modules = (IModule[]) m_availPkgMap.get(wires[wireIdx].getExport().getName());
+                modules = removeModuleFromArray(modules, wires[wireIdx].getExportingModule());
+                m_availPkgMap.put(wires[wireIdx].getExport().getName(), modules);
+    
+                // Also remove any exported packages from the "available"
+                // package map that are from the module associated with
+                // the current wires where the exported packages were not
+                // actually exported; an export may not be exported if
+                // the module also imports the same package and was wired
+                // to a different module. If the exported package is not
+                // actually exported, then we just want to remove it
+                // completely, since it cannot be used.
+                if (wires[wireIdx].getExportingModule() != module)
+                {
+                    modules = (IModule[]) m_availPkgMap.get(wires[wireIdx].getExport().getName());
+                    modules = removeModuleFromArray(modules, module);
+                    m_availPkgMap.put(wires[wireIdx].getExport().getName(), modules);
+                }
+    
+                // Add the module of the wire to the "in use" package map.
+                modules = (IModule[]) m_inUsePkgMap.get(wires[wireIdx].getExport().getName());
+                modules = addModuleToArray(modules, wires[wireIdx].getExportingModule());
+                m_inUsePkgMap.put(wires[wireIdx].getExport().getName(), modules);
+            }
+        }
+        return resolvedModuleWireMap;
+    }
+
+    private Map populateWireMap(Map resolverMap, IModule module, Map wireMap)
+    {
+        // If the module is already resolved or it is part of
+        // a cycle, then just return the wire map.
+        if (isResolved(module) || (wireMap.get(module) != null))
+        {
+            return wireMap;
+        }
+    
+        List nodeList = (List) resolverMap.get(module);
+        R4Wire[] wires = new R4Wire[nodeList.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(module, wires);
+    
+        // Loop through each resolver node and create a wire
+        // for the selected candidate for the associated import.
+        for (int nodeIdx = 0; nodeIdx < nodeList.size(); nodeIdx++)
+        {
+            // Get the import's associated resolver node.
+            ResolverNode node = (ResolverNode) nodeList.get(nodeIdx);
+    
+            // Add the candidate to the list of wires.
+            R4Export export =
+                Util.getExportPackage(node.m_candidates[node.m_idx], node.m_import.getName());
+            wires[nodeIdx] = new R4Wire(module, node.m_candidates[node.m_idx], export);
+    
+            // Create the wires for the selected candidate module.
+            wireMap = populateWireMap(resolverMap, node.m_candidates[node.m_idx], wireMap);
+        }
+    
+        return wireMap;
+    }
+
+    //
+    // Event handling methods for validation events.
+    //
+
+    /**
+     * Adds a resolver listener to the search policy. Resolver
+     * listeners are notified when a module is resolve and/or unresolved
+     * by the search policy.
+     * @param l the resolver listener to add.
+    **/
+    public void addResolverListener(ResolveListener l)
+    {
+        // Verify listener.
+        if (l == null)
+        {
+            throw new IllegalArgumentException("Listener is null");
+        }
+
+        // Use the m_noListeners object as a lock.
+        synchronized (m_emptyListeners)
+        {
+            // If we have no listeners, then just add the new listener.
+            if (m_listeners == m_emptyListeners)
+            {
+                m_listeners = new ResolveListener[] { 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
+            {
+                ResolveListener[] newList = new ResolveListener[m_listeners.length + 1];
+                System.arraycopy(m_listeners, 0, newList, 0, m_listeners.length);
+                newList[m_listeners.length] = l;
+                m_listeners = newList;
+            }
+        }
+    }
+
+    /**
+     * Removes a resolver listener to this search policy.
+     * @param l the resolver listener to remove.
+    **/
+    public void removeResolverListener(ResolveListener l)
+    {
+        // Verify listener.
+        if (l == null)
+        {
+            throw new IllegalArgumentException("Listener is null");
+        }
+
+        // Use the m_emptyListeners object as a lock.
+        synchronized (m_emptyListeners)
+        {
+            // 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_emptyListeners;
+                }
+                // 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
+                {
+                    ResolveListener[] newList = new ResolveListener[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;
+                }
+            }
+        }
+    }
+
+    /**
+     * Fires a validation event for the specified module.
+     * @param module the module that was resolved.
+    **/
+    private void fireModuleResolved(IModule module)
+    {
+        // Event holder.
+        ModuleEvent event = null;
+
+        // Get a copy of the listener array, which is guaranteed
+        // to not be null.
+        ResolveListener[] 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(m_factory, module);
+            }
+            listeners[i].moduleResolved(event);
+        }
+    }
+
+    /**
+     * Fires an unresolved event for the specified module.
+     * @param module the module that was unresolved.
+    **/
+    private void fireModuleUnresolved(IModule module)
+    {
+// TODO: Call this method where appropriate.
+        // Event holder.
+        ModuleEvent event = null;
+
+        // Get a copy of the listener array, which is guaranteed
+        // to not be null.
+        ResolveListener[] 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(m_factory, module);
+            }
+            listeners[i].moduleUnresolved(event);
+        }
+    }
+
+    //
+    // ModuleListener callback methods.
+    //
+
+    public void moduleAdded(ModuleEvent event)
+    {
+    }
+
+    public void moduleRemoved(ModuleEvent event)
+    {
+        // When a module is removed from the system, we need remove
+        // its exports from the "in use" and "available" package maps
+        // as well as remove the module from the module data map.
+
+        // Synchronize on the module manager, since we don't want any
+        // bundles to be installed or removed.
+        synchronized (m_factory)
+        {
+            // Remove exports from package maps.
+            R4Export[] exports = getExports(event.getModule());
+            for (int i = 0; (exports != null) && (i < exports.length); i++)
+            {
+                // Remove from "available" package map.
+                IModule[] modules = (IModule[]) m_availPkgMap.get(exports[i].getName());
+                if (modules != null)
+                {
+                    modules = removeModuleFromArray(modules, event.getModule());
+                    m_availPkgMap.put(exports[i].getName(), modules);
+                }
+                // Remove from "in use" package map.
+                modules = (IModule[]) m_inUsePkgMap.get(exports[i].getName());
+                if (modules != null)
+                {
+                    modules = removeModuleFromArray(modules, event.getModule());
+                    m_inUsePkgMap.put(exports[i].getName(), modules);
+                }
+            }
+
+            // Finally, remove module data.
+            m_moduleDataMap.remove(event.getModule());
+        }
+    }
+
+    //
+    // Simple utility methods.
+    //
+
+    private static IModule[] addModuleToArray(IModule[] modules, IModule m)
+    {
+        // Verify that the module is not already in the array.
+        for (int i = 0; (modules != null) && (i < modules.length); i++)
+        {
+            if (modules[i] == m)
+            {
+                return modules;
+            }
+        }
+
+        if (modules != null)
+        {
+            IModule[] newModules = new IModule[modules.length + 1];
+            System.arraycopy(modules, 0, newModules, 0, modules.length);
+            newModules[modules.length] = m;
+            modules = newModules;
+        }
+        else
+        {
+            modules = new IModule[] { m };
+        }
+
+        return modules;
+    }
+
+    private static IModule[] removeModuleFromArray(IModule[] modules, IModule m)
+    {
+        if (modules == null)
+        {
+            return m_emptyModules;
+        }
+
+        int idx = -1;
+        for (int i = 0; i < modules.length; i++)
+        {
+            if (modules[i] == m)
+            {
+                idx = i;
+                break;
+            }
+        }
+
+        if (idx >= 0)
+        {
+            // If this is the module, then point to empty list.
+            if ((modules.length - 1) == 0)
+            {
+                modules = m_emptyModules;
+            }
+            // Otherwise, we need to do some array copying.
+            else
+            {
+                IModule[] newModules= new IModule[modules.length - 1];
+                System.arraycopy(modules, 0, newModules, 0, idx);
+                if (idx < newModules.length)
+                {
+                    System.arraycopy(
+                        modules, idx + 1, newModules, idx, newModules.length - idx);
+                }
+                modules = newModules;
+            }
+        }
+        return modules;
+    }
+
+    private static IModule[] shrinkModuleArray(IModule[] modules)
+    {
+        if (modules == null)
+        {
+            return m_emptyModules;
+        }
+
+        int count = 0;
+        for (int i = 0; i < modules.length; i++)
+        {
+            if (modules[i] == null)
+            {
+                count++;
+            }
+        }
+
+        if (count > 0)
+        {
+            IModule[] newModules = new IModule[modules.length - count];
+            count = 0;
+            for (int i = 0; i < modules.length; i++)
+            {
+                if (modules[i] != null)
+                {
+                    newModules[count++] = modules[i];
+                }
+            }
+            modules = newModules;
+        }
+
+        return modules;
+    }
+
+    //
+    // Simple utility classes.
+    //
+
+    private static class ModuleData
+    {
+        public IModule m_module = null;
+        public R4Export[] m_exports = null;
+        public R4Import[] m_imports = null;
+        public R4Import[] m_dynamicImports = null;
+        public R4Library[] m_libraries = null;
+        public R4Wire[] m_wires = null;
+        public boolean m_resolved = false;
+        public ModuleData(IModule module)
+        {
+            m_module = module;
+        }
+    }
+
+    private class ResolverNode
+    {
+        public IModule m_module = null;
+        public R4Import m_import = null;
+        public IModule[] m_candidates = null;
+        public int m_idx = 0;
+        public boolean m_visited = false;
+        public ResolverNode(IModule module, R4Import imp, IModule[] candidates)
+        {
+            m_module = module;
+            m_import = imp;
+            m_candidates = candidates;
+            if (isResolved(m_module))
+            {
+                m_visited = true;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Version.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Version.java
deleted file mode 100644
index c57975e..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Version.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.StringTokenizer;
-
-public class R4Version implements Comparable
-{
-    private int m_major = 0;
-    private int m_minor = 0;
-    private int m_micro = 0;
-    private String m_qualifier = "";
-    private boolean m_isInclusive = true;
-
-    private static final String SEPARATOR = ".";
-
-    public R4Version(String versionString)
-    {
-        this(versionString, true);
-    }
-
-    public R4Version(String versionString, boolean isInclusive)
-    {
-        if (versionString == null)
-        {
-            versionString = "0.0.0";
-        }
-        Object[] objs = parseVersion(versionString);
-        m_major = ((Integer) objs[0]).intValue();
-        m_minor = ((Integer) objs[1]).intValue();
-        m_micro = ((Integer) objs[2]).intValue();
-        m_qualifier = (String) objs[3];
-        m_isInclusive = isInclusive;
-    }
-
-    private static Object[] parseVersion(String versionString)
-    {
-        String s = versionString.trim();
-        Object[] objs = new Object[4];
-        objs[0] = objs[1] = objs[2] = new Integer(0);
-        objs[3] = "";
-        StringTokenizer tok = new StringTokenizer(s, SEPARATOR);
-        try
-        {
-            objs[0] = Integer.valueOf(tok.nextToken());
-            if (tok.hasMoreTokens())
-            {
-                objs[1] = Integer.valueOf(tok.nextToken());
-                if (tok.hasMoreTokens())
-                {
-                    objs[2] = Integer.valueOf(tok.nextToken());
-                    if (tok.hasMoreTokens())
-                    {
-                        objs[3] = tok.nextToken();
-                    }
-                }
-            }
-        }
-        catch (NumberFormatException ex)
-        {
-            throw new IllegalArgumentException("Invalid version: " + versionString);
-        }
-
-        if ((((Integer) objs[0]).intValue() < 0) ||
-            (((Integer) objs[0]).intValue() < 0) ||
-            (((Integer) objs[0]).intValue() < 0))
-        {
-            throw new IllegalArgumentException("Invalid version: " + versionString);
-        }
-
-        return objs;
-    }
-
-    public boolean equals(Object object)
-    {
-        if (!(object instanceof R4Version))
-        {
-            return false;
-        }
-        R4Version v = (R4Version) object;
-        return
-            (v.getMajorComponent() == m_major) &&
-            (v.getMinorComponent() == m_minor) &&
-            (v.getMicroComponent() == m_micro) &&
-            (v.getQualifierComponent().equals(m_qualifier));
-    }
-
-    public int getMajorComponent()
-    {
-        return m_major;
-    }
-
-    public int getMinorComponent()
-    {
-        return m_minor;
-    }
-
-    public int getMicroComponent()
-    {
-        return m_micro;
-    }
-
-    public String getQualifierComponent()
-    {
-        return m_qualifier;
-    }
-
-    public boolean isInclusive()
-    {
-        return m_isInclusive;
-    }
-
-    public int compareTo(Object o)
-    {
-        if (!(o instanceof R4Version))
-            throw new ClassCastException();
-
-        if (equals(o))
-            return 0;
-
-        if (isGreaterThan((R4Version) o))
-            return 1;
-
-        return -1;
-    }
-
-    public boolean isGreaterThan(R4Version v)
-    {
-        if (v == null)
-        {
-            return false;
-        }
-
-        if (m_major > v.getMajorComponent())
-        {
-            return true;
-        }
-        if (m_major < v.getMajorComponent())
-        {
-            return false;
-        }
-        if (m_minor > v.getMinorComponent())
-        {
-            return true;
-        }
-        if (m_minor < v.getMinorComponent())
-        {
-            return false;
-        }
-        if (m_micro > v.getMicroComponent())
-        {
-            return true;
-        }
-        if (m_micro < v.getMicroComponent())
-        {
-            return false;
-        }
-        if (m_qualifier.compareTo(v.getQualifierComponent()) > 0)
-        {
-            return true;
-        }
-        else
-        {
-            return false;
-        }
-    }
-
-    public String toString()
-    {
-        if (m_qualifier.length() == 0)
-        {
-            return m_major + "." + m_minor + "." + m_micro; 
-        }
-        return m_major + "." + m_minor + "." + m_micro + "." + m_qualifier; 
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java
index e249fcc..5f5e361 100755
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -16,21 +16,100 @@
  */
 package org.apache.felix.framework.searchpolicy;
 
-import org.apache.felix.moduleloader.Module;
+import java.net.URL;
+
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.moduleloader.*;
 
 public class R4Wire
 {
-    public R4Package m_pkg = null;
-    public Module m_module = null;
-    
-    public R4Wire(R4Package pkg, Module module)
+    private IModule m_importer = null;
+    private IModule m_exporter = null;
+    private R4Export m_export= null;
+
+    public R4Wire(IModule importer, IModule exporter, R4Export export)
     {
-        m_pkg = pkg;
-        m_module = module;
+        m_importer = importer;
+        m_exporter = exporter;
+        m_export = export;
     }
-    
+
+    public IModule getImportingModule()
+    {
+        return m_importer;
+    }
+
+    public IModule getExportingModule()
+    {
+        return m_exporter;
+    }
+
+    public R4Export getExport()
+    {
+        return m_export;
+    }
+
+    public Class getClass(String name) throws ClassNotFoundException
+    {
+        Class clazz = null;
+
+        // Get the package of the target class.
+        String pkgName = Util.getClassPackage(name);
+
+        // Only check when the package of the target class is
+        // the same as the package for the wire.
+        if (m_export.getName().equals(pkgName))
+        {
+            // Before delegating to the exporting module to satisfy
+            // the class load, we must check the include/exclude filters
+            // from the target package to make sure that the class is
+            // actually visible. However, if the exporting module is the
+            // same as the requesting module, then filtering is not
+            // performed since a module has complete access to itself.
+            if ((m_exporter == m_importer) || m_export.isIncluded(name))
+            {
+                clazz = m_exporter.getContentLoader().getClass(name);
+            }
+
+            // If no class was found, then we must throw an exception
+            // since the exporter for this package did not contain the
+            // requested class.
+            if (clazz == null)
+            {
+                throw new ClassNotFoundException(name);
+            }
+        }
+
+        return clazz;
+    }
+
+    public URL getResource(String name) throws ResourceNotFoundException
+    {
+        URL url = null;
+
+        // Get the package of the target class.
+        String pkgName = Util.getResourcePackage(name);
+
+        // Only check when the package of the target resource is
+        // the same as the package for the wire.
+        if (m_export.getName().equals(pkgName))
+        {
+            url = m_exporter.getContentLoader().getResource(name);
+
+            // If no resource was found, then we must throw an exception
+            // since the exporter for this package did not contain the
+            // requested class.
+            if (url == null)
+            {
+                throw new ResourceNotFoundException(name);
+            }
+        }
+
+        return url;
+    }
+
     public String toString()
     {
-        return m_pkg.getId() + " -> " + m_module;
+        return m_importer + " -> " + m_export.getName() + " -> " + m_exporter;
     }
 }
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ResolveException.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ResolveException.java
similarity index 84%
rename from org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ResolveException.java
rename to org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ResolveException.java
index abc342c..b1632da 100755
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ResolveException.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ResolveException.java
@@ -14,10 +14,9 @@
  *   limitations under the License.
  *
  */
-package org.apache.felix.moduleloader.search;
+package org.apache.felix.framework.searchpolicy;
 
-import org.apache.felix.framework.searchpolicy.R4Package;
-import org.apache.felix.moduleloader.Module;
+import org.apache.felix.moduleloader.IModule;
 
 /**
  * <p>
@@ -30,14 +29,14 @@
 **/
 public class ResolveException extends Exception
 {
-    private Module m_module = null;
+    private IModule m_module = null;
     private R4Package m_pkg = null;
 
     /**
      * Constructs an exception with the specified message, module,
      * import identifier, import version number, and propagation flag.
     **/
-    public ResolveException(String msg, Module module, R4Package pkg)
+    public ResolveException(String msg, IModule module, R4Package pkg)
     {
         super(msg);
         m_module = module;
@@ -48,7 +47,7 @@
      * Returns the module that was being resolved.
      * @return the module that was being resolved.
     **/
-    public Module getModule()
+    public IModule getModule()
     {
         return m_module;
     }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ResolveListener.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ResolveListener.java
similarity index 92%
rename from org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ResolveListener.java
rename to org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ResolveListener.java
index a502021..2ed2a62 100755
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ResolveListener.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/ResolveListener.java
@@ -14,7 +14,7 @@
  *   limitations under the License.
  *
  */
-package org.apache.felix.moduleloader.search;
+package org.apache.felix.framework.searchpolicy;
 
 import java.util.EventListener;
 
@@ -26,7 +26,7 @@
  * events that are generated by the <tt>R4SearchPolicy</tt>. Events
  * are fired when a module is resolved and when it is unresolved.
  * </p>
- * @see org.apache.felix.framework.searchpolicy.R4SearchPolicy
+ * @see org.apache.felix.framework.searchpolicy.R4SearchPolicyCore
 **/
 public interface ResolveListener extends EventListener
 {
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/URLPolicyImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/URLPolicyImpl.java
new file mode 100644
index 0000000..19cf1cf
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/URLPolicyImpl.java
@@ -0,0 +1,67 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.*;
+
+import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.framework.util.SecureAction;
+import org.apache.felix.moduleloader.IModule;
+import org.apache.felix.moduleloader.IURLPolicy;
+
+public class URLPolicyImpl implements IURLPolicy
+{
+    private Logger m_logger = null;
+    private URLStreamHandler m_streamHandler = null;
+    private IModule m_module = null;
+    private static SecureAction m_secureAction = new SecureAction();
+
+// TODO: FIX - IT SUCKS HAVING A URL POLICY OBJECT PER MODULE!
+    public URLPolicyImpl(Logger logger, URLStreamHandler streamHandler, IModule module)
+    {
+        m_logger = logger;
+        m_streamHandler = streamHandler;
+        m_module = module;
+    }
+
+    public URL createURL(String path)
+    {
+         // Add a slash if there is one already, otherwise
+         // the is no slash separating the host from the file
+         // in the resulting URL.
+         if (!path.startsWith("/"))
+         {
+             path = "/" + path;
+         }
+
+         try
+         {
+             return m_secureAction.createURL(
+                 FelixConstants.BUNDLE_URL_PROTOCOL,
+                 m_module.getId(), -1, path, m_streamHandler);
+         }
+         catch (MalformedURLException ex)
+         {
+             m_logger.log(
+                 Logger.LOG_ERROR,
+                 "Unable to create resource URL.",
+                 ex);
+         }
+         return null;
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/VersionRange.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/VersionRange.java
new file mode 100644
index 0000000..c77a63e
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/VersionRange.java
@@ -0,0 +1,96 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.osgi.framework.Version;
+
+public class VersionRange
+{
+    private Version m_low = null;
+    private boolean m_isLowInclusive = false;
+    private Version m_high = null;
+    private boolean m_isHighInclusive = false;
+
+    public VersionRange(Version low, boolean isLowInclusive,
+        Version high, boolean isHighInclusive)
+    {
+        m_low = low;
+        m_isLowInclusive = isLowInclusive;
+        m_high = high;
+        m_isHighInclusive = isHighInclusive;
+    }
+
+    public Version getLow()
+    {
+        return m_low;
+    }
+
+    public boolean isLowInclusive()
+    {
+        return m_isLowInclusive;
+    }
+
+    public Version getHigh()
+    {
+        return m_high;
+    }
+
+    public boolean isHighInclusive()
+    {
+        return m_isHighInclusive;
+    }
+
+    public boolean isInRange(Version version)
+    {
+        // We might not have an upper end to the range.
+        if (m_high == null)
+        {
+            return (version.compareTo(m_low) >= 0);
+        }
+        else if (isLowInclusive() && isHighInclusive())
+        {
+            return (version.compareTo(m_low) >= 0) && (version.compareTo(m_high) <= 0);
+        }
+        else if (isHighInclusive())
+        {
+            return (version.compareTo(m_low) > 0) && (version.compareTo(m_high) <= 0);
+        }
+        else if (isLowInclusive())
+        {
+            return (version.compareTo(m_low) >= 0) && (version.compareTo(m_high) < 0);
+        }
+        return (version.compareTo(m_low) > 0) && (version.compareTo(m_high) < 0);
+    }
+
+    public static VersionRange parse(String range)
+    {
+        // Check if the version is an interval.
+        if (range.indexOf(',') >= 0)
+        {
+            String s = range.substring(1, range.length() - 1);
+            String vlo = s.substring(0, s.indexOf(','));
+            String vhi = s.substring(s.indexOf(',') + 1, s.length());
+            return new VersionRange (
+                new Version(vlo), (range.charAt(0) == '['),
+                new Version(vhi), (range.charAt(range.length() - 1) == ']'));
+        }
+        else
+        {
+            return new VersionRange(new Version(range), true, null, false);
+        }
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/DispatchQueue.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/DispatchQueue.java
index 73d8086..b27278d 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/DispatchQueue.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/DispatchQueue.java
@@ -18,7 +18,7 @@
 
 import java.util.*;
 
-import org.apache.felix.framework.LogWrapper;
+import org.apache.felix.framework.Logger;
 
 /**
  * This class implements an event dispatching queue to simplify delivering
@@ -66,13 +66,13 @@
     // Cached dispatch requests to avoid memory allocation.
     private static final ArrayList m_requestCache = new ArrayList();
     // The logger for dispatch queue.
-    private static LogWrapper m_logger = null;
+    private static Logger m_logger = null;
 
     /**
      * Constructs a dispatch queue and starts a dispather thread if
      * necessary.
     **/
-    public DispatchQueue(LogWrapper logger)
+    public DispatchQueue(Logger logger)
     {
         synchronized (m_threadLock)
         {
@@ -127,7 +127,7 @@
         }
     }
 
-    public static LogWrapper getLogger()
+    public static Logger getLogger()
     {
         return m_logger;
     }
@@ -360,7 +360,7 @@
                     try {
                         m_requestList.wait();
                     } catch (InterruptedException ex) {
-                        m_logger.log(LogWrapper.LOG_ERROR, "DispatchQueue: Thread interrupted.", ex);
+                        m_logger.log(Logger.LOG_ERROR, "DispatchQueue: Thread interrupted.", ex);
                     }
                 }
 
@@ -396,7 +396,7 @@
                             dr.m_dispatcher.dispatch(
                                 (EventListener) dr.m_listeners[i + 1], dr.m_eventObj);
                         } catch (Throwable th) {
-                            m_logger.log(LogWrapper.LOG_ERROR, "DispatchQueue: Error during dispatch.", th);
+                            m_logger.log(Logger.LOG_ERROR, "DispatchQueue: Error during dispatch.", th);
                         }
                     }
                 }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/FelixDispatchQueue.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/FelixDispatchQueue.java
index 4a008b3..354c05b 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/FelixDispatchQueue.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/FelixDispatchQueue.java
@@ -19,7 +19,7 @@
 import java.util.EventListener;
 import java.util.EventObject;
 
-import org.apache.felix.framework.LogWrapper;
+import org.apache.felix.framework.Logger;
 import org.osgi.framework.*;
 
 /**
@@ -36,7 +36,7 @@
 **/
 public class FelixDispatchQueue extends DispatchQueue
 {
-    public FelixDispatchQueue(LogWrapper logger)
+    public FelixDispatchQueue(Logger logger)
     {
         super(logger);
     }
@@ -77,7 +77,7 @@
                             (EventListener) lw, eventObj);
                     } catch (Throwable th) {
                         getLogger().log(
-                            LogWrapper.LOG_ERROR,
+                            Logger.LOG_ERROR,
                             "FelixDispatchQueue: Error during dispatch.", th);
                     }
                 }
@@ -100,7 +100,7 @@
                             (EventListener) lw, eventObj);
                     } catch (Throwable th) {
                         getLogger().log(
-                            LogWrapper.LOG_ERROR,
+                            Logger.LOG_ERROR,
                             "FelixDispatchQueue: Error during dispatch.", th);
                     }
                 }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/ObjectInputStreamX.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/ObjectInputStreamX.java
index b7f79a8..e30b47c 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/ObjectInputStreamX.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/ObjectInputStreamX.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@
 
 import java.io.*;
 
+import org.apache.felix.moduleloader.IContentLoader;
+
 /**
  * The ObjectInputStreamX class is a simple extension to the ObjectInputStream
  * class.  The purpose of ObjectInputStreamX is to allow objects to be deserialized
@@ -25,7 +27,7 @@
  */
 public class ObjectInputStreamX extends ObjectInputStream
 {
-    private ClassLoader m_loader = null;
+    private IContentLoader m_contentLoader = null;
 
     /**
      * Construct an ObjectInputStreamX for the specified InputStream and the specified
@@ -33,11 +35,11 @@
      * @param in the input stream to read.
      * @param loader the class loader used to resolve classes.
      */
-    public ObjectInputStreamX(InputStream in, ClassLoader loader)
+    public ObjectInputStreamX(InputStream in, IContentLoader contentLoader)
         throws IOException, StreamCorruptedException
     {
         super(in);
-        this.m_loader = loader;
+        m_contentLoader = contentLoader;
     }
 
     /**
@@ -47,7 +49,6 @@
     protected Class resolveClass(ObjectStreamClass v)
         throws IOException, ClassNotFoundException
     {
-        Class clazz = m_loader.loadClass(v.getName());
-        return clazz;
+        return m_contentLoader.getClass(v.getName());
     }
 }
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/SecureAction.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
index 759305d..545425a 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
@@ -16,6 +16,7 @@
  */
 package org.apache.felix.framework.util;
 
+import java.net.*;
 import java.security.*;
 
 /**
@@ -33,20 +34,21 @@
 public class SecureAction
 {
     private AccessControlContext m_acc = null;
+    private Actions m_actions = new Actions();
 
     public SecureAction()
     {
         m_acc = AccessController.getContext();
     }
 
-    public String getProperty(String name, String def)
+    public synchronized String getProperty(String name, String def)
     {
         if (System.getSecurityManager() != null)
         {
             try
             {
-                return (String) AccessController.doPrivileged(
-                    new Actions(Actions.GET_PROPERTY_ACTION, name, def), m_acc);
+                m_actions.set(Actions.GET_PROPERTY_ACTION, name, def);
+                return (String) AccessController.doPrivileged(m_actions, m_acc);
             }
             catch (PrivilegedActionException ex)
             {
@@ -59,14 +61,14 @@
         }
     }
 
-    public Class forName(String name) throws ClassNotFoundException
+    public synchronized Class forName(String name) throws ClassNotFoundException
     {
         if (System.getSecurityManager() != null)
         {
             try
             {
-                return (Class) AccessController.doPrivileged(
-                    new Actions(Actions.FOR_NAME_ACTION, name), m_acc);
+                m_actions.set(Actions.FOR_NAME_ACTION, name);
+                return (Class) AccessController.doPrivileged(m_actions, m_acc);
             }
             catch (PrivilegedActionException ex)
             {
@@ -83,26 +85,87 @@
         }
     }
 
+    public synchronized URL createURL(String protocol, String host,
+        int port, String path, URLStreamHandler handler)
+        throws MalformedURLException
+    {
+        if (System.getSecurityManager() != null)
+        {
+            try 
+            {
+                m_actions.set(
+                    Actions.CREATE_URL_ACTION, protocol, host, port, path, handler);
+                return (URL) AccessController.doPrivileged(m_actions, m_acc);
+            }
+            catch (PrivilegedActionException ex)
+            {
+                if (ex.getException() instanceof MalformedURLException)
+                {
+                    throw (MalformedURLException) ex.getException();
+                }
+                throw (RuntimeException) ex.getException();
+            }
+        }
+        else
+        {
+            return new URL(protocol, host, port, path, handler);
+        }
+    }
+
     private static class Actions implements PrivilegedExceptionAction
     {
         public static final int GET_PROPERTY_ACTION = 0;
         public static final int FOR_NAME_ACTION = 1;
+        public static final int CREATE_URL_ACTION = 2;
 
         private int m_action = -1;
         private Object m_arg1 = null;
         private Object m_arg2 = null;
 
-        public Actions(int action, Object arg1)
+        private String m_protocol = null;
+        private String m_host = null;
+        private int m_port = -1;
+        private String m_path = null;
+        private URLStreamHandler m_handler = null;
+
+        public void set(int action, Object arg1)
         {
             m_action = action;
             m_arg1 = arg1;
+
+            m_arg2 = null;
+            m_protocol = null;
+            m_host = null;
+            m_port = -1;
+            m_path = null;
+            m_handler = null;
         }
 
-        public Actions(int action, Object arg1, Object arg2)
+        public void set(int action, Object arg1, Object arg2)
         {
             m_action = action;
             m_arg1 = arg1;
             m_arg2 = arg2;
+
+            m_protocol = null;
+            m_host = null;
+            m_port = -1;
+            m_path = null;
+            m_handler = null;
+        }
+
+        public void set(int action, String protocol, String host,
+            int port, String path, URLStreamHandler handler)
+        {
+            m_action = action;
+            m_protocol = protocol;
+            m_host = host;
+            m_port = port;
+            m_path = path;
+            m_handler = handler;
+
+            m_arg1 = null;
+            m_arg2 = null;
         }
 
         public Object run() throws Exception
@@ -111,10 +174,14 @@
             {
                 return System.getProperty((String) m_arg1, (String) m_arg2);
             }
-            else if (m_action ==FOR_NAME_ACTION)
+            else if (m_action == FOR_NAME_ACTION)
             {
                 return Class.forName((String) m_arg1);
             }
+            else if (m_action == CREATE_URL_ACTION)
+            {
+                return new URL(m_protocol, m_host, m_port, m_path, m_handler);
+            }
             return null;
         }
     }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/Util.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/Util.java
index 534b776..bf3e922 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/Util.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/util/Util.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -20,9 +20,137 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.searchpolicy.*;
+import org.apache.felix.moduleloader.IModule;
+
 public class Util
 {
     /**
+     * Converts a module identifier to a bundle identifier. Module IDs
+     * are typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this
+     * method returns only the portion corresponding to the bundle ID.
+    **/
+    public static long getBundleIdFromModuleId(String id)
+    {
+        try
+        {
+            String bundleId = (id.indexOf('.') >= 0)
+                ? id.substring(0, id.indexOf('.')) : id;
+            return Long.parseLong(bundleId);
+        }
+        catch (NumberFormatException ex)
+        {
+            return -1;
+        }
+    }
+
+    /**
+     * Converts a module identifier to a bundle identifier. Module IDs
+     * are typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this
+     * method returns only the portion corresponding to the revision.
+    **/
+    public static int getModuleRevisionFromModuleId(String id)
+    {
+        try
+        {
+            String rev = (id.indexOf('.') >= 0)
+                ? id.substring(id.indexOf('.') + 1) : id;
+            return Integer.parseInt(rev);
+        }
+        catch (NumberFormatException ex)
+        {
+            return -1;
+        }
+    }
+
+    public static String getClassName(String className)
+    {
+        if (className == null)
+        {
+            className = "";
+        }
+        return (className.lastIndexOf('.') < 0)
+            ? "" : className.substring(className.lastIndexOf('.') + 1);
+    }
+
+    public static String getClassPackage(String className)
+    {
+        if (className == null)
+        {
+            className = "";
+        }
+        return (className.lastIndexOf('.') < 0)
+            ? "" : className.substring(0, className.lastIndexOf('.'));
+    }
+
+    public static String getResourcePackage(String resource)
+    {
+        if (resource == null)
+        {
+            resource = "";
+        }
+        // NOTE: The package of a resource is tricky to determine since
+        // resources do not follow the same naming conventions as classes.
+        // This code is pessimistic and assumes that the package of a
+        // resource is everything up to the last '/' character. By making
+        // this choice, it will not be possible to load resources from
+        // imports using relative resource names. For example, if a
+        // bundle exports "foo" and an importer of "foo" tries to load
+        // "/foo/bar/myresource.txt", this will not be found in the exporter
+        // because the following algorithm assumes the package name is
+        // "foo.bar", not just "foo". This only affects imported resources,
+        // local resources will work as expected.
+        String pkgName = (resource.startsWith("/")) ? resource.substring(1) : resource;
+        pkgName = (pkgName.lastIndexOf('/') < 0)
+            ? "" : pkgName.substring(0, pkgName.lastIndexOf('/'));
+        pkgName = pkgName.replace('/', '.');
+        return pkgName;
+    }
+
+    public static R4Export getExportPackage(IModule m, String name)
+    {
+        R4Export[] pkgs =
+            ((IR4SearchPolicy) m.getContentLoader().getSearchPolicy()).getExports();
+        for (int i = 0; (pkgs != null) && (i < pkgs.length); i++)
+        {
+            if (pkgs[i].getName().equals(name))
+            {
+                return pkgs[i];
+            }
+        }
+        return null;
+    }
+
+    public static R4Import getImportPackage(IModule m, String name)
+    {
+        R4Import[] pkgs =
+            ((IR4SearchPolicy) m.getContentLoader().getSearchPolicy()).getImports();
+        for (int i = 0; (pkgs != null) && (i < pkgs.length); i++)
+        {
+            if (pkgs[i].getName().equals(name))
+            {
+                return pkgs[i];
+            }
+        }
+        return null;
+    }
+
+    public static R4Wire getWire(IModule m, String name)
+    {
+        R4Wire[] wires =
+            ((IR4SearchPolicy) m.getContentLoader().getSearchPolicy()).getWires();
+        for (int i = 0; (wires != null) && (i < wires.length); i++)
+        {
+            if (wires[i].getExport().getName().equals(name))
+            {
+                return wires[i];
+            }
+        }
+        return null;
+    }
+
+    /**
      * Parses delimited string and returns an array containing the tokens. This
      * parser obeys quotes, so the delimiter character will be ignored if it is
      * inside of a quote. This method assumes that the quote character is not
@@ -97,19 +225,19 @@
      * @return an array of <tt>LibraryInfo</tt> objects for the
      *         passed in strings.
     **/
-    public static LibraryInfo[] parseLibraryStrings(String[] libStrs)
+    public static R4LibraryHeader[] parseLibraryStrings(Logger logger, String[] libStrs)
         throws IllegalArgumentException
     {
         if (libStrs == null)
         {
-            return null;
+            return new R4LibraryHeader[0];
         }
 
         List libList = new ArrayList();
 
         for (int i = 0; i < libStrs.length; i++)
         {
-            LibraryInfo[] libs = LibraryInfo.parse(libStrs[i]);
+            R4LibraryHeader[] libs = R4LibraryHeader.parse(logger, libStrs[i]);
             for (int libIdx = 0;
                 (libs != null) && (libIdx < libs.length);
                 libIdx++)
@@ -118,12 +246,7 @@
             }
         }
 
-        if (libList.size() == 0)
-        {
-            return null;
-        }
-
-        return (LibraryInfo[]) libList.toArray(new LibraryInfo[libList.size()]);
+        return (R4LibraryHeader[]) libList.toArray(new R4LibraryHeader[libList.size()]);
     }
 
     private static final byte encTab[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/DefaultURLPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/DefaultURLPolicy.java
deleted file mode 100644
index 0aa9d8d..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/DefaultURLPolicy.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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;
-
-/**
- * <p>
- * This class implements a simple <tt>URLPolicy</tt> that the <tt>ModuleManager</tt>
- * uses if the application does not specify one. This implementation always returns
- * <tt>null</tt> for <tt>CodeSource</tt> <tt>URL</tt>s, which means that security
- * is simply ignored. For resource <tt>URL</tt>s, it returns an <tt>URL</tt> in the
- * form of:
- * </p>
- * <pre>
- *     module://&lt;module-id&gt;/&lt;resource-path&gt;
- * </pre>
- * <p>
- * In order to properly handle the "<tt>module:</tt>" protocol, this policy
- * also defines a custom <tt>java.net.URLStreamHandler</tt> that it assigns
- * to each <tt>URL</tt> as it is created. This custom handler is used to
- * return a custom <tt>java.net.URLConnection</tt> that will correctly parse
- * the above <tt>URL</tt> and retrieve the associated resource bytes using
- * methods from <tt>ModuleManager</tt> and <tt>Module</tt>.
- * </p>
- * @see org.apache.felix.moduleloader.ModuleManager
- * @see org.apache.felix.moduleloader.Module
- * @see org.apache.felix.moduleloader.URLPolicy
-**/
-public class DefaultURLPolicy implements URLPolicy
-{
-    private ModuleURLStreamHandler m_handler = null;
-
-    /**
-     * <p>
-     * This method is a stub and always returns <tt>null</tt>.
-     * </p>
-     * @param mgr the <tt>ModuleManager</tt> of the module.
-     * @param module the module for which the <tt>URL</tt> is to be created.
-     * @return <tt>null</tt>.
-    **/
-    public URL createCodeSourceURL(ModuleManager mgr, Module module)
-    {
-        return null;
-    }
-
-    /**
-     * <p>
-     * This method returns a <tt>URL</tt> that is suitable
-     * for accessing the bytes of the specified resource.
-     * </p>
-     * @param mgr the <tt>ModuleManager</tt> of the module.
-     * @param module the module for which the resource is being loaded.
-     * @param rsIdx the index of the <tt>ResourceSource</tt> containing the resource.
-     * @param name the name of the resource being loaded.
-     * @return an <tt>URL</tt> for retrieving the resource.
-    **/
-    public URL createResourceURL(ModuleManager mgr, Module module, int rsIdx, String name)
-    {
-        if (m_handler == null)
-        {
-            m_handler = new ModuleURLStreamHandler(mgr);
-        }
-
-        // Add a slash if there is one already, otherwise
-        // the is no slash separating the host from the file
-        // in the resulting URL.
-        if (!name.startsWith("/"))
-        {
-            name = "/" + name;
-        }
-
-        try
-        {
-            return new URL("module", module.getId(), -1, "/" + rsIdx + name, m_handler);
-        }
-        catch (Exception ex)
-        {
-            System.err.println("DefaultResourceURLPolicy: " + ex);
-            return null;
-        }
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IContent.java
similarity index 62%
rename from org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java
rename to org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IContent.java
index 24595ec..a0e5653 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IContent.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -17,19 +17,15 @@
 package org.apache.felix.moduleloader;
 
 import java.io.IOException;
-import java.net.*;
+import java.io.InputStream;
 
-class ModuleURLStreamHandler extends URLStreamHandler
+public interface IContent
 {
-    private ModuleManager m_mgr = null;
-
-    public ModuleURLStreamHandler(ModuleManager mgr)
-    {
-        m_mgr = mgr;
-    }
-
-    protected URLConnection openConnection(URL url) throws IOException
-    {
-        return new ModuleURLConnection(m_mgr, url);
-    }
-}
+    public void open();
+    public void close();
+    public boolean hasEntry(String name);
+    public byte[] getEntry(String name);
+    public InputStream getEntryAsStream(String name)
+        throws IOException;
+    public String[] getEntryPaths(String path);
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IContentLoader.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IContentLoader.java
new file mode 100644
index 0000000..be88eca
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IContentLoader.java
@@ -0,0 +1,41 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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;
+
+public interface IContentLoader
+{
+    public void open();
+    public void close();
+
+    public IContent getContent();
+
+    public void setSearchPolicy(ISearchPolicy searchPolicy);
+    public ISearchPolicy getSearchPolicy();
+
+    public void setURLPolicy(IURLPolicy urlPolicy);
+    public IURLPolicy getURLPolicy();
+
+    public Class getClass(String name);
+    public URL getResource(String name);
+
+    public InputStream getResourceAsStream(String name)
+        throws IOException;
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IModule.java
similarity index 60%
copy from org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java
copy to org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IModule.java
index 24595ec..84a6db6 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IModule.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -16,20 +16,13 @@
  */
 package org.apache.felix.moduleloader;
 
-import java.io.IOException;
-import java.net.*;
+import java.net.URL;
 
-class ModuleURLStreamHandler extends URLStreamHandler
+public interface IModule
 {
-    private ModuleManager m_mgr = null;
+    public String getId();
+    public IContentLoader getContentLoader();
 
-    public ModuleURLStreamHandler(ModuleManager mgr)
-    {
-        m_mgr = mgr;
-    }
-
-    protected URLConnection openConnection(URL url) throws IOException
-    {
-        return new ModuleURLConnection(m_mgr, url);
-    }
-}
+    public Class getClass(String name);
+    public URL getResource(String name);
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IModuleFactory.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IModuleFactory.java
new file mode 100644
index 0000000..a920baa
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IModuleFactory.java
@@ -0,0 +1,31 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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);    
+    public void removeModule(IModule module);
+
+    public void setContentLoader(IModule module, IContentLoader contentLoader);
+
+    public void addModuleListener(ModuleListener l);
+    public void removeModuleListener(ModuleListener l);
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ISearchPolicy.java
similarity index 60%
copy from org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java
copy to org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ISearchPolicy.java
index 24595ec..d3dd0d1 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ISearchPolicy.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -16,20 +16,14 @@
  */
 package org.apache.felix.moduleloader;
 
-import java.io.IOException;
-import java.net.*;
+import java.net.URL;
 
-class ModuleURLStreamHandler extends URLStreamHandler
+import org.apache.felix.moduleloader.ResourceNotFoundException;
+
+public interface ISearchPolicy
 {
-    private ModuleManager m_mgr = null;
-
-    public ModuleURLStreamHandler(ModuleManager mgr)
-    {
-        m_mgr = mgr;
-    }
-
-    protected URLConnection openConnection(URL url) throws IOException
-    {
-        return new ModuleURLConnection(m_mgr, url);
-    }
-}
+    public Object[] definePackage(String name);
+    public Class findClass(String name) throws ClassNotFoundException;
+    public URL findResource(String name) throws ResourceNotFoundException;
+    public String findLibrary(String name);
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IURLPolicy.java
similarity index 60%
copy from org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java
copy to org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IURLPolicy.java
index 24595ec..4579b4d 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLStreamHandler.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IURLPolicy.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -16,20 +16,9 @@
  */
 package org.apache.felix.moduleloader;
 
-import java.io.IOException;
-import java.net.*;
+import java.net.URL;
 
-class ModuleURLStreamHandler extends URLStreamHandler
+public interface IURLPolicy
 {
-    private ModuleManager m_mgr = null;
-
-    public ModuleURLStreamHandler(ModuleManager mgr)
-    {
-        m_mgr = mgr;
-    }
-
-    protected URLConnection openConnection(URL url) throws IOException
-    {
-        return new ModuleURLConnection(m_mgr, url);
-    }
-}
+    public URL createURL(String path);
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/JarContent.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/JarContent.java
new file mode 100644
index 0000000..b7c9aa8
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/JarContent.java
@@ -0,0 +1,244 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+public class JarContent implements IContent
+{
+    private static final int BUFSIZE = 4096;
+
+    private File m_file = null;
+    private JarFile m_jarFile = null;
+    private boolean m_opened = false;
+
+    public JarContent(File file)
+    {
+        m_file = file;
+    }
+
+    protected void finalize()
+    {
+        if (m_jarFile != null)
+        {
+            try
+            {
+                m_jarFile.close();
+            }
+            catch (IOException ex)
+            {
+                // Not much we can do, so ignore it.
+            }
+        }
+    }
+
+    public void open()
+    {
+        m_opened = true;
+    }
+
+    public synchronized void close()
+    {
+        try
+        {
+            if (m_jarFile != null)
+            {
+                m_jarFile.close();
+            }
+        }
+        catch (Exception ex)
+        {
+            System.err.println("JarContent: " + ex);
+        }
+
+        m_jarFile = null;
+        m_opened = false;
+    }
+
+    public synchronized boolean hasEntry(String name) throws IllegalStateException
+    {
+        if (!m_opened)
+        {
+            throw new IllegalStateException("JarContent is not open");
+        }
+
+        // Open JAR file if not already opened.
+        if (m_jarFile == null)
+        {
+            try
+            {
+                openJarFile();
+            }
+            catch (IOException ex)
+            {
+                System.err.println("JarContent: " + ex);
+                return false;
+            }
+        }
+
+        try
+        {
+            ZipEntry ze = m_jarFile.getEntry(name);
+            return ze != null;
+        }
+        catch (Exception ex)
+        {
+            return false;
+        }
+        finally
+        {
+        }
+    }
+
+    public synchronized byte[] getEntry(String name) throws IllegalStateException
+    {
+        if (!m_opened)
+        {
+            throw new IllegalStateException("JarContent is not open");
+        }
+
+        // Open JAR file if not already opened.
+        if (m_jarFile == null)
+        {
+            try
+            {
+                openJarFile();
+            }
+            catch (IOException ex)
+            {
+                System.err.println("JarResourceSource: " + ex);
+                return null;
+            }
+        }
+
+        // Get the embedded resource.
+        InputStream is = null;
+        ByteArrayOutputStream baos = null;
+
+        try
+        {
+            ZipEntry ze = m_jarFile.getEntry(name);
+            if (ze == null)
+            {
+                return null;
+            }
+            is = m_jarFile.getInputStream(ze);
+            if (is == null)
+            {
+                return null;
+            }
+            baos = new ByteArrayOutputStream(BUFSIZE);
+            byte[] buf = new byte[BUFSIZE];
+            int n = 0;
+            while ((n = is.read(buf, 0, buf.length)) >= 0)
+            {
+                baos.write(buf, 0, n);
+            }
+            return baos.toByteArray();
+
+        }
+        catch (Exception ex)
+        {
+            return null;
+        }
+        finally
+        {
+            try
+            {
+                if (baos != null) baos.close();
+            }
+            catch (Exception ex)
+            {
+            }
+            try
+            {
+                if (is != null) is.close();
+            }
+            catch (Exception ex)
+            {
+            }
+        }
+    }
+
+    public synchronized InputStream getEntryAsStream(String name)
+        throws IllegalStateException, IOException
+    {
+        if (!m_opened)
+        {
+            throw new IllegalStateException("JarContent is not open");
+        }
+
+        // Open JAR file if not already opened.
+        if (m_jarFile == null)
+        {
+            try
+            {
+                openJarFile();
+            }
+            catch (IOException ex)
+            {
+                System.err.println("JarResourceSource: " + ex);
+                return null;
+            }
+        }
+
+        // Get the embedded resource.
+        InputStream is = null;
+
+        try
+        {
+            ZipEntry ze = m_jarFile.getEntry(name);
+            if (ze == null)
+            {
+                return null;
+            }
+            is = m_jarFile.getInputStream(ze);
+            if (is == null)
+            {
+                return null;
+            }
+        }
+        catch (Exception ex)
+        {
+            return null;
+        }
+
+        return is;
+    }
+
+    public String[] getEntryPaths(String path)
+    {
+        return null;
+    }
+
+    private void openJarFile() throws IOException
+    {
+        if (m_jarFile == null)
+        {
+            m_jarFile = new JarFile(m_file);
+        }
+    }
+
+    public String toString()
+    {
+        return "JAR " + m_file.getPath();
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/JarResourceSource.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/JarResourceSource.java
deleted file mode 100644
index 0f3fdbf..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/JarResourceSource.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.*;
-import java.util.jar.JarFile;
-import java.util.zip.ZipEntry;
-
-/**
- * <p>
- * This class implements a <tt>ResourceSource</tt> for retrieving resources
- * from a JAR file. The approach used by this implementation is to defer
- * opening the JAR file until a request for a resource is made.
- * </p>
- * @see org.apache.felix.moduleloader.ResourceSource
-**/
-public class JarResourceSource implements ResourceSource
-{
-    private static final int BUFSIZE = 4096;
-
-    private File m_file = null;
-    private JarFile m_jarFile = null;
-    private boolean m_opened = false;
-
-    /**
-     * <p>
-     * Constructs an instance using the specified file name as the source
-     * of the JAR file.
-     * </p>
-     * @param fileName the name of the JAR file to be used as the source.
-    **/
-    public JarResourceSource(String fileName)
-    {
-        m_file = new File(fileName);
-    }
-
-    /**
-     * <p>
-     * Constructs an instance using the specified file as the source
-     * of the JAR file.
-     * </p>
-     * @param file the JAR file to be used as the source.
-    **/
-    public JarResourceSource(File file)
-    {
-        m_file = file;
-    }
-
-    /**
-     * <p>
-     * Closes the JAR file if it has not already been closed.
-     * <p>
-    **/
-    protected void finalize()
-    {
-        if (m_jarFile != null)
-        {
-            try {
-                m_jarFile.close();
-            } catch (IOException ex) {
-                // Not much we can do, so ignore it.
-            }
-        }
-    }
-
-    /**
-     * <p>
-     * This method initializes the resource source. Since opening
-     * the JAR file is deferred until a request for a resource is
-     * actually made, this method really only sets a flag indicating
-     * that the resource source has been initialized.
-     * <p>
-    **/
-    public void open()
-    {
-        m_opened = true;
-    }
-
-    /**
-     * <p>
-     * This method deinitializes the resource source by closing
-     * the associated JAR file if it is open.
-     * <p>
-    **/
-    public synchronized void close()
-    {
-        try {
-            if (m_jarFile != null)
-            {
-                m_jarFile.close();
-            }
-        } catch (Exception ex) {
-            System.err.println("JarResourceSource: " + ex);
-        }
-
-        m_jarFile = null;
-        m_opened = false;
-    }
-
-    // JavaDoc comments are copied from ResourceSource.
-    public synchronized boolean hasResource(String name) throws IllegalStateException
-    {
-        if (!m_opened)
-        {
-            throw new IllegalStateException("JarResourceSource is not open");
-        }
-
-        // Open JAR file if not already opened.
-        if (m_jarFile == null)
-        {
-            try {
-                openJarFile();
-            } catch (IOException ex) {
-                System.err.println("JarResourceSource: " + ex);
-                return false;
-            }
-        }
-
-        try {
-            ZipEntry ze = m_jarFile.getEntry(name);
-            return ze != null;
-        } catch (Exception ex) {
-            return false;
-        } finally {
-        }
-    }
-
-    // JavaDoc comments are copied from ResourceSource.
-    public synchronized byte[] getBytes(String name) throws IllegalStateException
-    {
-        if (!m_opened)
-        {
-            throw new IllegalStateException("JarResourceSource is not open");
-        }
-
-        // Open JAR file if not already opened.
-        if (m_jarFile == null)
-        {
-            try {
-                openJarFile();
-            } catch (IOException ex) {
-                System.err.println("JarResourceSource: " + ex);
-                return null;
-            }
-        }
-
-        // Get the embedded resource.
-        InputStream is = null;
-        ByteArrayOutputStream baos = null;
-
-        try {
-            ZipEntry ze = m_jarFile.getEntry(name);
-            if (ze == null)
-            {
-                return null;
-            }
-            is = m_jarFile.getInputStream(ze);
-            if (is == null)
-            {
-                return null;
-            }
-            baos = new ByteArrayOutputStream(BUFSIZE);
-            byte[] buf = new byte[BUFSIZE];
-            int n = 0;
-            while ((n = is.read(buf, 0, buf.length)) >= 0)
-            {
-                baos.write(buf, 0, n);
-            }
-            return baos.toByteArray();
-
-        } catch (Exception ex) {
-            return null;
-        } finally {
-            try {
-                if (baos != null) baos.close();
-            } catch (Exception ex) {
-            }
-            try {
-                if (is != null) is.close();
-            } catch (Exception ex) {
-            }
-        }
-    }
-
-    private void openJarFile() throws IOException
-    {
-        if (m_jarFile == null)
-        {
-            m_jarFile = new JarFile(m_file);
-        }
-    }
-
-    public String toString()
-    {
-        return "JAR " + m_file.getPath();
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/LibrarySource.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/LibrarySource.java
deleted file mode 100644
index a0538ae..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/LibrarySource.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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;
-
-/**
- * <p>
- * This interface represents a source for obtaining native libraries for a
- * given module via the module's class loader. The main goal of a library
- * source is to map a library name to a path in the file system.
- * </p>
- * <p>
- * All library sources are initialized before first usage via a call
- * to the <a href="#open()"><tt>LibrarySource.open()</tt></a> method and
- * are also deinitialized via a call to
- * <a href="#open()"><tt>LibrarySource.close()</tt></a>. Library sources
- * should be implemented such that they can be opened, closed, and then
- * re-opened.
- * </p>
- * @see org.apache.felix.moduleloader.Module
- * @see org.apache.felix.moduleloader.ModuleClassLoader
-**/
-public interface LibrarySource
-{
-    /**
-     * <p>
-     * This method initializes the library source. It is called when
-     * the associated module is added to the <tt>ModuleManager</tt>. It
-     * is acceptable for implementations to ignore duplicate calls to this
-     * method if the library source is already opened.
-     * </p>
-    **/
-    public void open();
-
-    /**
-     * <p>
-     * This method de-initializes the library source. It is called when
-     * the associated module is removed from the <tt>ModuleManager</tt> or
-     * when the module is reset by the <tt>ModuleManager</tt>.
-     * </p>
-    **/
-    public void close();
-
-    /**
-     * <p>
-     * Returns a file system path to the specified library.
-     * </p>
-     * @param name the name of the library that is being requested.
-     * @return a file system path to the specified library.
-     * @throws java.lang.IllegalStateException if the resource source has not
-     *         been opened.
-    **/
-    public String getPath(String name) throws IllegalStateException;
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/Module.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/Module.java
deleted file mode 100644
index 66b64a2..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/Module.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.*;
-
-/**
- * <p>
- * The <tt>Module</tt> class is a grouping mechanism for application classes
- * and resources. Conceptually, most applications are grouped into
- * entities such as JAR files (containing classes and resources) and native
- * libraries. In some cases, these entities are core application classes and
- * resources, while in other cases, these entities are ancillary, such as
- * dynamically loaded plug-ins. Applications place some level of semantics
- * onto these types of entities or <i>modules</i>, but for the <tt>ModuleLoader</tt>,
- * no particular semantics are attached to modules (other than they are a grouping
- * mechanism for classes and resources). This means that the application
- * is free to map itself into modules any way that is appropriate.
- * </p>
- * <p>
- * A module has the following features:
- * </p>
- * <ul>
- *   <li>A unique identifier within the scope of its <tt>ModuleManager</tt>.
- *   </li>
- *   <li>A set of key-value attribute pairs.
- *   </li>
- *   <li>A set of resource sources from which it is possible to
- *       retrieve classes and resources.
- *   </li>
- *   <li>A set of native library sources from which it is possible
- *       to retrieve native libraries.
- *   </li>
- * </ul>
- * <p>
- * A module's identifier must be unique within the scope of its
- * <tt>ModuleManager</tt>, but there is no meaning associated with it. The
- * set of attribute-value pairs attached to the module have no meaning to
- * the <tt>ModuleManager</tt>, nor does it consult them at all. The point
- * of these attributes is to attach meta-data for use by
- * <a href="SearchPolicy.html"><tt>SearchPolicy</tt></a> implementations.
- * Attributes are represented as an array of <tt>Object</tt>
- * arrays, i.e., <tt>Object[][]</tt>. Each element in the attribute array is
- * a two-element <tt>Object</tt> array, where <tt>Module.KEY_IDX</tt> is the attribute's
- * key and <tt>Module.VALUE_IDX</tt> is the attribute's value.
- * </p>
- * <p>
- * The actual contents of a module is contained in two sets of sources
- * for its resources and native libraries,
- * <a href="ResourceSource.html"><tt>ResourceSource</tt></a>s
- * and <a href="LibrarySource.html"><tt>LibrarySource</tt></a>s, respectively.
- * Each module also has a <a href="ModuleClassLoader.html"><tt>ModuleClassLoader</tt></a>
- * associated with it. The <tt>ModuleClassLoader</tt> consults these two types
- * of sources to find classes, resources, and native libraries.
- * </p>
- * @see org.apache.felix.moduleloader.ModuleManager
- * @see org.apache.felix.moduleloader.ModuleClassLoader
- * @see org.apache.felix.moduleloader.ResourceSource
- * @see org.apache.felix.moduleloader.LibrarySource
-**/
-public class Module
-{
-    /**
-     * This is the index used to retrieve the key of an attribute;
-     * an attribute is represented as an <tt>Object[]</tt> instance.
-    **/
-    public static final int KEY_IDX = 0;
-    /**
-     * This is the index used to retrieve the value of an attribute;
-     * an attribute is represented as an <tt>Object[]</tt> instance.
-    **/
-    public static final int VALUE_IDX = 1;
-
-    private ModuleManager m_mgr = null;
-    private String m_id = null;
-    private boolean m_useParentSource = false;
-    private Map m_attributeMap = new HashMap();
-    private ResourceSource[] m_resSources = null;
-    private LibrarySource[] m_libSources = null;
-    private ModuleClassLoader m_loader = null;
-
-    /**
-     * <p>
-     * Constructs a <tt>Module</tt> instance that will be associated with
-     * the specified <tt>ModuleManager</tt> and will have the specified
-     * identifier, attributes, resource sources, and library sources. In general,
-     * modules should not be created directly, but should be created by making
-     * a call to <tt>ModuleManager.addModule()</tt>.
-     * </p>
-     * @param mgr the <tt>ModuleManager</tt> that will be associated to
-     *       the instance.
-     * @param id the identifier of the instance.
-     * @param attributes the set of attributes associated with the instance.
-     * @param resSources the set of <tt>ResourceSource</tt>s associated with
-     *        the instance.
-     * @param libSources the set of <tt>LibrarySource</tt>s associated with
-     *        the instance.
-     * @param useParentSource a flag indicating whether or not the parent
-     *        class loader should be used as a resource source; this is an
-     *        ugly hack to allow a module to masquerade as the system
-     *        class loader.
-     * @see org.apache.felix.moduleloader.ModuleManager
-     * @see org.apache.felix.moduleloader.ResourceSource
-     * @see org.apache.felix.moduleloader.LibrarySource
-    **/
-    public Module(
-        ModuleManager mgr, String id, Object[][] attributes,
-        ResourceSource[] resSources, LibrarySource[] libSources,
-        boolean useParentSource)
-    {
-        m_mgr = mgr;
-        m_id = id;
-        m_useParentSource = useParentSource;
-        initialize(attributes, resSources, libSources);
-    }
-
-    /**
-     * <p>
-     * Returns the identifier of the module.
-     * </p>
-     * @return the identifier of the module.
-    **/
-    public String getId()
-    {
-        return m_id;
-    }
-
-    /**
-     * <p>
-     * Returns the attribute set associated with this module. Attributes
-     * are represented as an array of <tt>Object</tt> arrays, i.e.,
-     * <tt>Object[][]</tt>. Each element in the attribute array is
-     * two-element <tt>Object</tt> array, where <tt>Module.KEY_IDX</tt>
-     * is the index to the attribute key and <tt>Module.VALUE_IDX</tt>
-     * is the index to the attribute value. The returned array is a
-     * copy and may be freely modified.
-     * </p>
-     * @return the attribute set associated with this module.
-    **/
-    public synchronized Object[][] getAttributes()
-    {
-        Set s = m_attributeMap.entrySet();
-        Object[][] attributes = new Object[s.size()][];
-        Iterator iter = s.iterator();
-        for (int i = 0; iter.hasNext(); i++)
-        {
-            Map.Entry entry = (Map.Entry) iter.next();
-            attributes[i] = new Object[] { entry.getKey(), entry.getValue() };
-        }
-        return attributes;
-    }
-
-    /**
-     * <p>
-     * Returns the attribute value associated with the specified key.
-     * </p>
-     * @param key the key of the attribute whose value is to be retrieved.
-     * @return the attribute's value or <tt>null</tt>.
-    **/
-    public synchronized Object getAttribute(String key)
-    {
-        return m_attributeMap.get(key);
-    }
-
-    /**
-     * <p>
-     * Sets the attribute value associated with the specified key. The
-     * attribute will be added if it does not currently exist.
-     * </p>
-     * @param key the key of the attribute whose value is to be set.
-     * @param value the new value to be associated with the attribute key.
-    **/
-    public synchronized void setAttribute(String key, Object value)
-    {
-        m_attributeMap.put(key, value);
-    }
-
-    /**
-     * <p>
-     * Returns the array of <tt>ResourceSource</tt>s associated with
-     * the module. The returned array is not a copy and therefore should
-     * not be modified.
-     * </p>
-     * @return the array of <tt>ResourceSource</tt>s associated with
-     *         the module.
-     * @see org.apache.felix.moduleloader.ResourceSource
-    **/
-    public ResourceSource[] getResourceSources()
-    {
-        return m_resSources;
-    }
-
-    /**
-     * <p>
-     * Returns the array of <tt>LibrarySource</tt>s associated with
-     * the module. The returned array is not a copy and therefore should
-     * not be modified.
-     * </p>
-     * @return the array of <tt>LibrarySource</tt>s associated with
-     *         the module.
-     * @see org.apache.felix.moduleloader.LibrarySource
-    **/
-    public LibrarySource[] getLibrarySources()
-    {
-        return m_libSources;
-    }
-
-    /**
-     * <p>
-     * Returns the <tt>ModuleClassLoader</tt> associated with this module.
-     * If a security manager is installed, then this method uses a privileged
-     * action to avoid a security exception being thrown to the caller.
-     * </p>
-     * @return the <tt>ModuleClassLoader</tt> associated with this module.
-     * @see org.apache.felix.moduleloader.ModuleClassLoader
-    **/
-    public synchronized ModuleClassLoader getClassLoader()
-    {
-        if (m_loader == null)
-        {
-            if (System.getSecurityManager() != null)
-            {
-                m_loader = (ModuleClassLoader) AccessController.doPrivileged(
-                    new GetClassLoaderPrivileged(m_mgr, this, m_useParentSource));
-            }
-            else
-            {
-                m_loader = new ModuleClassLoader(m_mgr, this, m_useParentSource);
-            }
-        }
-
-        return m_loader;
-    }
-
-    /**
-     * <p>
-     * Returns the module's identifier.
-     * </p>
-     * @return the module's identifier.
-    **/
-    public String toString()
-    {
-        return m_id;
-    }
-
-    /**
-     * <p>
-     * Resets the module by throwing away its associated class loader and
-     * re-initializing its attributes, resource sources, and library sources
-     * with the specified values.
-     * </p>
-     * @param attributes the new attributes to be associated with the module.
-     * @param resSources the new resource sources to be associated with the module.
-     * @param libSources the new library sources to be associated with the module.
-     * @see org.apache.felix.moduleloader.ResourceSource
-     * @see org.apache.felix.moduleloader.LibrarySource
-    **/
-    protected synchronized void reset(
-        Object[][] attributes, ResourceSource[] resSources,
-        LibrarySource[] libSources)
-    {
-        // Throw away class loader.
-        m_loader = null;
-        // Clear attribute map.
-        m_attributeMap.clear();
-        // Close all sources.
-        dispose();
-        // Re-initialize.
-        initialize(attributes, resSources, libSources);
-    }
-
-    /**
-     * <p>
-     * Disposes the module by closing all resource and library sources.
-     * </p>
-    **/
-    protected synchronized void dispose()
-    {
-        // Close sources.
-        for (int i = 0; (m_resSources != null) && (i < m_resSources.length); i++)
-        {
-            m_resSources[i].close();
-        }
-        for (int i = 0; (m_libSources != null) && (i < m_libSources.length); i++)
-        {
-            m_libSources[i].close();
-        }
-    }
-
-    /**
-     * <p>
-     * Initializes the module by copying the specified attribute array into
-     * a map and opening all resource and library sources.
-     * </p>
-     * @param attributes the attributes to be put into a map.
-     * @param resSources the resource sources to be opened.
-     * @param libSources the library sources to be opened.
-     * @see org.apache.felix.moduleloader.ResourceSource
-     * @see org.apache.felix.moduleloader.LibrarySource
-    **/
-    private void initialize(
-        Object[][] attributes, ResourceSource[] resSources, LibrarySource[] libSources)
-    {
-        for (int i = 0; (attributes != null) && (i < attributes.length); i++)
-        {
-            m_attributeMap.put(attributes[i][KEY_IDX], attributes[i][VALUE_IDX]);
-        }
-
-        m_resSources = resSources;
-        m_libSources = libSources;
-
-        // Open sources.
-        for (int i = 0; (m_resSources != null) && (i < m_resSources.length); i++)
-        {
-            m_resSources[i].open();
-        }
-        for (int i = 0; (m_libSources != null) && (i < m_libSources.length); i++)
-        {
-            m_libSources[i].open();
-        }
-    }
-
-    private static class GetClassLoaderPrivileged implements PrivilegedAction
-    {
-        private ModuleManager m_mgr = null;
-        private Module m_module = null;
-        private boolean m_useParentSource = false;
-
-        public GetClassLoaderPrivileged(ModuleManager mgr, Module module, boolean useParentSource)
-        {
-            m_mgr = mgr;
-            m_module = module;
-            m_useParentSource = useParentSource;
-        }
-
-        public Object run()
-        {
-            return new ModuleClassLoader(m_mgr, m_module, m_useParentSource);
-        }
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleClassLoader.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleClassLoader.java
deleted file mode 100644
index 5585979..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleClassLoader.java
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.net.URL;
-import java.security.CodeSource;
-import java.security.SecureClassLoader;
-import java.security.cert.Certificate;
-import java.util.Enumeration;
-import java.util.Vector;
-
-/**
- * <p>
- * Each module that is managed by a <tt>ModuleManager</tt> has a
- * <tt>ModuleClassLoader</tt> associated with it. The <tt>ModuleClassLoader</tt>
- * is responsible for loading all classes, resources, and native libraries
- * for its module. The <tt>ModuleClassLoader</tt> of a module
- * is accessed using the <tt>Module.getClassLoader()</tt> method. The
- * <tt>ModuleClassLoader</tt> uses its module's
- * <a href="ResourceSource.html"><tt>ResourceSource</tt></a>s
- * and <a href="LibrarySource.html"><tt>LibrarySource</tt></a>s
- * to perform its function.
- * </p>
- * <p>
- * When loading a class or resource, the <tt>ModuleClassLoader</tt> does
- * not immediately search its module's <tt>ResourceSource</tt>s, instead
- * it first delegates the request to the
- * <a href="SearchPolicy.html"><tt>SearchPolicy</tt></a> of the
- * <tt>ModuleManager</tt>; this allows applications to inject specific
- * class/resource loading policies. When the <tt>ModuleClassLoader</tt> delegates
- * to the search policy, the search policy uses application-specific behavior
- * to typically service the request from the <tt>ResourceSource</tt>s of
- * other modules. If the search policy returns a result, then this result is
- * returned immediately by the <tt>ModuleClassLoader</tt>; otherwise, it searches
- * the <tt>ResourceSource</tt>s its module in an attempt to satisfy the
- * original request.
- * </p>
- * <p>
- * <b><i>Important:</i></b> The search policy <i>searches</i> modules in
- * some application-specific manner in order to find a class or resource.
- * This <i>search</i> is instigated, either directly or indirectly, by calls
- * to <tt>ModuleClassLoader.loadClass()</tt> and <tt>ModuleClassLoader.getResource()</tt>,
- * respectively. In order for the search policy to load a class or resource,
- * it must <b>not</b> use <tt>ModuleClassLoader.loadClass()</tt> or
- * <tt>ModuleClassLoader.getResource()</tt> again, because this would result
- * in an infinite loop. Instead, the <tt>ModuleClassLoader</tt> offers the
- * the methods <tt>ModuleClassLoader.loadClassFromModule()</tt> and
- * <tt>ModuleClassLoader.getResourceFromModule()</tt> to search a given module
- * and to avoid an infinite loop. As an example, consider the following
- * snippet of code that implements an "exhaustive" search policy:
- * </p>
- * <pre>
- *     ...
- *     public Class findClass(Module module, String name)
- *     {
- *         Module[] modules = m_mgr.getModules();
- *         for (int i = 0; i < modules.length; i++)
- *         {
- *             try {
- *                 Class clazz = modules[i].getClassLoader().loadClassFromModule(name);
- *                 if (clazz != null)
- *                 {
- *                     return clazz;
- *                 }
- *             } catch (Throwable th) {
- *             }
- *         }
- *
- *         return null;
- *     }
- *     ...
- * </pre>
- * <p>
- * In the above code, the search policy "exhaustively" searches every module in the
- * <tt>ModuleManager</tt> to find the requested resource. Note that this policy
- * will also search the module that originated the request, which is not totally
- * necessary since returning <tt>null</tt> will cause the <tt>ModuleClassLoader</tt>
- * to search the originating module's <tt>ResourceSource</tt>s.
- * </p>
-**/
-public class ModuleClassLoader extends SecureClassLoader
-{
-    private ModuleManager m_mgr = null;
-    private Module m_module = null;
-    private boolean m_useParentSource = false;
-
-    /**
-     * <p>
-     * Constructs an instance using the specified <tt>ModuleManager</tt>, for
-     * the specified <tt>Module</tt>. This constructor is protected so that
-     * it cannot be created publicly.
-     * </p>
-     * @param mgr the <tt>ModuleManager</tt> of the <tt>Module</tt>.
-     * @param module the <tt>Module</tt> instance associated with the class loader.
-    **/
-    protected ModuleClassLoader(ModuleManager mgr, Module module, boolean useParentSource)
-    {
-        super(ModuleClassLoader.class.getClassLoader());
-        m_mgr = mgr;
-        m_module = module;
-        m_useParentSource = useParentSource;
-    }
-
-    /**
-     * <p>
-     * This method is only used by a framework instance so that it can determine
-     * if a given module class loader is for a module of a bundle inside of it;
-     * this is used for the URL Handlers service implementation.
-     * </p>
-     * @return <tt>true</tt> if the specified module manager is the same as
-     *         the one associated with this module class loader.
-    **/
-    public boolean isModuleManagerEqual(ModuleManager mgr)
-    {
-        return m_mgr == mgr;
-    }
-
-    /**
-     * <p>
-     * This method is nearly an exact copy of the ClassLoader.loadClass()
-     * method. The main difference is that it delegates to its associated
-     * <tt>ModuleManager</tt>'s search policy before calling the
-     * <tt>ClassLoader.findClass()</tt> method. Additionally, the synchronized
-     * modifier was removed from the superclass method; this change was necessary
-     * because ClassLoader class assumes a tree of class loaders, but the class
-     * loading structure in the <tt>ModuleManager</tt> might actually be a graph
-     * of class loaders; thus, it was necessary to loosen the concurrency locking
-     * to allow for cycles.
-     * </p>
-     * @param name the class to be loaded.
-     * @param resolve flag indicating whether the class should be resolved or not.
-     * @return the loaded class.
-     * @throws java.lang.ClassNotFoundException if the class could not be loaded.
-    **/
-    protected Class loadClass(String name, boolean resolve)
-        throws ClassNotFoundException
-    {
-        // Make sure the class was not already loaded.
-        Class c = findLoadedClass(name);
-        // Ask the search policy for the clas before consulting the module.
-        c = m_mgr.getSearchPolicy().findClassBeforeModule(getParent(), m_module, name);
-        // If the search policy didn't find it, then consult the module.
-        if (c == null)
-        {
-            c = findClass(name);
-        }
-        // If the module didn't find it, then consult the search policy
-        // one more time.
-        if (c == null)
-        {
-            c = m_mgr.getSearchPolicy().findClassAfterModule(getParent(), m_module, name);
-        }
-        // If still not found, then throw an exception.
-        if (c == null)
-        {
-            throw new ClassNotFoundException(name);
-        }
-        // Otherwise resolve the class.
-        if (resolve)
-        {
-            resolveClass(c);
-        }
-        return c;
-    }
-
-    /**
-     * <p>
-     * This method overriden from from <tt>ClassLoader</tt>.
-     * It is implemented such that it loads classes from the set of
-     * <tt>ResourceSource</tt>s from its associated module.
-     * </p>
-     * @param name the name of the resource to load.
-     * @return the loaded <tt>Class</tt> object.
-     * @throws java.lang.ClassNotFoundException if the class could not be loaded.
-    **/
-    protected Class findClass(String name) throws ClassNotFoundException
-    {
-        Class clazz = findLoadedClass(name);
-
-        // If the parent is used as a source, try to
-        // load the class from it.
-        // TODO: This is really a hack and should be generalized somehow.
-        if (m_useParentSource)
-        {
-            clazz = (getParent() == null) ? null : getParent().loadClass(name);
-        }
-
-        // Otherwise search for class in resource sources.
-        if (clazz == null)
-        {
-            String actual = name.replace('.', '/') + ".class";
-            ResourceSource[] sources = m_module.getResourceSources();
-            for (int i = 0;
-                (clazz == null) && (sources != null) && (i < sources.length);
-                i++)
-            {
-                byte[] bytes = sources[i].getBytes(actual);
-                if (bytes != 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_mgr.getSearchPolicy().definePackage(m_module, 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);
-                            }
-                        }
-                    }
-
-                    // Get the code source URL for this class. For concurrency
-                    // purposes, we are performing this call outside of the
-                    // synchronized block below since we call out to application
-                    // code, which might in turn need to call back into the
-                    // module loader code. Because of this, it is better to
-                    // not be holding any locks before making the call.
-                    URL url = m_mgr.getURLPolicy().createCodeSourceURL(
-                        m_mgr, m_module);
-
-                    // If we have a valid code source URL, then use it to
-                    // define the class for security purposes, otherwise
-                    // define the class without a code source.
-                    if (url != null)
-                    {
-                        CodeSource cs = new CodeSource(url, (Certificate[]) null);
-                        clazz = defineClass(name, bytes, 0, bytes.length, cs);
-                    }
-                    else
-                    {
-                        clazz = defineClass(name, bytes, 0, bytes.length);
-                    }
-                }
-            }
-        }
-
-        if (clazz != null)
-        {
-            return clazz;
-        }
-
-        return null;
-    }
-
-    /**
-     * <p>
-     * This method is used by <tt>SearchPolicy</tt> instances when they want
-     * to load a class from a module. The search policy is initially invoked when
-     * <tt>ModuleClassLoader.loadClass()</tt> delegates a class loading
-     * request to it. In general, the ultimate goal of the search policy is to
-     * return a class from another module if possible. Unfortunately, if a search
-     * policy tries to directly load a class from another module's class loader, an
-     * infinite loop will result because the module's class loader will delegate the
-     * request back to the search policy. To avoid this situation, search policies
-     * must use this method when trying to load a class from a module.
-     * </p>
-     * @param name the name of the class to load.
-     * @return the loaded class or <tt>null</tt>.
-    **/
-    public Class loadClassFromModule(String name)
-    {
-        try
-        {
-            return findClass(name);
-        } catch (Throwable th) {
-            // Not much we can do.
-// TODO: Do something with this error message.
-//            System.err.println("ModuleClassLoader: " + th.getMessage());
-        }
-        return null;
-    }
-
-    /**
-     * <p>
-     * This method is nearly an exact copy of the ClassLoader.getResource()
-     * method. The main difference is that it delegates to its associated
-     * <tt>ModuleManager</tt>'s search policy before calling the
-     * <tt>ClassLoader.findResource()</tt> method.
-     * </p>
-     * @param name the class to be loaded.
-     * @return a URL to the resource or <tt>null</tt> if the resource was not found.
-    **/
-    public URL getResource(String name)
-    {
-        URL url = null;
-
-        // Ask the search policy for the resource.
-        if (m_mgr.getSearchPolicy() != null)
-        {
-            try
-            {
-                url = m_mgr.getSearchPolicy().findResource(getParent(), m_module, name);
-            }
-            catch (ResourceNotFoundException ex)
-            {
-                // We return null here because if SearchPolicy.findResource()
-                // throws an exception we interpret that to mean that the
-                // search should be stopped.
-                return null;
-            }
-        }
-
-        // If not found, then search locally.
-        if (url == null)
-        {
-            url = findResource(name);
-        }
-
-        return url;
-    }
-
-    /**
-     * <p>
-     * This method overriden from from <tt>ClassLoader</tt>.
-     * It is implemented such that it loads resources from the set of
-     * <tt>ResourceSource</tt>s from its associated module.
-     * </p>
-     * @param name the name of the resource to load.
-     * @return the <tt>URL</tt> associated with the resource or <tt>null</tt>.
-    **/
-    protected URL findResource(String name)
-    {
-        URL url = null;
-
-        // If the parent is used as a source, try to
-        // load the class from it.
-        if (m_useParentSource)
-        {
-            url = (getParent() == null) ? null : getParent().getResource(name);
-        }
-
-        // Try to load the resource from the module's resource
-        // sources.
-        if (url == null)
-        {
-            // Remove leading slash, if present.
-            if (name.startsWith("/"))
-            {
-                name = name.substring(1);
-            }
-
-            ResourceSource[] sources = m_module.getResourceSources();
-            for (int i = 0;
-                (url == null) && (sources != null) && (i < sources.length);
-                i++)
-            {
-                if (sources[i].hasResource(name))
-                {
-                    url = m_mgr.getURLPolicy().createResourceURL(m_mgr, m_module, i, name);
-                }
-            }
-        }
-
-        return url;
-    }
-
-    /**
-     * <p>
-     * This method is used by <tt>SearchPolicy</tt> instances when they want
-     * to load a resource from a module. The search policy is initially invoked when
-     * <tt>ModuleClassLoader.loadClass()</tt> delegates a resource loading
-     * request to it. In general, the ultimate goal of the search policy is to
-     * return a resource from another module if possible. Unfortunately, if a search
-     * policy tries to directly load a resource from another module's class loader, an
-     * infinite loop will result because the module's class loader will delegate the
-     * request back to the search policy. To avoid this situation, search policies
-     * must use this method when trying to load a resource from a module.
-     * </p>
-     * @param name the name of the resource to load.
-     * @return a URL to the resource or <tt>null</tt>.
-    **/
-    public URL getResourceFromModule(String name)
-    {
-        try
-        {
-            return findResource(name);
-        }
-        catch (Throwable th)
-        {
-            // Ignore and just return null.
-        }
-        return null;
-    }
-
-    protected Enumeration findResources(String name)
-    {
-        Vector v = new Vector();
-        // If the parent is used as a source, try to
-        // load the class from it.
-        if (m_useParentSource)
-        {
-            try
-            {
-                Enumeration e = (getParent() == null)
-                    ? null : getParent().getResources(name);
-                while ((e != null) && e.hasMoreElements())
-                {
-                    v.addElement(e.nextElement());
-                }
-            }
-            catch (IOException ex)
-            {
-                // What can we do?
-            }
-        }
-
-        // Remove leading slash, if present.
-        if (name.startsWith("/"))
-        {
-            name = name.substring(1);
-        }
-
-        // Try to load the resource from the module's resource
-        // sources.
-
-        ResourceSource[] sources = m_module.getResourceSources();
-        for (int i = 0; (sources != null) && (i < sources.length); i++)
-        {
-            if (sources[i].hasResource(name))
-            {
-                v.addElement(m_mgr.getURLPolicy().createResourceURL(m_mgr, m_module, i, name));
-            }
-        }
-
-        return v.elements();
-    }
-
-    /**
-     * <p>
-     * This method overriden from from <tt>ClassLoader</tt>. It maps a library
-     * name to a library path by consulting the <tt>LibrarySource</tt>s of the
-     * class loader's module.
-     * </p>
-     * @param name the name of the library to find.
-     * @return the file system path of library or <tt>null</tt>
-    **/
-    protected String findLibrary(String name)
-    {
-        // Remove leading slash, if present.
-        if (name.startsWith("/"))
-        {
-            name = name.substring(1);
-        }
-
-        LibrarySource[] sources = m_module.getLibrarySources();
-        for (int i = 0;
-            (sources != null) && (i < sources.length);
-            i++)
-        {
-            String path = sources[i].getPath(name);
-            if (path != null)
-            {
-                return path;
-            }
-        }
-
-        return null;
-    }
-}
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java
index ec15d49..8a00403 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java
@@ -25,13 +25,13 @@
  * events, a <tt>ModuleListener</tt> must be added to the <tt>ModuleManager</tt>
  * instance.
  * </p>
- * @see org.apache.felix.moduleloader.ModuleManager
- * @see org.apache.felix.moduleloader.Module
+ * @see org.apache.felix.moduleloader.ModuleFactoryImpl
+ * @see org.apache.felix.moduleloader.ModuleImpl
  * @see org.apache.felix.moduleloader.ModuleListener
 **/
 public class ModuleEvent extends EventObject
 {
-    private Module m_module = null;
+    private IModule m_module = null;
 
     /**
      * <p>
@@ -42,9 +42,9 @@
      * @param mgr the source of the event.
      * @param module the subject of the event.
     **/
-    public ModuleEvent(ModuleManager mgr, Module module)
+    public ModuleEvent(IModuleFactory factory, IModule module)
     {
-        super(mgr);
+        super(factory);
         m_module = module;
     }
 
@@ -54,7 +54,7 @@
      * </p>
      * @return the module that is the subject of the event.
     **/
-    public Module getModule()
+    public IModule getModule()
     {
         return m_module;
     }
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleFactoryImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleFactoryImpl.java
new file mode 100644
index 0000000..84cfd67
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleFactoryImpl.java
@@ -0,0 +1,262 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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)
+    {
+        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);
+                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;
+    }
+
+    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);
+            // Open the module's content loader to initialize it.
+            // TODO: This is not really the best place for this, but at
+            // least it is centralized with the call to IContentLoader.close()
+            // when the module is removed above.
+            contentLoader.open();
+        }
+    }
+
+    /**
+     * <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);
+        }
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleImpl.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleImpl.java
new file mode 100644
index 0000000..e7f6536
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleImpl.java
@@ -0,0 +1,86 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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 org.apache.felix.framework.Logger;
+
+public class ModuleImpl implements IModule
+{
+    private Logger m_logger = null;
+    private String m_id = null;
+    private IContentLoader m_contentLoader = null;
+
+    ModuleImpl(Logger logger, String id)
+    {
+        m_logger = logger;
+        m_id = id;
+    }
+
+    public String getId()
+    {
+        return m_id;
+    }
+
+    public IContentLoader getContentLoader()
+    {
+        return m_contentLoader;
+    }
+
+    protected void setContentLoader(IContentLoader contentLoader)
+    {
+        m_contentLoader = contentLoader;
+    }
+
+    public Class getClass(String name)
+    {
+        try
+        {
+            return m_contentLoader.getSearchPolicy().findClass(name);
+        }
+        catch (ClassNotFoundException ex)
+        {
+            m_logger.log(
+                Logger.LOG_WARNING,
+                ex.getMessage(),
+                ex);
+        }
+        return null;
+    }
+
+    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 String toString()
+    {
+        return m_id;
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleListener.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleListener.java
index 4a583d9..813187a 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleListener.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleListener.java
@@ -1,5 +1,5 @@
 /*
- *   Copyright 2005 The Apache Software Foundation
+ *   Copyright 2006 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
  *   you may not use this file except in compliance with the License.
@@ -22,9 +22,9 @@
  * <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>ModuleManager</tt> instance.
+ * to the <tt>IModuleFactory</tt> instance.
  * </p>
- * @see org.apache.felix.moduleloader.ModuleManager
+ * @see org.apache.felix.moduleloader.IModuleFactory
  * @see org.apache.felix.moduleloader.ModuleEvent
 **/
 public interface ModuleListener extends EventListener
@@ -32,7 +32,7 @@
     /**
      * <p>
      * This method is called after a module is added to the
-     * <tt>ModuleManager</tt>.
+     * <tt>IModuleFactory</tt>.
      * </p>
      * @param event the event object containing the event details.
     **/
@@ -40,17 +40,8 @@
 
     /**
      * <p>
-     * This method is called after a module has been reset by the
-     * <tt>ModuleManager</tt>.
-     * </p>
-     * @param event the event object containing the event details.
-    **/
-    public void moduleReset(ModuleEvent event);
-
-    /**
-     * <p>
      * This method is called after a module is remove from the
-     * <tt>ModuleManager</tt>.
+     * <tt>IModuleFactory</tt>.
      * </p>
      * @param event the event object containing the event details.
     **/
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleManager.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleManager.java
deleted file mode 100644
index 7640479..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleManager.java
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.*;
-
-/**
- * <p>
- * The <tt>ModuleManager</tt> class is the core facility for defining a
- * re-usable, policy-driven class loader for applications that require
- * flexible class loading mechanisms. The <tt>ModuleManager</tt> is not
- * class loader itself, but it supports the concept of a
- * <a href="Module.html"><tt>Module</tt></a>,
- * which is a unit of organization for application classes and resources.
- * The <tt>ModuleManager</tt> has only a handful of methods that allow
- * an application to add, remove, reset, and query modules; the intent
- * is to place as few assumptions in the <tt>ModuleManager</tt> as possible.
- * </p>
- * <p>
- * The idea is simple, allow the application to map itself into modules
- * however it sees fit and let the <tt>ModuleManager</tt> assume the
- * responsibility of managing the modules and loading classes and resources
- * from them as necessary via <a href="ModuleClassLoader.html"><tt>ModuleClassLoader</tt></a>s
- * that are associated with each module. In order to achieve this goal, though, the
- * <tt>ModuleManager</tt> must make at least one assumption on behalf of
- * the application. This assumption is that the loading of classes and resources
- * from the available modules must happen using a search algorithm
- * that is particular to the application itself. As a result of this assumption,
- * the <tt>ModuleManager</tt> requires that the application provide a concrete
- * implementation of the <a href="SearchPolicy.html"><tt>SearchPolicy</tt></a>
- * interface.
- * </p>
- * <p>
- * The search policy allows the <tt>ModuleLoader</tt> to let applications inject
- * their own particular class loading policies, without dictating strict or
- * constraining base assumptions. Of course, it is likely that many applications
- * will use the same or very similar search policies. Because of this, another
- * goal of the <tt>ModuleLoader</tt> approach is to foster a common library of
- * search policies that applications are free to use or customize as they see
- * fit. These common search policies are analagous to patterns, where each search
- * policy is viewable as a <i>class loading pattern</i>. Some initial search
- * policies included with the <tt>ModuleLoader</tt> are
- * <a href="search/ExhaustiveSearchPolicy.html"><tt>ExhaustiveSearchPolicy</tt></a>,
- * <a href="search/SelfContainedSearchPolicy.html"><tt>SelfContainedSearchPolicy</tt></a>, and
- * <a href="search/ImportSearchPolicy.html"><tt>ImportSearchPolicy</tt></a>.
- * </p>
- * <p>
- * Due to the fact that class loaders are tied to security and resource loading,
- * the search policy alone is not sufficient for the <tt>ModuleLoader</tt> to
- * perform its function. To fulfill these other purposes, the <tt>ModuleLoader</tt>
- * introduces another policy interface, called the <a href="URLPolicy.html"><tt>URLPolicy</tt></a>.
- * The <tt>URLPolicy</tt> allows the application to inject its particular policy
- * for to purposes:
- * </p>
- * <ol>
- *   <li>Creating the <tt>URL</tt> associated with loading a resource, such as
- *       the <tt>URL</tt> returned from a call to <tt>Class.getResource()</tt>.
- *   </li>
- *   <li>Creating the <tt>URL</tt> that will be associated with a class's
- *       <tt>CodeSource</tt> when defining the class for purposes of security
- *       and assigning permissions.
- *   </li>
- * </ol>
- * <p>
- * The <tt>ModuleLoader</tt> defines a default <tt>URLPolicy</tt>, called
- * <a href="DefaultURLPolicy.html"><tt>DefaultURLPolicy</tt></a>, that provides
- * a simple <tt>URLStreamHandler</tt> for accessing resources inside of modules
- * and that returns <tt>null</tt> for the <tt>CodeSource</tt> <tt>URL</tt>.
- * Applications only need to supply their own <tt>URLPolicy</tt> if the default
- * one does not provide the appropriate behavior.
- * </p>
- * <p>
- * It is possible for an application to create multiple instances of the
- * <tt>ModuleManager</tt> within a single JVM, but it is not possible to
- * share modules across multiple <tt>ModuleManager</tt>s. A given <tt>ModuleManager</tt>
- * can only have one <tt>SelectionPolicy</tt> and one <tt>URLPolicy</tt>.
- * </p>
- * @see org.apache.felix.moduleloader.Module
- * @see org.apache.felix.moduleloader.ModuleClassLoader
- * @see org.apache.felix.moduleloader.SearchPolicy
- * @see org.apache.felix.moduleloader.URLPolicy
- * @see org.apache.felix.moduleloader.DefaultURLPolicy
-**/
-public class ModuleManager
-{
-    private List m_moduleList = new ArrayList();
-    private Map m_moduleMap = new HashMap();
-    private SearchPolicy m_searchPolicy = null;
-    private URLPolicy m_urlPolicy = null;
-    private ModuleListener[] m_listeners = null;
-    private static final ModuleListener[] m_noListeners = new ModuleListener[0];
-
-    /**
-     * <p>
-     * Constructs a <tt>ModuleManager</tt> instance using the specified
-     * search policy and the default <tt>URL</tt> policy.
-     * </p>
-     * @param searchPolicy the search policy that the instance should use.
-     * @see org.apache.felix.moduleloader.SearchPolicy
-    **/
-    public ModuleManager(SearchPolicy searchPolicy)
-    {
-        this(searchPolicy, null);
-    }
-
-    /**
-     * <p>
-     * Constructs a <tt>ModuleManager</tt> instance using the specified
-     * search policy and the specified <tt>URL</tt> policy.
-     * </p>
-     * @param searchPolicy the search policy that the instance should use.
-     * @param urlPolicy the <tt>URL</tt> policy that the instance should use.
-     * @see org.apache.felix.moduleloader.SearchPolicy
-     * @see org.apache.felix.moduleloader.URLPolicy
-    **/
-    public ModuleManager(SearchPolicy searchPolicy, URLPolicy urlPolicy)
-    {
-        m_listeners = m_noListeners;
-        m_searchPolicy = searchPolicy;
-        m_searchPolicy.setModuleManager(this);
-
-        if (urlPolicy == null)
-        {
-            m_urlPolicy = new DefaultURLPolicy();
-        }
-        else
-        {
-            m_urlPolicy = urlPolicy;
-        }
-    }
-
-    /**
-     * <p>
-     * Returns the <tt>URL</tt> policy used by this instance.
-     * </p>
-     * @return the <tt>URL</tt> policy used by this instance.
-     * @see org.apache.felix.moduleloader.URLPolicy
-    **/
-    public URLPolicy getURLPolicy()
-    {
-        return m_urlPolicy;
-    }
-
-    /**
-     * <p>
-     * Returns the search policy used by this instance.
-     * </p>
-     * @return the search policy used by this instance.
-     * @see org.apache.felix.moduleloader.SearchPolicy
-    **/
-    public SearchPolicy getSearchPolicy()
-    {
-        return m_searchPolicy;
-    }
-
-    /**
-     * <p>
-     * Returns an array of all modules being managed by the
-     * <tt>ModuleManager</tt> instance. The array contains a snapshot of
-     * all modules in the <tt>ModuleManager</tt> at the time when this
-     * method was called.
-     * </p>
-     * @return an array of all modules being managed by the <tt>ModuleManager</tt>
-     *         instance.
-     * @see org.apache.felix.moduleloader.Module
-    **/
-    public synchronized Module[] getModules()
-    {
-        Module[] modules = new Module[m_moduleList.size()];
-        return (Module[]) m_moduleList.toArray(modules);
-    }
-
-    /**
-     * <p>
-     * Returns a module associated with the specified identifier.
-     * </p>
-     * @param id the identifier for the module to be retrieved.
-     * @return the module associated with the identifier or <tt>null</tt>.
-     * @see org.apache.felix.moduleloader.Module
-    **/
-    public synchronized Module getModule(String id)
-    {
-        return (Module) m_moduleMap.get(id);
-    }
-
-    /**
-     * <p>
-     * Adds a module to the module manager. The module will have the specified
-     * unique identifier, with the associated attributes, resource sources, and
-     * library sources. If the identifier is not unique, then an exception is
-     * thrown.
-     * </p>
-     * @param id the unique identifier of the new module.
-     * @param attributes an array of key-value attribute pairs to
-     *        associate with the module.
-     * @param resSources an array of <tt>ResourceSource</tt>s to associate
-     *        with the module.
-     * @param libSources an array of <tt>LibrarySource</tt>s to associate
-     *        with the module.
-     * @return the newly created module.
-     * @throws java.lang.IllegalArgumentException if the module identifier
-     *         is not unique.
-     * @see org.apache.felix.moduleloader.Module
-     * @see org.apache.felix.moduleloader.ResourceSource
-     * @see org.apache.felix.moduleloader.LibrarySource
-    **/
-    public Module addModule(String id, Object[][] attributes,
-        ResourceSource[] resSources, LibrarySource[] libSources)
-    {
-        return addModule(id, attributes, resSources, libSources, false);
-    }
-
-    public Module addModule(String id, Object[][] attributes,
-        ResourceSource[] resSources, LibrarySource[] libSources,
-        boolean useParentSource)
-    {
-        Module 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 Module(this, id, attributes, resSources, libSources, useParentSource);
-                m_moduleList.add(module);
-                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;
-    }
-
-    /**
-     * <p>
-     * Resets a given module. In resetting a module, the module's associated
-     * class loader is thrown away; it is the application's responsibility to
-     * determine when and how that application code stops using classes (and
-     * subsequent instances) from the class loader of the reset module.
-     * This method allows the associated elements of the module (i.e.,
-     * attributes, resource sources, and library sources) to be changed also;
-     * if these elements have not changed then they simply need to be passed
-     * back in from the existing module. This method is useful in situations
-     * where the underlying module needs to be changed at run time, such as
-     * might be necessary if a module was updated.
-     * </p>
-     * <p>
-     * The same effect could be achieved by first removing and then re-adding
-     * a module, but with one subtle different. By removing and then re-adding
-     * a module, a new module is created and, thus, all existing references
-     * become invalid. By explicitly having this method, the <tt>ModuleManager</tt>
-     * maintains the integrity of the module reference, which is more intuitive
-     * in the case where an updated module is intended to be the same module,
-     * only updated.
-     * </p>
-     * @param module the module reset.
-     * @param attributes an array of key-value attribute pairs to
-     *        associate with the module.
-     * @param resSources an array of <tt>ResourceSource</tt>s to associate
-     *        with the module.
-     * @param libSources an array of <tt>LibrarySource</tt>s to associate
-     *        with the module.
-     * @see org.apache.felix.moduleloader.Module
-     * @see org.apache.felix.moduleloader.ResourceSource
-     * @see org.apache.felix.moduleloader.LibrarySource
-    **/
-    public void resetModule(
-        Module module, Object[][] attributes,
-        ResourceSource[] resSources, LibrarySource[] libSources)
-    {
-        // Use a synchronized block instead of synchronizing the
-        // method, so we can fire our event outside of the block.
-        synchronized (this)
-        {
-            module = (Module) m_moduleMap.get(module.getId());
-            if (module != null)
-            {
-                module.reset(attributes, resSources, libSources);
-            }
-            else
-            {
-                // Don't fire event.
-                return;
-            }
-        }
-
-        // Fire event here instead of inside synchronized block.
-        fireModuleReset(module);
-    }
-
-    /**
-     * <p>
-     * Removes the specified module from the <tt>ModuleManager</tt>. Removing
-     * a module only removed the module from the <tt>ModuleManager</tt>. It is
-     * the application's responsibility to determine when and how application code
-     * stop using classes (and subsequent instances) that were loaded from
-     * the class loader of the removed module.
-     * </p>
-     * @param module the module to remove.
-    **/
-    public void removeModule(Module 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_moduleList.remove(module);
-                m_moduleMap.remove(module.getId());
-
-                // Dispose of the module.
-                module.dispose();
-            }
-            else
-            {
-                // Don't fire event.
-                return;
-            }
-        }
-
-        // Fire event here instead of inside synchronized block.
-        fireModuleRemoved(module);
-    }
-
-    /**
-     * <p>
-     * Adds a listener to the <tt>ModuleManager</tt> to listen for
-     * module added, reset, 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>ModuleManager</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>ModuleManager</tt>.
-     * </p>
-     * @param module the module that was added.
-    **/
-    protected void fireModuleAdded(Module 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 reset.
-     * </p>
-     * @param module the module that was reset.
-    **/
-    protected void fireModuleReset(Module 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].moduleReset(event);
-        }
-    }
-
-    /**
-     * <p>
-     * Fires an event indicating that the specified module was removed
-     * from the <tt>ModuleManager</tt>.
-     * </p>
-     * @param module the module that was removed.
-    **/
-    protected void fireModuleRemoved(Module 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);
-        }
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLConnection.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLConnection.java
deleted file mode 100644
index 9015bbf..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ModuleURLConnection.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.*;
-import java.net.URL;
-import java.net.URLConnection;
-import java.security.Permission;
-
-class ModuleURLConnection extends URLConnection
-{
-    private ModuleManager m_mgr = null;
-    private int m_contentLength;
-    private long m_contentTime;
-    private String m_contentType;
-    private InputStream m_is;
-
-    public ModuleURLConnection(ModuleManager mgr, URL url)
-    {
-        super(url);
-        m_mgr = mgr;
-    }
-
-    public void connect() throws IOException
-    {
-        if (!connected)
-        {
-            // The URL is constructed like this:
-            // module://<module-id>/<source-idx>/<resource-path>
-            Module module = m_mgr.getModule(url.getHost());
-            if (module == null)
-            {
-                throw new IOException("Unable to find bundle's module.");
-            }
-
-            String resource = url.getFile();
-            if (resource == null)
-            {
-                throw new IOException("Unable to find resource: " + url.toString());
-            }
-            if (resource.startsWith("/"))
-            {
-                resource = resource.substring(1);
-            }
-            int rsIdx = -1;
-            try
-            {
-                rsIdx = Integer.parseInt(resource.substring(0, resource.indexOf("/")));
-            }
-            catch (NumberFormatException ex)
-            {
-                new IOException("Error parsing resource index.");
-            }
-            resource = resource.substring(resource.indexOf("/") + 1);
-
-            // Get the resource bytes from the resource source.
-            byte[] bytes = null;
-            ResourceSource[] resSources = module.getResourceSources();
-            if ((resSources != null) && (rsIdx < resSources.length))
-            {
-                if (resSources[rsIdx].hasResource(resource))
-                {
-                    bytes = resSources[rsIdx].getBytes(resource);
-                }
-            }
-
-            if (bytes == null)
-            {
-                throw new IOException("Unable to find resource: " + url.toString());
-            }
-
-            m_is = new ByteArrayInputStream(bytes);
-            m_contentLength = bytes.length;
-            m_contentTime = 0L;  // TODO: Change this.
-            m_contentType = URLConnection.guessContentTypeFromName(resource);
-            connected = true;
-        }
-    }
-
-    public InputStream getInputStream()
-        throws IOException
-    {
-        if (!connected)
-        {
-            connect();
-        }
-        return m_is;
-    }
-
-    public int getContentLength()
-    {
-        if (!connected)
-        {
-            try {
-                connect();
-            } catch(IOException ex) {
-                return -1;
-            }
-        }
-        return m_contentLength;
-    }
-
-    public long getLastModified()
-    {
-        if (!connected)
-        {
-            try {
-                connect();
-            } catch(IOException ex) {
-                return 0;
-            }
-        }
-        if (m_contentTime != -1L)
-        {
-            return m_contentTime;
-        }
-        else
-        {
-            return 0L;
-        }
-    }
-
-    public String getContentType()
-    {
-        if (!connected)
-        {
-            try {
-                connect();
-            } catch(IOException ex) {
-                return null;
-            }
-        }
-        return m_contentType;
-    }
-
-    public Permission getPermission()
-    {
-        // TODO: This should probably return a FilePermission
-        // to access the bundle JAR file, but we don't have the
-        // necessary information here to construct the absolute
-        // path of the JAR file...so it would take some
-        // re-arranging to get this to work.
-        return null;
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ResourceSource.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ResourceSource.java
deleted file mode 100644
index 78d1ee1..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ResourceSource.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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;
-
-/**
- * <p>
- * This interface represents a source for obtaining resources for a
- * given module via the module's class loader. A resource source is used
- * for retrieving both classes and resources; at this level, classes are
- * treated in an identical manner as an ordinary resource. Resource sources
- * are completely arbitrary and implementations may load resources from a JAR
- * file, the network, a database, or anywhere.
- * </p>
- * <p>
- * All resource sources are initialized before first usage via a call
- * to the <a href="#open()"><tt>ResourceSource.open()</tt></a> method and
- * are also deinitialized via a call to
- * <a href="#open()"><tt>ResourceSource.close()</tt></a>. Resource sources
- * should be implemented such that they can be opened, closed, and then
- * re-opened.
- * </p>
- * @see org.apache.felix.moduleloader.Module
- * @see org.apache.felix.moduleloader.ModuleClassLoader
-**/
-public interface ResourceSource
-{
-    /**
-     * <p>
-     * This method initializes the resource source. It is called when
-     * the associated module is added to the <tt>ModuleManager</tt>. It
-     * is acceptable for implementations to ignore duplicate calls to this
-     * method if the resource source is already opened.
-     * </p>
-    **/
-    public void open();
-
-    /**
-     * <p>
-     * This method de-initializes the resource source. It is called when
-     * the associated module is removed from the <tt>ModuleManager</tt> or
-     * when the module is reset by the <tt>ModuleManager</tt>.
-     * </p>
-    **/
-    public void close();
-
-    /**
-     * <p>
-     * This method returns a boolean indicating whether the resource source
-     * contains the specified resource.
-     * </p>
-     * @param name the name of the resource whose existence is being checked.
-     * @param <tt>true</tt> if the resource source has the resource, <tt>false</tt>
-     *        otherwise.
-     * @throws java.lang.IllegalStateException if the resource source has not
-     *         been opened.
-    **/
-    public boolean hasResource(String name) throws IllegalStateException;
-
-    /**
-     * <p>
-     * This method returns a byte array of the specified resource's contents.
-     * </p>
-     * @param name the name of the resource to retrieve.
-     * @param a byte array of the resource's contents or <tt>null</tt>
-     *        if the resource was not found.
-     * @throws java.lang.IllegalStateException if the resource source has not
-     *         been opened.
-    **/
-    public byte[] getBytes(String name) throws IllegalStateException;
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/SearchPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/SearchPolicy.java
deleted file mode 100644
index dfa51f2..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/SearchPolicy.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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;
-
-/**
- * <p>
- * This interface represents a policy to define the most basic behavior
- * of how classes, resources, and native libraries within a specific instance
- * of <tt>ModuleManager</tt> are found. A <tt>ModuleManager</tt> manages a set of
- * <tt>Module</tt>s, each of which is a potential source of classes, resources,
- * and native libraries. The search policy makes it possible to consult these
- * sources without hard-coding assumptions about application behavior
- * or structure. Applicaitons inject their own specific class loading policy
- * by creating a custom search policy or by selecting a pre-existing search
- * policy that matches their needs.
- * </p>
- * <p>
- * The search policy is used by <tt>ModuleClassLoader</tt>, of which, there
- * is one per <tt>Module</tt> within a given <tt>ModuleManager</tt> instance.
- * The search policy is consulted by the <tt>ModuleClassLoader</tt> whenever
- * there is a request for a class, resource, or native library. The search
- * policy will generally search other modules in an application-specific
- * way in order to find the requested item; for example, an application may
- * use a policy where module's may import from one another. If the search
- * policy provides an answer, then the <tt>ModuleClassLoader</tt> will use
- * this to answer the originating request.
- * </p>
- * <p>
- * <b><i>Important:</i></b> The search policy <i>searches</i> modules in
- * some application-specific manner in order to find a class or resource.
- * This <i>search</i> is instigated, either directly or indirectly, by calls
- * to <tt>ModuleClassLoader.loadClass()</tt> and <tt>ModuleClassLoader.getResource()</tt>,
- * respectively. In order for the search policy to load a class or resource,
- * it must <b>not</b> use <tt>ModuleClassLoader.loadClass()</tt> or
- * <tt>ModuleClassLoader.getResource()</tt> again, because this would result
- * in an infinite loop. Instead, the <tt>ModuleClassLoader</tt> offers the
- * the methods <tt>ModuleClassLoader.loadClassFromModule()</tt> and
- * <tt>ModuleClassLoader.getResourceFromModule()</tt> to search a given module
- * and to avoid an infinite loop.
- * </p>
- * <pre>
- *     ...
- *     public Class findClass(Module module, String name)
- *     {
- *         Module[] modules = m_mgr.getModules();
- *         for (int i = 0; i < modules.length; i++)
- *         {
- *             try {
- *                 Class clazz = modules[i].getClassLoader().loadClassFromModule(name);
- *                 if (clazz != null)
- *                 {
- *                     return clazz;
- *                 }
- *             } catch (Throwable th) {
- *             }
- *         }
- *
- *         return null;
- *     }
- *     ...
- * </pre>
- * <p>
- * In the above code, the search policy "exhaustively" searches every module in the
- * <tt>ModuleManager</tt> to find the requested resource. Note that this policy
- * will also search the module that originated the request, which is not totally
- * necessary since returning <tt>null</tt> will cause the <tt>ModuleClassLoader</tt>
- * to search the originating module's <tt>ResourceSource</tt>s.
- * </p>
-**/
-public interface SearchPolicy
-{
-    /**
-     * <p>
-     * This method is called once by the <tt>ModuleManager</tt> to
-     * give the search policy instance a reference to its associated
-     * module manager. This method should be implemented such that
-     * it cannot be called twice; calling this method a second time
-     * should produce an illegal state exception.
-     * </p>
-     * @param mgr the module manager associated with this search policy.
-     * @throws java.lang.IllegalStateException if the method is called
-     *         more than once.
-    **/
-    public void setModuleManager(ModuleManager mgr)
-        throws IllegalStateException;
-
-    /**
-     * <p>
-     * The <tt>ModuleClassLoader</tt> calls this method before performing
-     * the call to <tt>ClassLoader.defineClass()</tt> to give the search policy
-     * an opportunity to define the <tt>Package</tt> object for the specified
-     * package. The method should return an array of <tt>String</tt> values for
-     * each of the following: specTitle, specVersion, specVendor, implTitle,
-     * implVersion, and implVendor. See <tt>ClassLoader.definePackage()</tt>
-     * for more details. The returned array may contain <tt>null</tt>s, but
-     * the return array must have six elements.
-     * </p>
-     * @param module the module requesting a class from the package.
-     * @param pkgName the package name of the class being requested.
-     * @return an array containing values for creating the <tt>Package</tt>
-     *         object for the specified package.
-    **/
-    public Object[] definePackage(Module module, String pkgName);
-
-    /**
-     * <p>
-     * When a module instigates a class load operation, this method is called
-     * to find the desired class for the instigating module. This method is
-     * called <b>before</b> searching the module's resource sources for the class.
-     * How the class is found is dependent upon the search policy implementation.
-     * </p>
-     * <p>
-     * This method may return <tt>null</tt> or throw an exception if the
-     * specified class is not found. Whether a specific search policy
-     * implementation should do one or the other depends on the details
-     * of the specific search policy. The <tt>ModuleClassLoader</tt>
-     * first delegates to this method, then to the local resources
-     * sources of the module, and then finally to then the
-     * <tt>SearchPolicy.findClassAfterModule()</tt> method. If this method
-     * returns null, then the search for the class will continue to these
-     * latter two steps. On the other hand, if this method returns a class
-     * or throws an exception, then the latter two steps will not be searched.
-     * </p>
-     * <p>
-     * <b>Important:</b> If the implementation of this method delegates
-     * the class loading to a <tt>ModuleClassLoader</tt> of another module,
-     * then it should <b>not</b> use the method <tt>ModuleClassLoader.loadClass()</tt>
-     * to load the class; it should use <tt>ModuleClassLoader.loadClassFromModule()</tt>
-     * instead. This is necessary to eliminate an infinite loop that would
-     * occur otherwise. Also, with respect to the <tt>ModuleLoader</tt> framework,
-     * this method will only be called by a single thread at a time and is only
-     * intended to be called by <tt>ModuleClassLoader.loadClass()</tt>.
-     * </p>
-     * @param parent the parent class loader of the delegating class loader.
-     * @param module the target module that is loading the class.
-     * @param name the name of the class being loaded.
-     * @return the class if found, <tt>null</tt> otherwise.
-     * @throws java.lang.ClassNotFoundException if the class could not be
-     *         found and the entire search operation should fail.
-    **/
-    public Class findClassBeforeModule(ClassLoader parent, Module module, String name)
-        throws ClassNotFoundException;
-
-    /**
-     * <p>
-     * When a module instigates a class load operation, this method is called
-     * to find the desired class for the instigating module. This method is
-     * called <b>after</b> searching the module's resource sources for the class.
-     * How the class is found is dependent upon the search policy implementation.
-     * </p>
-     * <p>
-     * The <tt>ModuleClassLoader</tt> first delegates to the
-     * <tt>SearchPolicy.findClassBeforeModule() method, then to the local
-     * resources sources of the module, and then finally to this method.
-     * This method is the last attempt to find the class and if it fails
-     * (by either return <tt>null</tt> or throwing an exception), then the
-     * result of the entire class load will fail.
-     * </p>
-     * <p>
-     * <b>Important:</b> If the implementation of this method delegates
-     * the class loading to a <tt>ModuleClassLoader</tt> of another module,
-     * then it should <b>not</b> use the method <tt>ModuleClassLoader.loadClass()</tt>
-     * to load the class; it should use <tt>ModuleClassLoader.loadClassFromModule()</tt>
-     * instead. This is necessary to eliminate an infinite loop that would
-     * occur otherwise. Also, with respect to the <tt>ModuleLoader</tt> framework,
-     * this method will only be called by a single thread at a time and is only
-     * intended to be called by <tt>ModuleClassLoader.loadClass()</tt>.
-     * </p>
-     * @param parent the parent class loader of the delegating class loader.
-     * @param module the target module that is loading the class.
-     * @param name the name of the class being loaded.
-     * @return the class if found, <tt>null</tt> otherwise.
-     * @throws java.lang.ClassNotFoundException if the class could not be
-     *         found and the entire search operation should fail.
-    **/
-    public Class findClassAfterModule(ClassLoader parent, Module module, String name)
-        throws ClassNotFoundException;
-
-    /**
-     * <p>
-     * This method tries to find the specified resource for the specified
-     * module. How the resource is found or whether it is actually retrieved
-     * from the specified module is dependent upon the implementation. The
-     * default <tt>ModuleClassLoader.getResource()</tt> method does not do
-     * any searching on its own.
-     * </p>
-     * <p>
-     * This method may return <tt>null</tt> or throw an exception if the
-     * specified resource is not found. Whether a specific search policy
-     * implementation should do one or the other depends on the details
-     * of the specific search policy. The <tt>ModuleClassLoader</tt>
-     * first delegates to this method and then to the local resource
-     * sources of the module. If this method returns null, then the local
-     * resource sources will be searched. On the other hand, if this method
-     * throws an exception, then the local resource sources will not be
-     * searched.
-     * </p>
-     * <p>
-     * <b>Important:</b> If the implementation of this method delegates
-     * the resource loading to a <tt>ModuleClassLoader</tt> of another module,
-     * then it should not use the method <tt>ModuleClassLoader.getResource()</tt>
-     * to get the resource; it should use <tt>ModuleClassLoader.getResourceFromModule()</tt>
-     * instead. This is necessary to eliminate an infinite loop that would
-     * occur otherwise. Also, with respect to the <tt>ModuleLoader</tt> framework,
-     * this method will only be called by a single thread at a time and is not
-     * intended to be called directly.
-     * </p>
-     * @param parent the parent class loader of the delegating class loader.
-     * @param module the target module that is loading the resource.
-     * @param name the name of the resource being loaded.
-     * @return a <tt>URL</tt> to the resource if found, <tt>null</tt> otherwise.
-     * @throws org.apache.felix.moduleloader.ResourceNotFoundException if the
-     *         resource could not be found and the entire search operation
-     *         should fail.
-    **/
-    public URL findResource(ClassLoader parent, Module module, String name)
-        throws ResourceNotFoundException;
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/URLPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/URLPolicy.java
deleted file mode 100644
index 452aebc..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/URLPolicy.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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;
-
-/**
- * <p>
- * This interface represents the <tt>ModuleLoader</tt>'s policy for creating
- * <tt>URL</tt> for resource loading and security purposes. Java requires the
- * use of <tt>URL</tt>s for resource loading and security. For resource loading,
- * <tt>URL</tt>s are returned for requested resources. Subsequently, the resource
- * <tt>URL</tt> is used to create an input stream for reading the resources
- * bytes. With respect to security, <tt>URL</tt>s are used when defining a
- * class in order to determine where the code came from, this concept is called
- * a <tt>CodeSource</tt>. This approach enables Java to assign permissions to
- * code that originates from particular locations.
- * </p>
- * <p>
- * The <tt>ModuleManager</tt> requires a concrete implementation of this
- * interface in order to function. Whenever the <tt>ModuleManager</tt> requires
- * a <tt>URL</tt> for either resource loading or security, it delegates to
- * the policy implementation. A default implementation is provided,
- * called <a href="DefaultURLPolicy.html"><tt>DefaultURLPolicy</tt></a>, but
- * it only supports resource loading, not security.
- * </p>
- * @see org.apache.felix.moduleloader.ModuleManager
- * @see org.apache.felix.moduleloader.DefaultURLPolicy
-**/
-public interface URLPolicy
-{
-    /**
-     * <p>
-     * This method should return a <tt>URL</tt> that represents the
-     * location from which the module originated. This <tt>URL</tt>
-     * can be used when assigning permissions to the module, such as
-     * is done in the Java permissions policy file.
-     * </p>
-     * @param mgr the <tt>ModuleManager</tt> of the module.
-     * @param module the module for which the <tt>URL</tt> is to be created.
-     * @return an <tt>URL</tt> to associate with the module.
-    **/
-    public URL createCodeSourceURL(ModuleManager mgr, Module module);
-
-    /**
-     * <p>
-     * This method should return a <tt>URL</tt> that is suitable
-     * for accessing the bytes of the specified resource. It must be possible
-     * open a connection to this <tt>URL</tt>, which may require that
-     * the implementer of this method also introduce a custom
-     * <tt>java.net.URLStreamHander</tt> when creating the <tt>URL</tt>.
-     * </p>
-     * @param mgr the <tt>ModuleManager</tt> of the module.
-     * @param module the module for which the resource is being loaded.
-     * @param rsIdx the index of the <tt>ResourceSource</tt> containing the resource.
-     * @param name the name of the resource being loaded.
-     * @return an <tt>URL</tt> for retrieving the resource.
-    **/
-    public URL createResourceURL(ModuleManager mgr, Module module, int rsIdx, String name);
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/Util.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/Util.java
deleted file mode 100755
index 34b16d7..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/Util.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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 class Util
-{
-    public static String getClassName(String className)
-    {
-        if (className == null)
-        {
-            className = "";
-        }
-        return (className.lastIndexOf('.') < 0)
-            ? "" : className.substring(className.lastIndexOf('.') + 1);
-    }
-
-    public static String getClassPackage(String className)
-    {
-        if (className == null)
-        {
-            className = "";
-        }
-        return (className.lastIndexOf('.') < 0)
-            ? "" : className.substring(0, className.lastIndexOf('.'));
-    }
-
-    public static String getResourcePackage(String resource)
-    {
-        if (resource == null)
-        {
-            resource = "";
-        }
-        // NOTE: The package of a resource is tricky to determine since
-        // resources do not follow the same naming conventions as classes.
-        // This code is pessimistic and assumes that the package of a
-        // resource is everything up to the last '/' character. By making
-        // this choice, it will not be possible to load resources from
-        // imports using relative resource names. For example, if a
-        // bundle exports "foo" and an importer of "foo" tries to load
-        // "/foo/bar/myresource.txt", this will not be found in the exporter
-        // because the following algorithm assumes the package name is
-        // "foo.bar", not just "foo". This only affects imported resources,
-        // local resources will work as expected.
-        String pkgName = (resource.startsWith("/")) ? resource.substring(1) : resource;
-        pkgName = (pkgName.lastIndexOf('/') < 0)
-            ? "" : pkgName.substring(0, pkgName.lastIndexOf('/'));
-        pkgName = pkgName.replace('/', '.');
-        return pkgName;
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/CompatibilityPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/CompatibilityPolicy.java
deleted file mode 100644
index 86b7efd..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/CompatibilityPolicy.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.search;
-
-/**
- * <p>
- * This interface represents the naming and version numbering policy of
- * import and export identifiers for the <tt>ImportSearchPolicy</tt>. A concrete
- * implementation of this interface is required to create an instance
- * of <tt>ImportSearchPolicy</tt>. The sole purpose of this interface
- * is to allow the <tt>ImportSearchPolicy</tt> to determine if one
- * import/export identifier and version is compatible with another.
- * </p>
- * @see org.apache.felix.moduleloader.search.ImportSearchPolicy
-**/
-public interface CompatibilityPolicy
-{
-    /**
-     * Compares two import/export identifiers.
-     * @param leftId the identifier to test for compatibility.
-     * @param leftVersion the version number to test for compatibility.
-     * @param rightId the identifier used as the compatibility base line.
-     * @param rightVersion the version used as the compatibility base line.
-     * @return <tt>0</tt> if the identifiers are equal, <tt>-1</tt> if the
-     *         left identifier is less then the right identifier, and <tt>1</tt>
-     *         if the left identifier is greater than the right identifier.
-     * @throws java.lang.IllegalArgumentException if the two identifiers
-     *         are not comparable, i.e., they refer to intrinsically different
-     *         entities.
-    **/
-    public int compare(
-        Object leftId, Object leftVersion,
-        Object rightId, Object rightVersion);
-
-    /**
-     * Returns whether the first import/export identifer is compatible
-     * with the second; this method should not throw any exceptions.
-     * @param leftId the identifier to test for compatibility.
-     * @param leftVersion the version number to test for compatibility.
-     * @param rightId the identifier used as the compatibility base line.
-     * @param rightVersion the version used as the compatibility base line.
-     * @return <tt>true</tt> if the left version number object is compatible
-     *         with the right version number object, otherwise <tt>false</tt>.
-    **/
-    public boolean isCompatible(
-        Object leftId, Object leftVersion,
-        Object rightId, Object rightVersion);
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ExhaustiveSearchPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ExhaustiveSearchPolicy.java
deleted file mode 100644
index d98d8e6..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ExhaustiveSearchPolicy.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.search;
-
-import java.net.URL;
-
-import org.apache.felix.moduleloader.*;
-
-/**
- * <p>
- * This class implements a <tt>ModuleLoader</tt> search policy that
- * exhaustively and linearly searches all modules when trying to load
- * a particular class or resource. As a result of this algorithm, every class loader
- * for every module is essentially identical, meaning that each will
- * load a given class or resource from the same class loader. This search policy
- * provides behavior similar to the standard <tt>CLASSPATH</tt> environment
- * variable approach. The main difference is that modules can be added
- * to the module manager at run time; thus, the class path is dynamically
- * extended. This search policy is not fully dynamic, since it does not
- * support the removal of modules at run time; if a module is removed from
- * the module manager at run time, there is no attempt to clean up its
- * loaded classes.
- * </p>
- * @see org.apache.felix.moduleloader.SearchPolicy
- * @see org.apache.felix.moduleloader.Module
- * @see org.apache.felix.moduleloader.ModuleClassLoader
- * @see org.apache.felix.moduleloader.ModuleManager
-**/
-public class ExhaustiveSearchPolicy implements SearchPolicy
-{
-    private ModuleManager m_mgr = null;
-
-    /**
-     * This method is part of the <tt>SearchPolicy</tt> interface.
-     * This method is called by the <tt>ModuleManager</tt> once to
-     * give the search policy instance a reference to its associated
-     * module manager. This method should be implemented such that
-     * it cannot be called twice; calling this method a second time
-     * should produce an illegal state exception.
-     * @param mgr the module manager associated with this search policy.
-     * @throws java.lang.IllegalStateException if the method is called
-     *         more than once.
-    **/
-    public void setModuleManager(ModuleManager mgr)
-        throws IllegalStateException
-    {
-        if (m_mgr == null)
-        {
-            m_mgr = mgr;
-        }
-        else
-        {
-            throw new IllegalStateException("Module manager is already initialized");
-        }
-    }
-
-    public Object[] definePackage(Module module, String pkgName)
-    {
-        return null;
-    }
-
-    /**
-     * This method finds the specified class for the specified module. It
-     * finds the class by linearly asking each module in the module manager
-     * for the specific class. As soon as the class is found, it is returned.
-     * @param parent the parent class loader of the delegating class loader.
-     * @param module the target module that is loading the class.
-     * @param name the name of the class being loaded.
-     * @return the class if found, <tt>null</tt> otherwise.
-    **/
-    public Class findClassBeforeModule(ClassLoader parent, Module module, String name)
-    {
-        // First, try to load from parent.
-        if (parent != null)
-        {
-            try
-            {
-                Class c = parent.loadClass(name);
-                if (c != null)
-                {
-                    return c;
-                }
-            }
-            catch (ClassNotFoundException ex)
-            {
-                // Ignore and search modules.
-            }
-        }
-
-        Module[] modules = m_mgr.getModules();
-        for (int i = 0; i < modules.length; i++)
-        {
-            try {
-                Class clazz = modules[i].getClassLoader().loadClassFromModule(name);
-                if (clazz != null)
-                {
-                    return clazz;
-                }
-            } catch (Throwable th) {
-            }
-        }
-
-        return null;
-    }
-
-    public Class findClassAfterModule(ClassLoader parent, Module module, String name)
-    {
-        return null;
-    }
-
-    /**
-     * This method finds the specified resource for the specified module. It
-     * finds the resource by linearly asking each module in the module manager
-     * for specific resource. As soon as the resource is found, a <tt>URL</tt>
-     * to it is returned.
-     * @param parent the parent class loader of the delegating class loader.
-     * @param module the target module that is loading the resource.
-     * @param name the name of the resource being loaded.
-     * @return a <tt>URL</tt> to the resource if found, <tt>null</tt> otherwise.
-    **/
-    public URL findResource(ClassLoader parent, Module module, String name)
-    {
-        // First, try to load from parent.
-        if (parent != null)
-        {
-            URL url = parent.getResource(name);
-            if (url != null)
-            {
-                return url;
-            }
-        }
-
-        Module[] modules = m_mgr.getModules();
-        for (int i = 0; i < modules.length; i++)
-        {
-            try {
-                URL url = modules[i].getClassLoader().getResourceFromModule(name);
-                if (url != null)
-                {
-                    return url;
-                }
-            } catch (Throwable th) {
-            }
-        }
-
-        return null;
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ImportSearchPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ImportSearchPolicy.java
deleted file mode 100644
index 3fefc24..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ImportSearchPolicy.java
+++ /dev/null
@@ -1,1322 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.search;
-
-import java.net.URL;
-import java.util.*;
-
-import org.apache.felix.moduleloader.*;
-
-/**
- * <p>
- * This class implements a <tt>ModuleLoader</tt> search policy to support
- * modules that import and export classes and resources from/to one another.
- * Modules import from other modules by specifying a set of import identifiers
- * and associated version numbers. Modules export their classes and
- * resources by specifying a set of export identifiers and associated
- * versions. Exports for a given module are also treated as imports for that module,
- * meaning that it is possible for a module that exports classes to not use
- * the classes it exports, but to actually use classes that are exported from
- * another module. This search policy requires the following meta-data
- * attributes be attached to each module:
- * </p>
- * <ul>
- *   <li><tt>ImportSearchPolicy.EXPORTS_ATTR</tt> - the "<tt>exports</tt>"
- *       meta-data attribute is used to declare the module's exports,
- *   </li>
- *   <li><tt>ImportSearchPolicy.IMPORTS_ATTR</tt> - the "<tt>imports</tt>"
- *       meta-data attribute is used to declare the module's imports,
- *   </li>
- *   <li><tt>ImportSearchPolicy.PROPAGATES_ATTR</tt> - the "<tt>propagates</tt>"
- *       meta-data attribute is used to declare which imports are exposed or
- *       "propagated" to clients of the module's exports, and
- *   </li>
- *   <li><tt>ImportSearchPolicy.VALID_ATTR</tt> - the "<tt>valid</tt>"
- *       meta-data attribute signifies the current <i>validation</i> status
- *       of the module (this will be defined more fully below).
- *   </li>
- * </ul>
- * <p>
- * The value of the <tt>ImportSearchPolicy.EXPORTS_ATTR</tt> attribute is
- * an array of <tt>Object</tt> arrays, i.e., <tt>Object[][]</tt>. Each element
- * in the array signifies a particular export that is offered by this
- * associated module. Each element is an array triple of
- * <tt>Object</tt>, where the index into this triple is:
- * </p>
- * <ul>
- *   <li><tt>ImportSearchPolicy.IDENTIFIER_IDX</tt> - the first element
- *       is the export identifier object, used to identify the
- *       export target. The export identifier does not have any special
- *       meaning to the search policy and any value is allowed. A
- *       typical identifier might be the package name of the exported classes,
- *       such as <tt>javax.servlet</tt>.
- *   </li>
- *   <li><tt>ImportSearchPolicy.VERSION_IDX</tt> - the second element
- *       is the export version number. The version number does not have
- *       any special meaning to the search policy and any value is allowed.
- *       A typical version number might be major, minor, and release number.
- *   </li>
- *   <li><tt>ImportSearchPolicy.RESOLVING_MODULE_IDX</tt> - the third element
- *       is the resolving module for this export; since exports are treated like
- *       imports, it is possible that the resolving module will not be the
- *       exporting module itself. This value is filled in automatically by the
- *       search policy and is initially <tt>null</tt>.
- *   </li>
- * </ul>
- * </p>
- * <p>
- * The value of the <tt>ImportSearchPolicy.IMPORTS_ATTR</tt> attribute is
- * essentially the same as the <tt>ImportSearchPolicy.EXPORTS_ATTR</tt> defined
- * above; the only difference is that the array of versioned identifiers denote
- * import targets rather than exports.
- * </p>
- * <p>
- * The value of the <tt>ImportSearchPolicy.PROPAGATES_ATTR</tt> attribute is
- * an array of <tt>Object</tt>s, i.e., <tt>Object[]</tt>. Each element in the
- * array is an identifier of a propagated import target from the
- * <tt>ImportSearchPolicy.IMPORTS_ATTR</tt> attribute. Only identifiers for
- * import targets are candidates for inclusion and the version number is
- * unnecessary since it is assumed from the corresponding import target.
- * </p>
- * <p>
- * The value of the <tt>ImportSearchPolicy.VALID_ATTR</tt> attribute is a
- * <tt>Boolean</tt>. The value is initially set to <tt>Boolean.FALSE</tt>
- * and indicates that the module has not yet been validated. After the module
- * is validated, the value is set to <tt>Boolean.TRUE</tt>. The search policy
- * automatically adds this attribute to all modules and maintains its value.
- * </p>
- * <p>
- * These meta-data attributes help the search policy enforce consistency
- * using a process called <i>validation</i>; validation ensures that classes
- * and resources are only loaded from a module whose imports are satisfied.
- * Therefore, a <i>valid</i> module is a module whose imports are satisfied and
- * an <i>invalid</i> module is a module whose imports are not yet satisfied.
- * An invalid module may be invalid for two reasons:
- * </p>
- * <p>
- * <ol>
- *   <li>Its imports are not available or</li>
- *   <li>It has not yet been validated.</li>
- * </ol>
- * </p>
- * <p>
- * These two possibilities arise due to the fact that module validation
- * is not performed until it is necessary (i.e., lazy evaluation). A module
- * is automatically validated when an attempt is made to get classes or
- * resources from it, although it is possible to manually validate a module.
- * For a given module, called <tt>M</tt>, the validation process attempts to
- * find an exporting module for every import target of <tt>M</tt>. If an
- * exporter is not found for a specific import target, then the validation of
- * module <tt>M</tt> fails. If an exporting module is found, then this module
- * is also validated, if it is not already. As a result, the validation of
- * module <tt>M</tt> depends on the validation of the transitive closure of
- * all modules on which <tt>M</tt> depends. It is also possible for modules
- * to exhibit dependency cycles; circular dependencies are allowed.
- * Initially, a module's <tt>VALID_ATTR</tt> is set to <tt>Boolean.FALSE</tt>,
- * but after the module is successfully validated, this attribute is set to
- * <tt>Boolean.TRUE</tt>.
- * </p>
- * <p>
- * Besides ensuring that every import target is resolved to an appropriate
- * exporting module, the validation process also attempts to maintain
- * consistency along "propagation" chains. Propagation occurs when a module
- * imports classes that are also visible from its own exports; for example,
- * an HTTP server implementation may import classes from <tt>javax.servlet</tt>
- * and export classes that have methods that use the type <tt>javax.servlet.Servlet</tt>
- * in their signatures. Monitoring these types of occurences is important
- * to uncover import source and version conflicts when multiple sources or
- * versions of an import target are available within one virtual machine. When
- * a module <tt>M</tt> is validated, the propagation information of each
- * module that resolves the imports of <tt>M</tt> is checked to ensure
- * that they do not propagate conflicting sources of <tt>M</tt>'s
- * imports; specifically, it is verified that all propagators of a
- * particular import target have the same source module for that import
- * target.
- * </p>
- * <p>
- * To facilitate applicability in as many scenarios as possible, this search
- * policy delegates some decisions via additional policy interfaces. The following
- * two policy interfaces must be specified by the code that instantiates the
- * <tt>ImportSearchPolicy</tt> object:
- * </p>
- * <ul>
- *   <li><tt>CompatibilityPolicy</tt> - this policy is used to determine
- *       whether import/export version numbers are compatible.
- *   </li>
- *   <li><tt>SelectionPolicy</tt> - this policy is used to resolve a specific
- *       import target when multiple candidate exporting modules exist.
- *   </li>
- * </ul>
- * <p>
- * Once an instance is created with definitions of the above policy interfaces,
- * this search policy will operate largely self-contained. There are a few utility
- * methods for manually validating modules, adding validation listeners, and
- * access meta-data attributes, but for the most part these are not necessary
- * except for implementing more sophisticated infrastructure.
- * </p>
- * <p>
- * The follow snippet of code illustrates a typical usage scenario for
- * this search policy:
- * </p>
- * <pre>
- *     ...
- *     ImportSearchPolicy searchPolicy =
- *         new ImportSearchPolicy(
- *             new MyCompatibilityPolicy(), new MySelectionPolicy());
- *     ModuleManager mgr = new ModuleManager(searchPolicy);
- *     ...
- *     Object[][] exports = new Object[][] {
- *         { "org.apache.jasper", "2.1.0", null }
- *     };
- *     Object[][] imports = new Object[][] {
- *         { "javax.servlet", "2.3.1", null }
- *     };
- *     Object[][] attributes = new Object[][] {
- *         new Object[] { ImportSearchPolicy.EXPORTS_ATTR, exports },
- *         new Object[] { ImportSearchPolicy.IMPORTS_ATTR, imports },
- *         new Object[] { ImportSearchPolicy.PROPAGATES_ATTR, new Object[] { "javax.servlet" } }
- *      };
- *     ResourceSource[] resSources = new ResourceSource[] {
- *         new JarResourceSource(file1)
- *         new JarResourceSource(file2)
- *     };
- *     Module module = mgr.addModule(id, attributes, resSources, null);
- *     ClassLoader loader = module.getClassLoader();
- *     // Assuming that all imports are satisfied...
- *     Class clazz = loader.loadClass("org.foo.MyClass");
- *     ...
- * </pre>
- * <p>
- * The above code snippet illustrates creating a module with one export and one
- * import, where the import is also propagated via the module's export. The module
- * has multiple resource sources, but no library sources.
- * </p>
- * @see org.apache.felix.moduleloader.SearchPolicy
- * @see org.apache.felix.moduleloader.Module
- * @see org.apache.felix.moduleloader.ModuleClassLoader
- * @see org.apache.felix.moduleloader.ModuleManager
-**/
-public class ImportSearchPolicy implements SearchPolicy, ModuleListener
-{
-    /**
-     * This is the name of the "exports" meta-data attribute that
-     * should be attached to each module. The value of this attribute
-     * is of type <tt>Object[][]</tt> and is described in the overview
-     * documentation for this class.
-    **/
-    public static final String EXPORTS_ATTR = "exports";
-    /**
-     * This is the name of the "imports" meta-data attribute that
-     * should be attached to each module. The value of this attribute
-     * is of type <tt>Object[][]</tt> and is described in the overview
-     * documentation for this class.
-    **/
-    public static final String IMPORTS_ATTR = "imports";
-    /**
-     * This is the name of the "propagates" meta-data attribute that
-     * should be attached to each module. The value of this attribute
-     * is of type <tt>Object[]</tt> and is described in the overview
-     * documentation for this class.
-    **/
-    public static final String PROPAGATES_ATTR = "propagates";
-    /**
-     * This is the name of the "valid" meta-data attribute that is
-     * automatically attached to each module. The value of this attribute
-     * is of type <tt>Boolean</tt> and is described in the overview
-     * documentation for this class.
-    **/
-    public static final String VALID_ATTR = "valid";
-
-    /**
-     * This is the index used to retrieve the import or export identifier
-     * from a given element of the <tt>EXPORTS_ATTR</tt> or the <tt>IMPORTS_ATTR</tt>
-     * attribute.
-    **/
-    public static final int IDENTIFIER_IDX = 0;
-    /**
-     * This is the index used to retrieve the import or export version number
-     * from a given element of the <tt>EXPORTS_ATTR</tt> or the <tt>IMPORTS_ATTR</tt>
-     * attribute.
-    **/
-    public static final int VERSION_IDX = 1;
-    /**
-     * This is the index used to retrieve the resolving module for an import
-     * or export target from a given element of the <tt>EXPORTS_ATTR</tt> or
-     * the <tt>IMPORTS_ATTR</tt> attribute.
-    **/
-    public static final int RESOLVING_MODULE_IDX = 2;
-
-    private ModuleManager m_mgr = null;
-    private CompatibilityPolicy m_compatPolicy = null;
-    private SelectionPolicy m_selectPolicy = null;
-    private ValidationListener[] m_listeners = null;
-    private String[] m_searchAttrs = { IMPORTS_ATTR, EXPORTS_ATTR };
-    private static final ValidationListener[] m_noListeners = new ValidationListener[0];
-
-    /**
-     * Constructs an import search policy instance with the supplied
-     * compatibility and selection policies.
-     * @param compatPolicy the compatibility policy implementation to be used
-     *        by the search policy.
-     * @param selectPolicy the selection policy implementation to be used
-     *        by the search policy.
-    **/
-    public ImportSearchPolicy(
-        CompatibilityPolicy compatPolicy,
-        SelectionPolicy selectPolicy)
-    {
-        m_compatPolicy = compatPolicy;
-        m_selectPolicy = selectPolicy;
-        m_listeners = m_noListeners;
-    }
-
-    /**
-     * Returns the compatibility policy used by this import search policy instance.
-     * @return the compatibility policy of this import search policy instance.
-    **/
-    public CompatibilityPolicy getCompatibilityPolicy()
-    {
-        return m_compatPolicy;
-    }
-
-    /**
-     * Returns the selection policy used by this import search policy instance.
-     * @return the selection policy of this import search policy instance.
-    **/
-    public SelectionPolicy getSelectionPolicy()
-    {
-        return m_selectPolicy;
-    }
-
-    // JavaDoc comment copied from SearchPolicy.
-    public void setModuleManager(ModuleManager mgr)
-        throws IllegalStateException
-    {
-        if (m_mgr == null)
-        {
-            m_mgr = mgr;
-            m_mgr.addModuleListener(this);
-        }
-        else
-        {
-            throw new IllegalStateException("Module manager is already initialized");
-        }
-    }
-
-    public Object[] definePackage(Module module, String pkgName)
-    {
-        return null;
-    }
-
-    /**
-     * This method is part of the <tt>SearchPolicy</tt> interface; it
-     * should not be called directly. This method finds a class
-     * based on the import/export meta-data attached to the module.
-     * It first attempts to validate the target module, if it cannot
-     * be validated, then a <tt>ClassNotFoundException</tt> is thrown.
-     * Once the module is validated, the module's imports are searched
-     * for the target class, then the module's exports are searched.
-     * If the class is found in either place, then it is returned;
-     * otherwise, <tt>null</tt> is returned.
-     * @param parent the parent class loader of the delegating class loader.
-     * @param module the target module that is loading the class.
-     * @param name the name of the class being loaded.
-     * @return the class if found, <tt>null</tt> otherwise.
-     * @throws java.lang.ClassNotFoundException if the target module
-     *         could not be validated.
-    **/
-    public Class findClassBeforeModule(ClassLoader parent, Module module, String name)
-        throws ClassNotFoundException
-    {
-        // First, try to validate the originating module.
-        try {
-            validate(module);
-        } catch (ValidationException ex) {
-            throw new ClassNotFoundException(name);
-        }
-
-        // Try to load from parent.
-        if (parent != null)
-        {
-            try
-            {
-                Class c = parent.loadClass(name);
-                if (c != null)
-                {
-                    return c;
-                }
-            }
-            catch (ClassNotFoundException ex)
-            {
-                // Ignore and search imports/exports.
-            }
-        }
-
-        // Get the package of the target class.
-        String pkgName = Util.getClassPackage(name);
-
-        // We delegate to the module's imports for finding the
-        // desired class first, then we delegate to the module's
-        // exports for finding the desired class. We do this because
-        // implicitly a module imports everything that it exports.
-        // To avoid code duplication, we use a simple array of
-        // attribute names to loop through both of the imports
-        // and exports meta-data searching for the desired class.
-        for (int attrIdx = 0; attrIdx < m_searchAttrs.length; attrIdx++)
-        {
-            Object[][] imports = getImportsOrExports(module, m_searchAttrs[attrIdx]);
-
-            // If the module doesn't import anything, then just
-            // return null.
-            if ((imports != null) && (imports.length > 0))
-            {
-                for (int i = 0; i < imports.length; i++)
-                {
-                    // Only check when the package of the class is
-                    // the same as the import package.
-                    if (imports[i][IDENTIFIER_IDX].equals(pkgName))
-                    {
-                        Module resolvingModule = (Module) imports[i][RESOLVING_MODULE_IDX];
-                        try {
-                            Class clazz =
-                                resolvingModule.getClassLoader().loadClassFromModule(name);
-                            if (clazz != null)
-                            {
-                                return clazz;
-                            }
-                        } catch (Throwable th) {
-                            // Not much we can do.
-                            System.err.println("ImportSearchPolicy: " + th.getMessage());
-                        }
-                    }
-                }
-            }
-        }
-
-        return null;
-    }
-
-    public Class findClassAfterModule(ClassLoader parent, Module module, String name)
-    {
-        return null;
-    }
-
-    /**
-     * This method is part of the <tt>SearchPolicy</tt> interface; it
-     * should not be called directly. This method finds a resource
-     * based on the import/export meta-data attached to the module.
-     * It first attempts to validate the target module, if it cannot
-     * be validated, then it returns <tt>null</tt>. Once the module is
-     * validated, the module's imports are searched for the target
-     * resource, then the module's exports are searched. If the resource
-     * is found in either place, then a <tt>URL</tt> to is is returned;
-     * otherwise, <tt>null</tt> is returned.
-     * @param parent the parent class loader of the delegating class loader.
-     * @param module the target module that is loading the resource.
-     * @param name the name of the resource being loaded.
-     * @return a <tt>URL</tt> to the resource if found, <tt>null</tt> otherwise.
-    **/
-    public URL findResource(ClassLoader parent, Module module, String name)
-    {
-        // First, try to validate the originating module.
-        try
-        {
-            validate(module);
-        }
-        catch (ValidationException ex)
-        {
-            return null;
-        }
-
-        // Try to load from parent.
-        if (parent != null)
-        {
-            URL url = parent.getResource(name);
-            if (url != null)
-            {
-                return url;
-            }
-        }
-
-        // Get the package of the target resource.
-        String pkgName = Util.getResourcePackage(name);
-
-        // We delegate to the module's imports for finding the
-        // desired class first, then we delegate to the module's
-        // exports for finding the desired class. We do this because
-        // implicitly a module imports everything that it exports.
-        // To avoid code duplication, we use a simple array of
-        // attribute names to loop through both of the imports
-        // and exports meta-data searching for the desired class.
-        for (int attrIdx = 0; attrIdx < m_searchAttrs.length; attrIdx++)
-        {
-            Object[][] imports = getImportsOrExports(module, m_searchAttrs[attrIdx]);
-
-            // If the module doesn't import or export anything,
-            // then just return null.
-            if ((imports != null) && (imports.length > 0))
-            {
-                for (int i = 0; i < imports.length; i++)
-                {
-                    // Only check when the package of the resource is
-                    // the same as the import package.
-                    if (imports[i][IDENTIFIER_IDX].equals(pkgName))
-                    {
-                        Module resolvingModule = (Module) imports[i][RESOLVING_MODULE_IDX];
-                        try {
-                            URL url =
-                                resolvingModule.getClassLoader().getResourceFromModule(name);
-                            if (url != null)
-                            {
-                                return url;
-                            }
-                        } catch (Throwable th) {
-                        }
-                    }
-                }
-            }
-        }
-
-        return null;
-    }
-
-    private Map m_validateMap = new HashMap();
-    private Module m_rootModule = null;
-
-    /**
-     * This method validates the specified target module. If the module
-     * is already validated, then this method returns immediately. This
-     * method synchronizes on the associated module manager to ensure that
-     * modules are not added or removed while the validation is occuring.
-     * Each import and export for the target module are resolved by first
-     * using the compatibility policy to create a list of candidate export
-     * modules, then using the selection policy to choose among the
-     * candidates. Each selected candidate is also recursively validated;
-     * this process validates a transitive closure of all dependent modules.
-     * After the selected candidate is validated, its propagated imports
-     * are checked to make sure that they do not conflict with any existing
-     * propagated imports. If no validation errors occur, then all dependent
-     * modules are marked as validated, if they are not already validated.
-     * If an error occurs, the valid state of all modules remains unchanged.
-     * @param module the module to validate.
-     * @throws org.apache.felix.moduleloader.search.ValidationException if
-     *         the module or any dependent modules could not be validated.
-    **/
-    public void validate(Module module)
-        throws ValidationException
-    {
-        if (getValidAttribute(module).booleanValue())
-        {
-            return;
-        }
-
-        // Flag to indicate whether the bundle is valid or not.
-        boolean isValid = true;
-
-        // This list will be used to remember which bundles
-        // were validated so that the validation events can
-        // be fired outside of the synchronized block.
-        List fireValidatedList = null;
-
-        // Will hold the exception to be thrown or rethrown.
-        ValidationException invalidException = null;
-
-        // Synchronize on the module manager, because we don't want
-        // anything to change while we are in the middle of this
-        // operation.
-        synchronized (m_mgr)
-        {
-            // If we are already validating this module, then
-            // just return; this is necessary for cycles.
-            if (m_validateMap.get(module) != null)
-            {
-                return;
-            }
-
-            // Add the module to the validation map; this
-            // is necessary for cycles.
-            m_validateMap.put(module, module);
-
-            // Keep track of the root module that started
-            // the validation request; this is necessary
-            // for cycles.
-            if (m_rootModule == null)
-            {
-                m_rootModule = module;
-            }
-
-            // Now perform the validation algorithm.
-            Map propagateMap = new HashMap();
-  
-            // Validation binds the module's imports to a specific exporting
-            // module. A module also implicitly imports whatever it exports,
-            // so exports are validated in the same fashion as imports. It
-            // is possible, given the selection policy that a given export
-            // may actually be satisfied by a different module (i.e., a
-            // module is not guaranteed to be bound to what it exports). Since
-            // the imports and exports meta-data are validated in the same
-            // fashion, we will use the follow attribute array to loop and
-            // validate both imports and exports using the same code.
-            for (int attrIdx = 0; (isValid) && (attrIdx < m_searchAttrs.length); attrIdx++)
-            {
-                // Get the imports (exports are treated as imports to)
-                // for the current module.
-                Object[][] imports = getImportsOrExports(module, m_searchAttrs[attrIdx]);
-                // See if each import has available exporters.
-                for (int impIdx = 0; impIdx < imports.length; impIdx++)
-                {
-                    // Get all exporter candidates.
-                    Module[] candidates =
-                        getCompatibleModules(
-                            imports[impIdx][IDENTIFIER_IDX], imports[impIdx][VERSION_IDX]);
-                    // If there are no candidates, then prepare a
-                    // validation exception.
-                    if (candidates == null)
-                    {
-                        isValid = false;
-                        invalidException =
-                            new ValidationException(
-                                "Unable to validate module",
-                                module,
-                                imports[impIdx][IDENTIFIER_IDX],
-                                imports[impIdx][VERSION_IDX],
-                                false);
-                        break;
-                    }
-
-                    // Use selection policy to choose a single export candidate.
-                    Module exportingModule = m_selectPolicy.select(
-                        module, imports[impIdx][IDENTIFIER_IDX],
-                        imports[impIdx][VERSION_IDX], candidates, m_compatPolicy);
-                    // If there is no export module chosen, then prepare
-                    // a validation exception.
-                    if (exportingModule == null)
-                    {
-                        isValid = false;
-                        invalidException =
-                            new ValidationException(
-                                "Unable to validate module",
-                                module,
-                                imports[impIdx][IDENTIFIER_IDX],
-                                imports[impIdx][VERSION_IDX],
-                                false);
-                        break;
-                    }
-
-                    // Make sure that the export module is
-                    // also validated.
-                    try
-                    {
-                        validate(exportingModule);
-                    }
-                    catch (ValidationException ex)
-                    {
-                        // Prepare to rethrow the exception if
-                        // the exporter could not be validated.
-                        isValid = false;
-                        invalidException = ex;
-                        break;
-                    }
-
-                    // Keep track of all propagations from each module that this
-                    // module imports from. Verify that any given import always
-                    // comes form the same export module, otherwise there will be
-                    // class cast exceptions.
-                    Object[] propagates = getPropagatesAttribute(exportingModule);
-                    for (int propIdx = 0; propIdx < propagates.length; propIdx++)
-                    {
-                        // If the module does not import the propagated target,
-                        // then it can be safely ignored.
-                        if (doesImport(module, propagates[propIdx]))
-                        {
-                            Module sourceModule =
-                                (Module) propagateMap.get(propagates[propIdx]);
-
-                            // If the propagation source module has not already been
-                            // found, then remember the resolving module of the
-                            // exporting module as the source of the propagated
-                            // target.
-                            if (sourceModule == null)
-                            {
-                                propagateMap.put(
-                                    propagates[propIdx],
-                                    getImportResolvingModule(
-                                        exportingModule, propagates[propIdx]));
-                            }
-                            // If the propagation source module is found, then check to
-                            // see if it is propagating the import target from the same
-                            // module as previously determined for this module. If not,
-                            // then this is a propagation conflict.
-                            else if (sourceModule !=
-                                getImportResolvingModule(
-                                    exportingModule, propagates[propIdx]))
-                            {
-                                isValid = false;
-                                invalidException =
-                                    new ValidationException(
-                                        "Unable to validate module",
-                                        exportingModule,
-                                        propagates[propIdx],
-                                        null,
-                                        true);
-                                break;
-                            }
-                        }
-                    }
-
-                    // Set the chosen exporting module for the module
-                    // being validated.
-                    imports[impIdx][RESOLVING_MODULE_IDX] = exportingModule;
-                }
-            }
-
-            // Since this method is recursive, check to see it we are
-            // back at the root module that started the request, which
-            // would indicate that the request is finished.
-            if (m_rootModule == module)
-            {
-                // If the result is valid, then we have validated successfully.
-                if (isValid)
-                {
-                    // Loop through all modules in validate map
-                    // and mark them as valid.
-                    Iterator iter = m_validateMap.keySet().iterator();
-                    while (iter.hasNext())
-                    {
-                        Module m = (Module) iter.next();
-                        if (!getValidAttribute(m).booleanValue())
-                        {
-                            m.setAttribute(VALID_ATTR, Boolean.TRUE);
-                            if (fireValidatedList == null)
-                            {
-                                fireValidatedList = new ArrayList();
-                            }
-                            fireValidatedList.add(m);
-                        }
-                    }
-                }
-                // If we are here, then the validate failed, so we
-                // need to reset any partially validated modules.
-                else
-                {
-                    Iterator iter = m_validateMap.keySet().iterator();
-                    while (iter.hasNext())
-                    {
-                        Module m = (Module) iter.next();
-                        invalidate(
-                            m,
-                            m.getAttributes(),
-                            m.getResourceSources(),
-                            m.getLibrarySources());
-                    }
-                }
-
-                // Clear the root module and validation map
-                // before leaving the synchronized block.
-                m_rootModule = null;
-                m_validateMap.clear();
-            }
-        }
-
-        // (Re)throw the exception if invalid, otherwise
-        // fire validation events if the validated event
-        // list is not null.
-        if (!isValid)
-        {
-            throw invalidException;
-        }
-        else if (fireValidatedList != null)
-        {
-            for (int i = 0; i < fireValidatedList.size(); i++)
-            {
-                fireModuleValidated((Module) fireValidatedList.get(i));
-            }
-        }
-    }
-
-    /**
-     * This method returns a list of modules that have an export
-     * that is compatible with the given import identifier and version.
-     * @param identifier the import identifier.
-     * @param version the version of the import identifier.
-     * @return an array of modules that have compatible exports or <tt>null</tt>
-     *         if none are found.
-    **/
-    protected Module[] getCompatibleModules(Object identifier, Object version)
-    {
-        List list = null;
-        Module[] modules = m_mgr.getModules();
-        for (int modIdx = 0; modIdx < modules.length; modIdx++)
-        {
-            Object[][] exports = getExportsAttribute(modules[modIdx]);
-            for (int expIdx = 0; expIdx < exports.length; expIdx++)
-            {
-                // If the identifiers are comparable and compatible,
-                // then add the export identifier to the list.
-                if (m_compatPolicy.isCompatible(
-                        exports[expIdx][IDENTIFIER_IDX], exports[expIdx][VERSION_IDX],
-                        identifier, version))
-                {
-                    if (list == null)
-                    {
-                        list = new ArrayList();
-                    }
-                    list.add(modules[modIdx]);
-                }
-            }
-        }
-
-        if (list == null)
-        {
-            return null;
-        }
-
-        Module[] result = new Module[list.size()];
-        return (Module[]) list.toArray(result);
-    }
-
-    /**
-     * Invalidates a module by flushing its class loader and
-     * re-initializing its meta-data values.
-     * @param module the module to be invalidated.
-     * @param attributes the attributes associated with the module, since they
-     *        might have changed.
-     * @param resSources the resource sources associated wih the module, since they
-     *        might have changed.
-     * @param libSources the library sources associated wih the module, since they
-     *        might have changed.
-    **/
-    public void invalidate(
-        Module module, Object[][] attributes,
-        ResourceSource[] resSources, LibrarySource[] libSources)
-    {
-        // Synchronize on the module manager, because we don't want
-        // anything to change while we are in the middle of this
-        // operation.
-        synchronized (m_mgr)
-        {
-            m_mgr.resetModule(module, attributes, resSources, libSources);
-        }
-
-        // Fire invalidation event if necessary.
-        fireModuleInvalidated(m_mgr.getModule(module.getId()));
-    }
-
-    //
-    // Event handling methods for validation events.
-    //
-
-    /**
-     * Adds a validation listener to this import search policy. Validation
-     * listeners are notified when a module is validated and/or invalidated
-     * by the search policy.
-     * @param l the validation listener to add.
-    **/
-    public void addValidationListener(ValidationListener 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 ValidationListener[] { 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
-            {
-                ValidationListener[] newList = new ValidationListener[m_listeners.length + 1];
-                System.arraycopy(m_listeners, 0, newList, 0, m_listeners.length);
-                newList[m_listeners.length] = l;
-                m_listeners = newList;
-            }
-        }
-    }
-
-    /**
-     * Removes a validation listener to this import search policy.
-     * @param l the validation listener to remove.
-    **/
-    public void removeValidationListener(ValidationListener 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
-                {
-                    ValidationListener[] newList = new ValidationListener[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;
-                }
-            }
-        }
-    }
-
-    /**
-     * Fires a validation event for the specified module.
-     * @param module the module that was validated.
-    **/
-    protected void fireModuleValidated(Module module)
-    {
-        // Event holder.
-        ModuleEvent event = null;
-
-        // Get a copy of the listener array, which is guaranteed
-        // to not be null.
-        ValidationListener[] 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(m_mgr, module);
-            }
-            listeners[i].moduleValidated(event);
-        }
-    }
-
-    /**
-     * Fires an invalidation event for the specified module.
-     * @param module the module that was invalidated.
-    **/
-    protected void fireModuleInvalidated(Module module)
-    {
-        // Event holder.
-        ModuleEvent event = null;
-
-        // Get a copy of the listener array, which is guaranteed
-        // to not be null.
-        ValidationListener[] 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(m_mgr, module);
-            }
-            listeners[i].moduleInvalidated(event);
-        }
-    }
-
-    //
-    // ModuleListener methods.
-    //
-
-    /**
-     * Callback method for <tt>ModuleListener</tt>; this should not
-     * be called directly. This callback is used to initialize module
-     * meta-data attributes; it adds the <tt>VALID_ATTR</tt> attribute
-     * and initializes the resolving module entries in <tt>EXPORTS_ATTR</tt>
-     * and <tt>IMPORTS_ATTR</tt> to <tt>null</tt>.
-    **/
-    public void moduleAdded(ModuleEvent event)
-    {
-        synchronized (event.getModule())
-        {
-            // Add valid attribute to all modules.
-            event.getModule().setAttribute(VALID_ATTR, Boolean.FALSE);
-
-            for (int attrIdx = 0; attrIdx < m_searchAttrs.length; attrIdx++)
-            {
-                Object[][] imports =
-                    getImportsOrExports(event.getModule(), m_searchAttrs[attrIdx]);
-                for (int i = 0; i < imports.length; i++)
-                {
-                    imports[i][RESOLVING_MODULE_IDX] = null;
-                }
-            }
-        }
-    }
-
-    /**
-     * Callback method for <tt>ModuleListener</tt>; this should not
-     * be called directly. This callback is used to re-initialize module
-     * meta-data attributes; it adds the <tt>VALID_ATTR</tt> attribute
-     * and initializes the resolving module entries in <tt>EXPORTS_ATTR</tt>
-     * and <tt>IMPORTS_ATTR</tt> to <tt>null</tt>. It then invalidates
-     * all modules that import from the reset module.
-    **/
-    public void moduleReset(ModuleEvent event)
-    {
-        // This will reset module meta-data.
-        moduleAdded(event);
-
-// TODO: Synchronization?
-        ModuleManager m_mgr = (ModuleManager) event.getSource();
-        List list = createImporterList(m_mgr, event.getModule());
-        for (int i = 0; (list != null) && (i < list.size()); i++)
-        {
-            Module module = (Module) list.get(i);
-            invalidate(
-                module, module.getAttributes(),
-                module.getResourceSources(), module.getLibrarySources());
-        }
-    }
-
-    /**
-     * Callback method for <tt>ModuleListener</tt>; this should not
-     * be called directly. Used to listen for module removal events
-     * in order to invalidate all the modules that import form the
-     * removed moduled.
-    **/
-    public void moduleRemoved(ModuleEvent event)
-    {
-// TODO: Synchronization?
-        ModuleManager m_mgr = (ModuleManager) event.getSource();
-        List list = createImporterList(m_mgr, event.getModule());
-        for (int i = 0; (list != null) && (i < list.size()); i++)
-        {
-            Module module = (Module) list.get(i);
-            invalidate(
-                module, module.getAttributes(),
-                module.getResourceSources(), module.getLibrarySources());
-        }
-    }
-
-    //
-    // Instance utility methods.
-    //
-
-    /**
-     * This utility method returns the module that exports the
-     * specified import identifier and version. This method uses the
-     * <tt>validate()</tt> method to find the exporting module and,
-     * as a result, relies on the compatibility and selection
-     * policies associated with this <tt>ImportSearchPolicy</tt>
-     * instance. If successful, the returned module is guaranteed
-     * to be validated. This method only needs to be used for more
-     * advanced purposes (i.e., check import availability dynamically,
-     * etc.) and need not be used under normal circumstances.
-     * @param identifier the identifier of the import to resolve.
-     * @param version the version of the import to resolve.
-     * @return the exporting module selected to resolve the specified
-     *         import target.
-    **/
-    public Module resolveImportTarget(Object identifier, Object version)
-    {
-        // Create a fake module that imports the specified target
-        // and then try to validate it so we can get the exporting
-        // module that is used to satisfy the import.
-        Object[] targetImport = { identifier, version, null };
-        Object[][] attrs = new Object[][] {
-            new Object[] { EXPORTS_ATTR, new Object[0][0] },
-            new Object[] { IMPORTS_ATTR, new Object[][] { targetImport } },
-            new Object[] { PROPAGATES_ATTR, new Object[0] },
-            new Object[] { VALID_ATTR, Boolean.FALSE}
-        };
-        Module fake = new Module(m_mgr, "resolve import", attrs, null, null, false);
-        try {
-            validate(fake);
-        } catch (ValidationException ex) {
-            // Ignore this.
-        }
-        return (Module) targetImport[RESOLVING_MODULE_IDX];
-    }
-
-    //
-    // Static utility methods.
-    //
-
-    private static final Object[][] m_emptyImports = new Object[0][0];
-    private static final Object[] m_emptyProp = new Object[0];
-
-    /**
-     * Utility method that returns the <tt>VALID_ATTR</tt> attribute for
-     * the specified module.
-     * @param module the module whose <tt>VALID_ATTR</tt> attribute is to
-     *        be retrieved.
-     * @return an instance of <tt>Boolean</tt>.
-    **/
-    public static Boolean getValidAttribute(Module module)
-    {
-        Object value = module.getAttribute(VALID_ATTR);
-        if (value != null)
-        {
-            return (Boolean) value;
-        }
-        return Boolean.FALSE;
-    }
-
-    /**
-     * Utility method that returns the <tt>IMPORTS_ATTR</tt> attribute for
-     * the specified module.
-     * @param module the module whose <tt>IMPORTS_ATTR</tt> attribute is to
-     *        be retrieved.
-     * @return an <tt>Object[][]</tt> value or <tt>null</tt>.
-    **/
-    public static Object[][] getImportsAttribute(Module module)
-    {
-        Object value = module.getAttribute(IMPORTS_ATTR);
-        if (value != null)
-        {
-            return (Object[][]) value;
-        }
-        return m_emptyImports;
-    }
-
-    /**
-     * Utility method that returns the <tt>EXPORTS_ATTR</tt> attribute for
-     * the specified module.
-     * @param module the module whose <tt>EXPORTS_ATTR</tt> attribute is to
-     *        be retrieved.
-     * @return an <tt>Object[][]</tt> value or <tt>null</tt>.
-    **/
-    public static Object[][] getExportsAttribute(Module module)
-    {
-        Object value = module.getAttribute(EXPORTS_ATTR);
-        if (value != null)
-        {
-            return (Object[][]) value;
-        }
-        return m_emptyImports;
-    }
-
-    /**
-     * Utility method that returns the <tt>IMPORTS_ATTR</tt> or the
-     * <tt>EXPORTS_ATTR</tt> attribute for the specified module.
-     * @param module the module whose <tt>IMPORTS_ATTR</tt> or
-     *        <tt>EXPORTS_ATTR</tt> attribute is to be retrieved.
-     * @param name either <tt>IMPORTS_ATTR</tt> or <tt>EXPORTS_ATTR</tt>
-     *        depending on which attribute should be retrieved.
-     * @return an <tt>Object[][]</tt> value or <tt>null</tt>.
-    **/
-    public static Object[][] getImportsOrExports(Module module, String name)
-    {
-        Object value = module.getAttribute(name);
-        if (value != null)
-        {
-            return (Object[][]) value;
-        }
-        return m_emptyImports;
-    }
-
-    /**
-     * Utility method that returns the <tt>PROPAGATES_ATTR</tt> attribute for
-     * the specified module.
-     * @param module the module whose <tt>PROPAGATES_ATTR</tt> attribute is to
-     *        be retrieved.
-     * @return an <tt>Object[]</tt> value or <tt>null</tt>.
-    **/
-    public static Object[] getPropagatesAttribute(Module module)
-    {
-        Object value = module.getAttribute(PROPAGATES_ATTR);
-        if (value != null)
-        {
-            return (Object[]) value;
-        }
-        return m_emptyProp;
-    }
-
-    /**
-     * Utility method to determine if the specified module imports a given
-     * import identifier, regardless of version. This method checks both
-     * imports and exports, since a module is assumed to import what it exports.
-     * @param module the module to check.
-     * @param identifier the import identifier to check.
-     * @return <tt>true</tt> if the module imports the specified
-     *         import identifier or <tt>false</tt> if it does not.
-    **/
-    public static boolean doesImport(Module module, Object identifier)
-    {
-        Object[][] imports = getImportsAttribute(module);
-        for (int i = 0; i < imports.length; i++)
-        {
-            if (imports[i][IDENTIFIER_IDX].equals(identifier))
-            {
-                return true;
-            }
-        }
-        imports = getExportsAttribute(module);
-        for (int i = 0; i < imports.length; i++)
-        {
-            if (imports[i][IDENTIFIER_IDX].equals(identifier))
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Utility method to create a list of modules that import from
-     * the specified module.
-     * @param mgr the module manager that contains the module.
-     * @param module the module for which to create an importer list.
-     * @return a list of modules that import from the specified module
-     *         or <tt>null</tt>.
-    **/
-    public static List createImporterList(ModuleManager mgr, Module module)
-    {
-        List list = null;
-        Module[] modules = mgr.getModules();
-        for (int modIdx = 0; modIdx < modules.length; modIdx++)
-        {
-            Object[][] imports = getImportsAttribute(modules[modIdx]);
-            for (int impIdx = 0; impIdx < imports.length; impIdx++)
-            {
-                if (imports[impIdx][RESOLVING_MODULE_IDX] == module)
-                {
-                    if (list == null)
-                    {
-                        list = new ArrayList();
-                    }
-                    list.add(modules[modIdx]);
-                    break;
-                }
-            }
-        }
-
-        return list;
-    }
-
-    /**
-     * Utility method to get the import version number associated with a specific
-     * import identifier of the specified module.
-     * @param module the module to investigate.
-     * @param identifier the import identifier for which the version should
-     *        be retrieved.
-     * @return the version number object or <tt>null</tt>.
-    **/
-    public static Object getImportVersion(Module module, Object identifier)
-    {
-        Object[][] imports = getImportsAttribute(module);
-        for (int i = 0; i < imports.length; i++)
-        {
-            if (imports[i][IDENTIFIER_IDX].equals(identifier))
-            {
-                return imports[i][VERSION_IDX];
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Utility method to get the export version number associated with a specific
-     * export identifier of the specified module.
-     * @param module the module to investigate.
-     * @param identifier the export identifier for which the version should
-     *        be retrieved.
-     * @return the version number object or <tt>null</tt>.
-    **/
-    public static Object getExportVersion(Module module, Object identifier)
-    {
-        Object[][] exports = getExportsAttribute(module);
-        for (int i = 0; i < exports.length; i++)
-        {
-            if (exports[i][IDENTIFIER_IDX].equals(identifier))
-            {
-                return exports[i][VERSION_IDX];
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Utility method to get the resolving module of a specific import
-     * identifier for the specified module.
-     * @param module the module to investigate.
-     * @param identifier the import identifier for which the resolving
-     *        module should be retrieved.
-     * @return the resolving module or <tt>null</tt>.
-    **/
-    public static Module getImportResolvingModule(Module module, Object identifier)
-    {
-        Object[][] imports = getImportsAttribute(module);
-
-        for (int i = 0; i < imports.length; i++)
-        {
-            if (imports[i][IDENTIFIER_IDX].equals(identifier))
-            {
-                return (Module) imports[i][RESOLVING_MODULE_IDX];
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Utility method to get the resolving module of a specific export
-     * identifier for the specified module.
-     * @param module the module to investigate.
-     * @param identifier the export identifier for which the resolving
-     *        module should be retrieved.
-     * @return the resolving module or <tt>null</tt>.
-    **/
-    public static Module getExportResolvingModule(Module module, Object identifier)
-    {
-        Object[][] exports = getExportsAttribute(module);
-
-        for (int i = 0; i < exports.length; i++)
-        {
-            if (exports[i][IDENTIFIER_IDX].equals(identifier))
-            {
-                return (Module) exports[i][RESOLVING_MODULE_IDX];
-            }
-        }
-
-        return null;
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/SelectionPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/SelectionPolicy.java
deleted file mode 100644
index 2436bce..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/SelectionPolicy.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.search;
-
-import org.apache.felix.moduleloader.Module;
-
-/**
- * <p>
- * This interface represents the policy for selecting a specific export
- * target from multiple <i>compatible</i> candidate export targets when
- * the <tt>ImportSearchPolicy</tt> is trying to resolve an import target
- * for a given module. A concrete implementation of this interface is
- * required to create an instance of <tt>ImportSearchPolicy</tt>.
- * </p>
- * @see org.apache.felix.moduleloader.search.ImportSearchPolicy
-**/
-public interface SelectionPolicy
-{
-    /**
-     * Selects a single module to resolve the specified import
-     * from the array of compatible candidate modules.
-     * @param module the module that is importing the target.
-     * @param identifier the identifier of the import target.
-     * @param version the version number of the import target.
-     * @param candidates array of compatible candidate modules from which to choose.
-     * @param compatPolicy the compatibility policy that is being used.
-     * @return the selected module or <tt>null</tt> if no module
-     *         can be selected.
-    **/
-    public Module select(
-        Module module, Object identifier, Object version, Module[] candidates,
-        CompatibilityPolicy compatPolicy);
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/SelfContainedSearchPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/SelfContainedSearchPolicy.java
deleted file mode 100644
index e2608c6..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/SelfContainedSearchPolicy.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.search;
-
-import java.net.URL;
-
-import org.apache.felix.moduleloader.*;
-
-/**
- * <p>
- * This class implements a <tt>ModuleLoader</tt> search policy that
- * assumes that all modules are self-contained. In other words, when
- * loading a class or resource for a particular module, only that
- * particular module's resource sources are search. No classes or
- * resources are shared among modules.
- * </p>
- * @see org.apache.felix.moduleloader.SearchPolicy
- * @see org.apache.felix.moduleloader.Module
- * @see org.apache.felix.moduleloader.ModuleClassLoader
- * @see org.apache.felix.moduleloader.ModuleManager
-**/
-public class SelfContainedSearchPolicy implements SearchPolicy
-{
-    private ModuleManager m_mgr = null;
-
-    /**
-     * This method is part of the <tt>SearchPolicy</tt> interface.
-     * This method is called by the <tt>ModuleManager</tt> once to
-     * give the search policy instance a reference to its associated
-     * module manager. This method should be implemented such that
-     * it cannot be called twice; calling this method a second time
-     * should produce an illegal state exception.
-     * @param mgr the module manager associated with this search policy.
-     * @throws java.lang.IllegalStateException if the method is called
-     *         more than once.
-    **/
-    public void setModuleManager(ModuleManager mgr)
-        throws IllegalStateException
-    {
-        if (m_mgr == null)
-        {
-            m_mgr = mgr;
-        }
-        else
-        {
-            throw new IllegalStateException("Module manager is already initialized");
-        }
-    }
-
-    public Object[] definePackage(Module module, String pkgName)
-    {
-        return null;
-    }
-
-    /**
-     * Simply returns <tt>null</tt> which forces the module class
-     * loader to only search the target module's resource sources
-     * for the specified class.
-     * @param parent the parent class loader of the delegating class loader.
-     * @param module the target module that is loading the class.
-     * @param name the name of the class being loaded.
-     * @return <tt>null</tt>.
-    **/
-    public Class findClassBeforeModule(ClassLoader parent, Module module, String name)
-    {
-        // First, try to load from parent.
-        if (parent != null)
-        {
-            try
-            {
-                Class c = parent.loadClass(name);
-                if (c != null)
-                {
-                    return c;
-                }
-            }
-            catch (ClassNotFoundException ex)
-            {
-                // Ignore.
-            }
-        }
-
-        return null;
-    }
-
-    public Class findClassAfterModule(ClassLoader parent, Module module, String name)
-    {
-        return null;
-    }
-
-    /**
-     * Simply returns <tt>null</tt> which forces the module class
-     * loader to only search the target module's resource sources
-     * for the specified resource.
-     * @param parent the parent class loader of the delegating class loader.
-     * @param module the target module that is loading the class.
-     * @param name the name of the resource being loaded.
-     * @return <tt>null</tt>.
-    **/
-    public URL findResource(ClassLoader parent, Module module, String name)
-    {
-        if (parent != null)
-        {
-            return parent.getResource(name);
-        }
-        return null;
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ValidationException.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ValidationException.java
deleted file mode 100644
index b996454..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ValidationException.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.search;
-
-import org.apache.felix.moduleloader.Module;
-
-/**
- * <p>
- * This exception is thrown if a module cannot be validated. The module
- * that failed to be validated is recorded, along with the failed import target
- * identifier and version number. If the error was a result of a propagation
- * conflict, then the propagation error flag is set.
- * </p>
- * @see org.apache.felix.moduleloader.search.ImportSearchPolicy#validate(org.apache.felix.moduleloader.Module)
-**/
-public class ValidationException extends Exception
-{
-    private Module m_module = null;
-    private Object m_identifier = null;
-    private Object m_version = null;
-    private boolean m_isPropagation = false;
-
-    /**
-     * Constructs an exception with the specified message, module,
-     * import identifier, import version number, and propagation flag.
-    **/
-    public ValidationException(String msg, Module module,
-        Object identifier, Object version, boolean isPropagation)
-    {
-        super(msg);
-        m_module = module;
-        m_identifier = identifier;
-        m_version = version;
-        m_isPropagation = isPropagation;
-    }
-
-    /**
-     * Returns the module that was being validated.
-     * @return the module that was being validated.
-    **/
-    public Module getModule()
-    {
-        return m_module;
-    }
-
-    /**
-     * Returns the identifier of the import target that could not be resolved.
-     * @return the identifier of the import target that could not be resolved.
-    **/
-    public Object getIdentifier()
-    {
-        return m_identifier;
-    }
-
-    /**
-     * Returns the version number of the import target that could not be resolved.
-     * @return the version number of the import target that could not be resolved.
-    **/
-    public Object getVersion()
-    {
-        return m_version;
-    }
-
-    /**
-     * Returns a flag indicating whether the exception was caused by a
-     * a propagation conflict.
-     * @return <tt>true</tt> if the exception was thrown due to a propagation
-     *         conflict, <tt>false</tt> otherwise.
-    **/
-    public boolean isPropagationError()
-    {
-        return m_isPropagation;
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ValidationListener.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ValidationListener.java
deleted file mode 100644
index 9491531..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/ValidationListener.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.search;
-
-import java.util.EventListener;
-
-import org.apache.felix.moduleloader.ModuleEvent;
-
-/**
- * <p>
- * This is an event listener interface for listening to validation
- * events that are generated by the <tt>ImportSearchPolicy</tt>. Events
- * are fired when a module is validated and when it is invalidated.
- * </p>
- * @see org.apache.felix.moduleloader.search.ImportSearchPolicy
-**/
-public interface ValidationListener extends EventListener
-{
-    /**
-     * This is an event callback method that indicates that
-     * a module was validated.
-     * @param event the module event containing the event data.
-    **/
-    public void moduleValidated(ModuleEvent event);
-
-    /**
-     * This is an event callback method that indicates that
-     * a module was invalidated.
-     * @param event the module event containing the event data.
-    **/
-    public void moduleInvalidated(ModuleEvent event);
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/compatibility/ExactCompatibilityPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/compatibility/ExactCompatibilityPolicy.java
deleted file mode 100644
index f971683..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/compatibility/ExactCompatibilityPolicy.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.search.compatibility;
-
-import org.apache.felix.moduleloader.search.CompatibilityPolicy;
-
-/**
- * This class implements a simple version numbering compatibility policy for the
- * <tt>ImportSearchPolicy</tt> where only exact version numbers are considered
- * to be compatible.  This policy simply returns the result of
- * "<tt>leftId.equals(rightId) && leftVersion.equals(rightVersion)</tt>". Any
- * calls to the <tt>compare()</tt> method result in an exception since this
- * policy has no basis for comparing identifiers and versions.
- * @see org.apache.felix.moduleloader.search.CompatibilityPolicy
- * @see org.apache.felix.moduleloader.search.ImportSearchPolicy
-**/
-public class ExactCompatibilityPolicy implements CompatibilityPolicy
-{
-    /**
-     * Compares two versioned identifiers, but since this policy has
-     * no understanding of how to compare identifiers, it always throws
-     * an <tt>IllegalArgumentException</tt>.
-     * @param leftId the identifier to test for compatibility.
-     * @param leftVersion the version number to test for compatibility.
-     * @param rightId the identifier used as the compatibility base line.
-     * @param rightVersion the version used as the compatibility base line.
-     * @return <tt>0</tt> if the identifiers are equal, <tt>-1</tt> if the
-     *         left identifier is less then the right identifier, and <tt>1</tt>
-     *         if the left identifier is greater than the right identifier.
-     * @throws java.lang.IllegalArgumentException if the two identifiers
-     *         are not comparable, i.e., they refer to completely different
-     *         entities.
-    **/
-    public int compare(
-        Object leftId, Object leftVersion,
-        Object rightId, Object rightVersion)
-    {
-        throw new IllegalArgumentException("Identifiers are not comparable.");
-    }
-
-    /**
-     * Returns whether the first import/export target is compatible
-     * with the second. This method simply uses the "<tt>equals()</tt>" method
-     * to test both the identifier and the verison number.
-     * @param leftId the identifier to test for compatibility.
-     * @param leftVersion the version number to test for compatibility.
-     * @param rightId the identifier used as the compatibility base line.
-     * @param rightVersion the version used as the compatibility base line.
-     * @return <tt>true</tt> if the left version number object is compatible
-     *         with the right version number object, otherwise <tt>false</tt>.
-    **/
-    public boolean isCompatible(
-        Object leftId, Object leftVersion,
-        Object rightId, Object rightVersion)
-    {
-        return leftId.equals(rightId) && leftVersion.equals(rightVersion);
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/selection/InteractiveSelectionPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/selection/InteractiveSelectionPolicy.java
deleted file mode 100644
index f1ddee7..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/selection/InteractiveSelectionPolicy.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.search.selection;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-
-import org.apache.felix.moduleloader.Module;
-import org.apache.felix.moduleloader.search.CompatibilityPolicy;
-import org.apache.felix.moduleloader.search.SelectionPolicy;
-
-/**
- * This class implements an interactive selection policy for the
- * <tt>ImportSearchPolicy</tt>. This policy simply uses standard
- * output to present the list of candidate modules and uses standard
- * input to allow the user to select a specific module from the
- * candidates. This selection policy is generally only useful for
- * debugging purposes.
- * @see org.apache.felix.moduleloader.search.SelectionPolicy
- * @see org.apache.felix.moduleloader.search.ImportSearchPolicy
-**/
-public class InteractiveSelectionPolicy implements SelectionPolicy
-{
-    /**
-     * Returns a single package from an array of packages.
-     * @param sources array of packages from which to choose.
-     * @return the selected package or <tt>null</tt> if no package
-     *         can be selected.
-    **/
-    public Module select(Module module, Object target,
-        Object version, Module[] candidates, CompatibilityPolicy compatPolicy)
-    {
-        try {
-            if (candidates.length == 1)
-            {
-                return candidates[0];
-            }
-            // Now start an interactive prompt.
-            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
-            do
-            {
-                System.out.println("\nImporting '" + target
-                    + "(" + version + ")" + "' for '" + module + "'.");
-                System.out.println("");
-                for (int i = 0; i < candidates.length; i++)
-                {
-                    System.out.println((i + 1) + ". " + candidates[i]);
-                }
-                System.out.print("Select: ");
-                String s = br.readLine();
-
-                int choice = -1;
-                try {
-                    choice = Integer.parseInt(s);
-                } catch (Exception ex) {
-                }
-
-                if (choice == 0)
-                {
-                    break;
-                }
-                else if ((choice > 0) && (choice <= candidates.length))
-                {
-                    return candidates[choice - 1];
-                }
-            }
-            while (true);
-        } catch (Exception ex) {
-        }
-
-        return null;
-    }
-}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/selection/SimpleSelectionPolicy.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/selection/SimpleSelectionPolicy.java
deleted file mode 100644
index a2f9648..0000000
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/search/selection/SimpleSelectionPolicy.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- *   Copyright 2005 The Apache Software Foundation
- *
- *   Licensed 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.search.selection;
-
-import java.util.*;
-
-import org.apache.felix.moduleloader.*;
-import org.apache.felix.moduleloader.search.*;
-
-/**
- * This class implements a reasonably simple selection policy for the
- * <tt>ImportSearchPolicy</tt>. When given a choice, this selection
- * policy will always select the newest version of the available
- * candidates to satisfy the import identifier. In the case where
- * a candidate has already been selected for a given import identifier,
- * then the previously selected module will be returned, if possible.
- * If it is not possible to return the previously selected module, then
- * a <tt>null</tt> is returned. This policy assumes that classes are
- * shared globally.
-**/
-public class SimpleSelectionPolicy implements SelectionPolicy, ModuleListener
-{
-    private Map m_resolvedPackageMap = new HashMap();
-    private Map m_resolvedModuleMap = new HashMap();
-
-    /**
-     * Selects a single module to resolve the specified import identifier
-     * from the array of compatible candidate modules. If the import
-     * identifier has not been resolved before, then this selection policy
-     * chooses the module that exports the newest version of the
-     * import identifer. If the import identifier has been resolved already,
-     * then the same module that was chosen before is chosen again.
-     * This ensures that all modules use the same version of all
-     * exported classes.
-     * @param module the module that is importing the target.
-     * @param identifier the identifier of the import target.
-     * @param version the version number of the import target.
-     * @param candidates array of compatible candidate modules from which to choose.
-     * @return the selected module or <tt>null</tt> if no module
-     *         can be selected.
-    **/
-    public synchronized Module select(Module module, Object identifier,
-        Object version, Module[] candidates, CompatibilityPolicy compatPolicy)
-    {
-        // See if package is already resolved.
-        Module selModule = (Module) m_resolvedPackageMap.get(identifier);
-
-        // If no module was previously selected to export the package,
-        // then try to choose one now.
-        if (selModule == null)
-        {
-            Object selVersion = null;
-
-            // Examine all exported instances of the identifier and
-            // choose the one with the newest version number. If
-            // there is more than one source for the newest version,
-            // then just select the first one found.
-            for (int i = 0; i < candidates.length; i++)
-            {
-                Object tmpVersion =
-                    ImportSearchPolicy.getExportVersion(candidates[i], identifier);
-
-                // If this is the first comparison, then
-                // just record it.
-                if (selVersion == null)
-                {
-                    selModule = candidates[i];
-                    selVersion = tmpVersion;
-                }
-                // If the current export package version is greater
-                // than the selected export package version, then
-                // record it instead.
-                else if (compatPolicy.compare(identifier, tmpVersion, identifier, selVersion) >= 0)
-                {
-                    selModule = candidates[i];
-                    selVersion = tmpVersion;
-                }
-            }
-
-            m_resolvedPackageMap.put(identifier, selModule);
-            m_resolvedModuleMap.put(selModule, selModule);
-        }
-        // See if the previously selected export module satisfies
-        // the current request, otherwise return null.
-        else
-        {
-            Object selVersion =
-                ImportSearchPolicy.getExportVersion(selModule, identifier);
-            Module tmpModule = selModule;
-            selModule = null;
-            if (compatPolicy.isCompatible(identifier, selVersion, identifier, version))
-            {
-                selModule = tmpModule;
-            }
-        }
-
-        return selModule;
-    }
-
-    public void moduleAdded(ModuleEvent event)
-    {
-    }
-
-    public void moduleReset(ModuleEvent event)
-    {
-        moduleRemoved(event);
-    }
-
-    public synchronized void moduleRemoved(ModuleEvent event)
-    {
-        // If the module that was removed was chosen for
-        // exporting identifier, then flush it from our
-        // data structures; we assume here that the application
-        // will flush references to the removed module's classes.
-        if (m_resolvedModuleMap.get(event.getModule()) != null)
-        {
-            // Remove from module map.
-            m_resolvedModuleMap.remove(event.getModule());
-            // Remove each exported package from package map.
-            Iterator iter = m_resolvedPackageMap.entrySet().iterator();
-            while (iter.hasNext())
-            {
-                Map.Entry entry = (Map.Entry) iter.next();
-                if (entry.getValue() == event.getModule())
-                {
-                    iter.remove();
-                }
-            }
-        }
-    }
-}
\ No newline at end of file