felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickh...@apache.org
Subject svn commit: r952424 [2/3] - in /felix/sandbox/rickhall/framework-vb: ./ src/main/java/org/apache/felix/framework/ src/main/java/org/apache/felix/framework/ext/ src/main/java/org/apache/felix/framework/resolver/ src/main/java/org/apache/felix/framework/...
Date Mon, 07 Jun 2010 20:40:21 GMT
Modified: felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ModuleImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ModuleImpl.java?rev=952424&r1=952423&r2=952424&view=diff
==============================================================================
--- felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ModuleImpl.java (original)
+++ felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ModuleImpl.java Mon Jun  7 20:40:20 2010
@@ -18,67 +18,39 @@
  */
 package org.apache.felix.framework;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLStreamHandler;
-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.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.Vector;
 
 import org.apache.felix.framework.Felix.FelixResolver;
-import org.apache.felix.framework.cache.JarContent;
-import org.apache.felix.framework.capabilityset.Attribute;
 import org.apache.felix.framework.capabilityset.Capability;
 import org.apache.felix.framework.capabilityset.Directive;
 import org.apache.felix.framework.capabilityset.Requirement;
 import org.apache.felix.framework.capabilityset.SimpleFilter;
+import org.apache.felix.framework.ext.VirtualContent;
 import org.apache.felix.framework.resolver.Content;
 import org.apache.felix.framework.resolver.Module;
 import org.apache.felix.framework.resolver.ResolveException;
-import org.apache.felix.framework.resolver.ResourceNotFoundException;
 import org.apache.felix.framework.resolver.Wire;
-import org.apache.felix.framework.resolver.WireImpl;
-import org.apache.felix.framework.resolver.WireModuleImpl;
-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.CapabilityImpl;
 import org.apache.felix.framework.util.manifestparser.ManifestParser;
 import org.apache.felix.framework.util.manifestparser.R4Library;
