Separate BundleWire implementation from BundleRevision implementation. (FELIX-2950)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1102824 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index f6d2c99..88bfd9d 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -131,21 +131,6 @@
             // Remove the revision from the resolver state.
             getFramework().getResolver().removeRevision(br);
 
-            // Set fragments to null, which will remove the revision from all
-            // of its dependent fragment revisions.
-            try
-            {
-                ((BundleRevisionImpl) br).attachFragments(null);
-            }
-            catch (Exception ex)
-            {
-                getFramework().getLogger().log(
-                    br.getBundle(), Logger.LOG_ERROR, "Error detaching fragments.", ex);
-            }
-            // Set wires to null, which will remove the revision from all
-            // of its dependent revisions.
-            ((BundleRevisionImpl) br).setWires(null, null);
-
             // Close the revision's content.
             ((BundleRevisionImpl) br).close();
         }
@@ -467,8 +452,7 @@
         }
     }
 
-    private static List<BundleRevision> createLocalizationRevisionList(
-        BundleRevisionImpl bri)
+    private static List<BundleRevision> createLocalizationRevisionList(BundleRevision br)
     {
         // If the revision is a fragment, then we actually need
         // to search its host and associated fragments for its
@@ -477,19 +461,21 @@
         // version instead of the fragment itself. If there are
         // no hosts, but the revision is a fragment, then just
         // search the revision itself.
-        if (Util.isFragment(bri))
+        if (Util.isFragment(br))
         {
-            List<BundleWire> hostWires = bri.getWires();
-            if ((hostWires != null) && (hostWires.size() > 0))
+            if (br.getWiring() != null)
             {
-                bri = (BundleRevisionImpl) hostWires.get(0).getProviderWiring().getRevision();
-                for (int hostIdx = 1; hostIdx < hostWires.size(); hostIdx++)
+                List<BundleWire> hostWires = br.getWiring().getRequiredWires(null);
+                if ((hostWires != null) && (hostWires.size() > 0))
                 {
-                    if (bri.getVersion().compareTo(
-                        hostWires.get(hostIdx).getProviderWiring().getRevision().getVersion()) < 0)
+                    br = hostWires.get(0).getProviderWiring().getRevision();
+                    for (int hostIdx = 1; hostIdx < hostWires.size(); hostIdx++)
                     {
-                        bri = (BundleRevisionImpl)
-                            hostWires.get(hostIdx).getProviderWiring().getRevision();
+                        if (br.getVersion().compareTo(
+                            hostWires.get(hostIdx).getProviderWiring().getRevision().getVersion()) < 0)
+                        {
+                            br = hostWires.get(hostIdx).getProviderWiring().getRevision();
+                        }
                     }
                 }
             }
@@ -497,8 +483,8 @@
 
         // Create a list of the revision and any attached fragment revisions.
         List<BundleRevision> result = new ArrayList<BundleRevision>();
-        result.add(bri);
-        List<BundleRevision> fragments = bri.getFragments();
+        result.add(br);
+        List<BundleRevision> fragments = ((BundleWiringImpl) br.getWiring()).getFragments();
         if (fragments != null)
         {
             result.addAll(fragments);
@@ -1075,13 +1061,16 @@
         boolean used = false;
         for (int i = 0; !unresolved && !used && (i < m_revisions.size()); i++)
         {
-            List<BundleRevision> dependents =
-                ((BundleRevisionImpl) m_revisions.get(i)).getDependents();
-            for (int j = 0; (dependents != null) && (j < dependents.size()) && !used; j++)
+            if (m_revisions.get(i).getWiring() != null)
             {
-                if (dependents.get(j) != m_revisions.get(i))
+                List<BundleRevision> dependents =
+                    ((BundleRevisionImpl) m_revisions.get(i)).getDependents();
+                for (int j = 0; (dependents != null) && (j < dependents.size()) && !used; j++)
                 {
-                    used = true;
+                    if (dependents.get(j) != m_revisions.get(i))
+                    {
+                        used = true;
+                    }
                 }
             }
         }
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
index 032419d..1813617 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
@@ -31,7 +31,6 @@
 import java.security.ProtectionDomain;
 import java.security.SecureClassLoader;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -45,8 +44,6 @@
 import org.apache.felix.framework.Felix.StatefulResolver;
 import org.apache.felix.framework.cache.JarContent;
 import org.apache.felix.framework.resolver.Content;
-import org.apache.felix.framework.resolver.HostedCapability;
-import org.apache.felix.framework.resolver.HostedRequirement;
 import org.apache.felix.framework.resolver.ResolveException;
 import org.apache.felix.framework.resolver.ResolverWire;
 import org.apache.felix.framework.resolver.ResourceNotFoundException;
@@ -71,7 +68,7 @@
 import org.osgi.framework.wiring.BundleWire;
 import org.osgi.framework.wiring.BundleWiring;
 
-public class BundleRevisionImpl implements BundleRevision, BundleWiring
+public class BundleRevisionImpl implements BundleRevision
 {
     public final static int EAGER_ACTIVATION = 0;
     public final static int LAZY_ACTIVATION = 1;
@@ -90,81 +87,33 @@
     private final Version m_version;
 
     private final List<BundleCapability> m_declaredCaps;
-    private List<BundleCapability> m_resolvedCaps = null;
     private final List<BundleRequirement> m_declaredReqs;
-    private List<BundleRequirement> m_resolvedReqs = null;
-    private final List<BundleRequirement> m_declaredDynReqs;
-    private List<BundleRequirement> m_resolvedDynReqs = null;
-    private final List<R4Library> m_nativeLibraries;
+    private final List<BundleRequirement> m_declaredDynamicReqs;
+    private final List<R4Library> m_declaredNativeLibs;
     private final int m_declaredActivationPolicy;
     private final List<String> m_activationIncludes;
     private final List<String> m_activationExcludes;
 
     private final Bundle m_bundle;
 
-    private List<BundleRevision> m_fragments = null;
-    private List<BundleWire> m_wires = null;
-    private Map<String, BundleRevision> m_importedPkgs = null;
-    private Map<String, List<BundleRevision>> m_requiredPkgs = null;
     private List<BundleRevision> m_dependentImporters = new ArrayList<BundleRevision>(0);
     private List<BundleRevision> m_dependentRequirers = new ArrayList<BundleRevision>(0);
-    private volatile boolean m_isResolved = false;
 
     private Content[] m_contentPath;
-    private Content[] m_fragmentContents = null;
-    private BundleClassLoader m_classLoader;
     private boolean m_isActivationTriggered = false;
     private ProtectionDomain m_protectionDomain = null;
     private final static SecureAction m_secureAction = new SecureAction();
 
-    // Bundle-specific class loader for boot delegation.
-    private final ClassLoader m_bootClassLoader;
-    // Default class loader for boot delegation.
-    private final static ClassLoader m_defBootClassLoader;
-
-    // Statically define the default class loader for boot delegation.
-    static
-    {
-        ClassLoader cl = null;
-        try
-        {
-            Constructor ctor = m_secureAction.getDeclaredConstructor(
-                SecureClassLoader.class, new Class[] { ClassLoader.class });
-            m_secureAction.setAccesssible(ctor);
-            cl = (ClassLoader) m_secureAction.invoke(ctor, new Object[] { null });
-        }
-        catch (Throwable ex)
-        {
-            // On Android we get an exception if we set the parent class loader
-            // to null, so we will work around that case by setting the parent
-            // class loader to the system class loader in getClassLoader() below.
-            cl = null;
-            System.err.println("Problem creating boot delegation class loader: " + ex);
-        }
-        m_defBootClassLoader = cl;
-    }
+    // Bundle wiring when resolved.
+    private volatile BundleWiringImpl m_wiring = null;
 
     // Boot delegation packages.
     private final String[] m_bootPkgs;
     private final boolean[] m_bootPkgWildcards;
 
-    // Boolean flag to enable/disable implicit boot delegation.
-    private final boolean m_implicitBootDelegation;
-    // Boolean flag to enable/disable local URLs.
-    private final boolean m_useLocalURLs;
-
     // Re-usable security manager for accessing class context.
     private static SecurityManagerEx m_sm = new SecurityManagerEx();
 
-    // Thread local to detect class loading cycles.
-    private final ThreadLocal m_cycleCheck = new ThreadLocal();
-
-    // Thread local to keep track of deferred activation.
-    private static final ThreadLocal m_deferredActivation = new ThreadLocal();
-
-    // Flag indicating whether we are on an old JVM or not.
-    private volatile static boolean m_isPreJava5 = false;
-
     /**
      * This constructor is used by the extension manager, since it needs
      * a constructor that does not throw an exception.
@@ -195,16 +144,11 @@
         m_version = null;
         m_declaredCaps = Collections.EMPTY_LIST;
         m_declaredReqs = Collections.EMPTY_LIST;
-        m_declaredDynReqs = Collections.EMPTY_LIST;
-        m_nativeLibraries = null;
+        m_declaredDynamicReqs = Collections.EMPTY_LIST;
+        m_declaredNativeLibs = null;
         m_declaredActivationPolicy = EAGER_ACTIVATION;
         m_activationExcludes = null;
         m_activationIncludes = null;
-        m_implicitBootDelegation = false;
-        m_useLocalURLs =
-            (m_configMap.get(FelixConstants.USE_LOCALURLS_PROP) == null)
-                ? false : true;
-        m_bootClassLoader = m_defBootClassLoader;
     }
 
     BundleRevisionImpl(
@@ -225,28 +169,6 @@
         m_bootPkgs = bootPkgs;
         m_bootPkgWildcards = bootPkgWildcards;
 
-        m_implicitBootDelegation =
-            (m_configMap.get(FelixConstants.IMPLICIT_BOOT_DELEGATION_PROP) == null)
-            || Boolean.valueOf(
-                (String) m_configMap.get(
-                    FelixConstants.IMPLICIT_BOOT_DELEGATION_PROP)).booleanValue();
-
-        m_useLocalURLs =
-            (m_configMap.get(FelixConstants.USE_LOCALURLS_PROP) == null)
-                ? false : true;
-
-        ClassLoader bootLoader = m_defBootClassLoader;
-        Object map = m_configMap.get(FelixConstants.BOOT_CLASSLOADERS_PROP);
-        if (map instanceof Map)
-        {
-            Object l = ((Map) map).get(bundle);
-            if (l instanceof ClassLoader)
-            {
-                bootLoader = (ClassLoader) l;
-            }
-        }
-        m_bootClassLoader = bootLoader;
-
         ManifestParser mp = new ManifestParser(m_logger, m_configMap, this, m_headerMap);
 
         // Record some of the parsed metadata. Note, if this is an extension
@@ -256,8 +178,8 @@
         m_version = mp.getBundleVersion();
         m_declaredCaps = mp.isExtension() ? null : mp.getCapabilities();
         m_declaredReqs = mp.getRequirements();
-        m_declaredDynReqs = mp.getDynamicRequirements();
-        m_nativeLibraries = mp.getLibraries();
+        m_declaredDynamicReqs = mp.getDynamicRequirements();
+        m_declaredNativeLibs = mp.getLibraries();
         m_declaredActivationPolicy = mp.getActivationPolicy();
         m_activationExcludes = (mp.getActivationExcludeDirective() == null)
             ? null
@@ -269,6 +191,42 @@
         m_isExtension = mp.isExtension();
     }
 
+    int getDeclaredActivationPolicy()
+    {
+        return m_declaredActivationPolicy;
+    }
+
+    List<String> getActivationExcludes()
+    {
+        return m_activationExcludes;
+    }
+
+    List<String> getActivationIncludes()
+    {
+        return m_activationIncludes;
+    }
+
+    URLStreamHandler getURLStreamHandler()
+    {
+        return m_streamHandler;
+    }
+
+    // TODO: OSGi R4.3 - Figure out how to handle this. Here we provide access
+    //       needed for BundleWiringImpl, but for implicit boot delegation property
+    //       we store it in BundleWiringImpl.
+    String[] getBootDelegationPackages()
+    {
+        return m_bootPkgs;
+    }
+
+    // TODO: OSGi R4.3 - Figure out how to handle this. Here we provide access
+    //       needed for BundleWiringImpl, but for implicit boot delegation property
+    //       we store it in BundleWiringImpl.
+    boolean[] getBootDelegationPackageWildcards()
+    {
+        return m_bootPkgWildcards;
+    }
+
     //
     // BundleRevision methods.
     //
@@ -283,7 +241,7 @@
         return m_version;
     }
 
-    public synchronized List<BundleCapability> getDeclaredCapabilities(String namespace)
+    public List<BundleCapability> getDeclaredCapabilities(String namespace)
     {
         List<BundleCapability> result = m_declaredCaps;
         if (namespace != null)
@@ -300,7 +258,7 @@
         return result;
     }
 
-    public synchronized List<BundleRequirement> getDeclaredRequirements(String namespace)
+    public List<BundleRequirement> getDeclaredRequirements(String namespace)
     {
         List<BundleRequirement> result = m_declaredReqs;
         if (namespace != null)
@@ -317,11 +275,6 @@
         return result;
     }
 
-    public synchronized List<BundleRequirement> getDeclaredDynamicRequirements()
-    {
-        return m_declaredDynReqs;
-    }
-
     public int getTypes()
     {
         if (getHeaders().containsKey(Constants.FRAGMENT_HOST))
@@ -333,7 +286,7 @@
 
     public BundleWiring getWiring()
     {
-        return (m_isResolved) ? this : null;
+        return m_wiring;
     }
 
     public Bundle getBundle()
@@ -342,182 +295,9 @@
     }
 
     //
-    // BundleWiring methods.
-    //
-
-    public boolean isCurrent()
-    {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    public boolean isInUse()
-    {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    public synchronized List<BundleCapability> getCapabilities(String namespace)
-    {
-        if (m_isResolved && (m_resolvedCaps == null))
-        {
-            List capList = (m_declaredCaps == null)
-                ? new ArrayList<BundleCapability>()
-                : new ArrayList<BundleCapability>(m_declaredCaps);
-            for (int fragIdx = 0;
-                (m_fragments != null) && (fragIdx < m_fragments.size());
-                fragIdx++)
-            {
-                List<BundleCapability> caps =
-                    m_fragments.get(fragIdx).getDeclaredCapabilities(null);
-                for (int capIdx = 0;
-                    (caps != null) && (capIdx < caps.size());
-                    capIdx++)
-                {
-                    if (caps.get(capIdx).getNamespace().equals(
-                        BundleCapabilityImpl.PACKAGE_NAMESPACE))
-                    {
-                        capList.add(
-                            new HostedCapability(
-                                this, (BundleCapabilityImpl) caps.get(capIdx)));
-                    }
-                }
-            }
-            m_resolvedCaps = Collections.unmodifiableList(capList);
-        }
-        List<BundleCapability> result = m_resolvedCaps;
-        if (namespace != null)
-        {
-            result = new ArrayList<BundleCapability>();
-            for (BundleCapability cap : m_resolvedCaps)
-            {
-                if (cap.getNamespace().equals(namespace))
-                {
-                    result.add(cap);
-                }
-            }
-        }
-        return result;
-    }
-
-    public synchronized List<BundleRequirement> getRequirements(String namespace)
-    {
-        if (m_isResolved && (m_resolvedReqs == null))
-        {
-            List<BundleRequirement> reqList = (m_declaredReqs == null)
-                ? new ArrayList() : new ArrayList(m_declaredReqs);
-            for (int fragIdx = 0;
-                (m_fragments != null) && (fragIdx < m_fragments.size());
-                fragIdx++)
-            {
-                List<BundleRequirement> reqs =
-                    m_fragments.get(fragIdx).getDeclaredRequirements(null);
-                for (int reqIdx = 0;
-                    (reqs != null) && (reqIdx < reqs.size());
-                    reqIdx++)
-                {
-                    if (reqs.get(reqIdx).getNamespace().equals(
-                            BundleCapabilityImpl.PACKAGE_NAMESPACE)
-                        || reqs.get(reqIdx).getNamespace().equals(
-                            BundleCapabilityImpl.BUNDLE_NAMESPACE))
-                    {
-                        reqList.add(
-                            new HostedRequirement(
-                                this, (BundleRequirementImpl) reqs.get(reqIdx)));
-                    }
-                }
-            }
-            m_resolvedReqs = Collections.unmodifiableList(reqList);
-        }
-        List<BundleRequirement> result = m_resolvedReqs;
-        if (namespace != null)
-        {
-            result = new ArrayList<BundleRequirement>();
-            for (BundleRequirement req : m_resolvedReqs)
-            {
-                if (req.getNamespace().equals(namespace))
-                {
-                    result.add(req);
-                }
-            }
-        }
-        return result;
-    }
-
-    public List<BundleWire> getProvidedWires(String namespace)
-    {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    public List<BundleWire> getRequiredWires(String namespace)
-    {
-        return m_wires;
-    }
-
-    public BundleRevision getRevision()
-    {
-        return this;
-    }
-
-    public synchronized ClassLoader getClassLoader()
-    {
-        if (m_classLoader == null)
-        {
-            // Determine which class loader to use based on which
-            // Java platform we are running on.
-            Class clazz;
-            if (m_isPreJava5)
-            {
-                clazz = BundleClassLoader.class;
-            }
-            else
-            {
-                try
-                {
-                    clazz = BundleClassLoaderJava5.class;
-                }
-                catch (Throwable th)
-                {
-                    // If we are on pre-Java5 then we will get a verify error
-                    // here since we try to override a getResources() which is
-                    // a final method in pre-Java5.
-                    m_isPreJava5 = true;
-                    clazz = BundleClassLoader.class;
-                }
-            }
-
-            // Use SecureAction to create the class loader if security is
-            // enabled; otherwise, create it directly.
-            try
-            {
-                Constructor ctor = (Constructor) m_secureAction.getConstructor(
-                    clazz, new Class[] { BundleRevisionImpl.class, ClassLoader.class });
-                m_classLoader = (BundleClassLoader)
-                    m_secureAction.invoke(ctor,
-                    new Object[] { this, determineParentClassLoader() });
-            }
-            catch (Exception ex)
-            {
-                throw new RuntimeException("Unable to create module class loader: "
-                    + ex.getMessage() + " [" + ex.getClass().getName() + "]");
-            }
-        }
-        return m_classLoader;
-    }
-
-    public List<URL> findEntries(String path, String filePattern, int options)
-    {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    public Collection<String> listResources(String path, String filePattern, int options)
-    {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    //
     // Implementating details.
     //
 
-
     public Map getHeaders()
     {
         return m_headerMap;
@@ -533,75 +313,14 @@
         return m_manifestVersion;
     }
 
-    public synchronized List<BundleRequirement> getResolvedDynamicRequirements()
+    public List<BundleRequirement> getDeclaredDynamicRequirements()
     {
-        if (m_isResolved && (m_resolvedDynReqs == null))
-        {
-            List<BundleRequirement> reqList = (m_declaredDynReqs == null)
-                ? new ArrayList() : new ArrayList(m_declaredDynReqs);
-            for (int fragIdx = 0;
-                (m_fragments != null) && (fragIdx < m_fragments.size());
-                fragIdx++)
-            {
-                List<BundleRequirement> reqs =
-                    ((BundleRevisionImpl) m_fragments.get(fragIdx))
-                        .getDeclaredDynamicRequirements();
-                for (int reqIdx = 0;
-                    (reqs != null) && (reqIdx < reqs.size());
-                    reqIdx++)
-                {
-                    if (reqs.get(reqIdx).getNamespace().equals(
-                        BundleCapabilityImpl.PACKAGE_NAMESPACE))
-                    {
-                        reqList.add(reqs.get(reqIdx));
-                    }
-                }
-            }
-            m_resolvedDynReqs = Collections.unmodifiableList(reqList);
-        }
-        return m_resolvedDynReqs;
+        return m_declaredDynamicReqs;
     }
 
-    public synchronized List<R4Library> getNativeLibraries()
+    public List<R4Library> getDeclaredNativeLibraries()
     {
-        List<R4Library> result = null;
-        if (m_isResolved)
-        {
-            List<R4Library> nativeList = (m_nativeLibraries == null)
-                ? new ArrayList() : new ArrayList(m_nativeLibraries);
-            for (int fragIdx = 0;
-                (m_fragments != null) && (fragIdx < m_fragments.size());
-                fragIdx++)
-            {
-                List<R4Library> libs =
-                    ((BundleRevisionImpl) m_fragments.get(fragIdx))
-                        .getNativeLibraries();
-                for (int reqIdx = 0;
-                    (libs != null) && (reqIdx < libs.size());
-                    reqIdx++)
-                {
-                    nativeList.add(libs.get(reqIdx));
-                }
-            }
-
-            // We need to return null here if we don't have any libraries, since a
-            // zero-length array is used to indicate that matching native libraries
-            // could not be found when resolving the bundle.
-            result = (nativeList.isEmpty())
-                ? null
-                : Collections.unmodifiableList(nativeList);
-        }
-        else
-        {
-            result = m_nativeLibraries;
-        }
-
-        return result;
-    }
-
-    public int getDeclaredActivationPolicy()
-    {
-        return m_declaredActivationPolicy;
+        return m_declaredNativeLibs;
     }
 
     synchronized boolean isActivationTriggered()
@@ -643,196 +362,31 @@
         return m_id;
     }
 
-// TODO: OSGi R4.3 - This really shouldn't be public, but it is needed by the
-//       resolver to determine if a bundle can dynamically import.
-    public synchronized boolean hasPackageSource(String pkgName)
-    {
-        return (m_importedPkgs.containsKey(pkgName) || m_requiredPkgs.containsKey(pkgName));
-    }
-
-// TODO: OSGi R4.3 - This really shouldn't be public, but it is needed by the
-//       to implement dynamic imports.
-    public synchronized BundleRevision getImportedPackageSource(String pkgName)
-    {
-        return m_importedPkgs.get(pkgName);
-    }
-
-    private synchronized List<BundleRevision> getRequiredPackageSources(String pkgName)
-    {
-        return m_requiredPkgs.get(pkgName);
-    }
-
-    public synchronized List<BundleWire> getWires()
-    {
-        return m_wires;
-    }
-
-    public synchronized void addDynamicWire(ResolverWire rw)
-    {
-        // This not only sets the wires for the module, but it also records
-        // the dependencies this module has on other modules (i.e., the provider
-        // end of the wire) to simplify bookkeeping.
-
-        BundleWire wire = new BundleWireImpl(
-            rw.getRequirer(),
-            rw.getRequirement(),
-            rw.getProvider(),
-            rw.getCapability());
-        m_wires.add(wire);
-        m_importedPkgs.put(
-            (String) wire.getCapability().getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR),
-            rw.getProvider());
-        
-// TODO: OSGi R4.3 - What's the correct way to handle this?
-//                ((BundleRevisionImpl) m_wires.get(i).getProviderWiring().getRevision())
-//                    .addDependentImporter(this);
-        ((BundleRevisionImpl) rw.getProvider()).addDependentImporter(this);
-    }
-
-    public synchronized void setWires(
+    public synchronized void resolve(
+        List<BundleRevision> fragments,
         List<ResolverWire> rws,
         Map<ResolverWire, Set<String>> requiredPkgWires)
+        throws Exception
     {
         // This not only sets the wires for the module, but it also records
         // the dependencies this module has on other modules (i.e., the provider
         // end of the wire) to simplify bookkeeping.
 
-        // For fragments we don't need to capture any additional dependency
-        // information, since the wires are sufficient, so just record the
-        // new wires. The wires are to the hosts to which the fragment is attached.
-        boolean isFragment = Util.isFragment(this);
-
-        // Fragments are allowed to add new wires to existing wires, but
-        // normal bundles should never be wired again if they already 
-        // have wires.
-        if (!isFragment && (m_wires != null) && (rws != null))
+        // If there is an existing wiring, then dispose of it, which will
+        // remove any dependencies on other wirings.
+        if (m_wiring != null)
         {
-            throw new IllegalStateException("The revision already has wires.");
+            m_wiring.dispose();
+            m_wiring = null;
         }
 
-        // Convert resolver wires to bundle wires and aggregate all imported
-        // or required packages.
-        List<BundleWire> wires = null;
-        Map<String, BundleRevision> importedPkgs = null;
-        Map<String, List<BundleRevision>> requiredPkgs = null;
         if (rws != null)
         {
-            wires = new ArrayList<BundleWire>(rws.size());
-            importedPkgs = new HashMap<String, BundleRevision>();
-            requiredPkgs = new HashMap<String, List<BundleRevision>>();
-
-            for (ResolverWire rw : rws)
-            {
-                wires.add(
-                    new BundleWireImpl(
-                        rw.getRequirer(),
-                        rw.getRequirement(),
-                        rw.getProvider(),
-                        rw.getCapability()));
-
-                if (isFragment)
-                {
-                    m_logger.log(
-                        Logger.LOG_DEBUG,
-                        "FRAGMENT WIRE: "
-                        + this + " -> hosted by -> " + rw.getProvider());
-                }
-                else
-                {
-                    m_logger.log(Logger.LOG_DEBUG, "WIRE: " + rw);
-
-                    if (rw.getCapability().getNamespace()
-                        .equals(BundleCapabilityImpl.PACKAGE_NAMESPACE))
-                    {
-                        importedPkgs.put(
-                            (String) rw.getCapability().getAttributes()
-                                .get(BundleCapabilityImpl.PACKAGE_ATTR),
-                            rw.getProvider());
-                    }
-                    else if (rw.getCapability().getNamespace()
-                        .equals(BundleCapabilityImpl.BUNDLE_NAMESPACE))
-                    {
-                        for (String pkgName : requiredPkgWires.get(rw))
-                        {
-                            List<BundleRevision> revs = requiredPkgs.get(pkgName);
-                            if (revs != null)
-                            {
-                                revs.add(rw.getProvider());
-                            }
-                            else
-                            {
-                                revs = new ArrayList<BundleRevision>();
-                                revs.add(rw.getProvider());
-                                requiredPkgs.put(pkgName, revs);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        // Remove module from old wire modules' dependencies,
-        // since we are no longer dependent on any the moduels
-        // from the old wires.
-        for (int i = 0; !isFragment && (m_wires != null) && (i < m_wires.size()); i++)
-        {
-            if (m_wires.get(i).getCapability().getNamespace()
-                .equals(BundleCapabilityImpl.BUNDLE_NAMESPACE))
-            {
-                ((BundleRevisionImpl) m_wires.get(i).getProviderWiring().getRevision())
-                    .removeDependentRequirer(this);
-            }
-            else if (m_wires.get(i).getCapability().getNamespace()
-                .equals(BundleCapabilityImpl.PACKAGE_NAMESPACE))
-            {
-                ((BundleRevisionImpl) m_wires.get(i).getProviderWiring().getRevision())
-                    .removeDependentImporter(this);
-            }
-        }
-
-        // If we already have wires, then add new wires to existing list (this
-        // should only happen for fragments). Otherwise, simply set wires value.
-        if ((m_wires != null) && (wires != null))
-        {
-            m_wires.addAll(wires);
-        }
-        else
-        {
-            m_wires = wires;
-        }
-        m_importedPkgs = importedPkgs;
-        m_requiredPkgs = requiredPkgs;
-
-        // Add ourself as a dependent to the new wires' modules.
-        if (!isFragment && (rws != null))
-        {
-            for (ResolverWire rw : rws)
-            {
-                if (rw.getCapability().getNamespace()
-                    .equals(BundleCapabilityImpl.BUNDLE_NAMESPACE))
-                {
-                    ((BundleRevisionImpl) rw.getProvider()).addDependentRequirer(this);
-                }
-                else if (rw.getCapability().getNamespace()
-                    .equals(BundleCapabilityImpl.PACKAGE_NAMESPACE))
-                {
-                    ((BundleRevisionImpl) rw.getProvider()).addDependentImporter(this);
-                }
-            }
+            m_wiring = new BundleWiringImpl(
+                m_logger, m_configMap, m_resolver, this, fragments, rws, requiredPkgWires);
         }
     }
 
-    public boolean isResolved()
-    {
-        return m_isResolved;
-    }
-
-    public void setResolved()
-    {
-        m_isResolved = true;
-    }
-
-
     public synchronized void setSecurityContext(Object securityContext)
     {
         m_protectionDomain = (ProtectionDomain) securityContext;
@@ -883,10 +437,6 @@
     {
         List contentList = new ArrayList();
         calculateContentPath(this, m_content, contentList, true);
-        for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
-        {
-            calculateContentPath(m_fragments.get(i), m_fragmentContents[i], contentList, false);
-        }
         return (Content[]) contentList.toArray(new Content[contentList.size()]);
     }
 
@@ -933,17 +483,6 @@
                 // Try to find the embedded class path entry in the current
                 // content.
                 Content embeddedContent = content.getEntryAsContent(classPathStrings.get(i));
-                // If the embedded class path entry was not found, it might be
-                // in one of the fragments if the current content is the bundle,
-                // so try to search the fragments if necessary.
-                for (int fragIdx = 0;
-                    searchFragments && (embeddedContent == null)
-                        && (m_fragmentContents != null) && (fragIdx < m_fragmentContents.length);
-                    fragIdx++)
-                {
-                    embeddedContent =
-                        m_fragmentContents[fragIdx].getEntryAsContent(classPathStrings.get(i));
-                }
                 // If we found the embedded content, then add it to the
                 // class path content list.
                 if (embeddedContent != null)
@@ -973,170 +512,6 @@
         return contentList;
     }
 
-    public Class getClassByDelegation(String name) throws ClassNotFoundException
-    {
-        // We do not call getClassLoader().loadClass() for arrays because
-        // it does not correctly handle array types, which is necessary in
-        // cases like deserialization using a wrapper class loader.
-        if ((name != null) && (name.length() > 0) && (name.charAt(0) == '['))
-        {
-            return Class.forName(name, false, getClassLoader());
-        }
-        return getClassLoader().loadClass(name);
-    }
-
-    public URL getResourceByDelegation(String name)
-    {
-        try
-        {
-            return (URL) findClassOrResourceByDelegation(name, false);
-        }
-        catch (ClassNotFoundException ex)
-        {
-            // This should never be thrown because we are loading resources.
-        }
-        catch (ResourceNotFoundException ex)
-        {
-            m_logger.log(m_bundle,
-                Logger.LOG_DEBUG,
-                ex.getMessage());
-        }
-        return null;
-    }
-
-    private Object findClassOrResourceByDelegation(String name, boolean isClass)
-        throws ClassNotFoundException, ResourceNotFoundException
-    {
-        Object result = null;
-
-        Set requestSet = (Set) m_cycleCheck.get();
-        if (requestSet == null)
-        {
-            requestSet = new HashSet();
-            m_cycleCheck.set(requestSet);
-        }
-        if (requestSet.add(name))
-        {
-            try
-            {
-                // First, try to resolve the originating revision.
-                m_resolver.resolve(this);
-
-                // Get the package of the target class/resource.
-                String pkgName = (isClass)
-                    ? Util.getClassPackage(name)
-                    : Util.getResourcePackage(name);
-
-                // Delegate any packages listed in the boot delegation
-                // property to the parent class loader.
-                if (shouldBootDelegate(pkgName))
-                {
-                    try
-                    {
-                        // Get the appropriate class loader for delegation.
-                        ClassLoader bdcl = getBootDelegationClassLoader();
-                        result = (isClass)
-                            ? (Object) bdcl.loadClass(name)
-                            : (Object) bdcl.getResource(name);
-                        // If this is a java.* package, then always terminate the
-                        // search; otherwise, continue to look locally if not found.
-                        if (pkgName.startsWith("java.") || (result != null))
-                        {
-                            return result;
-                        }
-                    }
-                    catch (ClassNotFoundException ex)
-                    {
-                        // If this is a java.* package, then always terminate the
-                        // search; otherwise, continue to look locally if not found.
-                        if (pkgName.startsWith("java."))
-                        {
-                            throw ex;
-                        }
-                    }
-                }
-
-                // Look in the revision's imports. Note that the search may
-                // be aborted if this method throws an exception, otherwise
-                // it continues if a null is returned.
-                result = searchImports(pkgName, name, isClass);
-
-                // If not found, try the revision's own class path.
-                if (result == null)
-                {
-                    result = (isClass)
-                        ? (Object) ((BundleClassLoader) getClassLoader()).findClass(name)
-                        : (Object) getResourceLocal(name);
-
-                    // If still not found, then try the revision's dynamic imports.
-                    if (result == null)
-                    {
-                        result = searchDynamicImports(pkgName, name, isClass);
-                    }
-                }
-            }
-            catch (ResolveException ex)
-            {
-                if (isClass)
-                {
-                    // We do not use the resolve exception as the
-                    // cause of the exception, since this would
-                    // potentially leak internal module information.
-                    throw new ClassNotFoundException(
-                        name + " not found because "
-                        + getBundle()
-                        + " cannot resolve: "
-                        + ex.getRequirement());
-                }
-                else
-                {
-                    // The spec states that if the bundle cannot be resolved, then
-                    // only the local bundle's resources should be searched. So we
-                    // will ask the module's own class path.
-                    URL url = getResourceLocal(name);
-                    if (url != null)
-                    {
-                        return url;
-                    }
-
-                    // We need to throw a resource not found exception.
-                    throw new ResourceNotFoundException(
-                        name + " not found because "
-                        + getBundle()
-                        + " cannot resolve: "
-                        + ex.getRequirement());
-                }
-            }
-            finally
-            {
-                requestSet.remove(name);
-            }
-        }
-        else
-        {
-            // If a cycle is detected, we should return null to break the
-            // cycle. This should only ever be return to internal class
-            // loading code and not to the actual instigator of the class load.
-            return null;
-        }
-
-        if (result == null)
-        {
-            if (isClass)
-            {
-                throw new ClassNotFoundException(
-                    name + " not found by " + this.getBundle());
-            }
-            else
-            {
-                throw new ResourceNotFoundException(
-                    name + " not found by " + this.getBundle());
-            }
-        }
-
-        return result;
-    }
-
     URL getResourceLocal(String name)
     {
         URL url = null;
@@ -1169,159 +544,7 @@
         return url;
     }
 
-    public Enumeration getResourcesByDelegation(String name)
-    {
-        Set requestSet = (Set) m_cycleCheck.get();
-        if (requestSet == null)
-        {
-            requestSet = new HashSet();
-            m_cycleCheck.set(requestSet);
-        }
-        if (!requestSet.contains(name))
-        {
-            requestSet.add(name);
-            try
-            {
-                return findResourcesByDelegation(name);
-            }
-            finally
-            {
-                requestSet.remove(name);
-            }
-        }
-
-        return null;
-    }
-
-    private Enumeration findResourcesByDelegation(String name)
-    {
-        Enumeration urls = null;
-        List completeUrlList = new ArrayList();
-
-        // First, try to resolve the originating module.
-        try
-        {
-            m_resolver.resolve(this);
-        }
-        catch (ResolveException ex)
-        {
-            // The spec states that if the bundle cannot be resolved, then
-            // only the local bundle's resources should be searched. So we
-            // will ask the module's own class path.
-            return getResourcesLocal(name);
-        }
-
-        // Get the package of the target class/resource.
-        String pkgName = Util.getResourcePackage(name);
-
-        // Delegate any packages listed in the boot delegation
-        // property to the parent class loader.
-        if (shouldBootDelegate(pkgName))
-        {
-            try
-            {
-                // Get the appropriate class loader for delegation.
-                ClassLoader bdcl = getBootDelegationClassLoader();
-                urls = bdcl.getResources(name);
-            }
-            catch (IOException ex)
-            {
-                // This shouldn't happen and even if it does, there
-                // is nothing we can do, so just ignore it.
-            }
-            // If this is a java.* package, then always terminate the
-            // search; otherwise, continue to look locally.
-            if (pkgName.startsWith("java."))
-            {
-                return urls;
-            }
-
-            completeUrlList.add(urls);
-        }
-
-        // Look in the revisions's imported packages. If the package is
-        // imported, then we stop searching no matter the result since
-        // imported packages cannot be split.
-        BundleRevision provider = getImportedPackageSource(pkgName);
-        if (provider != null)
-        {
-            // Delegate to the provider revision.
-            urls = ((BundleRevisionImpl) provider).getResourcesByDelegation(name);
-
-            // If we find any resources, then add them.
-            if ((urls != null) && (urls.hasMoreElements()))
-            {
-                completeUrlList.add(urls);
-            }
-
-            // Always return here since imported packages cannot be split
-            // across required bundles or the revision's content.
-            return new CompoundEnumeration((Enumeration[])
-                completeUrlList.toArray(new Enumeration[completeUrlList.size()]));
-        }
-
-        // See whether we can get the resource from the required bundles and
-        // regardless of whether or not this is the case continue to the next
-        // step potentially passing on the result of this search (if any).
-        List<BundleRevision> providers = getRequiredPackageSources(pkgName);
-        if (providers != null)
-        {
-            for (BundleRevision p : providers)
-            {
-                // Delegate to the provider revision.
-                urls = ((BundleRevisionImpl) p).getResourcesByDelegation(name);
-
-                // If we find any resources, then add them.
-                if ((urls != null) && (urls.hasMoreElements()))
-                {
-                    completeUrlList.add(urls);
-                }
-
-                // Do not return here, since required packages can be split
-                // across the revision's content.
-            }
-        }
-
-        // Try the module's own class path. If we can find the resource then
-        // return it together with the results from the other searches else
-        // try to look into the dynamic imports.
-        urls = getResourcesLocal(name);
-        if ((urls != null) && (urls.hasMoreElements()))
-        {
-            completeUrlList.add(urls);
-        }
-        else
-        {
-            // If not found, then try the module's dynamic imports.
-            // At this point, the module's imports were searched and so was the
-            // the module's content. Now we make an attempt to load the
-            // class/resource via a dynamic import, if possible.
-            try
-            {
-                provider = m_resolver.resolve(this, pkgName);
-            }
-            catch (ResolveException ex)
-            {
-                // Ignore this since it is likely normal.
-            }
-            if (provider != null)
-            {
-                // Delegate to the provider revision.
-                urls = ((BundleRevisionImpl) provider).getResourcesByDelegation(name);
-
-                // If we find any resources, then add them.
-                if ((urls != null) && (urls.hasMoreElements()))
-                {
-                    completeUrlList.add(urls);
-                }
-            }
-        }
-
-        return new CompoundEnumeration((Enumeration[])
-            completeUrlList.toArray(new Enumeration[completeUrlList.size()]));
-    }
-
-    private Enumeration getResourcesLocal(String name)
+    Enumeration getResourcesLocal(String name)
     {
         List l = new ArrayList();
 
@@ -1461,102 +684,6 @@
         return null;
     }
 
-    //
-    // Fragment and dependency management methods.
-    //
-
-    public synchronized List<BundleRevision> getFragments()
-    {
-        return m_fragments;
-    }
-
-    private synchronized void detachHost(BundleRevision host)
-    {
-        if (m_wires != null)
-        {
-            for (Iterator<BundleWire> it = m_wires.iterator(); it.hasNext(); )
-            {
-                BundleWire wire = it.next();
-                if (wire.getCapability().getNamespace().equals(BundleCapabilityImpl.HOST_NAMESPACE)
-                    && wire.getProviderWiring().getRevision().equals(host))
-                {
-                    it.remove();
-                    break;
-                }
-            }
-        }
-    }
-
-    public synchronized void attachFragments(List<BundleRevision> fragments) throws Exception
-    {
-        // Remove the host wires for this module from old fragments.
-        // We will generally only remove host wires when we are uninstalling
-        // the module.
-        if (m_fragments != null)
-        {
-            for (BundleRevision fragment : m_fragments)
-            {
-                ((BundleRevisionImpl) fragment).detachHost(this);
-            }
-        }
-
-        // Close previous fragment contents.
-        for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
-        {
-            m_fragmentContents[i].close();
-        }
-        m_fragmentContents = null;
-
-        // Close the old content path, since we'll need to recalculate it for
-        // for the added (or removed) fragments.
-        for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
-        {
-            // Don't close this module's content, if it is on the content path.
-            if (m_content != m_contentPath[i])
-            {
-                m_contentPath[i].close();
-            }
-        }
-        m_contentPath = null;
-
-        // Remove cached capabilities and requirements.
-        m_resolvedCaps = null;
-        m_resolvedReqs = null;
-        m_resolvedDynReqs = null;
-
-        // Update the dependencies on the new fragments.
-        m_fragments = fragments;
-
-        // We need to sort the fragments and add ourself as a dependent of each one.
-        // We also need to create an array of fragment contents to attach to our
-        // content path.
-        if (m_fragments != null)
-        {
-            // Sort fragments according to ID order, if necessary.
-            // Note that this sort order isn't 100% correct since
-            // it uses a string, but it is likely close enough and
-            // avoids having to create more objects.
-            if (m_fragments.size() > 1)
-            {
-                SortedMap<String, BundleRevision> sorted = new TreeMap<String, BundleRevision>();
-                for (BundleRevision f : m_fragments)
-                {
-                    sorted.put(((BundleRevisionImpl) f).getId(), f);
-                }
-                m_fragments = new ArrayList(sorted.values());
-            }
-            m_fragmentContents = new Content[m_fragments.size()];
-            for (int i = 0; (m_fragments != null) && (i < m_fragments.size()); i++)
-            {
-                m_fragmentContents[i] =
-                    ((BundleRevisionImpl) m_fragments.get(i)).getContent()
-                        .getEntryAsContent(FelixConstants.CLASS_PATH_DOT);
-            }
-            // Recalculate the content path for the new fragments.
-            m_contentPath = initializeContentPath();
-        }
-    }
-
     public synchronized List<BundleRevision> getDependentImporters()
     {
         return m_dependentImporters;
@@ -1599,9 +726,11 @@
         if (Util.isFragment(this))
         {
             dependents = new ArrayList<BundleRevision>();
-            for (int i = 0; (m_wires != null) && (i < m_wires.size()); i++)
+            List<BundleWire> wires = (m_wiring == null)
+                ? null : m_wiring.getRequiredWires(null);
+            for (int i = 0; (wires != null) && (i < wires.size()); i++)
             {
-                dependents.add(m_wires.get(i).getCapability().getRevision());
+                dependents.add(wires.get(i).getProviderWiring().getRevision());
             }
         }
         else
@@ -1616,18 +745,20 @@
 
     public synchronized void close()
     {
+        try
+        {
+            resolve(null, null, null);
+        }
+        catch (Exception ex)
+        {
+            m_logger.log(Logger.LOG_ERROR, "Error releasing revision: " + ex.getMessage(), ex);
+        }
         m_content.close();
         for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
         {
             m_contentPath[i].close();
         }
         m_contentPath = null;
-        for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
-        {
-            m_fragmentContents[i].close();
-        }
-        m_fragmentContents = null;
-        m_classLoader = null;
     }
 
     @Override
@@ -1636,815 +767,6 @@
         return m_id;
     }
 
-    private ClassLoader determineParentClassLoader()
-    {
-        // Determine the class loader's parent based on the
-        // configuration property; use boot class loader by
-        // default.
-        String cfg = (String) m_configMap.get(Constants.FRAMEWORK_BUNDLE_PARENT);
-        cfg = (cfg == null) ? Constants.FRAMEWORK_BUNDLE_PARENT_BOOT : cfg;
-        final ClassLoader parent;
-        if (cfg.equalsIgnoreCase(Constants.FRAMEWORK_BUNDLE_PARENT_APP))
-        {
-            parent = m_secureAction.getSystemClassLoader();
-        }
-        else if (cfg.equalsIgnoreCase(Constants.FRAMEWORK_BUNDLE_PARENT_EXT))
-        {
-            parent = m_secureAction.getParentClassLoader(m_secureAction.getSystemClassLoader());
-        }
-        else if (cfg.equalsIgnoreCase(Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK))
-        {
-            parent = m_secureAction.getClassLoader(BundleRevisionImpl.class);
-        }
-        // On Android we cannot set the parent class loader to be null, so
-        // we special case that situation here and set it to the system
-        // class loader by default instead, which is not really spec.
-        else if (m_bootClassLoader == null)
-        {
-            parent = m_secureAction.getSystemClassLoader();
-        }
-        else
-        {
-            parent = null;
-        }
-        return parent;
-    }
-
-    private Object searchImports(String pkgName, String name, boolean isClass)
-        throws ClassNotFoundException, ResourceNotFoundException
-    {
-        // Check if the package is imported.
-        BundleRevision provider = getImportedPackageSource(pkgName);
-        if (provider != null)
-        {
-            // If we find the class or resource, then return it.
-            Object result = (isClass)
-                ? (Object) ((BundleRevisionImpl) provider).getClassByDelegation(name)
-                : (Object) ((BundleRevisionImpl) provider).getResourceByDelegation(name);
-            if (result != null)
-            {
-                return result;
-            }
-
-            // If no class was found, then we must throw an exception
-            // since the provider of this package did not contain the
-            // requested class and imported packages are atomic.
-            throw new ClassNotFoundException(name);
-        }
-
-        // Check if the package is required.
-        List<BundleRevision> providers = getRequiredPackageSources(pkgName);
-        if (providers != null)
-        {
-            for (BundleRevision p : providers)
-            {
-                // If we find the class or resource, then return it.
-                try
-                {
-                    Object result = (isClass)
-                        ? (Object) ((BundleRevisionImpl) p).getClassByDelegation(name)
-                        : (Object) ((BundleRevisionImpl) p).getResourceByDelegation(name);
-                    if (result != null)
-                    {
-                        return result;
-                    }
-                }
-                catch (ClassNotFoundException ex)
-                {
-                    // Since required packages can be split, don't throw an
-                    // exception here if it is not found. Instead, we'll just
-                    // continue searching other required bundles and the
-                    // revision's local content.
-                }
-            }
-        }
-
-        return null;
-    }
-
-    private Object searchDynamicImports(
-        final String pkgName, final String name, final boolean isClass)
-        throws ClassNotFoundException, ResourceNotFoundException
-    {
-        // At this point, the module's imports were searched and so was the
-        // the module's content. Now we make an attempt to load the
-        // class/resource via a dynamic import, if possible.
-        BundleRevision provider = null;
-        try
-        {
-            provider = m_resolver.resolve(this, pkgName);
-        }
-        catch (ResolveException ex)
-        {
-            // Ignore this since it is likely normal.
-        }
-
-        // If the dynamic import was successful, then this initial
-        // time we must directly return the result from dynamically
-        // created package sources, but subsequent requests for
-        // classes/resources in the associated package will be
-        // processed as part of normal static imports.
-        if (provider != null)
-        {
-            // Return the class or resource.
-            return (isClass)
-                ? (Object) ((BundleRevisionImpl) provider).getClassByDelegation(name)
-                : (Object) ((BundleRevisionImpl) provider).getResourceByDelegation(name);
-        }
-
-        // If implicit boot delegation is enabled, then try to guess whether
-        // we should boot delegate.
-        if (m_implicitBootDelegation)
-        {
-            // At this point, the class/resource could not be found by the bundle's
-            // static or dynamic imports, nor its own content. Before we throw
-            // an exception, we will try to determine if the instigator of the
-            // class/resource load was a class from a bundle or not. This is necessary
-            // because the specification mandates that classes on the class path
-            // should be hidden (except for java.*), but it does allow for these
-            // classes/resources to be exposed by the system bundle as an export.
-            // However, in some situations classes on the class path make the faulty
-            // assumption that they can access everything on the class path from
-            // every other class loader that they come in contact with. This is
-            // not true if the class loader in question is from a bundle. Thus,
-            // this code tries to detect that situation. If the class instigating
-            // the load request was NOT from a bundle, then we will make the
-            // assumption that the caller actually wanted to use the parent class
-            // loader and we will delegate to it. If the class was
-            // from a bundle, then we will enforce strict class loading rules
-            // for the bundle and throw an exception.
-
-            // Get the class context to see the classes on the stack.
-            final Class[] classes = m_sm.getClassContext();
-            try
-            {
-                if (System.getSecurityManager() != null)
-                {
-                    return AccessController
-                        .doPrivileged(new PrivilegedExceptionAction()
-                        {
-                            public Object run() throws Exception
-                            {
-                                return doImplicitBootDelegation(classes, name,
-                                    isClass);
-                            }
-                        });
-                }
-                else
-                {
-                    return doImplicitBootDelegation(classes, name, isClass);
-                }
-            }
-            catch (PrivilegedActionException ex)
-            {
-                Exception cause = ex.getException();
-                if (cause instanceof ClassNotFoundException)
-                {
-                    throw (ClassNotFoundException) cause;
-                }
-                else
-                {
-                    throw (ResourceNotFoundException) cause;
-                }
-            }
-        }
-        return null;
-    }
-
-    private Object doImplicitBootDelegation(Class[] classes, String name, boolean isClass)
-        throws ClassNotFoundException, ResourceNotFoundException
-    {
-        // Start from 1 to skip security manager class.
-        for (int i = 1; i < classes.length; i++)
-        {
-            // Find the first class on the call stack that is not from
-            // the class loader that loaded the Felix classes or is not
-            // a class loader or class itself, because we want to ignore
-            // calls to ClassLoader.loadClass() and Class.forName() since
-            // we are trying to find out who instigated the class load.
-            // Also ignore inner classes of class loaders, since we can
-            // assume they are a class loader too.
-
-            // TODO: FRAMEWORK - This check is a hack and we should see if we can think
-            // of another way to do it, since it won't necessarily work in all situations.
-            // Since Felix uses threads for changing the start level
-            // and refreshing packages, it is possible that there are no
-            // bundle classes on the call stack; therefore, as soon as we
-            // see Thread on the call stack we exit this loop. Other cases
-            // where bundles actually use threads are not an issue because
-            // the bundle classes will be on the call stack before the
-            // Thread class.
-            if (Thread.class.equals(classes[i]))
-            {
-                break;
-            }
-            // Break if the current class came from a bundle, since we should
-            // not implicitly boot delegate in that case.
-            else if (isClassLoadedFromBundleRevision(classes[i]))
-            {
-                break;
-            }
-            // Break if this goes through BundleImpl because it must be a call
-            // to Bundle.loadClass() which should not implicitly boot delegate.
-            else if (BundleImpl.class.equals(classes[i]))
-            {
-                break;
-            }
-            else if (isClassExternal(classes[i]))
-            {
-                try
-                {
-                    // Return the class or resource from the parent class loader.
-                    return (isClass)
-                        ? (Object) m_secureAction.getClassLoader(this.getClass()).loadClass(name)
-                        : (Object) m_secureAction.getClassLoader(this.getClass()).getResource(name);
-                }
-                catch (NoClassDefFoundError ex)
-                {
-                    // Ignore, will return null
-                }
-                break;
-            }
-        }
-
-        return null;
-    }
-
-    private boolean isClassLoadedFromBundleRevision(Class clazz)
-    {
-        // The target class is loaded by a bundle class loader,
-        // then return true.
-        if (BundleClassLoader.class.isInstance(m_secureAction.getClassLoader(clazz)))
-        {
-            return true;
-        }
-
-        // If the target class was loaded from a class loader that
-        // came from a bundle, then return true.
-        ClassLoader last = null;
-        for (ClassLoader cl = m_secureAction.getClassLoader(clazz);
-            (cl != null) && (last != cl);
-            cl = m_secureAction.getClassLoader(cl.getClass()))
-        {
-            last = cl;
-            if (BundleClassLoader.class.isInstance(cl))
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Tries to determine whether the given class is part of the framework or not.
-     * Framework classes include everything in org.apache.felix.framework.* and
-     * org.osgi.framework.*. We also consider ClassLoader and Class to be internal
-     * classes, because they are inserted into the stack trace as a result of
-     * method overloading. Typically, ClassLoader or Class will be mixed in
-     * between framework classes or will be at the point where the class loading
-     * request enters the framework class loading mechanism, which will then be
-     * followed by either bundle or external code, which will then exit our
-     * attempt to determine if we should boot delegate or not. Other standard
-     * class loaders, like URLClassLoader, are considered external classes and
-     * should trigger boot delegation. This means that bundles can create standard
-     * class loaders to get access to boot packages, but this is the standard
-     * behavior of class loaders.
-     * @param clazz the class to determine if it is external or not.
-     * @return <tt>true</tt> if the class is external, otherwise <tt>false</tt>.
-     */
-    private boolean isClassExternal(Class clazz)
-    {
-        if (clazz.getName().startsWith("org.apache.felix.framework."))
-        {
-            return false;
-        }
-        else if (clazz.getName().startsWith("org.osgi.framework."))
-        {
-            return false;
-        }
-        else if (ClassLoader.class.equals(clazz))
-        {
-            return false;
-        }
-        else if (Class.class.equals(clazz))
-        {
-            return false;
-        }
-        return true;
-    }
-
-    boolean shouldBootDelegate(String pkgName)
-    {
-        // Always boot delegate if the bundle has a configured
-        // boot class loader.
-        if (m_bootClassLoader != m_defBootClassLoader)
-        {
-            return true;
-        }
-
-        boolean result = false;
-
-        // Only consider delegation if we have a package name, since
-        // we don't want to promote the default package. The spec does
-        // not take a stand on this issue.
-        if (pkgName.length() > 0)
-        {
-            for (int i = 0; !result && (i < m_bootPkgs.length); i++)
-            {
-                // Check if the boot package is wildcarded.
-                // A wildcarded boot package will be in the form "foo.",
-                // so a matching subpackage will start with "foo.", e.g.,
-                // "foo.bar".
-                if (m_bootPkgWildcards[i] && pkgName.startsWith(m_bootPkgs[i]))
-                {
-                    return true;
-                }
-                // If not wildcarded, then check for an exact match.
-                else if (m_bootPkgs[i].equals(pkgName))
-                {
-                    return true;
-                }
-            }
-        }
-
-        return result;
-    }
-
-    ClassLoader getBootDelegationClassLoader()
-    {
-        // Get the appropriate class loader for delegation.
-        ClassLoader parent = (m_classLoader == null)
-            ? determineParentClassLoader() : m_secureAction.getParentClassLoader(m_classLoader);
-        return (parent == null) ? m_bootClassLoader : parent;
-    }
-
-    private static final Constructor m_dexFileClassConstructor;
-    private static final Method m_dexFileClassLoadDex;
-    private static final Method m_dexFileClassLoadClass;
-
-    static
-    {
-        Constructor dexFileClassConstructor = null;
-        Method dexFileClassLoadDex = null;
-        Method dexFileClassLoadClass = null;
-        try
-        {
-            Class dexFileClass;
-            try
-            {
-                dexFileClass = Class.forName("dalvik.system.DexFile");
-            }
-            catch (Exception ex)
-            {
-                dexFileClass = Class.forName("android.dalvik.DexFile");
-            }
-
-            try
-            {
-                dexFileClassLoadDex = dexFileClass.getMethod("loadDex", 
-                    new Class[]{String.class, String.class, Integer.TYPE});
-            }
-            catch (Exception ex)
-            {
-                // Nothing we need to do 
-            }
-            dexFileClassConstructor = dexFileClass.getConstructor(
-                new Class[] { java.io.File.class });
-            dexFileClassLoadClass = dexFileClass.getMethod("loadClass",
-                new Class[] { String.class, ClassLoader.class });
-        }
-        catch (Throwable ex)
-        {
-           dexFileClassConstructor = null;
-           dexFileClassLoadDex = null;
-           dexFileClassLoadClass = null;
-        }
-        m_dexFileClassConstructor = dexFileClassConstructor;
-        m_dexFileClassLoadDex= dexFileClassLoadDex;
-        m_dexFileClassLoadClass = dexFileClassLoadClass;
-    }
-
-    public class BundleClassLoaderJava5 extends BundleClassLoader
-    {
-        public BundleClassLoaderJava5(ClassLoader parent)
-        {
-            super(parent);
-        }
-
-        @Override
-        public Enumeration getResources(String name)
-        {
-            Enumeration urls = BundleRevisionImpl.this.getResourcesByDelegation(name);
-            if (m_useLocalURLs)
-            {
-                urls = new ToLocalUrlEnumeration(urls);
-            }
-            return urls;
-        }
-
-        @Override
-        protected Enumeration findResources(String name)
-        {
-            return BundleRevisionImpl.this.getResourcesLocal(name);
-        }
-    }
-
-    public class BundleClassLoader extends SecureClassLoader implements BundleReference
-    {
-        private final Map m_jarContentToDexFile;
-        private Object[][] m_cachedLibs = new Object[0][];
-        private static final int LIBNAME_IDX = 0;
-        private static final int LIBPATH_IDX = 1;
-
-        public BundleClassLoader(ClassLoader parent)
-        {
-            super(parent);
-            if (m_dexFileClassLoadClass != null)
-            {
-                m_jarContentToDexFile = new HashMap();
-            }
-            else
-            {
-                m_jarContentToDexFile = null;
-            }
-        }
-
-        public Bundle getBundle()
-        {
-            return BundleRevisionImpl.this.getBundle();
-        }
-
-        @Override
-        protected Class loadClass(String name, boolean resolve)
-            throws ClassNotFoundException
-        {
-            Class clazz = null;
-
-            // Make sure the class was not already loaded.
-            synchronized (this)
-            {
-                clazz = findLoadedClass(name);
-            }
-
-            if (clazz == null)
-            {
-                try
-                {
-                    clazz = (Class) findClassOrResourceByDelegation(name, true);
-                }
-                catch (ResourceNotFoundException ex)
-                {
-                    // This should never happen since we are asking for a class,
-                    // so just ignore it.
-                }
-                catch (ClassNotFoundException cnfe)
-                {
-                    ClassNotFoundException ex = cnfe;
-                    String msg = name;
-                    if (m_logger.getLogLevel() >= Logger.LOG_DEBUG)
-                    {
-                        msg = diagnoseClassLoadError(m_resolver, BundleRevisionImpl.this, name);
-                        ex = (msg != null)
-                            ? new ClassNotFoundException(msg, cnfe)
-                            : ex;
-                    }
-                    throw ex;
-                }
-            }
-
-            // Resolve the class and return it.
-            if (resolve)
-            {
-                resolveClass(clazz);
-            }
-            return clazz;
-        }
-
-        @Override
-        protected Class findClass(String name) throws ClassNotFoundException
-        {
-            Class clazz = null;
-
-            // Search for class in bundle revision.
-            if (clazz == null)
-            {
-                String actual = name.replace('.', '/') + ".class";
-
-                byte[] bytes = null;
-
-                // Check the bundle class path.
-                Content[] contentPath = getContentPath();
-                Content content = null;
-                for (int i = 0;
-                    (bytes == null) &&
-                    (i < contentPath.length); i++)
-                {
-                    bytes = contentPath[i].getEntryAsBytes(actual);
-                    content = contentPath[i];
-                }
-
-                if (bytes != null)
-                {
-                    // Get package name.
-                    String pkgName = Util.getClassPackage(name);
-
-                    // Before we actually attempt to define the class, grab
-                    // the lock for this class loader and make sure than no
-                    // other thread has defined this class in the meantime.
-                    synchronized (this)
-                    {
-                        clazz = findLoadedClass(name);
-
-                        if (clazz == null)
-                        {
-                            int activationPolicy = 
-                                ((BundleImpl) getBundle()).isDeclaredActivationPolicyUsed()
-                                ? ((BundleRevisionImpl) ((BundleImpl) getBundle())
-                                    .getCurrentRevision()).getDeclaredActivationPolicy()
-                                : EAGER_ACTIVATION;
-
-                            // If the revision is using deferred activation, then if
-                            // we load this class from this revision we need to activate
-                            // the bundle before returning the class. We will short
-                            // circuit the trigger matching if the trigger is already
-                            // tripped.
-                            boolean isTriggerClass = m_isActivationTriggered
-                                ? false : isActivationTrigger(pkgName);
-                            if (!m_isActivationTriggered
-                                && isTriggerClass
-                                && (activationPolicy == BundleRevisionImpl.LAZY_ACTIVATION)
-                                && (getBundle().getState() == Bundle.STARTING))
-                            {
-                                List deferredList = (List) m_deferredActivation.get();
-                                if (deferredList == null)
-                                {
-                                    deferredList = new ArrayList();
-                                    m_deferredActivation.set(deferredList);
-                                }
-                                deferredList.add(new Object[] { name, getBundle() });
-                            }
-                            // We need to try to define a Package object for the class
-                            // before we call defineClass() if we haven't already
-                            // created it.
-                            if (pkgName.length() > 0)
-                            {
-                                if (getPackage(pkgName) == null)
-                                {
-                                    Object[] params = definePackage(pkgName);
-                                    if (params != null)
-                                    {
-                                        definePackage(
-                                            pkgName,
-                                            (String) params[0],
-                                            (String) params[1],
-                                            (String) params[2],
-                                            (String) params[3],
-                                            (String) params[4],
-                                            (String) params[5],
-                                            null);
-                                    }
-                                    else
-                                    {
-                                        definePackage(pkgName, null, null,
-                                            null, null, null, null, null);
-                                    }
-                                }
-                            }
-
-                            // If we can load the class from a dex file do so
-                            if (content instanceof JarContent)
-                            {
-                                try
-                                {
-                                    clazz = getDexFileClass((JarContent) content, name, this);
-                                }
-                                catch (Exception ex)
-                                {
-                                    // Looks like we can't
-                                }
-                            }
-
-                            if (clazz == null)
-                            {
-                                // If we have a security context, then use it to
-                                // define the class with it for security purposes,
-                                // otherwise define the class without a protection domain.
-                                if (m_protectionDomain != null)
-                                {
-                                    clazz = defineClass(name, bytes, 0, bytes.length,
-                                        m_protectionDomain);
-                                }
-                                else
-                                {
-                                    clazz = defineClass(name, bytes, 0, bytes.length);
-                                }
-                            }
-
-                            // At this point if we have a trigger class, then the deferred
-                            // activation trigger has tripped.
-                            if (!m_isActivationTriggered && isTriggerClass && (clazz != null))
-                            {
-                                m_isActivationTriggered = true;
-                            }
-                        }
-                    }
-
-                    // Perform deferred activation without holding the class loader lock,
-                    // if the class we are returning is the instigating class.
-                    List deferredList = (List) m_deferredActivation.get();
-                    if ((deferredList != null)
-                        && (deferredList.size() > 0)
-                        && ((Object[]) deferredList.get(0))[0].equals(name))
-                    {
-                        for (int i = deferredList.size() - 1; i >= 0; i--)
-                        {
-                            try
-                            {
-                                ((BundleImpl) ((Object[]) deferredList.get(i))[1]).getFramework().activateBundle(
-                                    (BundleImpl) ((Object[]) deferredList.get(i))[1], true);
-                            }
-                            catch (BundleException ex)
-                            {
-                                ex.printStackTrace();
-                            }
-                        }
-                        deferredList.clear();
-                    }
-                }
-            }
-
-            return clazz;
-        }
-
-        private Object[] definePackage(String pkgName)
-        {
-            String spectitle = (String) m_headerMap.get("Specification-Title");
-            String specversion = (String) m_headerMap.get("Specification-Version");
-            String specvendor = (String) m_headerMap.get("Specification-Vendor");
-            String impltitle = (String) m_headerMap.get("Implementation-Title");
-            String implversion = (String) m_headerMap.get("Implementation-Version");
-            String implvendor = (String) m_headerMap.get("Implementation-Vendor");
-            if ((spectitle != null)
-                || (specversion != null)
-                || (specvendor != null)
-                || (impltitle != null)
-                || (implversion != null)
-                || (implvendor != null))
-            {
-                return new Object[] {
-                    spectitle, specversion, specvendor, impltitle, implversion, implvendor
-                };
-            }
-            return null;
-        }
-
-        private Class getDexFileClass(JarContent content, String name, ClassLoader loader)
-            throws Exception
-        {
-            if (m_jarContentToDexFile == null)
-            {
-                return null;
-            }
-
-            Object dexFile = null;
-
-            if (!m_jarContentToDexFile.containsKey(content))
-            {
-                try
-                {
-                    if (m_dexFileClassLoadDex != null)
-                    {
-                        dexFile = m_dexFileClassLoadDex.invoke(null, 
-                            new Object[]{content.getFile().getAbsolutePath(), 
-                                content.getFile().getAbsolutePath() + ".dex", new Integer(0)});
-                    }
-                    else
-                    {
-                        dexFile = m_dexFileClassConstructor.newInstance(
-                            new Object[] { content.getFile() });
-                    }
-                }
-                finally
-                {
-                    m_jarContentToDexFile.put(content, dexFile);
-                }
-            }
-            else
-            {
-                dexFile = m_jarContentToDexFile.get(content);
-            }
-
-            if (dexFile != null)
-            {
-                return (Class) m_dexFileClassLoadClass.invoke(dexFile,
-                    new Object[] { name.replace('.','/'), loader });
-            }
-            return null;
-        }
-
-        @Override
-        public URL getResource(String name)
-        {
-            URL url = BundleRevisionImpl.this.getResourceByDelegation(name);
-            if (m_useLocalURLs)
-            {
-                url = convertToLocalUrl(url);
-            }
-            return url;
-        }
-
-        @Override
-        protected URL findResource(String name)
-        {
-            return BundleRevisionImpl.this.getResourceLocal(name);
-        }
-
-        // The findResources() method should only look at the revision itself, but
-        // instead it tries to delegate because in Java version prior to 1.5 the
-        // getResources() method was final and could not be overridden. We should
-        // override getResources() like getResource() to make it delegate, but we
-        // can't. As a workaround, we make findResources() delegate instead.
-        @Override
-        protected Enumeration findResources(String name)
-        {
-            Enumeration urls = BundleRevisionImpl.this.getResourcesByDelegation(name);
-            if (m_useLocalURLs)
-            {
-                urls = new ToLocalUrlEnumeration(urls);
-            }
-            return urls;
-        }
-
-        @Override
-        protected String findLibrary(String name)
-        {
-            // Remove leading slash, if present.
-            if (name.startsWith("/"))
-            {
-                name = name.substring(1);
-            }
-
-            String result = null;
-            // CONCURRENCY: In the long run, we might want to break this
-            // sync block in two to avoid manipulating the cache while
-            // holding the lock, but for now we will do it the simple way.
-            synchronized (this)
-            {
-                // Check to make sure we haven't already found this library.
-                for (int i = 0; (result == null) && (i < m_cachedLibs.length); i++)
-                {
-                    if (m_cachedLibs[i][LIBNAME_IDX].equals(name))
-                    {
-                        result = (String) m_cachedLibs[i][LIBPATH_IDX];
-                    }
-                }
-
-                // If we don't have a cached result, see if we have a matching
-                // native library.
-                if (result == null)
-                {
-                    List<R4Library> libs = getNativeLibraries();
-                    for (int libIdx = 0; (libs != null) && (libIdx < libs.size()); libIdx++)
-                    {
-                        if (libs.get(libIdx).match(m_configMap, name))
-                        {
-                            // Search bundle content first for native library.
-                            result = getContent().getEntryAsNativeLibrary(
-                                libs.get(libIdx).getEntryName());
-                            // If not found, then search fragments in order.
-                            for (int i = 0;
-                                (result == null) && (m_fragmentContents != null)
-                                    && (i < m_fragmentContents.length);
-                                i++)
-                            {
-                                result = m_fragmentContents[i].getEntryAsNativeLibrary(
-                                    libs.get(libIdx).getEntryName());
-                            }
-                        }
-                    }
-
-                    // Remember the result for future requests.
-                    if (result != null)
-                    {
-                        Object[][] tmp = new Object[m_cachedLibs.length + 1][];
-                        System.arraycopy(m_cachedLibs, 0, tmp, 0, m_cachedLibs.length);
-                        tmp[m_cachedLibs.length] = new Object[] { name, result };
-                        m_cachedLibs = tmp;
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        @Override
-        public String toString()
-        {
-            return BundleRevisionImpl.this.toString();
-        }
-    }
-
     static URL convertToLocalUrl(URL url)
     {
         if (url.getProtocol().equals("bundle"))
@@ -2461,281 +783,4 @@
         }
         return url;
     }
-
-    static class ToLocalUrlEnumeration implements Enumeration
-    {
-        final Enumeration m_enumeration;
-
-        ToLocalUrlEnumeration(Enumeration enumeration)
-        {
-            m_enumeration = enumeration;
-        }
-
-        public boolean hasMoreElements()
-        {
-            return m_enumeration.hasMoreElements();
-        }
-
-        public Object nextElement()
-        {
-            return convertToLocalUrl((URL) m_enumeration.nextElement());
-        }
-    }
-
-    private static String diagnoseClassLoadError(
-        StatefulResolver resolver, BundleRevisionImpl revision, String name)
-    {
-        // We will try to do some diagnostics here to help the developer
-        // deal with this exception.
-
-        // Get package name.
-        String pkgName = Util.getClassPackage(name);
-        if (pkgName.length() == 0)
-        {
-            return null;
-        }
-
-        // First, get the bundle string of the revision doing the class loader.
-        String importer = revision.getBundle().toString();
-
-        // Next, check to see if the revision imports the package.
-        List<BundleWire> wires = revision.getWires();
-        for (int i = 0; (wires != null) && (i < wires.size()); i++)
-        {
-            if (wires.get(i).getCapability().getNamespace().equals(BundleCapabilityImpl.PACKAGE_NAMESPACE) &&
-                wires.get(i).getCapability().getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR).equals(pkgName))
-            {
-                String exporter = wires.get(i).getProviderWiring().getBundle().toString();
-
-                StringBuffer sb = new StringBuffer("*** Package '");
-                sb.append(pkgName);
-                sb.append("' is imported by bundle ");
-                sb.append(importer);
-                sb.append(" from bundle ");
-                sb.append(exporter);
-                sb.append(", but the exported package from bundle ");
-                sb.append(exporter);
-                sb.append(" does not contain the requested class '");
-                sb.append(name);
-                sb.append("'. Please verify that the class name is correct in the importing bundle ");
-                sb.append(importer);
-                sb.append(" and/or that the exported package is correctly bundled in ");
-                sb.append(exporter);
-                sb.append(". ***");
-
-                return sb.toString();
-            }
-        }
-
-        // Next, check to see if the package was optionally imported and
-        // whether or not there is an exporter available.
-        List<BundleRequirement> reqs = revision.getWiring().getRequirements(null);
-/*
-* TODO: RB - Fix diagnostic message for optional imports.
-        for (int i = 0; (reqs != null) && (i < reqs.length); i++)
-        {
-            if (reqs[i].getName().equals(pkgName) && reqs[i].isOptional())
-            {
-                // Try to see if there is an exporter available.
-                IModule[] exporters = getResolvedExporters(reqs[i], true);
-                exporters = (exporters.length == 0)
-                    ? getUnresolvedExporters(reqs[i], true) : exporters;
-
-                // An exporter might be available, but it may have attributes
-                // that do not match the importer's required attributes, so
-                // check that case by simply looking for an exporter of the
-                // desired package without any attributes.
-                if (exporters.length == 0)
-                {
-                    IRequirement pkgReq = new Requirement(
-                        ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
-                    exporters = getResolvedExporters(pkgReq, true);
-                    exporters = (exporters.length == 0)
-                        ? getUnresolvedExporters(pkgReq, true) : exporters;
-                }
-
-                long expId = (exporters.length == 0)
-                    ? -1 : Util.getBundleIdFromModuleId(exporters[0].getId());
-
-                StringBuffer sb = new StringBuffer("*** Class '");
-                sb.append(name);
-                sb.append("' was not found, but this is likely normal since package '");
-                sb.append(pkgName);
-                sb.append("' is optionally imported by bundle ");
-                sb.append(impId);
-                sb.append(".");
-                if (exporters.length > 0)
-                {
-                    sb.append(" However, bundle ");
-                    sb.append(expId);
-                    if (reqs[i].isSatisfied(
-                        Util.getExportPackage(exporters[0], reqs[i].getName())))
-                    {
-                        sb.append(" does export this package. Bundle ");
-                        sb.append(expId);
-                        sb.append(" must be installed before bundle ");
-                        sb.append(impId);
-                        sb.append(" is resolved or else the optional import will be ignored.");
-                    }
-                    else
-                    {
-                        sb.append(" does export this package with attributes that do not match.");
-                    }
-                }
-                sb.append(" ***");
-
-                return sb.toString();
-            }
-        }
-*/
-        // Next, check to see if the package is dynamically imported by the revision.
-        if (resolver.isAllowedDynamicImport(revision, pkgName))
-        {
-            // Try to see if there is an exporter available.
-            Map<String, String> dirs = Collections.EMPTY_MAP;
-            Map<String, Object> attrs = new HashMap<String, Object>(1);
-            attrs.put(BundleCapabilityImpl.PACKAGE_ATTR, pkgName);
-            BundleRequirementImpl req = new BundleRequirementImpl(
-                revision, BundleCapabilityImpl.PACKAGE_NAMESPACE, dirs, attrs);
-            Set<BundleCapability> exporters = resolver.getCandidates(req, false);
-
-            BundleRevision provider = null;
-            try
-            {
-                provider = resolver.resolve(revision, pkgName);
-            }
-            catch (Exception ex)
-            {
-                provider = null;
-            }
-
-            String exporter = (exporters.isEmpty())
-                ? null : exporters.iterator().next().getRevision().getBundle().toString();
-
-            StringBuffer sb = new StringBuffer("*** Class '");
-            sb.append(name);
-            sb.append("' was not found, but this is likely normal since package '");
-            sb.append(pkgName);
-            sb.append("' is dynamically imported by bundle ");
-            sb.append(importer);
-            sb.append(".");
-            if ((exporters.size() > 0) && (provider == null))
-            {
-                sb.append(" However, bundle ");
-                sb.append(exporter);
-                sb.append(" does export this package with attributes that do not match.");
-            }
-            sb.append(" ***");
-
-            return sb.toString();
-        }
-
-        // Next, check to see if there are any exporters for the package at all.
-        Map<String, String> dirs = Collections.EMPTY_MAP;
-        Map<String, Object> attrs = new HashMap<String, Object>(1);
-        attrs.put(BundleCapabilityImpl.PACKAGE_ATTR, pkgName);
-        BundleRequirementImpl req = new BundleRequirementImpl(
-            revision, BundleCapabilityImpl.PACKAGE_NAMESPACE, dirs, attrs);
-        Set<BundleCapability> exports = resolver.getCandidates(req, false);
-        if (exports.size() > 0)
-        {
-            boolean classpath = false;
-            try
-            {
-                m_secureAction.getClassLoader(BundleClassLoader.class).loadClass(name);
-                classpath = true;
-            }
-            catch (NoClassDefFoundError err)
-            {
-                // Ignore
-            }
-            catch (Exception ex)
-            {
-                // Ignore
-            }
-
-            String exporter = exports.iterator().next().getRevision().getBundle().toString();
-
-            StringBuffer sb = new StringBuffer("*** Class '");
-            sb.append(name);
-            sb.append("' was not found because bundle ");
-            sb.append(importer);
-            sb.append(" does not import '");
-            sb.append(pkgName);
-            sb.append("' even though bundle ");
-            sb.append(exporter);
-            sb.append(" does export it.");
-            if (classpath)
-            {
-                sb.append(" Additionally, the class is also available from the system class loader. There are two fixes: 1) Add an import for '");
-                sb.append(pkgName);
-                sb.append("' to bundle ");
-                sb.append(importer);
-                sb.append("; imports are necessary for each class directly touched by bundle code or indirectly touched, such as super classes if their methods are used. ");
-                sb.append("2) Add package '");
-                sb.append(pkgName);
-                sb.append("' to the '");
-                sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
-                sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
-            }
-            else
-            {
-                sb.append(" To resolve this issue, add an import for '");
-                sb.append(pkgName);
-                sb.append("' to bundle ");
-                sb.append(importer);
-                sb.append(".");
-            }
-            sb.append(" ***");
-
-            return sb.toString();
-        }
-
-        // Next, try to see if the class is available from the system
-        // class loader.
-        try
-        {
-            m_secureAction.getClassLoader(BundleClassLoader.class).loadClass(name);
-
-            StringBuffer sb = new StringBuffer("*** Package '");
-            sb.append(pkgName);
-            sb.append("' is not imported by bundle ");
-            sb.append(importer);
-            sb.append(", nor is there any bundle that exports package '");
-            sb.append(pkgName);
-            sb.append("'. However, the class '");
-            sb.append(name);
-            sb.append("' is available from the system class loader. There are two fixes: 1) Add package '");
-            sb.append(pkgName);
-            sb.append("' to the '");
-            sb.append(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
-            sb.append("' property and modify bundle ");
-            sb.append(importer);
-            sb.append(" to import this package; this causes the system bundle to export class path packages. 2) Add package '");
-            sb.append(pkgName);
-            sb.append("' to the '");
-            sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
-            sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
-            sb.append(" ***");
-
-            return sb.toString();
-        }
-        catch (Exception ex2)
-        {
-        }
-
-        // Finally, if there are no imports or exports for the package
-        // and it is not available on the system class path, simply
-        // log a message saying so.
-        StringBuffer sb = new StringBuffer("*** Class '");
-        sb.append(name);
-        sb.append("' was not found. Bundle ");
-        sb.append(importer);
-        sb.append(" does not import package '");
-        sb.append(pkgName);
-        sb.append("', nor is the package exported by any other bundle or available from the system class loader.");
-        sb.append(" ***");
-
-        return sb.toString();
-    }
 }
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
new file mode 100644
index 0000000..db4c8cd
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
@@ -0,0 +1,2235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.security.SecureClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import org.apache.felix.framework.Felix.StatefulResolver;
+import org.apache.felix.framework.cache.JarContent;
+import org.apache.felix.framework.resolver.Content;
+import org.apache.felix.framework.resolver.HostedCapability;
+import org.apache.felix.framework.resolver.HostedRequirement;
+import org.apache.felix.framework.resolver.ResolveException;
+import org.apache.felix.framework.resolver.ResolverWire;
+import org.apache.felix.framework.resolver.ResourceNotFoundException;
+import org.apache.felix.framework.util.CompoundEnumeration;
+import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.framework.util.SecureAction;
+import org.apache.felix.framework.util.SecurityManagerEx;
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.framework.util.manifestparser.ManifestParser;
+import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.apache.felix.framework.wiring.BundleCapabilityImpl;
+import org.apache.felix.framework.wiring.BundleRequirementImpl;
+import org.apache.felix.framework.wiring.BundleWireImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.BundleReference;
+import org.osgi.framework.Constants;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+
+public class BundleWiringImpl implements BundleWiring
+{
+    public final static int EAGER_ACTIVATION = 0;
+    public final static int LAZY_ACTIVATION = 1;
+
+    private final Logger m_logger;
+    private final Map m_configMap;
+    private final StatefulResolver m_resolver;
+    private final BundleRevisionImpl m_revision;
+    private final List<BundleRevision> m_fragments;
+    private final List<BundleWire> m_wires;
+    private final Map<String, BundleRevision> m_importedPkgs;
+    private final Map<String, List<BundleRevision>> m_requiredPkgs;
+    private final List<BundleCapability> m_resolvedCaps;
+    private final List<BundleRequirement> m_resolvedReqs;
+    private final List<BundleRequirement> m_resolvedDynamicReqs;
+    private final List<R4Library> m_resolvedNativeLibs;
+    private final Content[] m_contentPath;
+    private final Content[] m_fragmentContents;
+
+    private BundleClassLoader m_classLoader;
+    private boolean m_isActivationTriggered = false;
+    private ProtectionDomain m_protectionDomain = null;
+    private final static SecureAction m_secureAction = new SecureAction();
+
+    // Bundle-specific class loader for boot delegation.
+    private final ClassLoader m_bootClassLoader;
+    // Default class loader for boot delegation.
+    private final static ClassLoader m_defBootClassLoader;
+
+    // Statically define the default class loader for boot delegation.
+    static
+    {
+        ClassLoader cl = null;
+        try
+        {
+            Constructor ctor = m_secureAction.getDeclaredConstructor(
+                SecureClassLoader.class, new Class[] { ClassLoader.class });
+            m_secureAction.setAccesssible(ctor);
+            cl = (ClassLoader) m_secureAction.invoke(ctor, new Object[] { null });
+        }
+        catch (Throwable ex)
+        {
+            // On Android we get an exception if we set the parent class loader
+            // to null, so we will work around that case by setting the parent
+            // class loader to the system class loader in getClassLoader() below.
+            cl = null;
+            System.err.println("Problem creating boot delegation class loader: " + ex);
+        }
+        m_defBootClassLoader = cl;
+    }
+
+    // Boolean flag to enable/disable implicit boot delegation.
+    private final boolean m_implicitBootDelegation;
+    // Boolean flag to enable/disable local URLs.
+    private final boolean m_useLocalURLs;
+
+    // Re-usable security manager for accessing class context.
+    private static SecurityManagerEx m_sm = new SecurityManagerEx();
+
+    // Thread local to detect class loading cycles.
+    private final ThreadLocal m_cycleCheck = new ThreadLocal();
+
+    // Thread local to keep track of deferred activation.
+    private static final ThreadLocal m_deferredActivation = new ThreadLocal();
+
+    // Flag indicating whether we are on an old JVM or not.
+    private volatile static boolean m_isPreJava5 = false;
+
+    BundleWiringImpl(
+        Logger logger, Map configMap, StatefulResolver resolver,
+        BundleRevisionImpl revision, List<BundleRevision> fragments,
+        List<ResolverWire> resolverWires,
+        Map<ResolverWire, Set<String>> requiredPkgWires)
+        throws Exception
+    {
+        m_logger = logger;
+        m_configMap = configMap;
+        m_resolver = resolver;
+        m_revision = revision;
+
+        List<BundleWire> wires = new ArrayList<BundleWire>(resolverWires.size());
+        Map<String, BundleRevision> importedPkgs =
+            new HashMap<String, BundleRevision>();
+        Map<String, List<BundleRevision>> requiredPkgs =
+            new HashMap<String, List<BundleRevision>>();
+
+        for (ResolverWire rw : resolverWires)
+        {
+            wires.add(
+                new BundleWireImpl(
+                    rw.getRequirer(),
+                    rw.getRequirement(),
+                    rw.getProvider(),
+                    rw.getCapability()));
+
+            if (Util.isFragment(m_revision))
+            {
+                m_logger.log(
+                    Logger.LOG_DEBUG,
+                    "FRAGMENT WIRE: "
+                    + this + " -> hosted by -> " + rw.getProvider());
+            }
+            else
+            {
+                m_logger.log(Logger.LOG_DEBUG, "WIRE: " + rw);
+
+                if (rw.getCapability().getNamespace()
+                    .equals(BundleCapabilityImpl.PACKAGE_NAMESPACE))
+                {
+                    ((BundleRevisionImpl) rw.getProvider()).addDependentImporter(m_revision);
+
+                    importedPkgs.put(
+                        (String) rw.getCapability().getAttributes()
+                            .get(BundleCapabilityImpl.PACKAGE_ATTR),
+                        rw.getProvider());
+                }
+                else if (rw.getCapability().getNamespace()
+                    .equals(BundleCapabilityImpl.BUNDLE_NAMESPACE))
+                {
+                    ((BundleRevisionImpl) rw.getProvider()).addDependentRequirer(m_revision);
+
+                    for (String pkgName : requiredPkgWires.get(rw))
+                    {
+                        List<BundleRevision> revs = requiredPkgs.get(pkgName);
+                        if (revs != null)
+                        {
+                            revs.add(rw.getProvider());
+                        }
+                        else
+                        {
+                            revs = new ArrayList<BundleRevision>();
+                            revs.add(rw.getProvider());
+                            requiredPkgs.put(pkgName, revs);
+                        }
+                    }
+                }
+            }
+        }
+        m_wires = wires;
+        m_requiredPkgs = requiredPkgs;
+        m_importedPkgs = importedPkgs;
+
+        // We need to sort the fragments and add ourself as a dependent of each one.
+        // We also need to create an array of fragment contents to attach to our
+        // content path.
+        Content[] fragmentContents = null;
+        if (fragments != null)
+        {
+            // Sort fragments according to ID order, if necessary.
+            // Note that this sort order isn't 100% correct since
+            // it uses a string, but it is likely close enough and
+            // avoids having to create more objects.
+            if (fragments.size() > 1)
+            {
+                SortedMap<String, BundleRevision> sorted = new TreeMap<String, BundleRevision>();
+                for (BundleRevision f : fragments)
+                {
+                    sorted.put(((BundleRevisionImpl) f).getId(), f);
+                }
+                fragments = new ArrayList(sorted.values());
+            }
+            fragmentContents = new Content[fragments.size()];
+            for (int i = 0; (fragments != null) && (i < fragments.size()); i++)
+            {
+                fragmentContents[i] =
+                    ((BundleRevisionImpl) fragments.get(i)).getContent()
+                        .getEntryAsContent(FelixConstants.CLASS_PATH_DOT);
+            }
+        }
+        m_fragments = fragments;
+        m_fragmentContents = fragmentContents;
+
+        // Recalculate the content path for the new fragments.
+        m_contentPath = initializeContentPath();
+
+        List<BundleCapability> capList = (m_revision.getDeclaredCapabilities(null) == null)
+            ? new ArrayList<BundleCapability>()
+            : new ArrayList<BundleCapability>(m_revision.getDeclaredCapabilities(null));
+        for (int fragIdx = 0;
+            (m_fragments != null) && (fragIdx < m_fragments.size());
+            fragIdx++)
+        {
+            List<BundleCapability> caps =
+                m_fragments.get(fragIdx).getDeclaredCapabilities(null);
+            for (int capIdx = 0;
+                (caps != null) && (capIdx < caps.size());
+                capIdx++)
+            {
+                if (caps.get(capIdx).getNamespace().equals(
+                    BundleCapabilityImpl.PACKAGE_NAMESPACE))
+                {
+                    capList.add(
+                        new HostedCapability(
+                            m_revision, (BundleCapabilityImpl) caps.get(capIdx)));
+                }
+            }
+        }
+        m_resolvedCaps = Collections.unmodifiableList(capList);
+
+        List<BundleRequirement> reqList = (m_revision.getDeclaredRequirements(null) == null)
+            ? new ArrayList() : new ArrayList(m_revision.getDeclaredRequirements(null));
+        for (int fragIdx = 0;
+            (m_fragments != null) && (fragIdx < m_fragments.size());
+            fragIdx++)
+        {
+            List<BundleRequirement> reqs =
+                m_fragments.get(fragIdx).getDeclaredRequirements(null);
+            for (int reqIdx = 0;
+                (reqs != null) && (reqIdx < reqs.size());
+                reqIdx++)
+            {
+                if (reqs.get(reqIdx).getNamespace().equals(
+                        BundleCapabilityImpl.PACKAGE_NAMESPACE)
+                    || reqs.get(reqIdx).getNamespace().equals(
+                        BundleCapabilityImpl.BUNDLE_NAMESPACE))
+                {
+                    reqList.add(
+                        new HostedRequirement(
+                            m_revision, (BundleRequirementImpl) reqs.get(reqIdx)));
+                }
+            }
+        }
+        m_resolvedReqs = Collections.unmodifiableList(reqList);
+
+        List<BundleRequirement> dynReqList = (m_revision.getDeclaredDynamicRequirements() == null)
+            ? new ArrayList()
+            : new ArrayList(m_revision.getDeclaredDynamicRequirements());
+        for (int fragIdx = 0;
+            (m_fragments != null) && (fragIdx < m_fragments.size());
+            fragIdx++)
+        {
+            List<BundleRequirement> reqs =
+                ((BundleRevisionImpl) m_fragments.get(fragIdx))
+                    .getDeclaredDynamicRequirements();
+            for (int reqIdx = 0;
+                (reqs != null) && (reqIdx < reqs.size());
+                reqIdx++)
+            {
+                if (reqs.get(reqIdx).getNamespace().equals(
+                    BundleCapabilityImpl.PACKAGE_NAMESPACE))
+                {
+                    dynReqList.add(reqs.get(reqIdx));
+                }
+            }
+        }
+        m_resolvedDynamicReqs = Collections.unmodifiableList(dynReqList);
+
+        List<R4Library> libList = (m_revision.getDeclaredNativeLibraries() == null)
+            ? new ArrayList<R4Library>()
+            : new ArrayList<R4Library>(m_revision.getDeclaredNativeLibraries());
+        for (int fragIdx = 0;
+            (m_fragments != null) && (fragIdx < m_fragments.size());
+            fragIdx++)
+        {
+            List<R4Library> libs =
+                ((BundleRevisionImpl) m_fragments.get(fragIdx))
+                    .getDeclaredNativeLibraries();
+            for (int reqIdx = 0;
+                (libs != null) && (reqIdx < libs.size());
+                reqIdx++)
+            {
+                libList.add(libs.get(reqIdx));
+            }
+        }
+        // We need to return null here if we don't have any libraries, since a
+        // zero-length array is used to indicate that matching native libraries
+        // could not be found when resolving the bundle.
+        m_resolvedNativeLibs = (libList.isEmpty())
+            ? null
+            : Collections.unmodifiableList(libList);
+
+        ClassLoader bootLoader = m_defBootClassLoader;
+        if (revision.getBundle().getBundleId() != 0)
+        {
+            Object map = m_configMap.get(FelixConstants.BOOT_CLASSLOADERS_PROP);
+            if (map instanceof Map)
+            {
+                Object l = ((Map) map).get(m_revision.getBundle());
+                if (l instanceof ClassLoader)
+                {
+                    bootLoader = (ClassLoader) l;
+                }
+            }
+        }
+        m_bootClassLoader = bootLoader;
+
+        m_implicitBootDelegation =
+            (m_configMap.get(FelixConstants.IMPLICIT_BOOT_DELEGATION_PROP) == null)
+            || Boolean.valueOf(
+                (String) m_configMap.get(
+                    FelixConstants.IMPLICIT_BOOT_DELEGATION_PROP)).booleanValue();
+
+        m_useLocalURLs =
+            (m_configMap.get(FelixConstants.USE_LOCALURLS_PROP) == null)
+                ? false : true;
+    }
+
+    public void dispose()
+    {
+        if (!Util.isFragment(m_revision) && (m_wires != null))
+        {
+            for (BundleWire bw : m_wires)
+            {
+                if (bw.getProviderWiring() != null)
+                {
+                    if (bw.getCapability().getNamespace()
+                        .equals(BundleCapabilityImpl.PACKAGE_NAMESPACE))
+                    {
+                        ((BundleRevisionImpl) bw.getProviderWiring().getRevision())
+                            .removeDependentImporter(m_revision);
+                    }
+                    else if (bw.getCapability().getNamespace()
+                        .equals(BundleCapabilityImpl.BUNDLE_NAMESPACE))
+                    {
+                        ((BundleRevisionImpl) bw.getProviderWiring().getRevision())
+                            .removeDependentRequirer(m_revision);
+                    }
+                }
+            }
+        }
+
+        for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
+        {
+            m_contentPath[i].close();
+        }
+        for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
+        {
+            m_fragmentContents[i].close();
+        }
+        m_classLoader = null;
+    }
+
+    private Content[] initializeContentPath() throws Exception
+    {
+        List contentList = new ArrayList();
+        calculateContentPath(m_revision, m_revision.getContent(), contentList, true);
+        for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
+        {
+            calculateContentPath(m_fragments.get(i), m_fragmentContents[i], contentList, false);
+        }
+        return (Content[]) contentList.toArray(new Content[contentList.size()]);
+    }
+
+    private List calculateContentPath(
+        BundleRevision revision, Content content, List contentList, boolean searchFragments)
+        throws Exception
+    {
+        // Creating the content path entails examining the bundle's
+        // class path to determine whether the bundle JAR file itself
+        // is on the bundle's class path and then creating content
+        // objects for everything on the class path.
+
+        // Create a list to contain the content path for the specified content.
+        List localContentList = new ArrayList();
+
+        // Find class path meta-data.
+        String classPath = (String) ((BundleRevisionImpl) revision)
+            .getHeaders().get(FelixConstants.BUNDLE_CLASSPATH);
+        // Parse the class path into strings.
+        List<String> classPathStrings = ManifestParser.parseDelimitedString(
+            classPath, FelixConstants.CLASS_PATH_SEPARATOR);
+
+        if (classPathStrings == null)
+        {
+            classPathStrings = new ArrayList<String>(0);
+        }
+
+        // Create the bundles class path.
+        for (int i = 0; i < classPathStrings.size(); i++)
+        {
+            // Remove any leading slash, since all bundle class path
+            // entries are relative to the root of the bundle.
+            classPathStrings.set(i, (classPathStrings.get(i).startsWith("/"))
+                ? classPathStrings.get(i).substring(1)
+                : classPathStrings.get(i));
+
+            // Check for the bundle itself on the class path.
+            if (classPathStrings.get(i).equals(FelixConstants.CLASS_PATH_DOT))
+            {
+                localContentList.add(content);
+            }
+            else
+            {
+                // Try to find the embedded class path entry in the current
+                // content.
+                Content embeddedContent = content.getEntryAsContent(classPathStrings.get(i));
+                // If the embedded class path entry was not found, it might be
+                // in one of the fragments if the current content is the bundle,
+                // so try to search the fragments if necessary.
+                for (int fragIdx = 0;
+                    searchFragments && (embeddedContent == null)
+                        && (m_fragmentContents != null) && (fragIdx < m_fragmentContents.length);
+                    fragIdx++)
+                {
+                    embeddedContent =
+                        m_fragmentContents[fragIdx].getEntryAsContent(classPathStrings.get(i));
+                }
+                // If we found the embedded content, then add it to the
+                // class path content list.
+                if (embeddedContent != null)
+                {
+                    localContentList.add(embeddedContent);
+                }
+                else
+                {
+// TODO: FRAMEWORK - Per the spec, this should fire a FrameworkEvent.INFO event;
+//       need to create an "Eventer" class like "Logger" perhaps.
+                    m_logger.log(m_revision.getBundle(), Logger.LOG_INFO,
+                        "Class path entry not found: "
+                        + classPathStrings.get(i));
+                }
+            }
+        }
+
+        // If there is nothing on the class path, then include
+        // "." by default, as per the spec.
+        if (localContentList.isEmpty())
+        {
+            localContentList.add(content);
+        }
+
+        // Now add the local contents to the global content list and return it.
+        contentList.addAll(localContentList);
+        return contentList;
+    }
+
+// TODO: OSGi R4.3 - This really shouldn't be public, but it is needed by the
+//       resolver to determine if a bundle can dynamically import.
+    public synchronized boolean hasPackageSource(String pkgName)
+    {
+        return (m_importedPkgs.containsKey(pkgName) || m_requiredPkgs.containsKey(pkgName));
+    }
+
+// TODO: OSGi R4.3 - This really shouldn't be public, but it is needed by the
+//       to implement dynamic imports.
+    public synchronized BundleRevision getImportedPackageSource(String pkgName)
+    {
+        return m_importedPkgs.get(pkgName);
+    }
+
+    public List<BundleRevision> getFragments()
+    {
+        return m_fragments;
+    }
+
+    public boolean isCurrent()
+    {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    public boolean isInUse()
+    {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    public List<BundleCapability> getCapabilities(String namespace)
+    {
+        List<BundleCapability> result = m_resolvedCaps;
+        if (namespace != null)
+        {
+            result = new ArrayList<BundleCapability>();
+            for (BundleCapability cap : m_resolvedCaps)
+            {
+                if (cap.getNamespace().equals(namespace))
+                {
+                    result.add(cap);
+                }
+            }
+        }
+        return result;
+    }
+
+    public List<BundleRequirement> getRequirements(String namespace)
+    {
+
+        List<BundleRequirement> result = m_resolvedReqs;
+        if (namespace != null)
+        {
+            result = new ArrayList<BundleRequirement>();
+            for (BundleRequirement req : m_resolvedReqs)
+            {
+                if (req.getNamespace().equals(namespace))
+                {
+                    result.add(req);
+                }
+            }
+        }
+        return result;
+    }
+
+    public List<BundleRequirement> getDynamicRequirements()
+    {
+        return m_resolvedDynamicReqs;
+    }
+
+    public List<R4Library> getNativeLibraries()
+    {
+        return m_resolvedNativeLibs;
+    }
+
+    public List<BundleWire> getProvidedWires(String namespace)
+    {
+// TODO: OSGI R4.3 - IMPLEMENT THIS!!
+        return Collections.EMPTY_LIST;
+    }
+
+    public List<BundleWire> getRequiredWires(String namespace)
+    {
+        return m_wires;
+    }
+
+    public synchronized void addDynamicWire(ResolverWire rw)
+    {
+        // This not only sets the wires for the module, but it also records
+        // the dependencies this module has on other modules (i.e., the provider
+        // end of the wire) to simplify bookkeeping.
+
+        BundleWire wire = new BundleWireImpl(
+            rw.getRequirer(),
+            rw.getRequirement(),
+            rw.getProvider(),
+            rw.getCapability());
+        m_wires.add(wire);
+        m_importedPkgs.put(
+            (String) wire.getCapability().getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR),
+            rw.getProvider());
+    }
+
+    public BundleRevision getRevision()
+    {
+        return m_revision;
+    }
+
+    public synchronized ClassLoader getClassLoader()
+    {
+        if (m_classLoader == null)
+        {
+            // Determine which class loader to use based on which
+            // Java platform we are running on.
+            Class clazz;
+            if (m_isPreJava5)
+            {
+                clazz = BundleClassLoader.class;
+            }
+            else
+            {
+                try
+                {
+                    clazz = BundleClassLoaderJava5.class;
+                }
+                catch (Throwable th)
+                {
+                    // If we are on pre-Java5 then we will get a verify error
+                    // here since we try to override a getResources() which is
+                    // a final method in pre-Java5.
+                    m_isPreJava5 = true;
+                    clazz = BundleClassLoader.class;
+                }
+            }
+
+            // Use SecureAction to create the class loader if security is
+            // enabled; otherwise, create it directly.
+            try
+            {
+                Constructor ctor = (Constructor) m_secureAction.getConstructor(
+                    clazz, new Class[] { BundleWiringImpl.class, ClassLoader.class });
+                m_classLoader = (BundleClassLoader)
+                    m_secureAction.invoke(ctor,
+                    new Object[] { this, determineParentClassLoader() });
+            }
+            catch (Exception ex)
+            {
+                throw new RuntimeException("Unable to create module class loader: "
+                    + ex.getMessage() + " [" + ex.getClass().getName() + "]");
+            }
+        }
+        return m_classLoader;
+    }
+
+    public List<URL> findEntries(String path, String filePattern, int options)
+    {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    public Collection<String> listResources(String path, String filePattern, int options)
+    {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    public Bundle getBundle()
+    {
+        return m_revision.getBundle();
+    }
+
+    //
+    // Class loader implementation methods.
+    //
+
+    public URL getLocalURL(int index, String urlPath)
+    {
+        if (urlPath.startsWith("/"))
+        {
+            urlPath = urlPath.substring(1);
+        }
+        if (index == 0)
+        {
+            return m_revision.getContent().getEntryAsURL(urlPath);
+        }
+        return m_contentPath[index - 1].getEntryAsURL(urlPath);
+    }
+
+    private URL createURL(int port, 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(null,
+                FelixConstants.BUNDLE_URL_PROTOCOL + "://" +
+                m_revision.getId() + ":" + port + path, m_revision.getURLStreamHandler());
+        }
+        catch (MalformedURLException ex)
+        {
+            m_logger.log(m_revision.getBundle(),
+                Logger.LOG_ERROR,
+                "Unable to create resource URL.",
+                ex);
+        }
+        return null;
+    }
+
+    URL getResourceLocal(String name)
+    {
+        URL url = null;
+
+        // Remove leading slash, if present, but special case
+        // "/" so that it returns a root URL...this isn't very
+        // clean or meaninful, but the Spring guys want it.
+        if (name.equals("/"))
+        {
+            // Just pick a class path index since it doesn't really matter.
+            url = createURL(1, name);
+        }
+        else if (name.startsWith("/"))
+        {
+            name = name.substring(1);
+        }
+
+        // Check the module class path.
+        for (int i = 0;
+            (url == null) &&
+            (i < m_contentPath.length); i++)
+        {
+            if (m_contentPath[i].hasEntry(name))
+            {
+                url = createURL(i + 1, name);
+            }
+        }
+
+        return url;
+    }
+
+    public Enumeration getResourcesByDelegation(String name)
+    {
+        Set requestSet = (Set) m_cycleCheck.get();
+        if (requestSet == null)
+        {
+            requestSet = new HashSet();
+            m_cycleCheck.set(requestSet);
+        }
+        if (!requestSet.contains(name))
+        {
+            requestSet.add(name);
+            try
+            {
+                return findResourcesByDelegation(name);
+            }
+            finally
+            {
+                requestSet.remove(name);
+            }
+        }
+
+        return null;
+    }
+
+    private Enumeration findResourcesByDelegation(String name)
+    {
+        Enumeration urls = null;
+        List completeUrlList = new ArrayList();
+
+        // First, try to resolve the originating module.
+        try
+        {
+            m_resolver.resolve(m_revision);
+        }
+        catch (ResolveException ex)
+        {
+            // The spec states that if the bundle cannot be resolved, then
+            // only the local bundle's resources should be searched. So we
+            // will ask the module's own class path.
+            return getResourcesLocal(name);
+        }
+
+        // Get the package of the target class/resource.
+        String pkgName = Util.getResourcePackage(name);
+
+        // Delegate any packages listed in the boot delegation
+        // property to the parent class loader.
+        if (shouldBootDelegate(pkgName))
+        {
+            try
+            {
+                // Get the appropriate class loader for delegation.
+                ClassLoader bdcl = getBootDelegationClassLoader();
+                urls = bdcl.getResources(name);
+            }
+            catch (IOException ex)
+            {
+                // This shouldn't happen and even if it does, there
+                // is nothing we can do, so just ignore it.
+            }
+            // If this is a java.* package, then always terminate the
+            // search; otherwise, continue to look locally.
+            if (pkgName.startsWith("java."))
+            {
+                return urls;
+            }
+
+            completeUrlList.add(urls);
+        }
+
+        // Look in the revisions's imported packages. If the package is
+        // imported, then we stop searching no matter the result since
+        // imported packages cannot be split.
+        BundleRevision provider = m_importedPkgs.get(pkgName);
+        if (provider != null)
+        {
+            // Delegate to the provider revision.
+            urls = ((BundleWiringImpl) provider.getWiring()).getResourcesByDelegation(name);
+
+            // If we find any resources, then add them.
+            if ((urls != null) && (urls.hasMoreElements()))
+            {
+                completeUrlList.add(urls);
+            }
+
+            // Always return here since imported packages cannot be split
+            // across required bundles or the revision's content.
+            return new CompoundEnumeration((Enumeration[])
+                completeUrlList.toArray(new Enumeration[completeUrlList.size()]));
+        }
+
+        // See whether we can get the resource from the required bundles and
+        // regardless of whether or not this is the case continue to the next
+        // step potentially passing on the result of this search (if any).
+        List<BundleRevision> providers = m_requiredPkgs.get(pkgName);
+        if (providers != null)
+        {
+            for (BundleRevision p : providers)
+            {
+                // Delegate to the provider revision.
+                urls = ((BundleWiringImpl) p.getWiring()).getResourcesByDelegation(name);
+
+                // If we find any resources, then add them.
+                if ((urls != null) && (urls.hasMoreElements()))
+                {
+                    completeUrlList.add(urls);
+                }
+
+                // Do not return here, since required packages can be split
+                // across the revision's content.
+            }
+        }
+
+        // Try the module's own class path. If we can find the resource then
+        // return it together with the results from the other searches else
+        // try to look into the dynamic imports.
+        urls = getResourcesLocal(name);
+        if ((urls != null) && (urls.hasMoreElements()))
+        {
+            completeUrlList.add(urls);
+        }
+        else
+        {
+            // If not found, then try the module's dynamic imports.
+            // At this point, the module's imports were searched and so was the
+            // the module's content. Now we make an attempt to load the
+            // class/resource via a dynamic import, if possible.
+            try
+            {
+                provider = m_resolver.resolve(m_revision, pkgName);
+            }
+            catch (ResolveException ex)
+            {
+                // Ignore this since it is likely normal.
+            }
+            if (provider != null)
+            {
+                // Delegate to the provider revision.
+                urls = ((BundleWiringImpl) provider.getWiring()).getResourcesByDelegation(name);
+
+                // If we find any resources, then add them.
+                if ((urls != null) && (urls.hasMoreElements()))
+                {
+                    completeUrlList.add(urls);
+                }
+            }
+        }
+
+        return new CompoundEnumeration((Enumeration[])
+            completeUrlList.toArray(new Enumeration[completeUrlList.size()]));
+    }
+
+    private Enumeration getResourcesLocal(String name)
+    {
+        List l = new ArrayList();
+
+        // Special case "/" so that it returns a root URLs for
+        // each bundle class path entry...this isn't very
+        // clean or meaningful, but the Spring guys want it.
+        if (name.equals("/"))
+        {
+            for (int i = 0; i < m_contentPath.length; i++)
+            {
+                l.add(createURL(i + 1, name));
+            }
+        }
+        else
+        {
+            // Remove leading slash, if present.
+            if (name.startsWith("/"))
+            {
+                name = name.substring(1);
+            }
+
+            // Check the module class path.
+            for (int i = 0; i < m_contentPath.length; i++)
+            {
+                if (m_contentPath[i].hasEntry(name))
+                {
+                    // Use the class path index + 1 for creating the path so
+                    // that we can differentiate between module content URLs
+                    // (where the path will start with 0) and module class
+                    // path URLs.
+                    l.add(createURL(i + 1, name));
+                }
+            }
+        }
+
+        return Collections.enumeration(l);
+    }
+
+    private ClassLoader determineParentClassLoader()
+    {
+        // Determine the class loader's parent based on the
+        // configuration property; use boot class loader by
+        // default.
+        String cfg = (String) m_configMap.get(Constants.FRAMEWORK_BUNDLE_PARENT);
+        cfg = (cfg == null) ? Constants.FRAMEWORK_BUNDLE_PARENT_BOOT : cfg;
+        final ClassLoader parent;
+        if (cfg.equalsIgnoreCase(Constants.FRAMEWORK_BUNDLE_PARENT_APP))
+        {
+            parent = m_secureAction.getSystemClassLoader();
+        }
+        else if (cfg.equalsIgnoreCase(Constants.FRAMEWORK_BUNDLE_PARENT_EXT))
+        {
+            parent = m_secureAction.getParentClassLoader(m_secureAction.getSystemClassLoader());
+        }
+        else if (cfg.equalsIgnoreCase(Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK))
+        {
+            parent = m_secureAction.getClassLoader(BundleRevisionImpl.class);
+        }
+        // On Android we cannot set the parent class loader to be null, so
+        // we special case that situation here and set it to the system
+        // class loader by default instead, which is not really spec.
+        else if (m_bootClassLoader == null)
+        {
+            parent = m_secureAction.getSystemClassLoader();
+        }
+        else
+        {
+            parent = null;
+        }
+        return parent;
+    }
+
+    boolean shouldBootDelegate(String pkgName)
+    {
+        // Always boot delegate if the bundle has a configured
+        // boot class loader.
+        if (m_bootClassLoader != m_defBootClassLoader)
+        {
+            return true;
+        }
+
+        boolean result = false;
+
+        // Only consider delegation if we have a package name, since
+        // we don't want to promote the default package. The spec does
+        // not take a stand on this issue.
+        if (pkgName.length() > 0)
+        {
+            for (int i = 0; !result && (i < m_revision.getBootDelegationPackages().length); i++)
+            {
+                // Check if the boot package is wildcarded.
+                // A wildcarded boot package will be in the form "foo.",
+                // so a matching subpackage will start with "foo.", e.g.,
+                // "foo.bar".
+                if (m_revision.getBootDelegationPackageWildcards()[i]
+                    && pkgName.startsWith(m_revision.getBootDelegationPackages()[i]))
+                {
+                    return true;
+                }
+                // If not wildcarded, then check for an exact match.
+                else if (m_revision.getBootDelegationPackages()[i].equals(pkgName))
+                {
+                    return true;
+                }
+            }
+        }
+
+        return result;
+    }
+
+    ClassLoader getBootDelegationClassLoader()
+    {
+        // Get the appropriate class loader for delegation.
+        ClassLoader parent = (m_classLoader == null)
+            ? determineParentClassLoader() : m_classLoader.getParent();
+        return (parent == null) ? m_bootClassLoader : parent;
+    }
+
+    private static final Constructor m_dexFileClassConstructor;
+    private static final Method m_dexFileClassLoadDex;
+    private static final Method m_dexFileClassLoadClass;
+
+    static
+    {
+        Constructor dexFileClassConstructor = null;
+        Method dexFileClassLoadDex = null;
+        Method dexFileClassLoadClass = null;
+        try
+        {
+            Class dexFileClass;
+            try
+            {
+                dexFileClass = Class.forName("dalvik.system.DexFile");
+            }
+            catch (Exception ex)
+            {
+                dexFileClass = Class.forName("android.dalvik.DexFile");
+            }
+
+            try
+            {
+                dexFileClassLoadDex = dexFileClass.getMethod("loadDex", 
+                    new Class[]{String.class, String.class, Integer.TYPE});
+            }
+            catch (Exception ex)
+            {
+                // Nothing we need to do 
+            }
+            dexFileClassConstructor = dexFileClass.getConstructor(
+                new Class[] { java.io.File.class });
+            dexFileClassLoadClass = dexFileClass.getMethod("loadClass",
+                new Class[] { String.class, ClassLoader.class });
+        }
+        catch (Throwable ex)
+        {
+           dexFileClassConstructor = null;
+           dexFileClassLoadDex = null;
+           dexFileClassLoadClass = null;
+        }
+        m_dexFileClassConstructor = dexFileClassConstructor;
+        m_dexFileClassLoadDex= dexFileClassLoadDex;
+        m_dexFileClassLoadClass = dexFileClassLoadClass;
+    }
+
+    public Class getClassByDelegation(String name) throws ClassNotFoundException
+    {
+        // We do not call getClassLoader().loadClass() for arrays because
+        // it does not correctly handle array types, which is necessary in
+        // cases like deserialization using a wrapper class loader.
+        if ((name != null) && (name.length() > 0) && (name.charAt(0) == '['))
+        {
+            return Class.forName(name, false, getClassLoader());
+        }
+        return getClassLoader().loadClass(name);
+    }
+
+    public URL getResourceByDelegation(String name)
+    {
+        try
+        {
+            return (URL) findClassOrResourceByDelegation(name, false);
+        }
+        catch (ClassNotFoundException ex)
+        {
+            // This should never be thrown because we are loading resources.
+        }
+        catch (ResourceNotFoundException ex)
+        {
+            m_logger.log(m_revision.getBundle(),
+                Logger.LOG_DEBUG,
+                ex.getMessage());
+        }
+        return null;
+    }
+
+    private Object findClassOrResourceByDelegation(String name, boolean isClass)
+        throws ClassNotFoundException, ResourceNotFoundException
+    {
+        Object result = null;
+
+        Set requestSet = (Set) m_cycleCheck.get();
+        if (requestSet == null)
+        {
+            requestSet = new HashSet();
+            m_cycleCheck.set(requestSet);
+        }
+        if (requestSet.add(name))
+        {
+            try
+            {
+                // First, try to resolve the originating revision.
+                m_resolver.resolve(m_revision);
+
+                // Get the package of the target class/resource.
+                String pkgName = (isClass)
+                    ? Util.getClassPackage(name)
+                    : Util.getResourcePackage(name);
+
+                // Delegate any packages listed in the boot delegation
+                // property to the parent class loader.
+                if (shouldBootDelegate(pkgName))
+                {
+                    try
+                    {
+                        // Get the appropriate class loader for delegation.
+                        ClassLoader bdcl = getBootDelegationClassLoader();
+                        result = (isClass)
+                            ? (Object) bdcl.loadClass(name)
+                            : (Object) bdcl.getResource(name);
+                        // If this is a java.* package, then always terminate the
+                        // search; otherwise, continue to look locally if not found.
+                        if (pkgName.startsWith("java.") || (result != null))
+                        {
+                            return result;
+                        }
+                    }
+                    catch (ClassNotFoundException ex)
+                    {
+                        // If this is a java.* package, then always terminate the
+                        // search; otherwise, continue to look locally if not found.
+                        if (pkgName.startsWith("java."))
+                        {
+                            throw ex;
+                        }
+                    }
+                }
+
+                // Look in the revision's imports. Note that the search may
+                // be aborted if this method throws an exception, otherwise
+                // it continues if a null is returned.
+                result = searchImports(pkgName, name, isClass);
+
+                // If not found, try the revision's own class path.
+                if (result == null)
+                {
+                    result = (isClass)
+                        ? (Object) ((BundleClassLoader) getClassLoader()).findClass(name)
+                        : (Object) getResourceLocal(name);
+
+                    // If still not found, then try the revision's dynamic imports.
+                    if (result == null)
+                    {
+                        result = searchDynamicImports(pkgName, name, isClass);
+                    }
+                }
+            }
+            catch (ResolveException ex)
+            {
+                if (isClass)
+                {
+                    // We do not use the resolve exception as the
+                    // cause of the exception, since this would
+                    // potentially leak internal module information.
+                    throw new ClassNotFoundException(
+                        name + " not found because "
+                        + getBundle()
+                        + " cannot resolve: "
+                        + ex.getRequirement());
+                }
+                else
+                {
+                    // The spec states that if the bundle cannot be resolved, then
+                    // only the local bundle's resources should be searched. So we
+                    // will ask the module's own class path.
+                    URL url = getResourceLocal(name);
+                    if (url != null)
+                    {
+                        return url;
+                    }
+
+                    // We need to throw a resource not found exception.
+                    throw new ResourceNotFoundException(
+                        name + " not found because "
+                        + getBundle()
+                        + " cannot resolve: "
+                        + ex.getRequirement());
+                }
+            }
+            finally
+            {
+                requestSet.remove(name);
+            }
+        }
+        else
+        {
+            // If a cycle is detected, we should return null to break the
+            // cycle. This should only ever be return to internal class
+            // loading code and not to the actual instigator of the class load.
+            return null;
+        }
+
+        if (result == null)
+        {
+            if (isClass)
+            {
+                throw new ClassNotFoundException(
+                    name + " not found by " + this.getBundle());
+            }
+            else
+            {
+                throw new ResourceNotFoundException(
+                    name + " not found by " + this.getBundle());
+            }
+        }
+
+        return result;
+    }
+
+    private Object searchImports(String pkgName, String name, boolean isClass)
+        throws ClassNotFoundException, ResourceNotFoundException
+    {
+        // Check if the package is imported.
+        BundleRevision provider = m_importedPkgs.get(pkgName);
+        if (provider != null)
+        {
+            // If we find the class or resource, then return it.
+            Object result = (isClass)
+                ? (Object) ((BundleWiringImpl) provider.getWiring()).getClassByDelegation(name)
+                : (Object) ((BundleWiringImpl) provider.getWiring()).getResourceByDelegation(name);
+            if (result != null)
+            {
+                return result;
+            }
+
+            // If no class was found, then we must throw an exception
+            // since the provider of this package did not contain the
+            // requested class and imported packages are atomic.
+            throw new ClassNotFoundException(name);
+        }
+
+        // Check if the package is required.
+        List<BundleRevision> providers = m_requiredPkgs.get(pkgName);
+        if (providers != null)
+        {
+            for (BundleRevision p : providers)
+            {
+                // If we find the class or resource, then return it.
+                try
+                {
+                    Object result = (isClass)
+                        ? (Object) ((BundleWiringImpl) p.getWiring()).getClassByDelegation(name)
+                        : (Object) ((BundleWiringImpl) p.getWiring()).getResourceByDelegation(name);
+                    if (result != null)
+                    {
+                        return result;
+                    }
+                }
+                catch (ClassNotFoundException ex)
+                {
+                    // Since required packages can be split, don't throw an
+                    // exception here if it is not found. Instead, we'll just
+                    // continue searching other required bundles and the
+                    // revision's local content.
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private Object searchDynamicImports(
+        final String pkgName, final String name, final boolean isClass)
+        throws ClassNotFoundException, ResourceNotFoundException
+    {
+        // At this point, the module's imports were searched and so was the
+        // the module's content. Now we make an attempt to load the
+        // class/resource via a dynamic import, if possible.
+        BundleRevision provider = null;
+        try
+        {
+            provider = m_resolver.resolve(m_revision, pkgName);
+        }
+        catch (ResolveException ex)
+        {
+            // Ignore this since it is likely normal.
+        }
+
+        // If the dynamic import was successful, then this initial
+        // time we must directly return the result from dynamically
+        // created package sources, but subsequent requests for
+        // classes/resources in the associated package will be
+        // processed as part of normal static imports.
+        if (provider != null)
+        {
+            // Return the class or resource.
+            return (isClass)
+                ? (Object) ((BundleWiringImpl) provider.getWiring()).getClassByDelegation(name)
+                : (Object) ((BundleWiringImpl) provider.getWiring()).getResourceByDelegation(name);
+        }
+
+        // If implicit boot delegation is enabled, then try to guess whether
+        // we should boot delegate.
+        if (m_implicitBootDelegation)
+        {
+            // At this point, the class/resource could not be found by the bundle's
+            // static or dynamic imports, nor its own content. Before we throw
+            // an exception, we will try to determine if the instigator of the
+            // class/resource load was a class from a bundle or not. This is necessary
+            // because the specification mandates that classes on the class path
+            // should be hidden (except for java.*), but it does allow for these
+            // classes/resources to be exposed by the system bundle as an export.
+            // However, in some situations classes on the class path make the faulty
+            // assumption that they can access everything on the class path from
+            // every other class loader that they come in contact with. This is
+            // not true if the class loader in question is from a bundle. Thus,
+            // this code tries to detect that situation. If the class instigating
+            // the load request was NOT from a bundle, then we will make the
+            // assumption that the caller actually wanted to use the parent class
+            // loader and we will delegate to it. If the class was
+            // from a bundle, then we will enforce strict class loading rules
+            // for the bundle and throw an exception.
+
+            // Get the class context to see the classes on the stack.
+            final Class[] classes = m_sm.getClassContext();
+            try
+            {
+                if (System.getSecurityManager() != null)
+                {
+                    return AccessController
+                        .doPrivileged(new PrivilegedExceptionAction()
+                        {
+                            public Object run() throws Exception
+                            {
+                                return doImplicitBootDelegation(classes, name,
+                                    isClass);
+                            }
+                        });
+                }
+                else
+                {
+                    return doImplicitBootDelegation(classes, name, isClass);
+                }
+            }
+            catch (PrivilegedActionException ex)
+            {
+                Exception cause = ex.getException();
+                if (cause instanceof ClassNotFoundException)
+                {
+                    throw (ClassNotFoundException) cause;
+                }
+                else
+                {
+                    throw (ResourceNotFoundException) cause;
+                }
+            }
+        }
+        return null;
+    }
+
+    private Object doImplicitBootDelegation(Class[] classes, String name, boolean isClass)
+        throws ClassNotFoundException, ResourceNotFoundException
+    {
+        // Start from 1 to skip security manager class.
+        for (int i = 1; i < classes.length; i++)
+        {
+            // Find the first class on the call stack that is not from
+            // the class loader that loaded the Felix classes or is not
+            // a class loader or class itself, because we want to ignore
+            // calls to ClassLoader.loadClass() and Class.forName() since
+            // we are trying to find out who instigated the class load.
+            // Also ignore inner classes of class loaders, since we can
+            // assume they are a class loader too.
+
+            // TODO: FRAMEWORK - This check is a hack and we should see if we can think
+            // of another way to do it, since it won't necessarily work in all situations.
+            // Since Felix uses threads for changing the start level
+            // and refreshing packages, it is possible that there are no
+            // bundle classes on the call stack; therefore, as soon as we
+            // see Thread on the call stack we exit this loop. Other cases
+            // where bundles actually use threads are not an issue because
+            // the bundle classes will be on the call stack before the
+            // Thread class.
+            if (Thread.class.equals(classes[i]))
+            {
+                break;
+            }
+            // Break if the current class came from a bundle, since we should
+            // not implicitly boot delegate in that case.
+            else if (isClassLoadedFromBundleRevision(classes[i]))
+            {
+                break;
+            }
+            // Break if this goes through BundleImpl because it must be a call
+            // to Bundle.loadClass() which should not implicitly boot delegate.
+            else if (BundleImpl.class.equals(classes[i]))
+            {
+                break;
+            }
+            else if (isClassExternal(classes[i]))
+            {
+                try
+                {
+                    // Return the class or resource from the parent class loader.
+                    return (isClass)
+                        ? (Object) m_secureAction.getClassLoader(this.getClass()).loadClass(name)
+                        : (Object) m_secureAction.getClassLoader(this.getClass()).getResource(name);
+                }
+                catch (NoClassDefFoundError ex)
+                {
+                    // Ignore, will return null
+                }
+                break;
+            }
+        }
+
+        return null;
+    }
+
+    private boolean isClassLoadedFromBundleRevision(Class clazz)
+    {
+        // The target class is loaded by a bundle class loader,
+        // then return true.
+        if (BundleClassLoader.class.isInstance(m_secureAction.getClassLoader(clazz)))
+        {
+            return true;
+        }
+
+        // If the target class was loaded from a class loader that
+        // came from a bundle, then return true.
+        ClassLoader last = null;
+        for (ClassLoader cl = m_secureAction.getClassLoader(clazz);
+            (cl != null) && (last != cl);
+            cl = m_secureAction.getClassLoader(cl.getClass()))
+        {
+            last = cl;
+            if (BundleClassLoader.class.isInstance(cl))
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Tries to determine whether the given class is part of the framework or not.
+     * Framework classes include everything in org.apache.felix.framework.* and
+     * org.osgi.framework.*. We also consider ClassLoader and Class to be internal
+     * classes, because they are inserted into the stack trace as a result of
+     * method overloading. Typically, ClassLoader or Class will be mixed in
+     * between framework classes or will be at the point where the class loading
+     * request enters the framework class loading mechanism, which will then be
+     * followed by either bundle or external code, which will then exit our
+     * attempt to determine if we should boot delegate or not. Other standard
+     * class loaders, like URLClassLoader, are considered external classes and
+     * should trigger boot delegation. This means that bundles can create standard
+     * class loaders to get access to boot packages, but this is the standard
+     * behavior of class loaders.
+     * @param clazz the class to determine if it is external or not.
+     * @return <tt>true</tt> if the class is external, otherwise <tt>false</tt>.
+     */
+    private boolean isClassExternal(Class clazz)
+    {
+        if (clazz.getName().startsWith("org.apache.felix.framework."))
+        {
+            return false;
+        }
+        else if (clazz.getName().startsWith("org.osgi.framework."))
+        {
+            return false;
+        }
+        else if (ClassLoader.class.equals(clazz))
+        {
+            return false;
+        }
+        else if (Class.class.equals(clazz))
+        {
+            return false;
+        }
+        return true;
+    }
+
+    synchronized boolean isActivationTriggered()
+    {
+        return m_isActivationTriggered;
+    }
+
+    boolean isActivationTrigger(String pkgName)
+    {
+        List<String> activationIncludes = m_revision.getActivationIncludes();
+        List<String> activationExcludes = m_revision.getActivationExcludes();
+
+        if ((activationIncludes == null) && (activationExcludes == null))
+        {
+            return true;
+        }
+
+        // If there are no include filters then all classes are included
+        // by default, otherwise try to find one match.
+        boolean included = (activationIncludes == null);
+        for (int i = 0;
+            (!included) && (activationIncludes != null) && (i < activationIncludes.size());
+            i++)
+        {
+            included = activationIncludes.get(i).equals(pkgName);
+        }
+
+        // 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) && (activationExcludes != null) && (i < activationExcludes.size());
+            i++)
+        {
+            excluded = activationExcludes.get(i).equals(pkgName);
+        }
+        return included && !excluded;
+    }
+
+    static class ToLocalUrlEnumeration implements Enumeration
+    {
+        final Enumeration m_enumeration;
+
+        ToLocalUrlEnumeration(Enumeration enumeration)
+        {
+            m_enumeration = enumeration;
+        }
+
+        public boolean hasMoreElements()
+        {
+            return m_enumeration.hasMoreElements();
+        }
+
+        public Object nextElement()
+        {
+            return convertToLocalUrl((URL) m_enumeration.nextElement());
+        }
+    }
+
+    public class BundleClassLoaderJava5 extends BundleClassLoader
+    {
+        public BundleClassLoaderJava5(ClassLoader parent)
+        {
+            super(parent);
+        }
+
+        @Override
+        public Enumeration getResources(String name)
+        {
+            Enumeration urls = BundleWiringImpl.this.getResourcesByDelegation(name);
+            if (m_useLocalURLs)
+            {
+                urls = new ToLocalUrlEnumeration(urls);
+            }
+            return urls;
+        }
+
+        @Override
+        protected Enumeration findResources(String name)
+        {
+            return BundleWiringImpl.this.getResourcesLocal(name);
+        }
+    }
+
+    public class BundleClassLoader extends SecureClassLoader implements BundleReference
+    {
+        private final Map m_jarContentToDexFile;
+        private Object[][] m_cachedLibs = new Object[0][];
+        private static final int LIBNAME_IDX = 0;
+        private static final int LIBPATH_IDX = 1;
+
+        public BundleClassLoader(ClassLoader parent)
+        {
+            super(parent);
+            if (m_dexFileClassLoadClass != null)
+            {
+                m_jarContentToDexFile = new HashMap();
+            }
+            else
+            {
+                m_jarContentToDexFile = null;
+            }
+        }
+
+        public Bundle getBundle()
+        {
+            return BundleWiringImpl.this.getBundle();
+        }
+
+        @Override
+        protected Class loadClass(String name, boolean resolve)
+            throws ClassNotFoundException
+        {
+            Class clazz = null;
+
+            // Make sure the class was not already loaded.
+            synchronized (this)
+            {
+                clazz = findLoadedClass(name);
+            }
+
+            if (clazz == null)
+            {
+                try
+                {
+                    clazz = (Class) findClassOrResourceByDelegation(name, true);
+                }
+                catch (ResourceNotFoundException ex)
+                {
+                    // This should never happen since we are asking for a class,
+                    // so just ignore it.
+                }
+                catch (ClassNotFoundException cnfe)
+                {
+                    ClassNotFoundException ex = cnfe;
+                    String msg = name;
+                    if (m_logger.getLogLevel() >= Logger.LOG_DEBUG)
+                    {
+                        msg = diagnoseClassLoadError(m_resolver, m_revision, name);
+                        ex = (msg != null)
+                            ? new ClassNotFoundException(msg, cnfe)
+                            : ex;
+                    }
+                    throw ex;
+                }
+            }
+
+            // Resolve the class and return it.
+            if (resolve)
+            {
+                resolveClass(clazz);
+            }
+            return clazz;
+        }
+
+        @Override
+        protected Class findClass(String name) throws ClassNotFoundException
+        {
+            Class clazz = null;
+
+            // Search for class in bundle revision.
+            if (clazz == null)
+            {
+                String actual = name.replace('.', '/') + ".class";
+
+                byte[] bytes = null;
+
+                // Check the bundle class path.
+                Content content = null;
+                for (int i = 0;
+                    (bytes == null) &&
+                    (i < m_contentPath.length); i++)
+                {
+                    bytes = m_contentPath[i].getEntryAsBytes(actual);
+                    content = m_contentPath[i];
+                }
+
+                if (bytes != null)
+                {
+                    // Get package name.
+                    String pkgName = Util.getClassPackage(name);
+
+                    // Before we actually attempt to define the class, grab
+                    // the lock for this class loader and make sure than no
+                    // other thread has defined this class in the meantime.
+                    synchronized (this)
+                    {
+                        clazz = findLoadedClass(name);
+
+                        if (clazz == null)
+                        {
+                            int activationPolicy = 
+                                ((BundleImpl) getBundle()).isDeclaredActivationPolicyUsed()
+                                ? ((BundleRevisionImpl) ((BundleImpl) getBundle())
+                                    .getCurrentRevision()).getDeclaredActivationPolicy()
+                                : EAGER_ACTIVATION;
+
+                            // If the revision is using deferred activation, then if
+                            // we load this class from this revision we need to activate
+                            // the bundle before returning the class. We will short
+                            // circuit the trigger matching if the trigger is already
+                            // tripped.
+                            boolean isTriggerClass = m_isActivationTriggered
+                                ? false : isActivationTrigger(pkgName);
+                            if (!m_isActivationTriggered
+                                && isTriggerClass
+                                && (activationPolicy == BundleRevisionImpl.LAZY_ACTIVATION)
+                                && (getBundle().getState() == Bundle.STARTING))
+                            {
+                                List deferredList = (List) m_deferredActivation.get();
+                                if (deferredList == null)
+                                {
+                                    deferredList = new ArrayList();
+                                    m_deferredActivation.set(deferredList);
+                                }
+                                deferredList.add(new Object[] { name, getBundle() });
+                            }
+                            // We need to try to define a Package object for the class
+                            // before we call defineClass() if we haven't already
+                            // created it.
+                            if (pkgName.length() > 0)
+                            {
+                                if (getPackage(pkgName) == null)
+                                {
+                                    Object[] params = definePackage(pkgName);
+                                    if (params != null)
+                                    {
+                                        definePackage(
+                                            pkgName,
+                                            (String) params[0],
+                                            (String) params[1],
+                                            (String) params[2],
+                                            (String) params[3],
+                                            (String) params[4],
+                                            (String) params[5],
+                                            null);
+                                    }
+                                    else
+                                    {
+                                        definePackage(pkgName, null, null,
+                                            null, null, null, null, null);
+                                    }
+                                }
+                            }
+
+                            // If we can load the class from a dex file do so
+                            if (content instanceof JarContent)
+                            {
+                                try
+                                {
+                                    clazz = getDexFileClass((JarContent) content, name, this);
+                                }
+                                catch (Exception ex)
+                                {
+                                    // Looks like we can't
+                                }
+                            }
+
+                            if (clazz == null)
+                            {
+                                // If we have a security context, then use it to
+                                // define the class with it for security purposes,
+                                // otherwise define the class without a protection domain.
+                                if (m_protectionDomain != null)
+                                {
+                                    clazz = defineClass(name, bytes, 0, bytes.length,
+                                        m_protectionDomain);
+                                }
+                                else
+                                {
+                                    clazz = defineClass(name, bytes, 0, bytes.length);
+                                }
+                            }
+
+                            // At this point if we have a trigger class, then the deferred
+                            // activation trigger has tripped.
+                            if (!m_isActivationTriggered && isTriggerClass && (clazz != null))
+                            {
+// TODO: OSGi R4.3 - This isn't protected by the correct lock.
+                                m_isActivationTriggered = true;
+                            }
+                        }
+                    }
+
+                    // Perform deferred activation without holding the class loader lock,
+                    // if the class we are returning is the instigating class.
+                    List deferredList = (List) m_deferredActivation.get();
+                    if ((deferredList != null)
+                        && (deferredList.size() > 0)
+                        && ((Object[]) deferredList.get(0))[0].equals(name))
+                    {
+                        for (int i = deferredList.size() - 1; i >= 0; i--)
+                        {
+                            try
+                            {
+                                ((BundleImpl) ((Object[]) deferredList.get(i))[1]).getFramework().activateBundle(
+                                    (BundleImpl) ((Object[]) deferredList.get(i))[1], true);
+                            }
+                            catch (BundleException ex)
+                            {
+                                ex.printStackTrace();
+                            }
+                        }
+                        deferredList.clear();
+                    }
+                }
+            }
+
+            return clazz;
+        }
+
+        private Object[] definePackage(String pkgName)
+        {
+            String spectitle = (String) m_revision.getHeaders().get("Specification-Title");
+            String specversion = (String) m_revision.getHeaders().get("Specification-Version");
+            String specvendor = (String) m_revision.getHeaders().get("Specification-Vendor");
+            String impltitle = (String) m_revision.getHeaders().get("Implementation-Title");
+            String implversion = (String) m_revision.getHeaders().get("Implementation-Version");
+            String implvendor = (String) m_revision.getHeaders().get("Implementation-Vendor");
+            if ((spectitle != null)
+                || (specversion != null)
+                || (specvendor != null)
+                || (impltitle != null)
+                || (implversion != null)
+                || (implvendor != null))
+            {
+                return new Object[] {
+                    spectitle, specversion, specvendor, impltitle, implversion, implvendor
+                };
+            }
+            return null;
+        }
+
+        private Class getDexFileClass(JarContent content, String name, ClassLoader loader)
+            throws Exception
+        {
+            if (m_jarContentToDexFile == null)
+            {
+                return null;
+            }
+
+            Object dexFile = null;
+
+            if (!m_jarContentToDexFile.containsKey(content))
+            {
+                try
+                {
+                    if (m_dexFileClassLoadDex != null)
+                    {
+                        dexFile = m_dexFileClassLoadDex.invoke(null, 
+                            new Object[]{content.getFile().getAbsolutePath(), 
+                                content.getFile().getAbsolutePath() + ".dex", new Integer(0)});
+                    }
+                    else
+                    {
+                        dexFile = m_dexFileClassConstructor.newInstance(
+                            new Object[] { content.getFile() });
+                    }
+                }
+                finally
+                {
+                    m_jarContentToDexFile.put(content, dexFile);
+                }
+            }
+            else
+            {
+                dexFile = m_jarContentToDexFile.get(content);
+            }
+
+            if (dexFile != null)
+            {
+                return (Class) m_dexFileClassLoadClass.invoke(dexFile,
+                    new Object[] { name.replace('.','/'), loader });
+            }
+            return null;
+        }
+
+        @Override
+        public URL getResource(String name)
+        {
+            URL url = BundleWiringImpl.this.getResourceByDelegation(name);
+            if (m_useLocalURLs)
+            {
+                url = convertToLocalUrl(url);
+            }
+            return url;
+        }
+
+        @Override
+        protected URL findResource(String name)
+        {
+            return BundleWiringImpl.this.getResourceLocal(name);
+        }
+
+        // The findResources() method should only look at the revision itself, but
+        // instead it tries to delegate because in Java version prior to 1.5 the
+        // getResources() method was final and could not be overridden. We should
+        // override getResources() like getResource() to make it delegate, but we
+        // can't. As a workaround, we make findResources() delegate instead.
+        @Override
+        protected Enumeration findResources(String name)
+        {
+            Enumeration urls = BundleWiringImpl.this.getResourcesByDelegation(name);
+            if (m_useLocalURLs)
+            {
+                urls = new ToLocalUrlEnumeration(urls);
+            }
+            return urls;
+        }
+
+        @Override
+        protected String findLibrary(String name)
+        {
+            // Remove leading slash, if present.
+            if (name.startsWith("/"))
+            {
+                name = name.substring(1);
+            }
+
+            String result = null;
+            // CONCURRENCY: In the long run, we might want to break this
+            // sync block in two to avoid manipulating the cache while
+            // holding the lock, but for now we will do it the simple way.
+            synchronized (this)
+            {
+                // Check to make sure we haven't already found this library.
+                for (int i = 0; (result == null) && (i < m_cachedLibs.length); i++)
+                {
+                    if (m_cachedLibs[i][LIBNAME_IDX].equals(name))
+                    {
+                        result = (String) m_cachedLibs[i][LIBPATH_IDX];
+                    }
+                }
+
+                // If we don't have a cached result, see if we have a matching
+                // native library.
+                if (result == null)
+                {
+                    List<R4Library> libs = getNativeLibraries();
+                    for (int libIdx = 0; (libs != null) && (libIdx < libs.size()); libIdx++)
+                    {
+                        if (libs.get(libIdx).match(m_configMap, name))
+                        {
+                            // Search bundle content first for native library.
+                            result = m_revision.getContent().getEntryAsNativeLibrary(
+                                libs.get(libIdx).getEntryName());
+                            // If not found, then search fragments in order.
+                            for (int i = 0;
+                                (result == null) && (m_fragmentContents != null)
+                                    && (i < m_fragmentContents.length);
+                                i++)
+                            {
+                                result = m_fragmentContents[i].getEntryAsNativeLibrary(
+                                    libs.get(libIdx).getEntryName());
+                            }
+                        }
+                    }
+
+                    // Remember the result for future requests.
+                    if (result != null)
+                    {
+                        Object[][] tmp = new Object[m_cachedLibs.length + 1][];
+                        System.arraycopy(m_cachedLibs, 0, tmp, 0, m_cachedLibs.length);
+                        tmp[m_cachedLibs.length] = new Object[] { name, result };
+                        m_cachedLibs = tmp;
+                    }
+                }
+            }
+
+            return result;
+        }
+
+        @Override
+        public String toString()
+        {
+            return BundleWiringImpl.this.toString();
+        }
+    }
+
+    static URL convertToLocalUrl(URL url)
+    {
+        if (url.getProtocol().equals("bundle"))
+        {
+            try
+            {
+                url = ((URLHandlersBundleURLConnection)
+                    url.openConnection()).getLocalURL();
+            }
+            catch (IOException ex)
+            {
+                // Ignore and add original url.
+            }
+        }
+        return url;
+    }
+
+    private static String diagnoseClassLoadError(
+        StatefulResolver resolver, BundleRevision revision, String name)
+    {
+        // We will try to do some diagnostics here to help the developer
+        // deal with this exception.
+
+        // Get package name.
+        String pkgName = Util.getClassPackage(name);
+        if (pkgName.length() == 0)
+        {
+            return null;
+        }
+
+        // First, get the bundle string of the revision doing the class loader.
+        String importer = revision.getBundle().toString();
+
+        // Next, check to see if the revision imports the package.
+        List<BundleWire> wires = (revision.getWiring() == null)
+            ? null : revision.getWiring().getProvidedWires(null);
+        for (int i = 0; (wires != null) && (i < wires.size()); i++)
+        {
+            if (wires.get(i).getCapability().getNamespace().equals(BundleCapabilityImpl.PACKAGE_NAMESPACE) &&
+                wires.get(i).getCapability().getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR).equals(pkgName))
+            {
+                String exporter = wires.get(i).getProviderWiring().getBundle().toString();
+
+                StringBuffer sb = new StringBuffer("*** Package '");
+                sb.append(pkgName);
+                sb.append("' is imported by bundle ");
+                sb.append(importer);
+                sb.append(" from bundle ");
+                sb.append(exporter);
+                sb.append(", but the exported package from bundle ");
+                sb.append(exporter);
+                sb.append(" does not contain the requested class '");
+                sb.append(name);
+                sb.append("'. Please verify that the class name is correct in the importing bundle ");
+                sb.append(importer);
+                sb.append(" and/or that the exported package is correctly bundled in ");
+                sb.append(exporter);
+                sb.append(". ***");
+
+                return sb.toString();
+            }
+        }
+
+        // Next, check to see if the package was optionally imported and
+        // whether or not there is an exporter available.
+        List<BundleRequirement> reqs = revision.getWiring().getRequirements(null);
+/*
+* TODO: RB - Fix diagnostic message for optional imports.
+        for (int i = 0; (reqs != null) && (i < reqs.length); i++)
+        {
+            if (reqs[i].getName().equals(pkgName) && reqs[i].isOptional())
+            {
+                // Try to see if there is an exporter available.
+                IModule[] exporters = getResolvedExporters(reqs[i], true);
+                exporters = (exporters.length == 0)
+                    ? getUnresolvedExporters(reqs[i], true) : exporters;
+
+                // An exporter might be available, but it may have attributes
+                // that do not match the importer's required attributes, so
+                // check that case by simply looking for an exporter of the
+                // desired package without any attributes.
+                if (exporters.length == 0)
+                {
+                    IRequirement pkgReq = new Requirement(
+                        ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
+                    exporters = getResolvedExporters(pkgReq, true);
+                    exporters = (exporters.length == 0)
+                        ? getUnresolvedExporters(pkgReq, true) : exporters;
+                }
+
+                long expId = (exporters.length == 0)
+                    ? -1 : Util.getBundleIdFromModuleId(exporters[0].getId());
+
+                StringBuffer sb = new StringBuffer("*** Class '");
+                sb.append(name);
+                sb.append("' was not found, but this is likely normal since package '");
+                sb.append(pkgName);
+                sb.append("' is optionally imported by bundle ");
+                sb.append(impId);
+                sb.append(".");
+                if (exporters.length > 0)
+                {
+                    sb.append(" However, bundle ");
+                    sb.append(expId);
+                    if (reqs[i].isSatisfied(
+                        Util.getExportPackage(exporters[0], reqs[i].getName())))
+                    {
+                        sb.append(" does export this package. Bundle ");
+                        sb.append(expId);
+                        sb.append(" must be installed before bundle ");
+                        sb.append(impId);
+                        sb.append(" is resolved or else the optional import will be ignored.");
+                    }
+                    else
+                    {
+                        sb.append(" does export this package with attributes that do not match.");
+                    }
+                }
+                sb.append(" ***");
+
+                return sb.toString();
+            }
+        }
+*/
+        // Next, check to see if the package is dynamically imported by the revision.
+        if (resolver.isAllowedDynamicImport(revision, pkgName))
+        {
+            // Try to see if there is an exporter available.
+            Map<String, String> dirs = Collections.EMPTY_MAP;
+            Map<String, Object> attrs = new HashMap<String, Object>(1);
+            attrs.put(BundleCapabilityImpl.PACKAGE_ATTR, pkgName);
+            BundleRequirementImpl req = new BundleRequirementImpl(
+                revision, BundleCapabilityImpl.PACKAGE_NAMESPACE, dirs, attrs);
+            Set<BundleCapability> exporters = resolver.getCandidates(req, false);
+
+            BundleRevision provider = null;
+            try
+            {
+                provider = resolver.resolve(revision, pkgName);
+            }
+            catch (Exception ex)
+            {
+                provider = null;
+            }
+
+            String exporter = (exporters.isEmpty())
+                ? null : exporters.iterator().next().getRevision().getBundle().toString();
+
+            StringBuffer sb = new StringBuffer("*** Class '");
+            sb.append(name);
+            sb.append("' was not found, but this is likely normal since package '");
+            sb.append(pkgName);
+            sb.append("' is dynamically imported by bundle ");
+            sb.append(importer);
+            sb.append(".");
+            if ((exporters.size() > 0) && (provider == null))
+            {
+                sb.append(" However, bundle ");
+                sb.append(exporter);
+                sb.append(" does export this package with attributes that do not match.");
+            }
+            sb.append(" ***");
+
+            return sb.toString();
+        }
+
+        // Next, check to see if there are any exporters for the package at all.
+        Map<String, String> dirs = Collections.EMPTY_MAP;
+        Map<String, Object> attrs = new HashMap<String, Object>(1);
+        attrs.put(BundleCapabilityImpl.PACKAGE_ATTR, pkgName);
+        BundleRequirementImpl req = new BundleRequirementImpl(
+            revision, BundleCapabilityImpl.PACKAGE_NAMESPACE, dirs, attrs);
+        Set<BundleCapability> exports = resolver.getCandidates(req, false);
+        if (exports.size() > 0)
+        {
+            boolean classpath = false;
+            try
+            {
+                m_secureAction.getClassLoader(BundleClassLoader.class).loadClass(name);
+                classpath = true;
+            }
+            catch (NoClassDefFoundError err)
+            {
+                // Ignore
+            }
+            catch (Exception ex)
+            {
+                // Ignore
+            }
+
+            String exporter = exports.iterator().next().getRevision().getBundle().toString();
+
+            StringBuffer sb = new StringBuffer("*** Class '");
+            sb.append(name);
+            sb.append("' was not found because bundle ");
+            sb.append(importer);
+            sb.append(" does not import '");
+            sb.append(pkgName);
+            sb.append("' even though bundle ");
+            sb.append(exporter);
+            sb.append(" does export it.");
+            if (classpath)
+            {
+                sb.append(" Additionally, the class is also available from the system class loader. There are two fixes: 1) Add an import for '");
+                sb.append(pkgName);
+                sb.append("' to bundle ");
+                sb.append(importer);
+                sb.append("; imports are necessary for each class directly touched by bundle code or indirectly touched, such as super classes if their methods are used. ");
+                sb.append("2) Add package '");
+                sb.append(pkgName);
+                sb.append("' to the '");
+                sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
+                sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
+            }
+            else
+            {
+                sb.append(" To resolve this issue, add an import for '");
+                sb.append(pkgName);
+                sb.append("' to bundle ");
+                sb.append(importer);
+                sb.append(".");
+            }
+            sb.append(" ***");
+
+            return sb.toString();
+        }
+
+        // Next, try to see if the class is available from the system
+        // class loader.
+        try
+        {
+            m_secureAction.getClassLoader(BundleClassLoader.class).loadClass(name);
+
+            StringBuffer sb = new StringBuffer("*** Package '");
+            sb.append(pkgName);
+            sb.append("' is not imported by bundle ");
+            sb.append(importer);
+            sb.append(", nor is there any bundle that exports package '");
+            sb.append(pkgName);
+            sb.append("'. However, the class '");
+            sb.append(name);
+            sb.append("' is available from the system class loader. There are two fixes: 1) Add package '");
+            sb.append(pkgName);
+            sb.append("' to the '");
+            sb.append(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
+            sb.append("' property and modify bundle ");
+            sb.append(importer);
+            sb.append(" to import this package; this causes the system bundle to export class path packages. 2) Add package '");
+            sb.append(pkgName);
+            sb.append("' to the '");
+            sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
+            sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
+            sb.append(" ***");
+
+            return sb.toString();
+        }
+        catch (Exception ex2)
+        {
+        }
+
+        // Finally, if there are no imports or exports for the package
+        // and it is not available on the system class path, simply
+        // log a message saying so.
+        StringBuffer sb = new StringBuffer("*** Class '");
+        sb.append(name);
+        sb.append("' was not found. Bundle ");
+        sb.append(importer);
+        sb.append(" does not import package '");
+        sb.append(pkgName);
+        sb.append("', nor is the package exported by any other bundle or available from the system class loader.");
+        sb.append(" ***");
+
+        return sb.toString();
+    }
+}
diff --git a/framework/src/main/java/org/apache/felix/framework/EntryFilterEnumeration.java b/framework/src/main/java/org/apache/felix/framework/EntryFilterEnumeration.java
index 51c17f8..7e039c7 100644
--- a/framework/src/main/java/org/apache/felix/framework/EntryFilterEnumeration.java
+++ b/framework/src/main/java/org/apache/felix/framework/EntryFilterEnumeration.java
@@ -43,7 +43,7 @@
     {
         m_bundle = bundle;
         BundleRevision br = m_bundle.getCurrentRevision();
-        List<BundleRevision> fragments = ((BundleRevisionImpl) br).getFragments();
+        List<BundleRevision> fragments = ((BundleWiringImpl) br.getWiring()).getFragments();
         if (includeFragments && (fragments != null))
         {
             m_revisions = new ArrayList(fragments.size() + 1);
diff --git a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
index f463c3a..be07bbc 100644
--- a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
+++ b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
@@ -27,6 +27,7 @@
 import java.security.AccessControlException;
 import java.security.AllPermission;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -36,13 +37,15 @@
 import java.util.Map.Entry;
 import java.util.NoSuchElementException;
 import java.util.Set;
-
 import org.apache.felix.framework.Felix.StatefulResolver;
+
+import org.apache.felix.framework.resolver.ResolverWire;
 import org.apache.felix.framework.util.FelixConstants;
 import org.apache.felix.framework.util.StringMap;
 import org.apache.felix.framework.util.Util;
 import org.apache.felix.framework.util.manifestparser.ManifestParser;
 import org.apache.felix.framework.resolver.Content;
+import org.apache.felix.framework.util.manifestparser.R4Library;
 import org.apache.felix.framework.wiring.BundleCapabilityImpl;
 import org.osgi.framework.AdminPermission;
 import org.osgi.framework.Bundle;
@@ -53,6 +56,7 @@
 import org.osgi.framework.Version;
 import org.osgi.framework.wiring.BundleCapability;
 import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWiring;
 
 /**
  * The ExtensionManager class is used in several ways.
@@ -115,6 +119,7 @@
     }
 
     private final Logger m_logger;
+    private final Map m_configMap;
     private final Map m_headerMap = new StringMap(false);
     private final BundleRevision m_systemBundleRevision;
     private List<BundleCapability> m_capabilities = null;
@@ -130,6 +135,7 @@
     private ExtensionManager()
     {
         m_logger = null;
+        m_configMap = null;
         m_systemBundleRevision = null;
         m_extensions = new ArrayList();
         m_extensionsCache = new Bundle[0];
@@ -148,19 +154,20 @@
      * @param config the configuration to read properties from.
      * @param systemBundleInfo the info to change if we need to add exports.
      */
-    ExtensionManager(Logger logger, Felix felix)
+    ExtensionManager(Logger logger, Map configMap, Felix felix)
     {
+        m_logger = logger;
+        m_configMap = configMap;
         m_systemBundleRevision = new ExtensionManagerRevision(felix);
         m_extensions = null;
         m_extensionsCache = null;
         m_names = null;
         m_sourceToExtensions = null;
-        m_logger = logger;
 
 // TODO: FRAMEWORK - Not all of this stuff really belongs here, probably only exports.
         // Populate system bundle header map.
         m_headerMap.put(FelixConstants.BUNDLE_VERSION,
-            felix.getConfig().get(FelixConstants.FELIX_VERSION_PROPERTY));
+            m_configMap.get(FelixConstants.FELIX_VERSION_PROPERTY));
         m_headerMap.put(FelixConstants.BUNDLE_SYMBOLICNAME,
             FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
         m_headerMap.put(FelixConstants.BUNDLE_NAME, "System Bundle");
@@ -176,21 +183,21 @@
         // We must construct the system bundle's export metadata.
         // Get configuration property that specifies which class path
         // packages should be exported by the system bundle.
-        String syspkgs = (String) felix.getConfig().get(FelixConstants.FRAMEWORK_SYSTEMPACKAGES);
+        String syspkgs = (String) m_configMap.get(FelixConstants.FRAMEWORK_SYSTEMPACKAGES);
         // If no system packages were specified, load our default value.
         syspkgs = (syspkgs == null)
             ? Util.getDefaultProperty(logger, Constants.FRAMEWORK_SYSTEMPACKAGES)
             : syspkgs;
         syspkgs = (syspkgs == null) ? "" : syspkgs;
         // If any extra packages are specified, then append them.
-        String extra = (String) felix.getConfig().get(FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
+        String extra = (String) m_configMap.get(FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
         syspkgs = (extra == null) ? syspkgs : syspkgs + "," + extra;
         m_headerMap.put(FelixConstants.BUNDLE_MANIFESTVERSION, "2");
         m_headerMap.put(FelixConstants.EXPORT_PACKAGE, syspkgs);
         try
         {
             ManifestParser mp = new ManifestParser(
-                m_logger, felix.getConfig(), m_systemBundleRevision, m_headerMap);
+                m_logger, m_configMap, m_systemBundleRevision, m_headerMap);
             List<BundleCapability> caps = aliasSymbolicName(mp.getCapabilities());
             setCapabilities(caps);
         }
@@ -635,14 +642,17 @@
     class ExtensionManagerRevision extends BundleRevisionImpl
     {
         private final Version m_version;
+        private volatile BundleWiring m_wiring;
+
         ExtensionManagerRevision(Felix felix)
         {
-            super(m_logger, felix.getConfig(), felix, "0",
+            super(m_logger, m_configMap, felix, "0",
                 felix.getBootPackages(), felix.getBootPackageWildcards());
             m_version = new Version((String)
-                felix.getConfig().get(FelixConstants.FELIX_VERSION_PROPERTY));
+                m_configMap.get(FelixConstants.FELIX_VERSION_PROPERTY));
         }
 
+        @Override
         public Map getHeaders()
         {
             synchronized (ExtensionManager.this)
@@ -651,6 +661,7 @@
             }
         }
 
+        @Override
         public List<BundleCapability> getDeclaredCapabilities(String namespace)
         {
             synchronized (ExtensionManager.this)
@@ -659,6 +670,85 @@
             }
         }
 
+        @Override
+        public String getSymbolicName()
+        {
+            return FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME;
+        }
+
+        @Override
+        public Version getVersion()
+        {
+            return m_version;
+        }
+
+        @Override
+        public void close()
+        {
+            // Nothing needed here.
+        }
+
+        @Override
+        public Content getContent()
+        {
+            return ExtensionManager.this;
+        }
+
+        @Override
+        public URL getEntry(String name)
+        {
+            // There is no content for the system bundle, so return null.
+            return null;
+        }
+
+        @Override
+        public boolean hasInputStream(int index, String urlPath)
+        {
+            return (getClass().getClassLoader().getResource(urlPath) != null);
+        }
+
+        @Override
+        public InputStream getInputStream(int index, String urlPath)
+        {
+            return getClass().getClassLoader().getResourceAsStream(urlPath);
+        }
+
+        @Override
+        public URL getLocalURL(int index, String urlPath)
+        {
+            return getClass().getClassLoader().getResource(urlPath);
+        }
+
+        @Override
+        public void resolve(
+            List<BundleRevision> fragments, List<ResolverWire> rws,
+            Map<ResolverWire, Set<String>> requiredPkgWires) throws Exception
+        {
+            m_wiring = new ExtensionManagerWiring(
+                m_logger, m_configMap, null, this, fragments, rws, requiredPkgWires);
+        }
+
+        @Override
+        public BundleWiring getWiring()
+        {
+            return m_wiring;
+        }
+    }
+
+    class ExtensionManagerWiring extends BundleWiringImpl
+    {
+        ExtensionManagerWiring(
+            Logger logger, Map configMap, StatefulResolver resolver,
+            BundleRevisionImpl revision, List<BundleRevision> fragments,
+            List<ResolverWire> resolverWires,
+            Map<ResolverWire, Set<String>> requiredPkgWires)
+            throws Exception
+        {
+            super(logger, configMap, resolver, revision,
+                fragments, resolverWires, requiredPkgWires);
+        }
+
+        @Override
         public List<BundleCapability> getCapabilities(String namespace)
         {
             synchronized (ExtensionManager.this)
@@ -667,16 +757,13 @@
             }
         }
 
-        public String getSymbolicName()
+        @Override
+        public List<R4Library> getNativeLibraries()
         {
-            return FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME;
+            return Collections.EMPTY_LIST;
         }
 
-        public Version getVersion()
-        {
-            return m_version;
-        }
-
+        @Override
         public Class getClassByDelegation(String name) throws ClassNotFoundException
         {
             Class clazz = null;
@@ -720,11 +807,13 @@
             return clazz;
         }
 
+        @Override
         public URL getResourceByDelegation(String name)
         {
             return getClass().getClassLoader().getResource(name);
         }
 
+        @Override
         public Enumeration getResourcesByDelegation(String name)
         {
            try
@@ -737,53 +826,13 @@
            }
         }
 
-        public Logger getLogger()
-        {
-            return m_logger;
-        }
-
-        public Map getConfig()
-        {
-            return null;
-        }
-
-        public StatefulResolver getResolver()
-        {
-            return null;
-        }
-
-        public void attachFragmentContents(Content[] fragmentContents)
-            throws Exception
-        {
-            throw new UnsupportedOperationException("Should not be used!");
-        }
-
-        public void close()
+        @Override
+        public void dispose()
         {
             // Nothing needed here.
         }
 
-        public Content getContent()
-        {
-            return ExtensionManager.this;
-        }
-
-        public URL getEntry(String name)
-        {
-            // There is no content for the system bundle, so return null.
-            return null;
-        }
-
-        public boolean hasInputStream(int index, String urlPath)
-        {
-            return (getClass().getClassLoader().getResource(urlPath) != null);
-        }
-
-        public InputStream getInputStream(int index, String urlPath)
-        {
-            return getClass().getClassLoader().getResourceAsStream(urlPath);
-        }
-
+        @Override
         public URL getLocalURL(int index, String urlPath)
         {
             return getClass().getClassLoader().getResource(urlPath);
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index db092bc..4889fa5 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -369,7 +369,7 @@
 
         // Create the extension manager, which we will use as the
         // revision for the system bundle.
-        m_extensionManager = new ExtensionManager(m_logger, this);
+        m_extensionManager = new ExtensionManager(m_logger, m_configMap, this);
         try
         {
             addRevision(m_extensionManager.getRevision());
@@ -1476,7 +1476,21 @@
         {
             return null;
         }
-        return ((BundleRevisionImpl) bundle.getCurrentRevision()).getResourceByDelegation(name);
+// TODO: OSGi R4.3 - Currently, we try to resolve resource requests in
+//       findClassOrResourceByDelegation() and fall back to local resource
+//       searching if it fails. Perhaps we should attempt the resolve here
+//       and do the local searching here. This means we could get rid of
+//       resolve attempts in findClassOrResourceByDelegation().
+        if (bundle.getCurrentRevision().getWiring() == null)
+        {
+            return ((BundleRevisionImpl) bundle.getCurrentRevision())
+                .getResourceLocal(name);
+        }
+        else
+        {
+            return ((BundleWiringImpl) bundle.getCurrentRevision().getWiring())
+                .getResourceByDelegation(name);
+        }
     }
 
     /**
@@ -1492,7 +1506,21 @@
         {
             return null;
         }
-        return ((BundleRevisionImpl) bundle.getCurrentRevision()).getResourcesByDelegation(name);
+// TODO: OSGi R4.3 - Currently, we try to resolve resource requests in
+//       findResourcesByDelegation() and fall back to local resource
+//       searching if it fails. Perhaps we should attempt the resolve here
+//       and do the local searching here. This means we could get rid of
+//       resolve attempts in findResourcesByDelegation().
+        if (bundle.getCurrentRevision().getWiring() == null)
+        {
+            return ((BundleRevisionImpl) bundle.getCurrentRevision())
+                .getResourcesLocal(name);
+        }
+        else
+        {
+            return ((BundleWiringImpl) bundle.getCurrentRevision().getWiring())
+                .getResourcesByDelegation(name);
+        }
     }
 
     /**
@@ -1651,7 +1679,8 @@
                 throw new ClassNotFoundException(name, ex);
             }
         }
-        return ((BundleRevisionImpl) bundle.getCurrentRevision()).getClassByDelegation(name);
+        return ((BundleWiringImpl)
+            bundle.getCurrentRevision().getWiring()).getClassByDelegation(name);
     }
 
     /**
@@ -3216,8 +3245,8 @@
                 Class sbClass = null;
                 try
                 {
-                    sbClass = ((BundleRevisionImpl) m_extensionManager
-                        .getRevision()).getClassByDelegation(clazz.getName());
+                    sbClass = ((BundleWiringImpl) m_extensionManager
+                        .getRevision().getWiring()).getClassByDelegation(clazz.getName());
                 }
                 catch (ClassNotFoundException ex)
                 {
@@ -3412,24 +3441,19 @@
                             BundleCapabilityImpl.PACKAGE_NAMESPACE,
                             Collections.EMPTY_MAP,
                             attrs);
-                        Set<BundleCapability> providers =
-                            m_resolver.getCandidates(req, false);
-                        // We only want resolved capabilities.
-                        for (Iterator<BundleCapability> it = providers.iterator();
-                            it.hasNext(); )
-                        {
-                            if (it.next().getRevision().getWiring() == null)
-                            {
-                                it.remove();
-                            }
-                        }
+                        Set<BundleCapability> providers = m_resolver.getCandidates(req, false);
 
                         // Search through the current providers to find the target revision.
-                        for (BundleCapability provider : providers)
+                        // We only want resolved capabilities.
+                        if (providers != null)
                         {
-                            if (provider == cap)
+                            for (BundleCapability provider : providers)
                             {
-                                list.add(new ExportedPackageImpl(this, bundle, br, cap));
+                                if ((provider.getRevision().getWiring() != null)
+                                    && (provider == cap))
+                                {
+                                    list.add(new ExportedPackageImpl(this, bundle, br, cap));
+                                }
                             }
                         }
                     }
@@ -3445,10 +3469,10 @@
 
         // Get all dependent revisions from all exporter revisions.
         List<BundleRevision> revisions = exporter.getRevisions();
-        for (int modIdx = 0; modIdx < revisions.size(); modIdx++)
+        for (int revIdx = 0; revIdx < revisions.size(); revIdx++)
         {
             List<BundleRevision> dependents =
-                ((BundleRevisionImpl) revisions.get(modIdx)).getDependents();
+                ((BundleRevisionImpl) revisions.get(revIdx)).getDependents();
             for (int depIdx = 0;
                 (dependents != null) && (depIdx < dependents.size());
                 depIdx++)
@@ -3475,24 +3499,31 @@
         {
             // Include any importers that have wires to the specific
             // exported package.
-            List<BundleRevision> dependents =
-                ((BundleRevisionImpl) expRevisions.get(expIdx)).getDependentImporters();
-            for (int depIdx = 0; (dependents != null) && (depIdx < dependents.size()); depIdx++)
+            if (expRevisions.get(expIdx).getWiring() != null)
             {
-                BundleRevision providerRevision =
-                    ((BundleRevisionImpl) dependents.get(depIdx))
-                        .getImportedPackageSource(ep.getName());                
-                if ((providerRevision != null)
-                    && (providerRevision == expRevisions.get(expIdx)))
+                List<BundleRevision> dependents = ((BundleRevisionImpl)
+                    expRevisions.get(expIdx)).getDependentImporters();
+                for (int depIdx = 0; (dependents != null) && (depIdx < dependents.size()); depIdx++)
+                {
+                    if (dependents.get(depIdx).getWiring() != null)
+                    {
+                        BundleRevision providerRevision =
+                            ((BundleWiringImpl) dependents.get(depIdx).getWiring())
+                                .getImportedPackageSource(ep.getName());                
+                        if ((providerRevision != null)
+                            && (providerRevision == expRevisions.get(expIdx)))
+                        {
+                            list.add(dependents.get(depIdx).getBundle());
+                        }
+                    }
+                }
+                dependents = ((BundleRevisionImpl)
+                    expRevisions.get(expIdx)).getDependentRequirers();
+                for (int depIdx = 0; (dependents != null) && (depIdx < dependents.size()); depIdx++)
                 {
                     list.add(dependents.get(depIdx).getBundle());
                 }
             }
-            dependents = ((BundleRevisionImpl) expRevisions.get(expIdx)).getDependentRequirers();
-            for (int depIdx = 0; (dependents != null) && (depIdx < dependents.size()); depIdx++)
-            {
-                list.add(dependents.get(depIdx).getBundle());
-            }
         }
 
         // Return the results.
@@ -3818,8 +3849,8 @@
             Class clazz;
             try
             {
-                clazz = ((BundleRevisionImpl)
-                    impl.getCurrentRevision()).getClassByDelegation(className);
+                clazz = ((BundleWiringImpl)
+                    impl.getCurrentRevision().getWiring()).getClassByDelegation(className);
             }
             catch (ClassNotFoundException ex)
             {
@@ -4206,7 +4237,7 @@
                     // dynamically importing the package, which can happen if two
                     // threads are racing to do so. If we have an existing wire,
                     // then just return it instead.
-                    provider = ((BundleRevisionImpl)revision)
+                    provider = ((BundleWiringImpl) revision.getWiring())
                         .getImportedPackageSource(pkgName);
                     if (provider == null)
                     {
@@ -4225,12 +4256,13 @@
                             // Dynamically add new wire to importing revision.
                             if (dynamicWire != null)
                             {
-                                ((BundleRevisionImpl) revision).addDynamicWire(dynamicWire);
+                                ((BundleWiringImpl) revision.getWiring())
+                                    .addDynamicWire(dynamicWire);
                                 m_logger.log(
                                     Logger.LOG_DEBUG,
                                     "DYNAMIC WIRE: " + dynamicWire);
 
-                                provider = ((BundleRevisionImpl) revision)
+                                provider = ((BundleWiringImpl) revision.getWiring())
                                     .getImportedPackageSource(pkgName);
                             }
                         }
@@ -4262,7 +4294,7 @@
             // If the revision doesn't have dynamic imports, then just return
             // immediately.
             List<BundleRequirement> dynamics =
-                ((BundleRevisionImpl) revision).getResolvedDynamicRequirements();
+                ((BundleWiringImpl) revision.getWiring()).getDynamicRequirements();
             if ((dynamics == null) || dynamics.isEmpty())
             {
                 return false;
@@ -4281,7 +4313,7 @@
 
             // If this revision already imports or requires this package, then
             // we cannot dynamically import it.
-            if (((BundleRevisionImpl) revision).hasPackageSource(pkgName))
+            if (((BundleWiringImpl) revision.getWiring()).hasPackageSource(pkgName))
             {
                 return false;
             }
@@ -4361,64 +4393,54 @@
                         }
                     }
 
-                    ((BundleRevisionImpl) revision).setWires(resolverWires, requiredPkgWires);
-
-                    // Attach fragments, if any.
                     List<BundleRevision> fragments = hosts.get(revision);
-                    if (fragments != null)
+                    try
                     {
-                        try
+// TODO: OSGi R4.3 - Technically, this is where the revision becomes resolved,
+//       but we used to wait and mark it as resolved in the third phase below. 
+                        ((BundleRevisionImpl) revision).resolve(
+                            fragments, resolverWires, requiredPkgWires);
+                    }
+                    catch (Exception ex)
+                    {
+                        // This is a fatal error, so undo everything and
+                        // throw an exception.
+                        for (Entry<BundleRevision, List<ResolverWire>> reentry : wireMap.entrySet())
                         {
-                            ((BundleRevisionImpl) revision).attachFragments(fragments);
-                        }
-                        catch (Exception ex)
-                        {
-                            // This is a fatal error, so undo everything and
-                            // throw an exception.
-                            for (Entry<BundleRevision, List<ResolverWire>> reentry : wireMap.entrySet())
+                            revision = reentry.getKey();
+
+                            // Undo wires.
+                            try
                             {
-                                revision = reentry.getKey();
-
-                                // Undo wires.
-                                ((BundleRevisionImpl) revision).setWires(null, null);
-
-                                fragments = hosts.get(revision);
-                                if (fragments != null)
-                                {
-                                    try
-                                    {
-                                        // Undo fragments.
-                                        ((BundleRevisionImpl) revision).attachFragments(null);
-                                    }
-                                    catch (Exception ex2)
-                                    {
-                                        // We are in big trouble.
-                                        RuntimeException rte = new RuntimeException(
-                                            "Unable to clean up resolver failure.", ex2);
-                                        m_logger.log(
-                                            Logger.LOG_ERROR,
-                                            rte.getMessage(), ex2);
-                                        throw rte;
-                                    }
-
-                                    // Reindex host with no fragments.
-                                    m_resolverState.addRevision(revision);
-                                }
+                                ((BundleRevisionImpl) revision).resolve(null, null, null);
+                            }
+                            catch (Exception ex2)
+                            {
+                                // We are in big trouble.
+                                RuntimeException rte = new RuntimeException(
+                                    "Unable to clean up resolver failure.", ex2);
+                                m_logger.log(
+                                    Logger.LOG_ERROR,
+                                    rte.getMessage(), ex2);
+                                throw rte;
                             }
 
-                            ResolveException re = new ResolveException(
-                                "Unable to attach fragments to " + revision,
-                                revision, null);
-                            re.initCause(ex);
-                            m_logger.log(
-                                Logger.LOG_ERROR,
-                                re.getMessage(), ex);
-                            throw re;
+                            // Reindex host with no fragments.
+                            m_resolverState.addRevision(revision);
                         }
 
-                        // Reindex host with attached fragments.
-                        m_resolverState.addRevision(revision);
+                        ResolveException re = new ResolveException(
+                            "Unable to resolve " + revision,
+                            revision, null);
+                        re.initCause(ex);
+                        m_logger.log(
+                            Logger.LOG_ERROR,
+                            re.getMessage(), ex);
+                        throw re;
                     }
+
+                    // Reindex host with attached fragments.
+                    m_resolverState.addRevision(revision);
                 }
 
                 // Third pass: Loop through the wire map to mark revision as resolved
@@ -4427,7 +4449,8 @@
                 {
                     BundleRevision revision = entry.getKey();
                     // Mark revision as resolved.
-                    ((BundleRevisionImpl) revision).setResolved();
+// TODO: OSGi R4.3 - See message above when we call BundleRevisionImpl.resolve().
+//                    ((BundleRevisionImpl) revision).setResolved();
                     // Update resolver state to remove substituted capabilities.
                     if (!Util.isFragment(revision))
                     {
@@ -4492,7 +4515,8 @@
                     BundleRevision revision = entry.getKey();
 
                     // Fire RESOLVED events for all fragments.
-                    List<BundleRevision> fragments = ((BundleRevisionImpl) revision).getFragments();
+                    List<BundleRevision> fragments =
+                        ((BundleWiringImpl) revision.getWiring()).getFragments();
                     for (int i = 0; (fragments != null) && (i < fragments.size()); i++)
                     {
                         fireBundleEvent(BundleEvent.RESOLVED, fragments.get(i).getBundle());
diff --git a/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java b/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
index f19531f..73ae668 100644
--- a/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/PackageAdminImpl.java
@@ -197,14 +197,13 @@
         {
             List<Bundle> list = new ArrayList<Bundle>();
             // Iterate through revisions
-            List<BundleRevision> revisions = ((BundleImpl) bundle).getRevisions();
-            for (int modIdx = 0; modIdx < revisions.size(); modIdx++)
+            for (BundleRevision revision : ((BundleImpl) bundle).getRevisions())
             {
                 // Get attached fragments.
-                BundleRevisionImpl revision = (BundleRevisionImpl) revisions.get(modIdx);
-                if (revision.isResolved())
+                if (revision.getWiring() != null)
                 {
-                    List<BundleRevision> fragments = revision.getFragments();
+                    List<BundleRevision> fragments =
+                        ((BundleWiringImpl) revision.getWiring()).getFragments();
                     for (int i = 0; (fragments != null) && (i < fragments.size()); i++)
                     {
                         Bundle b = fragments.get(i).getBundle();
@@ -230,14 +229,12 @@
         {
             List<Bundle> list = new ArrayList<Bundle>();
             // Iterate through revisions
-            List<BundleRevision> revisions = ((BundleImpl) bundle).getRevisions();
-            for (int modIdx = 0; modIdx < revisions.size(); modIdx++)
+            for (BundleRevision revision : ((BundleImpl) bundle).getRevisions())
             {
                 // Get hosts
-                BundleRevisionImpl revision = (BundleRevisionImpl) revisions.get(modIdx);
-                if (revision.isResolved())
+                if (revision.getWiring() != null)
                 {
-                    List<BundleWire> hostWires = revision.getWires();
+                    List<BundleWire> hostWires = revision.getWiring().getRequiredWires(null);
                     for (int i = 0; (hostWires != null) && (i < hostWires.size()); i++)
                     {
                         Bundle b = hostWires.get(i).getProviderWiring().getBundle();
@@ -259,14 +256,12 @@
     public RequiredBundle[] getRequiredBundles(String symbolicName)
     {
         List list = new ArrayList();
-        Bundle[] bundles = m_felix.getBundles();
-        for (int i = 0; i < bundles.length; i++)
+        for (Bundle bundle : m_felix.getBundles())
         {
-            BundleImpl impl = (BundleImpl) bundles[i];
             if ((symbolicName == null)
-                || (symbolicName.equals(impl.getCurrentRevision().getSymbolicName())))
+                || (symbolicName.equals(bundle.getSymbolicName())))
             {
-                list.add(new RequiredBundleImpl(m_felix, impl));
+                list.add(new RequiredBundleImpl(m_felix, (BundleImpl) bundle));
             }
         }
         return (list.isEmpty())
diff --git a/framework/src/main/java/org/apache/felix/framework/ResolverStateImpl.java b/framework/src/main/java/org/apache/felix/framework/ResolverStateImpl.java
index b76ade8..bdb4ade 100644
--- a/framework/src/main/java/org/apache/felix/framework/ResolverStateImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ResolverStateImpl.java
@@ -145,7 +145,7 @@
             // If so, then the framework must have chosen to have the revision
             // import rather than export the package, so we need to remove the
             // corresponding package capability from the package capability set.
-            for (BundleWire w : ((BundleRevisionImpl) br).getWires())
+            for (BundleWire w : br.getWiring().getRequiredWires(null))
             {
                 if (w.getCapability().getNamespace().equals(BundleCapabilityImpl.PACKAGE_NAMESPACE))
                 {
@@ -274,7 +274,9 @@
     {
         // Next, try to resolve any native code, since the revision is
         // not resolvable if its native code cannot be loaded.
-        List<R4Library> libs = ((BundleRevisionImpl) revision).getNativeLibraries();
+// TODO: OSGi R4.3 - Is it sufficient to just check declared native libs here?
+//        List<R4Library> libs = ((BundleWiringImpl) revision.getWiring()).getNativeLibraries();
+        List<R4Library> libs = ((BundleRevisionImpl) revision).getDeclaredNativeLibraries();
         if (libs != null)
         {
             String msg = null;
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java b/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
index f544c4a..02b5fd4 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
@@ -519,7 +519,8 @@
                 try
                 {
                     Class requestClass =
-                        ((BundleRevisionImpl) requesterRevision).getClassByDelegation(className);
+                        ((BundleWiringImpl) requesterRevision.getWiring())
+                            .getClassByDelegation(className);
                     allow = getRegistration().isClassAccessible(requestClass);
                 }
                 catch (Exception ex)
@@ -544,14 +545,15 @@
                     try
                     {
                         // Try to load class from requester.
-                        Class requestClass =((BundleRevisionImpl)
-                            requesterRevision).getClassByDelegation(className);
+                        Class requestClass =((BundleWiringImpl)
+                            requesterRevision.getWiring()).getClassByDelegation(className);
                         try
                         {
                             // If requester has access to the class, verify it is the
                             // same class as the provider.
-                            allow = (((BundleRevisionImpl) providerRevision)
-                                .getClassByDelegation(className) == requestClass);
+                            allow = (((BundleWiringImpl)
+                                providerRevision.getWiring())
+                                    .getClassByDelegation(className) == requestClass);
                         }
                         catch (Exception ex)
                         {
@@ -585,8 +587,9 @@
                     try
                     {
                         // Load the class from the requesting bundle.
-                        Class requestClass = ((BundleRevisionImpl)
-                            requesterRevision).getClassByDelegation(className);
+                        Class requestClass = ((BundleWiringImpl)
+                            requesterRevision.getWiring())
+                                .getClassByDelegation(className);
                         // Get the service registration and ask it to check
                         // if the service object is assignable to the requesting
                         // bundle's class.
diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
index 54f34c5..6092980 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
@@ -126,8 +126,8 @@
         if (!((BundleRevisionImpl) m_targetRevision)
             .hasInputStream(m_classPathIdx, url.getPath()))
         {
-            URL newurl = ((BundleRevisionImpl)
-                m_targetRevision).getResourceByDelegation(url.getPath());
+            URL newurl = ((BundleWiringImpl)
+                m_targetRevision.getWiring()).getResourceByDelegation(url.getPath());
             if (newurl == null)
             {
                 throw new IOException("Resource does not exist: " + url);
diff --git a/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java b/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java
index c6d6a5c..066a303 100644
--- a/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java
+++ b/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java
@@ -31,6 +31,7 @@
 import java.util.TreeMap;
 import java.util.TreeSet;
 import org.apache.felix.framework.BundleRevisionImpl;
+import org.apache.felix.framework.BundleWiringImpl;
 import org.apache.felix.framework.resolver.Resolver.ResolverState;
 import org.apache.felix.framework.util.Util;
 import org.apache.felix.framework.wiring.BundleCapabilityImpl;
@@ -990,8 +991,11 @@
                     System.out.println("    " + req + ": " + candidates);
                 }
             }
+// TODO: OSGi R4.3 - We need to get dynamic requirements using public API
+//       then we might not need to make the BundleWiringImpl and BundleRevisionImpl
+//       classes public.
             reqs = (br.getWiring() != null)
-                ? ((BundleRevisionImpl) br).getResolvedDynamicRequirements()
+                ? ((BundleWiringImpl) br.getWiring()).getDynamicRequirements()
                 : ((BundleRevisionImpl) br).getDeclaredDynamicRequirements();
             for (BundleRequirement req : reqs)
             {
diff --git a/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java b/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
index 829098e..3110261 100644
--- a/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
@@ -29,6 +29,7 @@
 import java.util.Set;
 import java.util.SortedSet;
 import org.apache.felix.framework.BundleRevisionImpl;
+import org.apache.felix.framework.BundleWiringImpl;
 import org.apache.felix.framework.Logger;
 import org.apache.felix.framework.capabilityset.CapabilitySet;
 import org.apache.felix.framework.util.Util;
@@ -62,7 +63,7 @@
         Map<BundleRevision, List<ResolverWire>> wireMap = new HashMap<BundleRevision, List<ResolverWire>>();
         Map<BundleRevision, Packages> revisionPkgMap = new HashMap<BundleRevision, Packages>();
 
-        if (!((BundleRevisionImpl) revision).isResolved())
+        if (revision.getWiring() == null)
         {
             boolean retryFragments;
             do
@@ -360,7 +361,7 @@
         // If the revision doesn't have dynamic imports, then just return
         // immediately.
         List<BundleRequirement> dynamics =
-            ((BundleRevisionImpl) revision).getResolvedDynamicRequirements();
+            ((BundleWiringImpl) revision.getWiring()).getDynamicRequirements();
         if ((dynamics == null) || dynamics.isEmpty())
         {
             return null;
@@ -379,7 +380,7 @@
 
         // If this revision already imports or requires this package, then
         // we cannot dynamically import it.
-        if (((BundleRevisionImpl) revision).hasPackageSource(pkgName))
+        if (((BundleWiringImpl) revision.getWiring()).hasPackageSource(pkgName))
         {
             return null;
         }
@@ -466,7 +467,7 @@
         if (revision.getWiring() != null)
         {
             // Use wires to get actual requirements and satisfying capabilities.
-            for (BundleWire wire : ((BundleRevisionImpl) revision).getWires())
+            for (BundleWire wire : revision.getWiring().getRequiredWires(null))
             {
                 // Wrap the requirement as a hosted requirement
                 // if it comes from a fragment, since we will need
@@ -496,7 +497,7 @@
             // so check to see if there are candidates for any of its dynamic
             // imports.
             for (BundleRequirement req
-                : ((BundleRevisionImpl) revision).getResolvedDynamicRequirements())
+                : ((BundleWiringImpl) revision.getWiring()).getDynamicRequirements())
             {
                 // Get the candidates for the current requirement.
                 SortedSet<BundleCapability> candCaps =
@@ -1171,7 +1172,7 @@
         // exports are substitutable.
         if (revision.getWiring() != null)
         {
-            for (BundleWire wire : ((BundleRevisionImpl) revision).getWires())
+            for (BundleWire wire : revision.getWiring().getRequiredWires(null))
             {
                 if (wire.getRequirement().getNamespace().equals(
                     BundleCapabilityImpl.PACKAGE_NAMESPACE))
diff --git a/framework/src/main/java/org/apache/felix/framework/util/Util.java b/framework/src/main/java/org/apache/felix/framework/util/Util.java
index 817ad66..8cc096f 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/Util.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/Util.java
@@ -329,17 +329,20 @@
 
     public static BundleWire getWire(BundleRevision br, String name)
     {
-        List<BundleWire> wires = ((BundleRevisionImpl) br).getWires();
-        if (wires != null)
+        if (br.getWiring() != null)
         {
-            for (BundleWire w : wires)
+            List<BundleWire> wires = br.getWiring().getRequiredWires(null);
+            if (wires != null)
             {
-                if (w.getCapability().getNamespace()
-                        .equals(BundleCapabilityImpl.PACKAGE_NAMESPACE) &&
-                    w.getCapability().getAttributes()
-                        .get(BundleCapabilityImpl.PACKAGE_ATTR).equals(name))
+                for (BundleWire w : wires)
                 {
-                    return w;
+                    if (w.getCapability().getNamespace()
+                            .equals(BundleCapabilityImpl.PACKAGE_NAMESPACE) &&
+                        w.getCapability().getAttributes()
+                            .get(BundleCapabilityImpl.PACKAGE_ATTR).equals(name))
+                    {
+                        return w;
+                    }
                 }
             }
         }