Return-Path: Delivered-To: apmail-felix-commits-archive@www.apache.org Received: (qmail 28180 invoked from network); 7 Jun 2010 20:40:51 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 7 Jun 2010 20:40:51 -0000 Received: (qmail 99842 invoked by uid 500); 7 Jun 2010 20:40:51 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 99810 invoked by uid 500); 7 Jun 2010 20:40:51 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 99803 invoked by uid 99); 7 Jun 2010 20:40:51 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 07 Jun 2010 20:40:51 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 07 Jun 2010 20:40:44 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 0730C23889ED; Mon, 7 Jun 2010 20:40:22 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r952424 [3/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 -0000 To: commits@felix.apache.org From: rickhall@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100607204022.0730C23889ED@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Copied: felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/VirtualContentImpl.java (from r951014, 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/VirtualContentImpl.java?p2=felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/VirtualContentImpl.java&p1=felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ModuleImpl.java&r1=951014&r2=952424&rev=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/VirtualContentImpl.java Mon Jun 7 20:40:20 2010 @@ -6,9 +6,9 @@ * 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 @@ -40,14 +40,13 @@ 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; @@ -60,63 +59,52 @@ import org.apache.felix.framework.util.F 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.BundleActivator; 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 +public class VirtualContentImpl implements VirtualContent { private final Logger m_logger; - private final Map m_configMap; + private final Map m_config; + private final URLStreamHandler m_streamHandler; private final FelixResolver m_resolver; - private final String m_id; + private final Module m_module; private final Content m_content; - private final Map m_headerMap; - private final URLStreamHandler m_streamHandler; - - private final String m_manifestVersion; - private final boolean m_isExtension; - private final String m_symbolicName; - private final Version m_version; - - private final List m_capabilities; - private List m_cachedCapabilities = null; - private final List m_requirements; - private List m_cachedRequirements = null; - private final List m_dynamicRequirements; - private List m_cachedDynamicRequirements = null; - private final List m_nativeLibraries; - private final int m_declaredActivationPolicy; - private final List m_activationIncludes; - private final List m_activationExcludes; - - private final Bundle m_bundle; - - private List m_fragments = null; - private List m_wires = null; - private List m_dependentHosts = new ArrayList(0); - private List m_dependentImporters = new ArrayList(0); - private List m_dependentRequirers = new ArrayList(0); - private volatile boolean m_isResolved = false; private Content[] m_contentPath; + private List m_fragments = null; private Content[] m_fragmentContents = null; private ModuleClassLoader m_classLoader; - private boolean m_isActivationTriggered = false; - private ProtectionDomain m_protectionDomain = null; + private volatile List m_wires = null; + private static final SecureAction m_secureAction = new SecureAction(); - // Bundle-specific class loader for boot delegation. - private final ClassLoader m_bootClassLoader; + // 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; // Default class loader for boot delegation. private final static ClassLoader m_defBootClassLoader; + private final List m_activationIncludes; + private final List m_activationExcludes; + private boolean m_isActivationTriggered = false; + // Thread local to keep track of deferred activation. + private static final ThreadLocal m_deferredActivation = new ThreadLocal(); + + // Thread local to detect class loading cycles. + private final ThreadLocal m_cycleCheck = new ThreadLocal(); + + // Re-usable security manager for accessing class context. + private static SecurityManagerEx m_sm = new SecurityManagerEx(); + // Statically define the default class loader for boot delegation. static { @@ -139,404 +127,384 @@ public class ModuleImpl implements Modul 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 - * a constructor that does not throw an exception. - * @param logger - * @param bundle - * @param id - * @param bootPkgs - * @param bootPkgWildcards - * @throws org.osgi.framework.BundleException - */ - public ModuleImpl( - Logger logger, Map configMap, Bundle bundle, String id, - String[] bootPkgs, boolean[] bootPkgWildcards) - { - 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_manifestVersion = null; - m_symbolicName = null; - m_isExtension = false; - m_version = null; - m_capabilities = null; - m_requirements = null; - m_dynamicRequirements = null; - m_nativeLibraries = null; - m_declaredActivationPolicy = EAGER_ACTIVATION; - m_activationExcludes = null; - m_activationIncludes = null; - m_implicitBootDelegation = false; - m_bootClassLoader = m_defBootClassLoader; - } - - public ModuleImpl( - Logger logger, Map configMap, FelixResolver resolver, - Bundle bundle, String id, Map headerMap, Content content, - URLStreamHandler streamHandler, String[] bootPkgs, - boolean[] bootPkgWildcards) - throws BundleException + public VirtualContentImpl(Logger logger, Map config, URLStreamHandler streamHandler, + FelixResolver resolver, Module module, Content content, + String[] bootPkgs, boolean[] bootPkgWildcards, + List activationIncludes, List activationExcludes) { m_logger = logger; - m_configMap = configMap; + m_config = config; + m_streamHandler = streamHandler; m_resolver = resolver; - m_bundle = bundle; - m_id = id; - m_headerMap = headerMap; + m_module = module; m_content = content; - m_streamHandler = streamHandler; m_bootPkgs = bootPkgs; m_bootPkgWildcards = bootPkgWildcards; + m_activationIncludes = activationIncludes; + m_activationExcludes = activationExcludes; m_implicitBootDelegation = - (m_configMap.get(FelixConstants.IMPLICIT_BOOT_DELEGATION_PROP) == null) + (m_config.get(FelixConstants.IMPLICIT_BOOT_DELEGATION_PROP) == null) || Boolean.valueOf( - (String) m_configMap.get( + (String) m_config.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); - - // Record some of the parsed metadata. Note, if this is an extension - // bundle it's exports are removed, since they will be added to the - // system bundle directly later on. - m_manifestVersion = mp.getManifestVersion(); - m_version = mp.getBundleVersion(); - m_capabilities = mp.isExtension() ? null : mp.getCapabilities(); - m_requirements = mp.getRequirements(); - m_dynamicRequirements = mp.getDynamicRequirements(); - m_nativeLibraries = mp.getLibraries(); - m_declaredActivationPolicy = mp.getActivationPolicy(); - m_activationExcludes = (mp.getActivationExcludeDirective() == null) - ? null - : ManifestParser.parseDelimitedString(mp.getActivationExcludeDirective(), ","); - m_activationIncludes = (mp.getActivationIncludeDirective() == null) - ? null - : ManifestParser.parseDelimitedString(mp.getActivationIncludeDirective(), ","); - m_symbolicName = mp.getSymbolicName(); - m_isExtension = mp.isExtension(); - } - - // - // Metadata access methods. - // - - public Map getHeaders() - { - return m_headerMap; } - public boolean isExtension() + synchronized void close() { - return m_isExtension; + 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; } - public String getSymbolicName() - { - return m_symbolicName; - } + // + // VirtualContent methods. + // - public String getManifestVersion() + public void resolve(List wires) throws BundleException { - return m_manifestVersion; + m_wires = wires; } - public Version getVersion() + public BundleActivator getActivator() { - return m_version; + throw new UnsupportedOperationException("Not supported yet."); } - public synchronized List getCapabilities() + public Class loadClass(String name) throws ClassNotFoundException { - if (m_cachedCapabilities == null) + // 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) == '[')) { - List capList = (m_capabilities == null) - ? new ArrayList() - : new ArrayList(m_capabilities); - for (int fragIdx = 0; - (m_fragments != null) && (fragIdx < m_fragments.size()); - fragIdx++) - { - List caps = m_fragments.get(fragIdx).getCapabilities(); - for (int capIdx = 0; - (caps != null) && (capIdx < caps.size()); - capIdx++) - { - if (caps.get(capIdx).getNamespace().equals(Capability.PACKAGE_NAMESPACE)) - { - capList.add( - new CapabilityImpl( - this, - caps.get(capIdx).getNamespace(), - caps.get(capIdx).getDirectives(), - caps.get(capIdx).getAttributes())); - } - } - } - m_cachedCapabilities = Collections.unmodifiableList(capList); + return Class.forName(name, false, getClassLoader()); } - return m_cachedCapabilities; + return getClassLoader().loadClass(name); } - public synchronized List getRequirements() + public URL getResource(String name) { - if (m_cachedRequirements == null) + try { - List reqList = (m_requirements == null) - ? new ArrayList() : new ArrayList(m_requirements); - for (int fragIdx = 0; - (m_fragments != null) && (fragIdx < m_fragments.size()); - fragIdx++) - { - List reqs = m_fragments.get(fragIdx).getRequirements(); - for (int reqIdx = 0; - (reqs != null) && (reqIdx < reqs.size()); - reqIdx++) - { - if (reqs.get(reqIdx).getNamespace().equals(Capability.PACKAGE_NAMESPACE) - || reqs.get(reqIdx).getNamespace().equals(Capability.MODULE_NAMESPACE)) - { - reqList.add( - new FragmentRequirement( - this, reqs.get(reqIdx))); - } - } - } - m_cachedRequirements = Collections.unmodifiableList(reqList); + return (URL) findClassOrResourceByDelegation(name, false); } - return m_cachedRequirements; - } - - public synchronized List getDynamicRequirements() - { - if (m_cachedDynamicRequirements == null) + catch (ClassNotFoundException ex) { - List reqList = (m_dynamicRequirements == null) - ? new ArrayList() : new ArrayList(m_dynamicRequirements); - for (int fragIdx = 0; - (m_fragments != null) && (fragIdx < m_fragments.size()); - fragIdx++) - { - List reqs = m_fragments.get(fragIdx).getDynamicRequirements(); - for (int reqIdx = 0; - (reqs != null) && (reqIdx < reqs.size()); - reqIdx++) - { - if (reqs.get(reqIdx).getNamespace().equals(Capability.PACKAGE_NAMESPACE)) - { - reqList.add(reqs.get(reqIdx)); - } - } - } - m_cachedDynamicRequirements = Collections.unmodifiableList(reqList); + // This should never be thrown because we are loading resources. } - return m_cachedDynamicRequirements; + catch (ResourceNotFoundException ex) + { + m_logger.log( + Logger.LOG_DEBUG, + ex.getMessage()); + } + return null; } - public synchronized List getNativeLibraries() + public Enumeration getResources(String name) { - List result = null; - if (m_isResolved) + Set requestSet = (Set) m_cycleCheck.get(); + if (requestSet == null) { - List nativeList = (m_nativeLibraries == null) - ? new ArrayList() : new ArrayList(m_nativeLibraries); - for (int fragIdx = 0; - (m_fragments != null) && (fragIdx < m_fragments.size()); - fragIdx++) - { - List libs = 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.size() == 0) - ? null - : Collections.unmodifiableList(nativeList); + requestSet = new HashSet(); + m_cycleCheck.set(requestSet); } - else + if (!requestSet.contains(name)) { - result = m_nativeLibraries; + requestSet.add(name); + try + { + Enumeration urls = findResourcesByDelegation(name); + return (urls.hasMoreElements()) ? urls : null; + } + finally + { + requestSet.remove(name); + } } - return result; - } - - public int getDeclaredActivationPolicy() - { - return m_declaredActivationPolicy; + return null; } - synchronized boolean isActivationTriggered() + // 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) { - return m_isActivationTriggered; - } + URL url = null; - boolean isActivationTrigger(String pkgName) - { - if ((m_activationIncludes == null) && (m_activationExcludes == null)) + // Check for the special case of "/", which represents + // the root of the bundle according to the spec. + if (name.equals("/")) { - return true; + url = createURL(0, "/"); } - // If there are no include filters then all classes are included - // by default, otherwise try to find one match. - boolean included = (m_activationIncludes == null); - for (int i = 0; - (!included) && (m_activationIncludes != null) && (i < m_activationIncludes.size()); - i++) + if (url == null) { - included = m_activationIncludes.get(i).equals(pkgName); - } + // Remove leading slash, if present. + if (name.startsWith("/")) + { + name = name.substring(1); + } - // If there are no exclude filters then no classes are excluded - // by default, otherwise try to find one match. - boolean excluded = false; - for (int i = 0; - (!excluded) && (m_activationExcludes != null) && (i < m_activationExcludes.size()); - i++) - { - excluded = m_activationExcludes.get(i).equals(pkgName); + // Check the module content. + if (m_content.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 included && !excluded; - } - - // - // Run-time data access. - // - public Bundle getBundle() - { - return m_bundle; + return url; } - public String getId() + public Enumeration getEntryPaths(String path) { - return m_id; + return new EntryFilterEnumeration(m_module, false, path, "*", false, false); } - public synchronized List getWires() + public Enumeration findEntries(String path, String filePattern, boolean recurse) { - return m_wires; + return new EntryFilterEnumeration(m_module, true, path, filePattern, recurse, true); } - public synchronized void setWires(List wires) + // + // Content access for bundle URL stream handler. + // + + // TODO: URL HANDLERS - For expediency, the index argument was added to these methods + // but it is not clear that this makes sense in the long run. This needs to + // be readdressed in the future, perhaps by the spec to clearly indicate + // how resources on the bundle class path are searched, which is why we + // need the index number in the first place -- to differentiate among + // resources with the same name on the bundle class path. This was previously + // handled as part of the resource path, but that approach is not spec + // compliant. + boolean hasInputStream(int index, String urlPath) { - // Remove module from old wire modules' dependencies, - // since we are no longer dependent on any the moduels - // from the old wires. - for (int i = 0; (m_wires != null) && (i < m_wires.size()); i++) + if (urlPath.startsWith("/")) { - if (m_wires.get(i).getCapability().getNamespace().equals(Capability.MODULE_NAMESPACE)) - { - ((ModuleImpl) m_wires.get(i).getExporter()).removeDependentRequirer(this); - } - else if (m_wires.get(i).getCapability().getNamespace().equals(Capability.PACKAGE_NAMESPACE)) - { - ((ModuleImpl) m_wires.get(i).getExporter()).removeDependentImporter(this); - } + urlPath = urlPath.substring(1); } - - m_wires = wires; - - // Add ourself as a dependent to the new wires' modules. - for (int i = 0; (m_wires != null) && (i < m_wires.size()); i++) + if (index == 0) { - if (m_wires.get(i).getCapability().getNamespace().equals(Capability.MODULE_NAMESPACE)) - { - ((ModuleImpl) m_wires.get(i).getExporter()).addDependentRequirer(this); - } - else if (m_wires.get(i).getCapability().getNamespace().equals(Capability.PACKAGE_NAMESPACE)) - { - ((ModuleImpl) m_wires.get(i).getExporter()).addDependentImporter(this); - } + return m_content.hasEntry(urlPath); } + return getContentPath()[index - 1].hasEntry(urlPath); } - public boolean isResolved() - { - return m_isResolved; - } - - public void setResolved() + InputStream getInputStream(int index, String urlPath) + throws IOException { - m_isResolved = true; + if (urlPath.startsWith("/")) + { + urlPath = urlPath.substring(1); + } + if (index == 0) + { + return m_content.getEntryAsStream(urlPath); + } + return getContentPath()[index - 1].getEntryAsStream(urlPath); } // - // Content access methods. + // Implementation details. // - public Content getContent() - { - return m_content; - } - - private synchronized Content[] getContentPath() + private synchronized ModuleClassLoader getClassLoader() { - if (m_contentPath == null) + if (m_classLoader == null) { - try + if (System.getSecurityManager() != null) { - m_contentPath = initializeContentPath(); + 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() + "]"); + } } - catch (Exception ex) + else { - m_logger.log(Logger.LOG_ERROR, "Unable to get module class path.", ex); + m_classLoader = new ModuleClassLoader(determineParentClassLoader()); } } - return m_contentPath; + return m_classLoader; } - private Content[] initializeContentPath() throws Exception + private ClassLoader determineParentClassLoader() { - 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); - } + // Determine the class loader's parent based on the + // configuration property; use boot class loader by + // default. + String cfg = (String) m_config.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. +// TODO: VB - I think this is incorrect now. + else if (m_defBootClassLoader == null) + { + parent = m_secureAction.getSystemClassLoader(); + } + else + { + parent = null; + } + return 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; + } + + synchronized void attachFragments(List fragments) throws Exception + { + // Update the dependencies on the new fragments. + m_fragments = fragments; + + if (m_fragments != null) + { + // We also need to create an array of fragment contents + // to attach to our class loader. + Content[] fragmentContents = new Content[m_fragments.size()]; + for (int i = 0; (m_fragments != null) && (i < m_fragments.size()); i++) + { + fragmentContents[i] = + ((VirtualContentImpl) m_fragments.get(i).getVirtualContent()) + .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(); + } + + Content getContent() + { + return m_content; + } + + private synchronized Content[] getContentPath() + { + 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; + } + + private Content[] initializeContentPath() throws Exception + { + List contentList = new ArrayList(); + calculateContentPath(m_module, 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()]); } @@ -622,37 +590,6 @@ public class ModuleImpl implements Modul 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( - Logger.LOG_DEBUG, - ex.getMessage()); - } - return null; - } - private Object findClassOrResourceByDelegation(String name, boolean isClass) throws ClassNotFoundException, ResourceNotFoundException { @@ -669,7 +606,7 @@ public class ModuleImpl implements Modul try { // First, try to resolve the originating module. - m_resolver.resolve(this); + m_resolver.resolve(m_module); // Get the package of the target class/resource. String pkgName = (isClass) @@ -812,31 +749,6 @@ public class ModuleImpl implements Modul 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 - { - Enumeration urls = findResourcesByDelegation(name); - return (urls.hasMoreElements()) ? urls : null; - } - finally - { - requestSet.remove(name); - } - } - - return null; - } - private Enumeration findResourcesByDelegation(String name) { Enumeration urls = null; @@ -845,7 +757,7 @@ public class ModuleImpl implements Modul // First, try to resolve the originating module. try { - m_resolver.resolve(this); + m_resolver.resolve(m_module); } catch (ResolveException ex) { @@ -892,7 +804,7 @@ public class ModuleImpl implements Modul // Note that the search may be aborted if this method throws an // exception, otherwise it continues if a null is returned. - List wires = getWires(); + List wires = m_wires; for (int i = 0; (wires != null) && (i < wires.size()); i++) { if (wires.get(i) instanceof WireImpl) @@ -912,433 +824,147 @@ public class ModuleImpl implements Modul 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). - 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); - } - } - } - - // 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. - 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); - } - } - } - - return new CompoundEnumeration((Enumeration[]) - completeUrlList.toArray(new Enumeration[completeUrlList.size()])); - } - - private Enumeration getResourcesLocal(String name) - { - Vector v = new Vector(); - - // Special case "/" so that it returns a root URLs for - // each bundle class path entry...this isn't very - // clean or meaningful, but the Spring guys want it. - final Content[] contentPath = getContentPath(); - if (name.equals("/")) - { - for (int i = 0; i < contentPath.length; i++) - { - v.addElement(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 < 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)); - } - } - } - - return v.elements(); - } - - // TODO: API: Investigate how to handle this better, perhaps we need - // multiple URL policies, one for content -- one for class path. - public URL getEntry(String name) - { - URL url = null; - - // Check for the special case of "/", which represents - // the root of the bundle according to the spec. - if (name.equals("/")) - { - url = 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 getFragments() - { - return m_fragments; - } - - public synchronized void attachFragments(List 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 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 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 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 getDependents() - { - List dependents = new ArrayList - (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; - } - - public synchronized void setSecurityContext(Object securityContext) - { - m_protectionDomain = (ProtectionDomain) securityContext; - } - - public synchronized Object getSecurityContext() - { - return m_protectionDomain; - } - - public String toString() - { - return m_id; - } - private synchronized ModuleClassLoader getClassLoader() - { - if (m_classLoader == null) + // 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 (System.getSecurityManager() != null) + if (wires.get(i) instanceof WireModuleImpl) { 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() }); + // If we find the class or resource, then add it. + urls = wires.get(i).getResources(name); } - catch (Exception ex) + catch (ResourceNotFoundException ex) { - throw new RuntimeException("Unable to create module class loader: " - + ex.getMessage() + " [" + ex.getClass().getName() + "]"); + urls = null; + } + if (urls != null) + { + completeUrlList.add(urls); } - } - 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)) + // 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())) { - parent = m_secureAction.getSystemClassLoader().getParent(); + completeUrlList.add(urls); } - else if (cfg.equalsIgnoreCase(Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK)) + else { - parent = ModuleImpl.class.getClassLoader(); + // 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(m_module, 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); + } + } } - // 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) + + return new CompoundEnumeration((Enumeration[]) + completeUrlList.toArray(new Enumeration[completeUrlList.size()])); + } + + private Enumeration getResourcesLocal(String name) + { + Vector v = new Vector(); + + // Special case "/" so that it returns a root URLs for + // each bundle class path entry...this isn't very + // clean or meaningful, but the Spring guys want it. + final Content[] contentPath = getContentPath(); + if (name.equals("/")) { - parent = m_secureAction.getSystemClassLoader(); + for (int i = 0; i < contentPath.length; i++) + { + v.addElement(createURL(i + 1, name)); + } } else { - parent = null; + // 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)); + } + } } - return parent; + + return v.elements(); + } + + 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_module.getId() + ":" + port + path, m_streamHandler); + } + catch (MalformedURLException ex) + { + m_logger.log( + Logger.LOG_ERROR, + "Unable to create resource URL.", + ex); + } + return null; } private Object searchImports(String name, boolean isClass) throws ClassNotFoundException, ResourceNotFoundException { // We delegate to the module's wires to find the class or resource. - List wires = getWires(); + List wires = m_wires; for (int i = 0; (wires != null) && (i < wires.size()); i++) { // If we find the class or resource, then return it. @@ -1364,7 +990,7 @@ public class ModuleImpl implements Modul Wire wire = null; try { - wire = m_resolver.resolve(this, pkgName); + wire = m_resolver.resolve(m_module, pkgName); } catch (ResolveException ex) { @@ -1444,7 +1070,7 @@ public class ModuleImpl implements Modul } private Object doImplicitBootDelegation(Class[] classes, String name, boolean isClass) - throws ClassNotFoundException, ResourceNotFoundException + throws ClassNotFoundException, ResourceNotFoundException { // Start from 1 to skip security manager class. for (int i = 1; i < classes.length; i++) @@ -1477,8 +1103,8 @@ public class ModuleImpl implements Modul // break out of loop and return null. boolean delegate = true; ClassLoader last = null; - for (ClassLoader cl = classes[i].getClassLoader(); - (cl != null) && (last != cl); + for (ClassLoader cl = classes[i].getClassLoader(); + (cl != null) && (last != cl); cl = cl.getClass().getClassLoader()) { last = cl; @@ -1551,15 +1177,8 @@ public class ModuleImpl implements Modul return clazz; } - boolean shouldBootDelegate(String pkgName) + private 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 @@ -1588,58 +1207,46 @@ public class ModuleImpl implements Modul return result; } - ClassLoader getBootDelegationClassLoader() + private ClassLoader getBootDelegationClassLoader() { // Get the appropriate class loader for delegation. ClassLoader parent = (m_classLoader == null) ? determineParentClassLoader() : m_classLoader.getParent(); - return (parent == null) ? m_bootClassLoader : parent; + return (parent == null) ? m_defBootClassLoader : parent; } - private static final Constructor m_dexFileClassConstructor; - private static final Method m_dexFileClassLoadDex; - private static final Method m_dexFileClassLoadClass; + private synchronized boolean isActivationTriggered() + { + return m_isActivationTriggered; + } - static + private boolean isActivationTrigger(String pkgName) { - Constructor dexFileClassConstructor = null; - Method dexFileClassLoadDex = null; - Method dexFileClassLoadClass = null; - try + if ((m_activationIncludes == null) && (m_activationExcludes == null)) { - Class dexFileClass; - try - { - dexFileClass = Class.forName("dalvik.system.DexFile"); - } - catch (Exception ex) - { - dexFileClass = Class.forName("android.dalvik.DexFile"); - } + return true; + } - 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 }); + // If there are no include filters then all classes are included + // by default, otherwise try to find one match. + boolean included = (m_activationIncludes == null); + for (int i = 0; + (!included) && (m_activationIncludes != null) && (i < m_activationIncludes.size()); + i++) + { + included = m_activationIncludes.get(i).equals(pkgName); } - catch (Throwable ex) + + // If there are no exclude filters then no classes are excluded + // by default, otherwise try to find one match. + boolean excluded = false; + for (int i = 0; + (!excluded) && (m_activationExcludes != null) && (i < m_activationExcludes.size()); + i++) { - dexFileClassConstructor = null; - dexFileClassLoadDex = null; - dexFileClassLoadClass = null; + excluded = m_activationExcludes.get(i).equals(pkgName); } - m_dexFileClassConstructor = dexFileClassConstructor; - m_dexFileClassLoadDex= dexFileClassLoadDex; - m_dexFileClassLoadClass = dexFileClassLoadClass; + return included && !excluded; } public class ModuleClassLoader extends SecureClassLoader implements BundleReference @@ -1664,7 +1271,7 @@ public class ModuleImpl implements Modul public Bundle getBundle() { - return ModuleImpl.this.getBundle(); + return m_module.getBundle(); } protected Class loadClass(String name, boolean resolve) @@ -1695,7 +1302,7 @@ public class ModuleImpl implements Modul String msg = name; if (m_logger.getLogLevel() >= Logger.LOG_DEBUG) { - msg = diagnoseClassLoadError(m_resolver, ModuleImpl.this, name); + msg = diagnoseClassLoadError(m_resolver, (ModuleImpl) m_module, name); ex = (msg != null) ? new ClassNotFoundException(msg, cnfe) : ex; @@ -1748,7 +1355,7 @@ public class ModuleImpl implements Modul if (clazz == null) { - int activationPolicy = + int activationPolicy = ((BundleImpl) getBundle()).isDeclaredActivationPolicyUsed() ? ((BundleImpl) getBundle()).getCurrentModule().getDeclaredActivationPolicy() : Module.EAGER_ACTIVATION; @@ -1819,10 +1426,10 @@ public class ModuleImpl implements Modul // 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) + if (m_module.getSecurityContext() != null) { clazz = defineClass(name, bytes, 0, bytes.length, - m_protectionDomain); + (ProtectionDomain) m_module.getSecurityContext()); } else { @@ -1868,12 +1475,12 @@ public class ModuleImpl implements Modul 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"); + String spectitle = (String) m_module.getHeaders().get("Specification-Title"); + String specversion = (String) m_module.getHeaders().get("Specification-Version"); + String specvendor = (String) m_module.getHeaders().get("Specification-Vendor"); + String impltitle = (String) m_module.getHeaders().get("Implementation-Title"); + String implversion = (String) m_module.getHeaders().get("Implementation-Version"); + String implvendor = (String) m_module.getHeaders().get("Implementation-Vendor"); if ((spectitle != null) || (specversion != null) || (specvendor != null) @@ -1904,8 +1511,8 @@ public class ModuleImpl implements Modul { if (m_dexFileClassLoadDex != null) { - dexFile = m_dexFileClassLoadDex.invoke(null, - new Object[]{content.getFile().getAbsolutePath(), + dexFile = m_dexFileClassLoadDex.invoke(null, + new Object[]{content.getFile().getAbsolutePath(), content.getFile().getAbsolutePath() + ".dex", new Integer(0)}); } else @@ -1934,12 +1541,12 @@ public class ModuleImpl implements Modul public URL getResource(String name) { - return ModuleImpl.this.getResourceByDelegation(name); + return VirtualContentImpl.this.getResource(name); } protected URL findResource(String name) { - return getResourceLocal(name); + return VirtualContentImpl.this.getResourceLocal(name); } // The findResources() method should only look at the module itself, but @@ -1949,7 +1556,7 @@ public class ModuleImpl implements Modul // can't. As a workaround, we make findResources() delegate instead. protected Enumeration findResources(String name) { - return getResourcesByDelegation(name); + return VirtualContentImpl.this.getResources(name); } protected String findLibrary(String name) @@ -1979,13 +1586,13 @@ public class ModuleImpl implements Modul // native library. if (result == null) { - List libs = getNativeLibraries(); + List libs = m_module.getNativeLibraries(); for (int libIdx = 0; (libs != null) && (libIdx < libs.size()); libIdx++) { - if (libs.get(libIdx).match(m_configMap, name)) + if (libs.get(libIdx).match(m_config, name)) { // Search bundle content first for native library. - result = getContent().getEntryAsNativeLibrary( + result = m_content.getEntryAsNativeLibrary( libs.get(libIdx).getEntryName()); // If not found, then search fragments in order. for (int i = 0; @@ -2015,7 +1622,7 @@ public class ModuleImpl implements Modul public String toString() { - return ModuleImpl.this.toString(); + return m_module.toString(); } } @@ -2275,56 +1882,4 @@ public class ModuleImpl implements Modul return sb.toString(); } - - static class FragmentRequirement implements Requirement - { - private final Module m_owner; - private final Requirement m_fragmentReq; - - public FragmentRequirement(Module owner, Requirement fragmentReq) - { - m_owner = owner; - m_fragmentReq = fragmentReq; - } - - public Module getFragment() - { - return m_fragmentReq.getModule(); - } - - public Module getModule() - { - return m_owner; - } - - public String getNamespace() - { - return m_fragmentReq.getNamespace(); - } - - public SimpleFilter getFilter() - { - return m_fragmentReq.getFilter(); - } - - public boolean isOptional() - { - return m_fragmentReq.isOptional(); - } - - public Directive getDirective(String name) - { - return m_fragmentReq.getDirective(name); - } - - public List getDirectives() - { - return m_fragmentReq.getDirectives(); - } - - public String toString() - { - return m_fragmentReq.toString(); - } - } } \ No newline at end of file Modified: felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/VirtualContent.java URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/VirtualContent.java?rev=952424&r1=952423&r2=952424&view=diff ============================================================================== --- felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/VirtualContent.java (original) +++ felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/VirtualContent.java Mon Jun 7 20:40:20 2010 @@ -30,11 +30,11 @@ public interface VirtualContent void resolve(List wires) throws BundleException; BundleActivator getActivator(); - Class loadClass(String name); + Class loadClass(String name) throws ClassNotFoundException; URL getResource(String name); Enumeration getResources(String name); URL getEntry(String entry); - Enumeration getEntryPaths(); - Enumeration findEntries(); + Enumeration getEntryPaths(String path); + Enumeration findEntries(String path, String filePattern, boolean recurse); } \ No newline at end of file Copied: felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/WireX.java (from r951014, felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/Wire.java) URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/WireX.java?p2=felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/WireX.java&p1=felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/Wire.java&r1=951014&r2=952424&rev=952424&view=diff ============================================================================== --- felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/Wire.java (original) +++ felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/ext/WireX.java Mon Jun 7 20:40:20 2010 @@ -21,7 +21,7 @@ package org.apache.felix.framework.ext; import java.net.URL; import java.util.Enumeration; -public interface Wire +public interface WireX { Class loadClass(String name); URL getResource(String name); Modified: felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/resolver/Module.java URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/resolver/Module.java?rev=952424&r1=952423&r2=952424&view=diff ============================================================================== --- felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/resolver/Module.java (original) +++ felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/resolver/Module.java Mon Jun 7 20:40:20 2010 @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import org.apache.felix.framework.capabilityset.Capability; import org.apache.felix.framework.capabilityset.Requirement; +import org.apache.felix.framework.ext.VirtualContent; import org.apache.felix.framework.util.manifestparser.R4Library; import org.osgi.framework.Bundle; import org.osgi.framework.Version; @@ -54,22 +55,9 @@ public interface Module Object getSecurityContext(); // Content access methods. - Content getContent(); + VirtualContent getVirtualContent(); Class getClassByDelegation(String name) throws ClassNotFoundException; URL getResourceByDelegation(String name); Enumeration getResourcesByDelegation(String name); URL getEntry(String name); - - // TODO: ML - For expediency, the index argument was added to these methods - // but it is not clear that this makes sense in the long run. This needs to - // be readdressed in the future, perhaps by the spec to clearly indicate - // how resources on the bundle class path are searched, which is why we - // need the index number in the first place -- to differentiate among - // resources with the same name on the bundle class path. This was previously - // handled as part of the resource path, but that approach is not spec - // compliant. - boolean hasInputStream(int index, String urlPath) - throws IOException; - InputStream getInputStream(int index, String urlPath) - throws IOException; } \ No newline at end of file Modified: felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/util/FelixConstants.java URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/util/FelixConstants.java?rev=952424&r1=952423&r2=952424&view=diff ============================================================================== --- felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/util/FelixConstants.java (original) +++ felix/sandbox/rickhall/framework-vb/src/main/java/org/apache/felix/framework/util/FelixConstants.java Mon Jun 7 20:40:20 2010 @@ -52,7 +52,6 @@ public interface FelixConstants extends = "felix.startlevel.bundle"; public static final String SERVICE_URLHANDLERS_PROP = "felix.service.urlhandlers"; public static final String IMPLICIT_BOOT_DELEGATION_PROP = "felix.bootdelegation.implicit"; - public static final String BOOT_CLASSLOADERS_PROP = "felix.bootdelegation.classloaders"; // Start level-related constants. public static final int FRAMEWORK_INACTIVE_STARTLEVEL = 0;