-import org.apache.felix.framework.util.manifestparser.RequirementImpl;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
-import org.osgi.framework.BundleReference;
-import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
 
 public class ModuleImpl implements Module
 {
     private final Logger m_logger;
     private final Map m_configMap;
-    private final FelixResolver m_resolver;
     private final String m_id;
-    private final Content m_content;
+    private final VirtualContent m_virtualContent;
     private final Map m_headerMap;
-    private final URLStreamHandler m_streamHandler;
 
     private final String m_manifestVersion;
     private final boolean m_isExtension;
@@ -105,55 +77,8 @@ public class ModuleImpl implements Modul
     private List<Module> m_dependentRequirers = new ArrayList<Module>(0);
     private volatile boolean m_isResolved = false;
 
-    private Content[] m_contentPath;
-    private Content[] m_fragmentContents = null;
-    private ModuleClassLoader m_classLoader;
     private boolean m_isActivationTriggered = false;
     private ProtectionDomain m_protectionDomain = null;
-    private static final 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;
-    }
-
-    // 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;
-
-    // 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();
 
     /**
      * This constructor is used by the extension manager, since it needs
@@ -171,14 +96,10 @@ public class ModuleImpl implements Modul
     {
         m_logger = logger;
         m_configMap = configMap;
-        m_resolver = null;
         m_bundle = bundle;
         m_id = id;
         m_headerMap = null;
-        m_content = null;
-        m_streamHandler = null;
-        m_bootPkgs = bootPkgs;
-        m_bootPkgWildcards = bootPkgWildcards;
+        m_virtualContent = null;
         m_manifestVersion = null;
         m_symbolicName = null;
         m_isExtension = false;
@@ -190,8 +111,6 @@ public class ModuleImpl implements Modul
         m_declaredActivationPolicy = EAGER_ACTIVATION;
         m_activationExcludes = null;
         m_activationIncludes = null;
-        m_implicitBootDelegation = false;
-        m_bootClassLoader = m_defBootClassLoader;
     }
 
     public ModuleImpl(
@@ -203,32 +122,9 @@ public class ModuleImpl implements Modul
     {
         m_logger = logger;
         m_configMap = configMap;
-        m_resolver = resolver;
         m_bundle = bundle;
         m_id = id;
         m_headerMap = headerMap;
-        m_content = content;
-        m_streamHandler = streamHandler;
-        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();
-
-        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);
 
@@ -250,6 +146,11 @@ public class ModuleImpl implements Modul
             : ManifestParser.parseDelimitedString(mp.getActivationIncludeDirective(), ",");
         m_symbolicName = mp.getSymbolicName();
         m_isExtension = mp.isExtension();
+
+        m_virtualContent = new VirtualContentImpl(
+            logger, configMap, streamHandler, resolver, this,
+            content, bootPkgs, bootPkgWildcards,
+            m_activationIncludes, m_activationExcludes);
     }
 
     //
@@ -461,8 +362,21 @@ public class ModuleImpl implements Modul
         return m_wires;
     }
 
-    public synchronized void setWires(List<Wire> wires)
+    public synchronized void resolve(List<Wire> wires) throws ResolveException
     {
+        // First try to inject wires into our virtual content.
+        try
+        {
+            if (m_virtualContent != null)
+            {
+                m_virtualContent.resolve(wires);
+            }
+        }
+        catch (BundleException ex)
+        {
+            throw new ResolveException(ex.getMessage(), this, null);
+        }
+
         // Remove module from old wire modules' dependencies,
         // since we are no longer dependent on any the moduels
         // from the old wires.
@@ -508,753 +422,142 @@ public class ModuleImpl implements Modul
     // Content access methods.
     //
 
-    public Content getContent()
+    public VirtualContent getVirtualContent()
     {
-        return m_content;
+        return m_virtualContent;
     }
 
-    private synchronized Content[] getContentPath()
+    public Class getClassByDelegation(String name) throws ClassNotFoundException
     {
-        if (m_contentPath == null)
-        {
-            try
-            {
-                m_contentPath = initializeContentPath();
-            }
-            catch (Exception ex)
-            {
-                m_logger.log(Logger.LOG_ERROR, "Unable to get module class path.", ex);
-            }
-        }
-        return m_contentPath;
+        return m_virtualContent.loadClass(name);
     }
 
-    private Content[] initializeContentPath() throws Exception
+    public URL getResourceByDelegation(String name)
     {
-        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()]);
+        return m_virtualContent.getResource(name);
     }
 
-    private List calculateContentPath(
-        Module module, Content content, List contentList, boolean searchFragments)
-        throws Exception
+    public Enumeration getResourcesByDelegation(String name)
     {
-        // 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) module.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(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.size() == 0)
-        {
-            localContentList.add(content);
-        }
-
-        // Now add the local contents to the global content list and return it.
-        contentList.addAll(localContentList);
-        return contentList;
+        return m_virtualContent.getResources(name);
     }
 
-    public Class getClassByDelegation(String name) throws ClassNotFoundException
+    public URL getEntry(String name)
     {
-        // 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);
+        return m_virtualContent.getEntry(name);
     }
 
-    public URL getResourceByDelegation(String name)
+    //
+    // Fragment and dependency management methods.
+    //
+
+    public synchronized List<Module> getFragments()
     {
-        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(
-                Logger.LOG_DEBUG,
-                ex.getMessage());
-        }
-        return null;
+        return m_fragments;
     }
 
-    private Object findClassOrResourceByDelegation(String name, boolean isClass)
-        throws ClassNotFoundException, ResourceNotFoundException
+    public synchronized void attachFragments(List<Module> fragments) throws Exception
     {
-        Object result = null;
-
-        Set requestSet = (Set) m_cycleCheck.get();
-        if (requestSet == null)
+        // Remove module from old fragment dependencies.
+        // We will generally only remove module fragment
+        // dependencies when we are uninstalling the module.
+        for (int i = 0; (m_fragments != null) && (i < m_fragments.size()); i++)
         {
-            requestSet = new HashSet();
-            m_cycleCheck.set(requestSet);
+            ((ModuleImpl) m_fragments.get(i)).removeDependentHost(this);
         }
-        if (requestSet.add(name))
-        {
-            try
-            {
-                // First, try to resolve the originating module.
-                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 module's imports. Note that the search may
-                // be aborted if this method throws an exception, otherwise
-                // it continues if a null is returned.
-                result = searchImports(name, isClass);
 
-                // If not found, try the module's own class path.
-                if (result == null)
-                {
-                    result = (isClass)
-                        ? (Object) getClassLoader().findClass(name)
-                        : (Object) getResourceLocal(name);
+        // Remove cached capabilities and requirements.
+        m_cachedCapabilities = null;
+        m_cachedRequirements = null;
+        m_cachedDynamicRequirements = null;
 
-                    // If still not found, then try the module's dynamic imports.
-                    if (result == null)
-                    {
-                        result = searchDynamicImports(name, pkgName, 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 + ": cannot resolve package "
-                        + ex.getRequirement());
-                }
-                else
-                {
-                    // The spec states that if the bundle cannot be resolved, then
-                    // only the local bundle's resources should be searched. So we
-                    // will ask the module's own class path.
-                    URL url = getResourceLocal(name);
-                    if (url != null)
-                    {
-                        return url;
-                    }
+        // Update the dependencies on the new fragments.
+        m_fragments = fragments;
 
-                    // We need to throw a resource not found exception.
-                    throw new ResourceNotFoundException(
-                        name + ": cannot resolve package "
-                        + ex.getRequirement());
-                }
-            }
-            finally
+        // We need to add ourself as a dependent of each fragment module.
+        if (m_fragments != null)
+        {
+            for (int i = 0; (m_fragments != null) && (i < m_fragments.size()); i++)
             {
-                requestSet.remove(name);
+                ((ModuleImpl) m_fragments.get(i)).addDependentHost(this);
             }
         }
-        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)
+        // Now actually actually attach the fragments to our virtual content.
+        if (m_virtualContent != null)
         {
-            if (isClass)
-            {
-                throw new ClassNotFoundException(name);
-            }
-            else
-            {
-                throw new ResourceNotFoundException(name);
-            }
+            ((VirtualContentImpl) m_virtualContent).attachFragments(fragments);
         }
-
-        return result;
     }
 
-    URL getResourceLocal(String name)
+    public synchronized List<Module> getDependentHosts()
     {
-        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.
-        Content[] contentPath = getContentPath();
-        for (int i = 0;
-            (url == null) &&
-            (i < contentPath.length); i++)
-        {
-            if (contentPath[i].hasEntry(name))
-            {
-                url = createURL(i + 1, name);
-            }
-        }
-
-        return url;
+        return m_dependentHosts;
     }
 
-    public Enumeration getResourcesByDelegation(String name)
+    public synchronized void addDependentHost(Module module)
     {
-        Set requestSet = (Set) m_cycleCheck.get();
-        if (requestSet == null)
-        {
-            requestSet = new HashSet();
-            m_cycleCheck.set(requestSet);
-        }
-        if (!requestSet.contains(name))
+        if (!m_dependentHosts.contains(module))
         {
-            requestSet.add(name);
-            try
-            {
-                Enumeration urls = findResourcesByDelegation(name);
-                return (urls.hasMoreElements()) ? urls : null;
-            }
-            finally
-            {
-                requestSet.remove(name);
-            }
+            m_dependentHosts.add(module);
         }
-
-        return null;
     }
 
-    private Enumeration findResourcesByDelegation(String name)
+    public synchronized void removeDependentHost(Module module)
     {
-        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.
-            urls = getResourcesLocal(name);
-            return urls;
-        }
-
-        // Get the package of the target class/resource.
-        String pkgName = Util.getResourcePackage(name);
-
-        // Delegate any packages listed in the boot delegation
-        // property to the parent class loader.
-        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 module's imports.
-        // We delegate to the module's wires for the resources.
-        // If any resources are found, this means that the package of these
-        // resources is imported, we must not keep looking since we do not
-        // support split-packages.
-
-        // Note that the search may be aborted if this method throws an
-        // exception, otherwise it continues if a null is returned.
-        List<Wire> wires = getWires();
-        for (int i = 0; (wires != null) && (i < wires.size()); i++)
-        {
-            if (wires.get(i) instanceof WireImpl)
-            {
-                try
-                {
-                    // If we find the class or resource, then return it.
-                    urls = wires.get(i).getResources(name);
-                }
-                catch (ResourceNotFoundException ex)
-                {
-                    urls = null;
-                }
-                if (urls != null)
-                {
-                    completeUrlList.add(urls);
-                    return new CompoundEnumeration((Enumeration[])
-                        completeUrlList.toArray(new Enumeration[completeUrlList.size()]));
-                }
-            }
-        }
+        m_dependentHosts.remove(module);
+    }
 
-        // See whether we can get the resource from the required bundles and
-        // regardless of whether or not this is the case continue to the next
-        // step potentially passing on the result of this search (if any).
-        for (int i = 0; (wires != null) && (i < wires.size()); i++)
-        {
-            if (wires.get(i) instanceof WireModuleImpl)
-            {
-                try
-                {
-                    // If we find the class or resource, then add it.
-                    urls = wires.get(i).getResources(name);
-                }
-                catch (ResourceNotFoundException ex)
-                {
-                    urls = null;
-                }
-                if (urls != null)
-                {
-                    completeUrlList.add(urls);
-                }
-            }
-        }
+    public synchronized List<Module> getDependentImporters()
+    {
+        return m_dependentImporters;
+    }
 
-        // 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
+    public synchronized void addDependentImporter(Module module)
+    {
+        if (!m_dependentImporters.contains(module))
         {
-            // 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.
-            Wire wire = null;
-            try
-            {
-                wire = m_resolver.resolve(this, pkgName);
-            }
-            catch (ResolveException ex)
-            {
-                // Ignore this since it is likely normal.
-            }
-            if (wire != null)
-            {
-                try
-                {
-                    urls = wire.getResources(name);
-                }
-                catch (ResourceNotFoundException ex)
-                {
-                    urls = null;
-                }
-                if (urls != null)
-                {
-                    completeUrlList.add(urls);
-                }
-            }
+            m_dependentImporters.add(module);
         }
+    }
 
-        return new CompoundEnumeration((Enumeration[])
-            completeUrlList.toArray(new Enumeration[completeUrlList.size()]));
+    public synchronized void removeDependentImporter(Module module)
+    {
+        m_dependentImporters.remove(module);
     }
 
-    private Enumeration getResourcesLocal(String name)
+    public synchronized List<Module> getDependentRequirers()
     {
-        Vector v = new Vector();
+        return m_dependentRequirers;
+    }
 
-        // 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.
-        final Content[] contentPath = getContentPath();
-        if (name.equals("/"))
+    public synchronized void addDependentRequirer(Module module)
+    {
+        if (!m_dependentRequirers.contains(module))
         {
-            for (int i = 0; i < contentPath.length; i++)
-            {
-                v.addElement(createURL(i + 1, name));
-            }
+            m_dependentRequirers.add(module);
         }
-        else
-        {
-            // Remove leading slash, if present.
-            if (name.startsWith("/"))
-            {
-                name = name.substring(1);
-            }
+    }
 
-            // Check the module class path.
-            for (int i = 0; i < contentPath.length; i++)
-            {
-                if (contentPath[i].hasEntry(name))
-                {
-                    // Use the class path index + 1 for creating the path so
-                    // that we can differentiate between module content URLs
-                    // (where the path will start with 0) and module class
-                    // path URLs.
-                    v.addElement(createURL(i + 1, name));
-                }
-            }
-        }
+    public synchronized void removeDependentRequirer(Module module)
+    {
+        m_dependentRequirers.remove(module);
+    }
 
-        return v.elements();
+    public synchronized List<Module> getDependents()
+    {
+        List<Module> dependents = new ArrayList<Module>
+            (m_dependentHosts.size() + m_dependentImporters.size() + m_dependentRequirers.size());
+        dependents.addAll(m_dependentHosts);
+        dependents.addAll(m_dependentImporters);
+        dependents.addAll(m_dependentRequirers);
+        return dependents;
     }
 
-    // TODO: API: Investigate how to handle this better, perhaps we need
-    // multiple URL policies, one for content -- one for class path.
-    public URL getEntry(String name)
+    public void close()
     {
-        URL url = null;
-
-        // Check for the special case of "/", which represents
-        // the root of the bundle according to the spec.
-        if (name.equals("/"))
-        {
-            url = createURL(0, "/");
-        }
-
-        if (url == null)
-        {
-            // Remove leading slash, if present.
-            if (name.startsWith("/"))
-            {
-                name = name.substring(1);
-            }
-
-            // Check the module content.
-            if (getContent().hasEntry(name))
-            {
-                // Module content URLs start with 0, whereas module
-                // class path URLs start with the index into the class
-                // path + 1.
-                url = createURL(0, name);
-            }
-        }
-
-        return url;
-    }
-
-    public boolean hasInputStream(int index, String urlPath)
-    {
-        if (urlPath.startsWith("/"))
-        {
-            urlPath = urlPath.substring(1);
-        }
-        if (index == 0)
-        {
-            return m_content.hasEntry(urlPath);
-        }
-        return getContentPath()[index - 1].hasEntry(urlPath);
-    }
-
-    public InputStream getInputStream(int index, String urlPath)
-        throws IOException
-    {
-        if (urlPath.startsWith("/"))
-        {
-            urlPath = urlPath.substring(1);
-        }
-        if (index == 0)
-        {
-            return m_content.getEntryAsStream(urlPath);
-        }
-        return getContentPath()[index - 1].getEntryAsStream(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_id + ":" + port + path, m_streamHandler);
-         }
-         catch (MalformedURLException ex)
-         {
-             m_logger.log(
-                 Logger.LOG_ERROR,
-                 "Unable to create resource URL.",
-                 ex);
-         }
-         return null;
-    }
-
-    //
-    // Fragment and dependency management methods.
-    //
-
-    public synchronized List<Module> getFragments()
-    {
-        return m_fragments;
-    }
-
-    public synchronized void attachFragments(List<Module> fragments) throws Exception
-    {
-        // Remove module from old fragment dependencies.
-        // We will generally only remove module fragment
-        // dependencies when we are uninstalling the module.
-        for (int i = 0; (m_fragments != null) && (i < m_fragments.size()); i++)
-        {
-            ((ModuleImpl) m_fragments.get(i)).removeDependentHost(this);
-        }
-
-        // Remove cached capabilities and requirements.
-        m_cachedCapabilities = null;
-        m_cachedRequirements = null;
-        m_cachedDynamicRequirements = null;
-
-        // Update the dependencies on the new fragments.
-        m_fragments = fragments;
-
-        // We need to add ourself as a dependent of each fragment
-        // module. We also need to create an array of fragment contents
-        // to attach to our content loader.
-        if (m_fragments != null)
-        {
-            Content[] fragmentContents = new Content[m_fragments.size()];
-            for (int i = 0; (m_fragments != null) && (i < m_fragments.size()); i++)
-            {
-                ((ModuleImpl) m_fragments.get(i)).addDependentHost(this);
-                fragmentContents[i] =
-                    m_fragments.get(i).getContent()
-                        .getEntryAsContent(FelixConstants.CLASS_PATH_DOT);
-            }
-            // Now attach the fragment contents to our content loader.
-            attachFragmentContents(fragmentContents);
-        }
-    }
-
-    // This must be called holding the object lock.
-    private void attachFragmentContents(Content[] fragmentContents)
-        throws Exception
-    {
-        // Close existing fragment contents.
-        if (m_fragmentContents != null)
-        {
-            for (int i = 0; i < m_fragmentContents.length; i++)
-            {
-                m_fragmentContents[i].close();
-            }
-        }
-        m_fragmentContents = fragmentContents;
-
-        if (m_contentPath != null)
-        {
-            for (int i = 0; i < m_contentPath.length; i++)
-            {
-                m_contentPath[i].close();
-            }
-        }
-        m_contentPath = initializeContentPath();
-    }
-
-    public synchronized List<Module> getDependentHosts()
-    {
-        return m_dependentHosts;
-    }
-
-    public synchronized void addDependentHost(Module module)
-    {
-        if (!m_dependentHosts.contains(module))
-        {
-            m_dependentHosts.add(module);
-        }
-    }
-
-    public synchronized void removeDependentHost(Module module)
-    {
-        m_dependentHosts.remove(module);
-    }
-
-    public synchronized List<Module> getDependentImporters()
-    {
-        return m_dependentImporters;
-    }
-
-    public synchronized void addDependentImporter(Module module)
-    {
-        if (!m_dependentImporters.contains(module))
-        {
-            m_dependentImporters.add(module);
-        }
-    }
-
-    public synchronized void removeDependentImporter(Module module)
-    {
-        m_dependentImporters.remove(module);
-    }
-
-    public synchronized List<Module> getDependentRequirers()
-    {
-        return m_dependentRequirers;
-    }
-
-    public synchronized void addDependentRequirer(Module module)
-    {
-        if (!m_dependentRequirers.contains(module))
-        {
-            m_dependentRequirers.add(module);
-        }
-    }
-
-    public synchronized void removeDependentRequirer(Module module)
-    {
-        m_dependentRequirers.remove(module);
-    }
-
-    public synchronized List<Module> getDependents()
-    {
-        List<Module> dependents = new ArrayList<Module>
-            (m_dependentHosts.size() + m_dependentImporters.size() + m_dependentRequirers.size());
-        dependents.addAll(m_dependentHosts);
-        dependents.addAll(m_dependentImporters);
-        dependents.addAll(m_dependentRequirers);
-        return dependents;
-    }
-
-    public synchronized void close()
-    {
-        m_content.close();
-        for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
-        {
-            m_contentPath[i].close();
-        }
-        for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
-        {
-            m_fragmentContents[i].close();
-        }
-        m_classLoader = null;
-    }
+        ((VirtualContentImpl) m_virtualContent).close();
+    }
 
     public synchronized void setSecurityContext(Object securityContext)
     {
@@ -1271,1011 +574,6 @@ public class ModuleImpl implements Modul
         return m_id;
     }
 
-    private synchronized ModuleClassLoader getClassLoader()
-    {
-        if (m_classLoader == null)
-        {
-            if (System.getSecurityManager() != null)
-            {
-                try
-                {
-                    Constructor ctor = (Constructor) m_secureAction.getConstructor(
-                        ModuleClassLoader.class,
-                        new Class[] { ModuleImpl.class, ClassLoader.class });
-                    m_classLoader = (ModuleClassLoader)
-                        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() + "]");
-                }
-            }
-            else
-            {
-                m_classLoader = new ModuleClassLoader(determineParentClassLoader());
-            }
-        }
-        return m_classLoader;
-    }
-
-    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.getSystemClassLoader().getParent();
-        }
-        else if (cfg.equalsIgnoreCase(Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK))
-        {
-            parent = ModuleImpl.class.getClassLoader();
-        }
-        // 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 name, boolean isClass)
-        throws ClassNotFoundException, ResourceNotFoundException
-    {
-        // We delegate to the module's wires to find the class or resource.
-        List<Wire> wires = getWires();
-        for (int i = 0; (wires != null) && (i < wires.size()); i++)
-        {
-            // If we find the class or resource, then return it.
-            Object result = (isClass)
-                ? (Object) wires.get(i).getClass(name)
-                : (Object) wires.get(i).getResource(name);
-            if (result != null)
-            {
-                return result;
-            }
-        }
-
-        return null;
-    }
-
-    private Object searchDynamicImports(
-        final String name, String pkgName, 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.
-        Wire wire = null;
-        try
-        {
-            wire = 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 wire, but subsequent requests for classes/resources
-        // in the associated package will be processed as part of
-        // normal static imports.
-        if (wire != null)
-        {
-            // Return the class or resource.
-            return (isClass)
-                ? (Object) wire.getClass(name)
-                : (Object) wire.getResource(name);
-        }
-
-        // 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 is no
-            // module classes on the call stack; therefore, as soon as we
-            // see Thread on the call stack we exit this loop. Other cases
-            // where modules actually use threads are not an issue because
-            // the module classes will be on the call stack before the
-            // Thread class.
-            if (Thread.class.equals(classes[i]))
-            {
-                break;
-            }
-            else if (isClassNotLoadedFromBundle(classes[i]))
-            {
-                // If the instigating class was not from a bundle,
-                // then delegate to the parent class loader; otherwise,
-                // break out of loop and return null.
-                boolean delegate = true;
-                ClassLoader last = null;
-                for (ClassLoader cl = classes[i].getClassLoader(); 
-                (cl != null) && (last != cl); 
-                cl = cl.getClass().getClassLoader())
-                {
-                    last = cl;
-                    if (ModuleClassLoader.class.isInstance(cl))
-                    {
-                        delegate = false;
-                        break;
-                    }
-                }
-                // Delegate to the parent class loader unless this call
-                // is due to outside code calling a method on the bundle
-                // interface (e.g., Bundle.loadClass()).
-                if (delegate && !Bundle.class.isAssignableFrom(classes[i - 1]))
-                {
-                    try
-                    {
-                        // Return the class or resource from the parent class loader.
-                        return (isClass)
-                        ? (Object) this.getClass().getClassLoader().loadClass(name)
-                            : (Object) this.getClass().getClassLoader().getResource(name);
-                    }
-                    catch (NoClassDefFoundError ex)
-                    {
-                        // Ignore, will return null
-                    }
-                }
-                break;
-            }
-        }
-
-        return null;
-    }
-
-    private boolean isClassNotLoadedFromBundle(Class clazz)
-    {
-        // If this is an inner class, try to get the enclosing class
-        // because we can assume that inner classes of class loaders
-        // are really just the class loader and we should ignore them.
-        clazz = getEnclosingClass(clazz);
-        return (this.getClass().getClassLoader() != clazz.getClassLoader())
-            && !ClassLoader.class.isAssignableFrom(clazz)
-            && !Class.class.equals(clazz)
-            && !Proxy.class.equals(clazz);
-    }
-
-    private static Class getEnclosingClass(Class clazz)
-    {
-        // This code determines if the class is an inner class and if so
-        // returns the enclosing class. At one point in time this code used
-        // Class.getEnclosingClass() for JDKs > 1.5, but due to a bug in the
-        // JDK which caused  invalid ClassCircularityErrors we had to remove it.
-        int idx = clazz.getName().lastIndexOf('$');
-        if (idx > 0)
-        {
-            ClassLoader cl = (clazz.getClassLoader() != null)
-                ? clazz.getClassLoader() : ClassLoader.getSystemClassLoader();
-            try
-            {
-                Class enclosing = cl.loadClass(clazz.getName().substring(0, idx));
-                clazz = (enclosing != null) ? enclosing : clazz;
-            }
-            catch (Throwable t)
-            {
-                // Ignore all problems since we are trying to load a class
-                // inside the class loader and this can lead to
-                // ClassCircularityError, for example.
-            }
-        }
-
-        return clazz;
-    }
-
-    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_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 ModuleClassLoader 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 ModuleClassLoader(ClassLoader parent)
-        {
-            super(parent);
-            if (m_dexFileClassLoadClass != null)
-            {
-                m_jarContentToDexFile = new HashMap();
-            }
-            else
-            {
-                m_jarContentToDexFile = null;
-            }
-        }
-
-        public Bundle getBundle()
-        {
-            return ModuleImpl.this.getBundle();
-        }
-
-        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, ModuleImpl.this, name);
-                        ex = (msg != null)
-                            ? new ClassNotFoundException(msg, cnfe)
-                            : ex;
-                    }
-                    throw ex;
-                }
-            }
-
-            // Resolve the class and return it.
-            if (resolve)
-            {
-                resolveClass(clazz);
-            }
-            return clazz;
-        }
-
-        protected Class findClass(String name) throws ClassNotFoundException
-        {
-            Class clazz = null;
-
-            // Search for class in module.
-            if (clazz == null)
-            {
-                String actual = name.replace('.', '/') + ".class";
-
-                byte[] bytes = null;
-
-                // Check the module 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()
-                                ? ((BundleImpl) getBundle()).getCurrentModule().getDeclaredActivationPolicy()
-                                : Module.EAGER_ACTIVATION;
-
-                            // If the module is using deferred activation, then if
-                            // we load this class from this module we need to activate
-                            // the module 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 == Module.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;
-        }
-
-        public URL getResource(String name)
-        {
-            return ModuleImpl.this.getResourceByDelegation(name);
-        }
-
-        protected URL findResource(String name)
-        {
-            return getResourceLocal(name);
-        }
-
-        // The findResources() method should only look at the module itself, but
-        // instead it tries to delegate because in Java version prior to 1.5 the
-        // getResources() method was final and could not be overridden. We should
-        // override getResources() like getResource() to make it delegate, but we
-        // can't. As a workaround, we make findResources() delegate instead.
-        protected Enumeration findResources(String name)
-        {
-            return getResourcesByDelegation(name);
-        }
-
-        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;
-        }
-
-        public String toString()
-        {
-            return ModuleImpl.this.toString();
-        }
-    }
-
-    private static String diagnoseClassLoadError(
-        FelixResolver resolver, ModuleImpl module, String name)
-    {
-        // We will try to do some diagnostics here to help the developer
-        // deal with this exception.
-
-        // Get package name.
-        String pkgName = Util.getClassPackage(name);
-        if (pkgName.length() == 0)
-        {
-            return null;
-        }
-
-        // First, get the bundle string of the module doing the class loader.
-        String importer = module.getBundle().toString();
-
-        // Next, check to see if the module imports the package.
-        List<Wire> wires = module.getWires();
-        for (int i = 0; (wires != null) && (i < wires.size()); i++)
-        {
-            if (wires.get(i).getCapability().getNamespace().equals(Capability.PACKAGE_NAMESPACE) &&
-                wires.get(i).getCapability().getAttribute(Capability.PACKAGE_ATTR).getValue().equals(pkgName))
-            {
-                String exporter = wires.get(i).getExporter().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<Requirement> reqs = module.getRequirements();
-/*
-* TODO: RB - Fix diagnostic message for optional imports.
-        for (int i = 0; (reqs != null) && (i < reqs.length); i++)
-        {
-            if (reqs[i].getName().equals(pkgName) && reqs[i].isOptional())
-            {
-                // Try to see if there is an exporter available.
-                IModule[] exporters = getResolvedExporters(reqs[i], true);
-                exporters = (exporters.length == 0)
-                    ? getUnresolvedExporters(reqs[i], true) : exporters;
-
-                // An exporter might be available, but it may have attributes
-                // that do not match the importer's required attributes, so
-                // check that case by simply looking for an exporter of the
-                // desired package without any attributes.
-                if (exporters.length == 0)
-                {
-                    IRequirement pkgReq = new Requirement(
-                        ICapability.PACKAGE_NAMESPACE, "(package=" + pkgName + ")");
-                    exporters = getResolvedExporters(pkgReq, true);
-                    exporters = (exporters.length == 0)
-                        ? getUnresolvedExporters(pkgReq, true) : exporters;
-                }
-
-                long expId = (exporters.length == 0)
-                    ? -1 : Util.getBundleIdFromModuleId(exporters[0].getId());
-
-                StringBuffer sb = new StringBuffer("*** Class '");
-                sb.append(name);
-                sb.append("' was not found, but this is likely normal since package '");
-                sb.append(pkgName);
-                sb.append("' is optionally imported by bundle ");
-                sb.append(impId);
-                sb.append(".");
-                if (exporters.length > 0)
-                {
-                    sb.append(" However, bundle ");
-                    sb.append(expId);
-                    if (reqs[i].isSatisfied(
-                        Util.getExportPackage(exporters[0], reqs[i].getName())))
-                    {
-                        sb.append(" does export this package. Bundle ");
-                        sb.append(expId);
-                        sb.append(" must be installed before bundle ");
-                        sb.append(impId);
-                        sb.append(" is resolved or else the optional import will be ignored.");
-                    }
-                    else
-                    {
-                        sb.append(" does export this package with attributes that do not match.");
-                    }
-                }
-                sb.append(" ***");
-
-                return sb.toString();
-            }
-        }
-*/
-        // Next, check to see if the package is dynamically imported by the module.
-        if (resolver.isAllowedDynamicImport(module, pkgName))
-        {
-            // Try to see if there is an exporter available.
-            List<Directive> dirs = Collections.EMPTY_LIST;
-            List<Attribute> attrs = new ArrayList(1);
-            attrs.add(new Attribute(Capability.PACKAGE_ATTR, pkgName, false));
-            Requirement req = new RequirementImpl(
-                module, Capability.PACKAGE_NAMESPACE, dirs, attrs);
-            Set<Capability> exporters = resolver.getCandidates(module, req, false);
-
-            Wire wire = null;
-            try
-            {
-                wire = resolver.resolve(module, pkgName);
-            }
-            catch (Exception ex)
-            {
-                wire = null;
-            }
-
-            String exporter = (exporters.size() == 0)
-                ? null : exporters.iterator().next().getModule().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) && (wire == 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.
-        List<Directive> dirs = Collections.EMPTY_LIST;
-        List<Attribute> attrs = new ArrayList(1);
-        attrs.add(new Attribute(Capability.PACKAGE_ATTR, pkgName, false));
-        Requirement req = new RequirementImpl(
-            module, Capability.PACKAGE_NAMESPACE, dirs, attrs);
-        Set<Capability> exports = resolver.getCandidates(module, req, false);
-        if (exports.size() > 0)
-        {
-            boolean classpath = false;
-            try
-            {
-                ModuleClassLoader.class.getClassLoader().loadClass(name);
-                classpath = true;
-            }
-            catch (NoClassDefFoundError err)
-            {
-                // Ignore
-            }
-            catch (Exception ex)
-            {
-                // Ignore
-            }
-
-            String exporter = exports.iterator().next().getModule().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
-        {
-            ModuleClassLoader.class.getClassLoader().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();
-    }
-
     static class FragmentRequirement implements Requirement
     {
         private final Module m_owner;

Modified: felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java?rev=952424&r1=952423&r2=952424&view=diff
==============================================================================
--- felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java (original)
+++ felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java Mon Jun  7 20:40:20 2010
@@ -103,7 +103,8 @@ class URLHandlersBundleURLConnection ext
         {
             m_classPathIdx = 0;
         }
-        if (!modules.get(revision).hasInputStream(m_classPathIdx, url.getPath()))
+        if (!((VirtualContentImpl) modules.get(revision).getVirtualContent())
+            .hasInputStream(m_classPathIdx, url.getPath()))
         {
             URL newurl = modules.get(revision).getResourceByDelegation(url.getPath());
             if (newurl == null)
@@ -122,7 +123,8 @@ class URLHandlersBundleURLConnection ext
             {
                 throw new IOException("Resource does not exist: " + url);
             }
-            m_is = m_targetModule.getInputStream(m_classPathIdx, url.getPath());
+            m_is = ((VirtualContentImpl) m_targetModule.getVirtualContent())
+                .getInputStream(m_classPathIdx, url.getPath());
             m_contentLength = (m_is == null) ? 0 : m_is.available();
             m_contentType = URLConnection.guessContentTypeFromName(url.getFile());
             connected = true;



Mime
View raw message