You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2009/01/08 20:35:09 UTC
svn commit: r732800 [4/4] - in
/felix/trunk/framework/src/main/java/org/apache/felix: framework/
framework/cache/ framework/searchpolicy/ framework/util/ moduleloader/
Added: felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java?rev=732800&view=auto
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java (added)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java Thu Jan 8 11:35:07 2009
@@ -0,0 +1,1191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework.searchpolicy;
+
+import org.apache.felix.moduleloader.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Proxy;
+import java.net.URL;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import org.apache.felix.framework.Felix.FelixResolver;
+import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.util.CompoundEnumeration;
+import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.framework.util.SecureAction;
+import org.apache.felix.framework.util.SecurityManagerEx;
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.framework.util.manifestparser.ManifestParser;
+import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+public class ModuleImpl implements IModule
+{
+ private final Logger m_logger;
+
+ private Bundle m_bundle = null;
+
+ private final Map m_headerMap;
+ private final ICapability[] m_capabilities;
+ private final IRequirement[] m_requirements;
+ private final IRequirement[] m_dynamicRequirements;
+ private final R4Library[] m_nativeLibraries;
+
+ private final String m_id;
+ private volatile String m_symbolicName = null;
+ private IModule[] m_fragments = null;
+ private IWire[] m_wires = null;
+ private IModule[] m_dependentHosts = new IModule[0];
+ private IModule[] m_dependentImporters = new IModule[0];
+ private IModule[] m_dependentRequirers = new IModule[0];
+ private volatile boolean m_isResolved = false;
+
+ // TODO: REFACTOR - Fields below are from ContentLoaderImpl
+ private final Map m_configMap;
+ private final FelixResolver m_resolver;
+ private final IContent m_content;
+ private IContent[] m_contentPath;
+ private IContent[] m_fragmentContents = null;
+ private IURLPolicy m_urlPolicy = null;
+ private ModuleClassLoader m_classLoader;
+ private ProtectionDomain m_protectionDomain = null;
+ private static SecureAction m_secureAction = new SecureAction();
+
+ // Boot delegation packages.
+ private final String[] m_bootPkgs;
+ private final boolean[] m_bootPkgWildcards;
+
+ // Re-usable security manager for accessing class context.
+ private static SecurityManagerEx m_sm = new SecurityManagerEx();
+
+// TODO: REFACTOR - Should the module constructor parse the manifest?
+ public ModuleImpl(Logger logger, Map configMap, FelixResolver resolver,
+ String id, IContent content, Map headerMap,
+ ICapability[] caps, IRequirement[] reqs, IRequirement[] dynReqs,
+ R4Library[] nativeLibs)
+ {
+ m_logger = logger;
+ m_configMap = configMap;
+ m_resolver = resolver;
+ m_id = id;
+ m_content = content;
+ m_headerMap = headerMap;
+ m_capabilities = caps;
+ m_requirements = reqs;
+ m_dynamicRequirements = dynReqs;
+ m_nativeLibraries = nativeLibs;
+
+ // Read the boot delegation property and parse it.
+// TODO: REFACTOR - This used to be per framework, now it is per module
+// which doesn't really make sense.
+ String s = (m_configMap == null)
+ ? null
+ : (String) m_configMap.get(Constants.FRAMEWORK_BOOTDELEGATION);
+ s = (s == null) ? "java.*" : s + ",java.*";
+ StringTokenizer st = new StringTokenizer(s, " ,");
+ m_bootPkgs = new String[st.countTokens()];
+ m_bootPkgWildcards = new boolean[m_bootPkgs.length];
+ for (int i = 0; i < m_bootPkgs.length; i++)
+ {
+ s = st.nextToken();
+ if (s.endsWith("*"))
+ {
+ m_bootPkgWildcards[i] = true;
+ s = s.substring(0, s.length() - 1);
+ }
+ m_bootPkgs[i] = s;
+ }
+ }
+
+ public synchronized Bundle getBundle()
+ {
+ return m_bundle;
+ }
+
+ public synchronized void setBundle(Bundle bundle)
+ {
+ if (m_bundle == null)
+ {
+ m_bundle = bundle;
+ }
+ }
+
+ public String getId()
+ {
+ return m_id;
+ }
+
+ public String getSymbolicName()
+ {
+ if (m_symbolicName == null)
+ {
+ for (int capIdx = 0;
+ (m_symbolicName == null) && (m_capabilities != null) && (capIdx < m_capabilities.length);
+ capIdx++)
+ {
+ if (m_capabilities[capIdx].getNamespace().equals(ICapability.MODULE_NAMESPACE))
+ {
+ m_symbolicName = (String) m_capabilities[capIdx].getProperties().get(
+ Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
+ }
+ }
+ }
+ return m_symbolicName;
+ }
+
+ public Map getHeaders()
+ {
+ return m_headerMap;
+ }
+
+ public ICapability[] getCapabilities()
+ {
+ return m_capabilities;
+ }
+
+ public IRequirement[] getRequirements()
+ {
+ return m_requirements;
+ }
+
+ public IRequirement[] getDynamicRequirements()
+ {
+ return m_dynamicRequirements;
+ }
+
+ public R4Library[] getNativeLibraries()
+ {
+ return m_nativeLibraries;
+ }
+
+ public synchronized IModule[] getFragments()
+ {
+ return m_fragments;
+ }
+
+ public synchronized void attachFragments(IModule[] fragments) throws Exception
+ {
+ // Remove module from old fragment dependencies.
+ // We will generally only remove module fragment
+ // dependencies when we are uninstalling the module.
+ for (int i = 0; (m_fragments != null) && (i < m_fragments.length); i++)
+ {
+ ((ModuleImpl) m_fragments[i]).removeDependentHost(this);
+ }
+
+ // Update the dependencies on the new fragments.
+ m_fragments = fragments;
+
+ // We need to add ourself as a dependent of each fragment
+ // module. We also need to create an array of fragment contents
+ // to attach to our content loader.
+ if (m_fragments != null)
+ {
+ IContent[] fragmentContents = new IContent[m_fragments.length];
+ for (int i = 0; (m_fragments != null) && (i < m_fragments.length); i++)
+ {
+ ((ModuleImpl) m_fragments[i]).addDependentHost(this);
+ fragmentContents[i] =
+ m_fragments[i].getContent()
+ .getEntryAsContent(FelixConstants.CLASS_PATH_DOT);
+ }
+ // Now attach the fragment contents to our content loader.
+ attachFragmentContents(fragmentContents);
+ }
+ }
+
+ private void attachFragmentContents(IContent[] fragmentContents)
+ throws Exception
+ {
+ // Close existing fragment contents.
+ if (m_fragmentContents != null)
+ {
+ for (int i = 0; i < m_fragmentContents.length; i++)
+ {
+ m_fragmentContents[i].close();
+ }
+ }
+ m_fragmentContents = fragmentContents;
+
+ if (m_contentPath != null)
+ {
+ for (int i = 0; i < m_contentPath.length; i++)
+ {
+ m_contentPath[i].close();
+ }
+ }
+ m_contentPath = initializeContentPath();
+ }
+
+ public synchronized IWire[] getWires()
+ {
+ return m_wires;
+ }
+
+ public synchronized void setWires(IWire[] wires)
+ {
+ // Remove module from old wire modules' dependencies,
+ // since we are no longer dependent on any the moduels
+ // from the old wires.
+ for (int i = 0; (m_wires != null) && (i < m_wires.length); i++)
+ {
+ if (m_wires[i].getCapability().getNamespace().equals(ICapability.MODULE_NAMESPACE))
+ {
+ ((ModuleImpl) m_wires[i].getExporter()).removeDependentRequirer(this);
+ }
+ else if (m_wires[i].getCapability().getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ {
+ ((ModuleImpl) m_wires[i].getExporter()).removeDependentImporter(this);
+ }
+ }
+
+ m_wires = wires;
+
+ // Add ourself as a dependent to the new wires' modules.
+ for (int i = 0; (m_wires != null) && (i < m_wires.length); i++)
+ {
+ if (m_wires[i].getCapability().getNamespace().equals(ICapability.MODULE_NAMESPACE))
+ {
+ ((ModuleImpl) m_wires[i].getExporter()).addDependentRequirer(this);
+ }
+ else if (m_wires[i].getCapability().getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ {
+ ((ModuleImpl) m_wires[i].getExporter()).addDependentImporter(this);
+ }
+ }
+ }
+
+ public synchronized IModule[] getDependentHosts()
+ {
+ return m_dependentHosts;
+ }
+
+ public synchronized void addDependentHost(IModule module)
+ {
+ m_dependentHosts = addDependent(m_dependentHosts, module);
+ }
+
+ public synchronized void removeDependentHost(IModule module)
+ {
+ m_dependentHosts = removeDependent(m_dependentHosts, module);
+ }
+
+ public synchronized IModule[] getDependentImporters()
+ {
+ return m_dependentImporters;
+ }
+
+ public synchronized void addDependentImporter(IModule module)
+ {
+ m_dependentImporters = addDependent(m_dependentImporters, module);
+ }
+
+ public synchronized void removeDependentImporter(IModule module)
+ {
+ m_dependentImporters = removeDependent(m_dependentImporters, module);
+ }
+
+ public synchronized IModule[] getDependentRequirers()
+ {
+ return m_dependentRequirers;
+ }
+
+ public synchronized void addDependentRequirer(IModule module)
+ {
+ m_dependentRequirers = addDependent(m_dependentRequirers, module);
+ }
+
+ public synchronized void removeDependentRequirer(IModule module)
+ {
+ m_dependentRequirers = removeDependent(m_dependentRequirers, module);
+ }
+
+ public synchronized IModule[] getDependents()
+ {
+ IModule[] dependents = new IModule[
+ m_dependentHosts.length + m_dependentImporters.length + m_dependentRequirers.length];
+ System.arraycopy(
+ m_dependentHosts,
+ 0,
+ dependents,
+ 0,
+ m_dependentHosts.length);
+ System.arraycopy(
+ m_dependentImporters,
+ 0,
+ dependents,
+ m_dependentHosts.length,
+ m_dependentImporters.length);
+ System.arraycopy(
+ m_dependentRequirers,
+ 0,
+ dependents,
+ m_dependentHosts.length + m_dependentImporters.length,
+ m_dependentRequirers.length);
+ return dependents;
+ }
+
+ public Class getClassByDelegation(String name) throws ClassNotFoundException
+ {
+ try
+ {
+ return getClassLoader().loadClass(name);
+ }
+ catch (ClassNotFoundException ex)
+ {
+// TODO: REFACTOR - Should this log?
+ m_logger.log(
+ Logger.LOG_WARNING,
+ ex.getMessage(),
+ ex);
+ throw ex;
+ }
+ }
+
+ public URL getResourceByDelegation(String name)
+ {
+ return getClassLoader().getResource(name);
+ }
+
+ public Enumeration getResourcesByDelegation(String name)
+ {
+ Enumeration urls = null;
+ List enums = new ArrayList();
+
+ // First, try to resolve the originating module.
+// TODO: FRAMEWORK - Consider opimizing this call to resolve, since it is called
+// for each class load.
+ try
+ {
+ m_resolver.resolve(this);
+ }
+ catch (ResolveException ex)
+ {
+ // The spec states that if the bundle cannot be resolved, then
+ // only the local bundle's resources should be searched. So we
+ // will ask the module's own class path.
+ urls = getResourcesFromModule(name);
+ return urls;
+ }
+
+ // Get the package of the target class/resource.
+ String pkgName = Util.getResourcePackage(name);
+
+ // Delegate any packages listed in the boot delegation
+ // property to the parent class loader.
+ // NOTE for the default package:
+ // Only consider delegation if we have a package name, since
+ // we don't want to promote the default package. The spec does
+ // not take a stand on this issue.
+ if (pkgName.length() > 0)
+ {
+ for (int i = 0; i < m_bootPkgs.length; i++)
+ {
+ // A wildcarded boot delegation package will be in the form of
+ // "foo.", so if the package is wildcarded do a startsWith() or a
+ // regionMatches() to ignore the trailing "." to determine if the
+ // request should be delegated to the parent class loader. If the
+ // package is not wildcarded, then simply do an equals() test to
+ // see if the request should be delegated to the parent class loader.
+ if ((m_bootPkgWildcards[i] &&
+ (pkgName.startsWith(m_bootPkgs[i]) ||
+ m_bootPkgs[i].regionMatches(0, pkgName, 0, pkgName.length())))
+ || (!m_bootPkgWildcards[i] && m_bootPkgs[i].equals(pkgName)))
+ {
+ try
+ {
+ urls = getClass().getClassLoader().getResources(name);
+ }
+ catch (IOException ex)
+ {
+ // This shouldn't happen and even if it does, there
+ // is nothing we can do, so just ignore it.
+ }
+ // If this is a java.* package, then always terminate the
+ // search; otherwise, continue to look locally.
+ if (m_bootPkgs[i].startsWith("java."))
+ {
+ return urls;
+ }
+
+ enums.add(urls);
+ break;
+ }
+ }
+ }
+
+ // Look in the module's imports.
+ // We delegate to the module's wires for the resources.
+ // If any resources are found, this means that the package of these
+ // resources is imported, we must not keep looking since we do not
+ // support split-packages.
+
+ // Note that the search may be aborted if this method throws an
+ // exception, otherwise it continues if a null is returned.
+ IWire[] wires = getWires();
+ for (int i = 0; (wires != null) && (i < wires.length); i++)
+ {
+ if (wires[i] instanceof R4Wire)
+ {
+ try
+ {
+ // If we find the class or resource, then return it.
+ urls = wires[i].getResources(name);
+ }
+ catch (ResourceNotFoundException ex)
+ {
+ urls = null;
+ }
+ if (urls != null)
+ {
+ enums.add(urls);
+ return new CompoundEnumeration((Enumeration[])
+ enums.toArray(new Enumeration[enums.size()]));
+ }
+ }
+ }
+
+ // See whether we can get the resource from the required bundles and
+ // regardless of whether or not this is the case continue to the next
+ // step potentially passing on the result of this search (if any).
+ for (int i = 0; (wires != null) && (i < wires.length); i++)
+ {
+ if (wires[i] instanceof R4WireModule)
+ {
+ try
+ {
+ // If we find the class or resource, then add it.
+ urls = wires[i].getResources(name);
+ }
+ catch (ResourceNotFoundException ex)
+ {
+ urls = null;
+ }
+ if (urls != null)
+ {
+ enums.add(urls);
+ }
+ }
+ }
+
+ // Try the module's own class path. If we can find the resource then
+ // return it together with the results from the other searches else
+ // try to look into the dynamic imports.
+ urls = getResourcesFromModule(name);
+ if (urls != null)
+ {
+ enums.add(urls);
+ }
+ else
+ {
+ // If not found, then try the module's dynamic imports.
+ // At this point, the module's imports were searched and so was the
+ // the module's content. Now we make an attempt to load the
+ // class/resource via a dynamic import, if possible.
+ IWire wire = null;
+ try
+ {
+ wire = m_resolver.resolveDynamicImport(this, pkgName);
+ }
+ catch (ResolveException ex)
+ {
+ // Ignore this since it is likely normal.
+ }
+ if (wire != null)
+ {
+ try
+ {
+ urls = wire.getResources(name);
+ }
+ catch (ResourceNotFoundException ex)
+ {
+ urls = null;
+ }
+ if (urls != null)
+ {
+ enums.add(urls);
+ }
+ }
+ }
+
+ return new CompoundEnumeration((Enumeration[])
+ enums.toArray(new Enumeration[enums.size()]));
+ }
+
+ public boolean isResolved()
+ {
+ return m_isResolved;
+ }
+
+ public void setResolved()
+ {
+ m_isResolved = true;
+ }
+
+ public String toString()
+ {
+ return m_id;
+ }
+
+ private static IModule[] addDependent(IModule[] modules, IModule module)
+ {
+ // Make sure the dependent module is not already present.
+ for (int i = 0; i < modules.length; i++)
+ {
+ if (modules[i].equals(module))
+ {
+ return modules;
+ }
+ }
+ IModule[] tmp = new IModule[modules.length + 1];
+ System.arraycopy(modules, 0, tmp, 0, modules.length);
+ tmp[modules.length] = module;
+ return tmp;
+ }
+
+ private static IModule[] removeDependent(IModule[] modules, IModule module)
+ {
+ IModule[] tmp = modules;
+
+ // Make sure the dependent module is present.
+ for (int i = 0; i < modules.length; i++)
+ {
+ if (modules[i].equals(module))
+ {
+ // If this is the module, then point to empty list.
+ if ((modules.length - 1) == 0)
+ {
+ tmp = new IModule[0];
+ }
+ // Otherwise, we need to do some array copying.
+ else
+ {
+ tmp = new IModule[modules.length - 1];
+ System.arraycopy(modules, 0, tmp, 0, i);
+ if (i < tmp.length)
+ {
+ System.arraycopy(modules, i + 1, tmp, i, tmp.length - i);
+ }
+ }
+ break;
+ }
+ }
+
+ return tmp;
+ }
+
+ // TODO: REFACTOR - Below are from ContentLoaderImpl
+
+ Logger getLogger()
+ {
+ return m_logger;
+ }
+
+ FelixResolver getResolver()
+ {
+ return m_resolver;
+ }
+
+ public synchronized void close()
+ {
+ m_content.close();
+ for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
+ {
+ m_contentPath[i].close();
+ }
+ for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
+ {
+ m_fragmentContents[i].close();
+ }
+ synchronized (this)
+ {
+ m_classLoader = null;
+ }
+ }
+
+ public IContent getContent()
+ {
+ return m_content;
+ }
+
+ synchronized IContent[] getClassPath()
+ {
+ if (m_contentPath == null)
+ {
+ try
+ {
+ m_contentPath = initializeContentPath();
+ }
+ catch (Exception ex)
+ {
+ m_logger.log(Logger.LOG_ERROR, "Unable to get module class path.", ex);
+ }
+ }
+ return m_contentPath;
+ }
+
+ public synchronized void setURLPolicy(IURLPolicy urlPolicy)
+ {
+ m_urlPolicy = urlPolicy;
+ }
+
+ public synchronized IURLPolicy getURLPolicy()
+ {
+ return m_urlPolicy;
+ }
+
+ public synchronized void setSecurityContext(Object securityContext)
+ {
+ m_protectionDomain = (ProtectionDomain) securityContext;
+ }
+
+ public synchronized Object getSecurityContext()
+ {
+ return m_protectionDomain;
+ }
+
+ public Class getClassFromModule(String name) throws ClassNotFoundException
+ {
+ try
+ {
+ return getClassLoader().findClass(name);
+ }
+ catch (ClassNotFoundException ex)
+ {
+ m_logger.log(
+ Logger.LOG_WARNING,
+ ex.getMessage(),
+ ex);
+ throw ex;
+ }
+ }
+
+// TODO: REFACTOR - This previously didn't cause the class loader to be created.
+ public URL getResourceFromModule(String name)
+ {
+ URL url = null;
+
+ // Remove leading slash, if present, but special case
+ // "/" so that it returns a root URL...this isn't very
+ // clean or meaninful, but the Spring guys want it.
+ if (name.equals("/"))
+ {
+ // Just pick a class path index since it doesn't really matter.
+ url = getURLPolicy().createURL(1, name);
+ }
+ else if (name.startsWith("/"))
+ {
+ name = name.substring(1);
+ }
+
+ // Check the module class path.
+ IContent[] contentPath = getClassPath();
+ for (int i = 0;
+ (url == null) &&
+ (i < contentPath.length); i++)
+ {
+ if (contentPath[i].hasEntry(name))
+ {
+ url = getURLPolicy().createURL(i + 1, name);
+ }
+ }
+
+ return url;
+ }
+
+// TODO: REFACTOR - This previously didn't cause the class loader to be created.
+ public Enumeration getResourcesFromModule(String name)
+ {
+ Vector v = new Vector();
+
+ // Special case "/" so that it returns a root URLs for
+ // each bundle class path entry...this isn't very
+ // clean or meaningful, but the Spring guys want it.
+ if (name.equals("/"))
+ {
+ for (int i = 0; i < getClassPath().length; i++)
+ {
+ v.addElement(getURLPolicy().createURL(i + 1, name));
+ }
+ }
+ else
+ {
+ // Remove leading slash, if present.
+ if (name.startsWith("/"))
+ {
+ name = name.substring(1);
+ }
+
+ // Check the module class path.
+ IContent[] contentPath = getClassPath();
+ for (int i = 0; i < contentPath.length; i++)
+ {
+ if (contentPath[i].hasEntry(name))
+ {
+ // Use the class path index + 1 for creating the path so
+ // that we can differentiate between module content URLs
+ // (where the path will start with 0) and module class
+ // path URLs.
+ v.addElement(getURLPolicy().createURL(i + 1, name));
+ }
+ }
+ }
+
+ return v.elements();
+ }
+
+ // TODO: API: Investigate how to handle this better, perhaps we need
+ // multiple URL policies, one for content -- one for class path.
+ public URL getResourceFromContent(String name)
+ {
+ URL url = null;
+
+ // Check for the special case of "/", which represents
+ // the root of the bundle according to the spec.
+ if (name.equals("/"))
+ {
+ url = getURLPolicy().createURL(0, "/");
+ }
+
+ if (url == null)
+ {
+ // Remove leading slash, if present.
+ if (name.startsWith("/"))
+ {
+ name = name.substring(1);
+ }
+
+ // Check the module content.
+ if (getContent().hasEntry(name))
+ {
+ // Module content URLs start with 0, whereas module
+ // class path URLs start with the index into the class
+ // path + 1.
+ url = getURLPolicy().createURL(0, name);
+ }
+ }
+
+ return url;
+ }
+
+ public boolean hasInputStream(int index, String urlPath)
+ {
+ if (urlPath.startsWith("/"))
+ {
+ urlPath = urlPath.substring(1);
+ }
+ if (index == 0)
+ {
+ return m_content.hasEntry(urlPath);
+ }
+ return getClassPath()[index - 1].hasEntry(urlPath);
+ }
+
+ public InputStream getInputStream(int index, String urlPath)
+ throws IOException
+ {
+ if (urlPath.startsWith("/"))
+ {
+ urlPath = urlPath.substring(1);
+ }
+ if (index == 0)
+ {
+ return m_content.getEntryAsStream(urlPath);
+ }
+ return getClassPath()[index - 1].getEntryAsStream(urlPath);
+ }
+
+ private ModuleClassLoader getClassLoader()
+ {
+ synchronized (this)
+ {
+ if (m_classLoader == null)
+ {
+ m_classLoader = m_secureAction.createModuleClassLoader(
+ this, m_protectionDomain);
+ }
+ }
+ return m_classLoader;
+ }
+
+ private IContent[] initializeContentPath() throws Exception
+ {
+ List contentList = new ArrayList();
+ calculateContentPath(m_content, contentList, true);
+ for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
+ {
+ calculateContentPath(m_fragmentContents[i], contentList, false);
+ }
+ return (IContent[]) contentList.toArray(new IContent[contentList.size()]);
+ }
+
+ private List calculateContentPath(IContent content, List contentList, boolean searchFragments)
+ throws Exception
+ {
+ // Creating the content path entails examining the bundle's
+ // class path to determine whether the bundle JAR file itself
+ // is on the bundle's class path and then creating content
+ // objects for everything on the class path.
+
+ // Create a list to contain the content path for the specified content.
+ List localContentList = new ArrayList();
+
+ // Find class path meta-data.
+ String classPath = (String) m_headerMap.get(FelixConstants.BUNDLE_CLASSPATH);
+ // Parse the class path into strings.
+ String[] classPathStrings = ManifestParser.parseDelimitedString(
+ classPath, FelixConstants.CLASS_PATH_SEPARATOR);
+
+ if (classPathStrings == null)
+ {
+ classPathStrings = new String[0];
+ }
+
+ // Create the bundles class path.
+ for (int i = 0; i < classPathStrings.length; i++)
+ {
+ // Remove any leading slash, since all bundle class path
+ // entries are relative to the root of the bundle.
+ classPathStrings[i] = (classPathStrings[i].startsWith("/"))
+ ? classPathStrings[i].substring(1)
+ : classPathStrings[i];
+
+ // Check for the bundle itself on the class path.
+ if (classPathStrings[i].equals(FelixConstants.CLASS_PATH_DOT))
+ {
+ localContentList.add(content);
+ }
+ else
+ {
+ // Try to find the embedded class path entry in the current
+ // content.
+ IContent embeddedContent = content.getEntryAsContent(classPathStrings[i]);
+ // If the embedded class path entry was not found, it might be
+ // in one of the fragments if the current content is the bundle,
+ // so try to search the fragments if necessary.
+ for (int fragIdx = 0;
+ searchFragments && (embeddedContent == null)
+ && (m_fragmentContents != null) && (fragIdx < m_fragmentContents.length);
+ fragIdx++)
+ {
+ embeddedContent = m_fragmentContents[fragIdx].getEntryAsContent(classPathStrings[i]);
+ }
+ // If we found the embedded content, then add it to the
+ // class path content list.
+ if (embeddedContent != null)
+ {
+ localContentList.add(embeddedContent);
+ }
+ else
+ {
+// TODO: FRAMEWORK - Per the spec, this should fire a FrameworkEvent.INFO event;
+// need to create an "Eventer" class like "Logger" perhaps.
+ m_logger.log(Logger.LOG_INFO,
+ "Class path entry not found: "
+ + classPathStrings[i]);
+ }
+ }
+ }
+
+ // If there is nothing on the class path, then include
+ // "." by default, as per the spec.
+ if (localContentList.size() == 0)
+ {
+ localContentList.add(content);
+ }
+
+ // Now add the local contents to the global content list and return it.
+ contentList.addAll(localContentList);
+ return contentList;
+ }
+
+// From ModuleClassLoader
+
+ Object findClassOrResourceByDelegation(String name, boolean isClass)
+ throws ClassNotFoundException, ResourceNotFoundException
+ {
+ // First, try to resolve the originating module.
+// TODO: FRAMEWORK - Consider opimizing this call to resolve, since it is called
+// for each class load.
+ try
+ {
+ m_resolver.resolve(this);
+ }
+ catch (ResolveException ex)
+ {
+ if (isClass)
+ {
+ // We do not use the resolve exception as the
+ // cause of the exception, since this would
+ // potentially leak internal module information.
+ throw new ClassNotFoundException(
+ name + ": cannot resolve package "
+ + ex.getRequirement());
+ }
+ else
+ {
+ // The spec states that if the bundle cannot be resolved, then
+ // only the local bundle's resources should be searched. So we
+ // will ask the module's own class path.
+ URL url = getResourceFromModule(name);
+ if (url != null)
+ {
+ return url;
+ }
+
+ // We need to throw a resource not found exception.
+ throw new ResourceNotFoundException(
+ name + ": cannot resolve package "
+ + ex.getRequirement());
+ }
+ }
+
+ // Get the package of the target class/resource.
+ String pkgName = (isClass)
+ ? Util.getClassPackage(name)
+ : Util.getResourcePackage(name);
+
+ // Delegate any packages listed in the boot delegation
+ // property to the parent class loader.
+ Object result = null;
+ for (int i = 0; i < m_bootPkgs.length; i++)
+ {
+ // A wildcarded boot delegation package will be in the form of "foo.",
+ // so if the package is wildcarded do a startsWith() or a regionMatches()
+ // to ignore the trailing "." to determine if the request should be
+ // delegated to the parent class loader. If the package is not wildcarded,
+ // then simply do an equals() test to see if the request should be
+ // delegated to the parent class loader.
+ if (pkgName.length() > 0)
+ {
+ // Only consider delegation if we have a package name, since
+ // we don't want to promote the default package. The spec does
+ // not take a stand on this issue.
+ if ((m_bootPkgWildcards[i] &&
+ (pkgName.startsWith(m_bootPkgs[i]) ||
+ m_bootPkgs[i].regionMatches(0, pkgName, 0, pkgName.length())))
+ || (!m_bootPkgWildcards[i] && m_bootPkgs[i].equals(pkgName)))
+ {
+ try
+ {
+ result = (isClass)
+ ? (Object) getClass().getClassLoader().loadClass(name)
+ : (Object) getClass().getClassLoader().getResource(name);
+ // If this is a java.* package, then always terminate the
+ // search; otherwise, continue to look locally if not found.
+ if (m_bootPkgs[i].startsWith("java.") || (result != null))
+ {
+ return result;
+ }
+ }
+ catch (ClassNotFoundException ex)
+ {
+ // If this is a java.* package, then always terminate the
+ // search; otherwise, continue to look locally if not found.
+ if (m_bootPkgs[i].startsWith("java."))
+ {
+ throw ex;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Look in the module's imports. Note that the search may
+ // be aborted if this method throws an exception, otherwise
+ // it continues if a null is returned.
+ result = searchImports(name, isClass);
+
+ // If not found, try the module's own class path.
+ if (result == null)
+ {
+ result = (isClass)
+ ? (Object) getClassFromModule(name)
+ : (Object) getResourceFromModule(name);
+
+ // If still not found, then try the module's dynamic imports.
+ if (result == null)
+ {
+ result = searchDynamicImports(name, pkgName, isClass);
+ }
+ }
+
+ if (result == null)
+ {
+ if (isClass)
+ {
+ throw new ClassNotFoundException(name);
+ }
+ else
+ {
+ throw new ResourceNotFoundException(name);
+ }
+ }
+
+ return result;
+ }
+
+ private Object searchImports(String name, boolean isClass)
+ throws ClassNotFoundException, ResourceNotFoundException
+ {
+ // We delegate to the module's wires to find the class or resource.
+ IWire[] wires = getWires();
+ for (int i = 0; (wires != null) && (i < wires.length); i++)
+ {
+ // If we find the class or resource, then return it.
+ Object result = (isClass)
+ ? (Object) wires[i].getClass(name)
+ : (Object) wires[i].getResource(name);
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ private Object searchDynamicImports(
+ String name, String pkgName, boolean isClass)
+ throws ClassNotFoundException, ResourceNotFoundException
+ {
+ // At this point, the module's imports were searched and so was the
+ // the module's content. Now we make an attempt to load the
+ // class/resource via a dynamic import, if possible.
+ IWire wire = null;
+ try
+ {
+ wire = m_resolver.resolveDynamicImport(this, pkgName);
+ }
+ catch (ResolveException ex)
+ {
+ // Ignore this since it is likely normal.
+ }
+
+ // If the dynamic import was successful, then this initial
+ // time we must directly return the result from dynamically
+ // created wire, but subsequent requests for classes/resources
+ // in the associated package will be processed as part of
+ // normal static imports.
+ if (wire != null)
+ {
+ // Return the class or resource.
+ return (isClass)
+ ? (Object) wire.getClass(name)
+ : (Object) wire.getResource(name);
+ }
+
+ // At this point, the class/resource could not be found by the bundle's
+ // static or dynamic imports, nor its own content. Before we throw
+ // an exception, we will try to determine if the instigator of the
+ // class/resource load was a class from a bundle or not. This is necessary
+ // because the specification mandates that classes on the class path
+ // should be hidden (except for java.*), but it does allow for these
+ // classes/resources to be exposed by the system bundle as an export.
+ // However, in some situations classes on the class path make the faulty
+ // assumption that they can access everything on the class path from
+ // every other class loader that they come in contact with. This is
+ // not true if the class loader in question is from a bundle. Thus,
+ // this code tries to detect that situation. If the class
+ // instigating the load request was NOT from a bundle, then we will
+ // make the assumption that the caller actually wanted to use the
+ // parent class loader and we will delegate to it. If the class was
+ // from a bundle, then we will enforce strict class loading rules
+ // for the bundle and throw an exception.
+
+ // Get the class context to see the classes on the stack.
+ Class[] classes = m_sm.getClassContext();
+ // Start from 1 to skip security manager class.
+ for (int i = 1; i < classes.length; i++)
+ {
+ // Find the first class on the call stack that is not from
+ // the class loader that loaded the Felix classes or is not
+ // a class loader or class itself, because we want to ignore
+ // calls to ClassLoader.loadClass() and Class.forName() since
+ // we are trying to find out who instigated the class load.
+ // Also since Felix uses threads for changing the start level
+ // and refreshing packages, it is possible that there is no
+ // module classes on the call stack; therefore, as soon as we
+ // see Thread on the call stack we exit this loop. Other cases
+ // where modules actually use threads are not an issue because
+ // the module classes will be on the call stack before the
+ // Thread class.
+// TODO: FRAMEWORK - This check is a hack and we should see if we can think
+// of another way to do it, since it won't necessarily work in all situations.
+ if (Thread.class.equals(classes[i]))
+ {
+ break;
+ }
+ else if ((this.getClass().getClassLoader() != classes[i].getClassLoader())
+ && !ClassLoader.class.isAssignableFrom(classes[i])
+ && !Class.class.equals(classes[i])
+ && !Proxy.class.equals(classes[i]))
+ {
+ // If there are no bundles providing exports for this
+ // package and if the instigating class was not from a
+ // bundle, then delegate to the parent class loader.
+ // Otherwise, break out of loop and return null.
+ boolean delegate = true;
+ for (ClassLoader cl = classes[i].getClassLoader(); cl != null; cl = cl.getClass().getClassLoader())
+ {
+ if (ModuleClassLoader.class.isInstance(cl))
+ {
+ delegate = false;
+ break;
+ }
+ }
+ // If delegate is true then there are no bundles
+ // providing exports for this package and the instigating
+ // class was not from a bundle. Therefore,
+ // delegate to the parent class loader in case
+ // that this is not due to outside code calling a method
+ // on the bundle interface (e.g., Bundle.loadClass()).
+ if (delegate && !Bundle.class.isInstance(classes[i - 1]))
+ {
+ try
+ {
+ // Return the class or resource from the parent class loader.
+ return (isClass)
+ ? (Object) this.getClass().getClassLoader().loadClass(name)
+ : (Object) this.getClass().getClassLoader().getResource(name);
+ }
+ catch (NoClassDefFoundError ex)
+ {
+ // Ignore, will return null
+ }
+ }
+ break;
+ }
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java?rev=732800&r1=732799&r2=732800&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4Wire.java Thu Jan 8 11:35:07 2009
@@ -97,23 +97,15 @@
if (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
m_capability.getProperties().get(ICapability.PACKAGE_PROPERTY).equals(pkgName))
{
- // If the importer and the exporter are the same, then
- // just ask for the class from the exporting module's
- // content directly.
- if (m_exporter == m_importer)
- {
- clazz = m_exporter.getContentLoader().getClass(name);
- }
- // Otherwise, check the include/exclude filters from the target
- // package to make sure that the class is actually visible. In
- // this case since the importing and exporting modules are different,
- // we delegate to the exporting module, rather than its content,
- // so that it can follow any internal wires it may have (e.g.,
- // if the package has multiple sources).
- else if (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
+ // Check the include/exclude filters from the target package
+ // to make sure that the class is actually visible. We delegate
+ // to the exporting module, rather than its content, so it can
+ // it can follow any internal wires it may have (e.g., if the
+ // package has multiple sources).
+ if (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
&& ((Capability) m_capability).isIncluded(name))
{
- clazz = m_exporter.getClass(name);
+ clazz = m_exporter.getClassByDelegation(name);
}
// If no class was found, then we must throw an exception
@@ -143,20 +135,10 @@
if (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
m_capability.getProperties().get(ICapability.PACKAGE_PROPERTY).equals(pkgName))
{
- // If the importer and the exporter are the same, then
- // just ask for the resource from the exporting module's
- // content directly.
- if (m_exporter == m_importer)
- {
- url = m_exporter.getContentLoader().getResource(name);
- }
- // Otherwise, delegate to the exporting module, rather than its
+ // Delegate to the exporting module, rather than its
// content, so that it can follow any internal wires it may have
// (e.g., if the package has multiple sources).
- else
- {
- url = m_exporter.getResource(name);
- }
+ url = m_exporter.getResourceByDelegation(name);
// If no resource was found, then we must throw an exception
// since the exporter for this package did not contain the
@@ -185,7 +167,7 @@
if (m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
m_capability.getProperties().get(ICapability.PACKAGE_PROPERTY).equals(pkgName))
{
- urls = m_exporter.getContentLoader().getResources(name);
+ urls = m_exporter.getResourcesByDelegation(name);
// If no resource was found, then we must throw an exception
// since the exporter for this package did not contain the
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java?rev=732800&r1=732799&r2=732800&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java Thu Jan 8 11:35:07 2009
@@ -100,14 +100,26 @@
for (int srcIdx = 0; srcIdx < rp.m_sourceList.size(); srcIdx++)
{
PackageSource ps = (PackageSource) rp.m_sourceList.get(srcIdx);
+// TODO: REFACTOR - Module's shouldn't depend on themself.
if ((ps.m_module == m_importer) ||
((ps.m_capability instanceof Capability) &&
((Capability) ps.m_capability).isIncluded(name)))
{
- Class clazz = ps.m_module.getContentLoader().getClass(name);
- if (clazz != null)
+// TODO: REFACTOR - It seems like we should be able to use getClassByDelegation()
+// here once we don't allow modules to require themself above.
+ try
{
- return clazz;
+ Class clazz = ps.m_module.getClassFromModule(name);
+ if (clazz != null)
+ {
+ return clazz;
+ }
+ }
+ catch (ClassNotFoundException ex)
+ {
+ // Do not throw the exception here, since we want
+ // to continue search other package sources and
+ // ultimately the module's own content.
}
}
}
@@ -130,7 +142,9 @@
for (int srcIdx = 0; srcIdx < rp.m_sourceList.size(); srcIdx++)
{
PackageSource ps = (PackageSource) rp.m_sourceList.get(srcIdx);
- URL url = ps.m_module.getContentLoader().getResource(name);
+// TODO: REFACTOR - It seems like we should be able to use getClassByDelegation()
+// here once we don't allow modules to require themself above.
+ URL url = ps.m_module.getResourceFromModule(name);
if (url != null)
{
return url;
@@ -164,7 +178,9 @@
for (int srcIdx = 0; srcIdx < rp.m_sourceList.size(); srcIdx++)
{
PackageSource ps = (PackageSource) rp.m_sourceList.get(srcIdx);
- Enumeration urls = ps.m_module.getContentLoader().getResources(name);
+// TODO: REFACTOR - It seems like we should be able to use getClassByDelegation()
+// here once we don't allow modules to require themself above.
+ Enumeration urls = ps.m_module.getResourcesFromModule(name);
if (urls != null)
{
enums.add(urls);
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java?rev=732800&r1=732799&r2=732800&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java Thu Jan 8 11:35:07 2009
@@ -40,6 +40,7 @@
private final Logger m_logger;
// Reusable empty array.
+ private static final IWire[] m_emptyWires = new IWire[0];
private static final IModule[] m_emptyModules = new IModule[0];
private static final PackageSource[] m_emptySources = new PackageSource[0];
@@ -55,7 +56,7 @@
public Map resolve(ResolverState state, IModule rootModule) throws ResolveException
{
// If the module is already resolved, then we can just return.
- if (state.isResolved(rootModule))
+ if (rootModule.isResolved())
{
return null;
}
@@ -119,7 +120,7 @@
// Loop through the importer's dynamic requirements to determine if
// there is a matching one for the package from which we want to
// load a class.
- IRequirement[] dynamics = importer.getDefinition().getDynamicRequirements();
+ IRequirement[] dynamics = importer.getDynamicRequirements();
for (int dynIdx = 0; (dynamics != null) && (dynIdx < dynamics.length); dynIdx++)
{
IRequirement target =
@@ -186,7 +187,7 @@
{
// If any of the module exports this package, then we cannot
// attempt to dynamically import it.
- ICapability[] caps = importer.getDefinition().getCapabilities();
+ ICapability[] caps = importer.getCapabilities();
for (int i = 0; (caps != null) && (i < caps.length); i++)
{
if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
@@ -258,7 +259,7 @@
// provider. If there is no consistent class space, then a resolve
// exception is thrown.
Map candidatesMap = new HashMap();
- if (!state.isResolved(provider))
+ if (!provider.isResolved())
{
populateCandidatesMap(state, candidatesMap, provider);
findConsistentClassSpace(state, candidatesMap, provider);
@@ -403,7 +404,7 @@
// Loop through each requirement and calculate its resolving
// set of candidates.
- IRequirement[] reqs = targetModule.getDefinition().getRequirements();
+ IRequirement[] reqs = targetModule.getRequirements();
for (int reqIdx = 0; (reqs != null) && (reqIdx < reqs.length); reqIdx++)
{
if (reqs[reqIdx].getNamespace().equals(ICapability.HOST_NAMESPACE))
@@ -421,7 +422,7 @@
{
// Only populate the resolver map with hosts that
// are not already resolved.
- if (!state.isResolved(hosts[hostIdx]))
+ if (!hosts[hostIdx].isResolved())
{
populateCandidatesMap(state, candidatesMap, hosts[hostIdx]);
}
@@ -489,7 +490,7 @@
{
// Only populate the resolver map with modules that
// are not already resolved.
- if (!state.isResolved(candidates[candIdx].m_module))
+ if (!candidates[candIdx].m_module.isResolved())
{
populateCandidatesMap(state, candidatesMap, candidates[candIdx].m_module);
}
@@ -606,9 +607,9 @@
IModule[] modules = state.getModules();
for (int i = 0; (modules != null) && (i < modules.length); i++)
{
- if (state.isResolved(modules[i]) && isSingleton(modules[i]))
+ if (modules[i].isResolved() && isSingleton(modules[i]))
{
- String symName = state.getBundleSymbolicName(modules[i]);
+ String symName = modules[i].getSymbolicName();
singletonMap.put(symName, symName);
}
}
@@ -648,7 +649,7 @@
// Check to see if the targetModule violates a singleton.
// If not and it is a singleton, then add it to the singleton
// map since it will constrain other singletons.
- String symName = state.getBundleSymbolicName(targetModule);
+ String symName = targetModule.getSymbolicName();
boolean isSingleton = isSingleton(targetModule);
if (isSingleton && singletonMap.containsKey(symName))
{
@@ -689,7 +690,7 @@
// we have to see if resolving it would violate a singleton
// constraint.
PackageSource ps = (PackageSource) rp.m_sourceList.get(srcIdx);
- if (!state.isResolved(ps.m_module))
+ if (!ps.m_module.isResolved())
{
return areCandidatesSingletonConsistent(state, ps.m_module, singletonMap, moduleMap, cycleMap, candidatesMap);
}
@@ -1099,7 +1100,7 @@
// Loop through the target module's capabilities that represent
// exported packages and add them to the exported package map.
- ICapability[] caps = targetModule.getDefinition().getCapabilities();
+ ICapability[] caps = targetModule.getCapabilities();
for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
{
if (caps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
@@ -1354,7 +1355,7 @@
// Now loop through the target module's export package capabilities and
// add the target module as a package source for any exported packages.
- ICapability[] candCaps = psTarget.m_module.getDefinition().getCapabilities();
+ ICapability[] candCaps = psTarget.m_module.getCapabilities();
for (int capIdx = 0; (candCaps != null) && (capIdx < candCaps.length); capIdx++)
{
if (candCaps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
@@ -1470,7 +1471,7 @@
// Now loop through the target module's export package capabilities and
// add the target module as a package source for any exported packages.
- ICapability[] caps = targetModule.getDefinition().getCapabilities();
+ ICapability[] caps = targetModule.getCapabilities();
for (int i = 0; (caps != null) && (i < caps.length); i++)
{
if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
@@ -1529,7 +1530,7 @@
{
// If the module is already resolved or it is part of
// a cycle, then just return the wire map.
- if (state.isResolved(importer) || (wireMap.get(importer) != null))
+ if (importer.isResolved() || (wireMap.get(importer) != null))
{
return wireMap;
}
@@ -1585,11 +1586,10 @@
List moduleWires = new ArrayList();
List packageWires = new ArrayList();
- IWire[] wires = new IWire[candSetList.size()];
// Put the module in the wireMap with an empty wire array;
// we do this early so we can use it to detect cycles.
- wireMap.put(importer, wires);
+ wireMap.put(importer, m_emptyModules);
// Loop through each candidate Set and create a wire
// for the selected candidate for the associated import.
@@ -1606,6 +1606,7 @@
}
else
{
+ // Create a module wire for module dependencies.
if (cs.m_requirement.getNamespace().equals(ICapability.MODULE_NAMESPACE))
{
moduleWires.add(new R4WireModule(
@@ -1615,7 +1616,11 @@
cs.m_candidates[cs.m_idx].m_capability,
calculateCandidateRequiredPackages(importer, cs.m_candidates[cs.m_idx], candidatesMap)));
}
- else
+ // Create a package wire for package dependencies.
+ // Filter out the case where a module imports from
+ // itself, since the module should simply load from
+ // its internal class path in this case.
+ else if (importer != cs.m_candidates[cs.m_idx].m_module)
{
// Add wire for imported package.
packageWires.add(new R4Wire(
@@ -1632,7 +1637,7 @@
}
packageWires.addAll(moduleWires);
- wireMap.put(importer, packageWires.toArray(wires));
+ wireMap.put(importer, packageWires.toArray(new IWire[packageWires.size()]));
return wireMap;
}
@@ -1705,9 +1710,6 @@
{
IModule[] getModules();
// TODO: RESOLVER - This should be on module.
- String getBundleSymbolicName(IModule module);
- // TODO: RESOLVER - This should be on module.
- boolean isResolved(IModule module);
Map getPotentialFragments(IModule module);
List getPotentialHosts(IModule module);
PackageSource[] getResolvedCandidates(IRequirement req);
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java?rev=732800&r1=732799&r2=732800&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java Thu Jan 8 11:35:07 2009
@@ -25,8 +25,8 @@
import java.util.Hashtable;
import java.util.jar.JarFile;
-import org.apache.felix.framework.searchpolicy.ContentClassLoader;
-import org.apache.felix.framework.searchpolicy.ContentLoaderImpl;
+import org.apache.felix.framework.searchpolicy.ModuleClassLoader;
+import org.apache.felix.framework.searchpolicy.ModuleImpl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
@@ -541,12 +541,12 @@
}
}
- public ContentClassLoader createContentClassLoader(ContentLoaderImpl impl)
+ public ModuleClassLoader createModuleClassLoader(ModuleImpl impl)
{
- return createContentClassLoader(impl, null);
+ return createModuleClassLoader(impl, null);
}
- public ContentClassLoader createContentClassLoader(ContentLoaderImpl impl,
+ public ModuleClassLoader createModuleClassLoader(ModuleImpl impl,
ProtectionDomain protectionDomain)
{
if (System.getSecurityManager() != null)
@@ -554,8 +554,8 @@
try
{
Actions actions = (Actions) m_actions.get();
- actions.set(Actions.CREATE_CONTENTCLASSLOADER_ACTION, impl, protectionDomain);
- return (ContentClassLoader) AccessController.doPrivileged(actions, m_acc);
+ actions.set(Actions.CREATE_MODULECLASSLOADER_ACTION, impl, protectionDomain);
+ return (ModuleClassLoader) AccessController.doPrivileged(actions, m_acc);
}
catch (PrivilegedActionException ex)
{
@@ -564,7 +564,7 @@
}
else
{
- return new ContentClassLoader(impl, protectionDomain);
+ return new ModuleClassLoader(impl, protectionDomain);
}
}
@@ -943,7 +943,7 @@
public static final int DELETE_FILE_ACTION = 13;
public static final int OPEN_JARX_ACTION = 14;
public static final int GET_URL_INPUT_ACTION = 15;
- public static final int CREATE_CONTENTCLASSLOADER_ACTION = 16;
+ public static final int CREATE_MODULECLASSLOADER_ACTION = 16;
public static final int START_ACTIVATOR_ACTION = 17;
public static final int STOP_ACTIVATOR_ACTION = 18;
public static final int SYSTEM_EXIT_ACTION = 19;
@@ -1104,10 +1104,9 @@
{
return ((URLConnection) arg1).getInputStream();
}
- else if (action == CREATE_CONTENTCLASSLOADER_ACTION)
+ else if (action == CREATE_MODULECLASSLOADER_ACTION)
{
- return new ContentClassLoader((ContentLoaderImpl) arg1,
- (ProtectionDomain) arg2);
+ return new ModuleClassLoader((ModuleImpl) arg1, (ProtectionDomain) arg2);
}
else if (action == START_ACTIVATOR_ACTION)
{
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java?rev=732800&r1=732799&r2=732800&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java Thu Jan 8 11:35:07 2009
@@ -26,7 +26,6 @@
import java.util.Map;
import java.util.Properties;
-import org.apache.felix.framework.searchpolicy.ModuleDefinition;
import org.apache.felix.framework.util.manifestparser.Capability;
import org.apache.felix.moduleloader.*;
import org.osgi.framework.Bundle;
@@ -232,7 +231,7 @@
public static ICapability getSatisfyingCapability(IModule m, IRequirement req)
{
- ICapability[] caps = m.getDefinition().getCapabilities();
+ ICapability[] caps = m.getCapabilities();
for (int i = 0; (caps != null) && (i < caps.length); i++)
{
if (caps[i].getNamespace().equals(req.getNamespace()) &&
@@ -254,7 +253,7 @@
public static ICapability[] getCapabilityByNamespace(IModule module, String namespace)
{
final List matching = new ArrayList();
- final ICapability[] caps = module.getDefinition().getCapabilities();
+ final ICapability[] caps = module.getCapabilities();
for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
{
if (caps[capIdx].getNamespace().equals(namespace))
@@ -525,11 +524,7 @@
*/
public static boolean isFragment(IModule module)
{
- if (module.getDefinition() instanceof ModuleDefinition)
- {
- Map headerMap = ((ModuleDefinition) module.getDefinition()).getHeaders();
- return headerMap.containsKey(Constants.FRAGMENT_HOST);
- }
- return false;
+ Map headerMap = module.getHeaders();
+ return headerMap.containsKey(Constants.FRAGMENT_HOST);
}
}
\ No newline at end of file
Modified: felix/trunk/framework/src/main/java/org/apache/felix/moduleloader/IModule.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/moduleloader/IModule.java?rev=732800&r1=732799&r2=732800&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/moduleloader/IModule.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/moduleloader/IModule.java Thu Jan 8 11:35:07 2009
@@ -18,27 +18,56 @@
*/
package org.apache.felix.moduleloader;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
+import java.util.Map;
+import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.osgi.framework.Bundle;
public interface IModule
{
- public String getId();
- public IModuleDefinition getDefinition();
- public IContentLoader getContentLoader();
- public IWire[] getWires();
-
- public Class getClass(String name) throws ClassNotFoundException;
- public URL getResource(String name);
- public Enumeration getResources(String name);
-
-
- /**
- * Returns whether the module is associated with an uninstalled bundle.
- * If so, then it should not be used when resolving fragments or fragment
- * hosts. However, it still can be used for resolving imported packages.
- * @return <tt>true</tt> if the module's bundle is uninstalled, otherwise
- * <tt>false</tt>.
- **/
- public boolean isStale();
-}
+ Bundle getBundle();
+
+ void setURLPolicy(IURLPolicy urlPolicy);
+ IURLPolicy getURLPolicy();
+ void setSecurityContext(Object securityContext);
+ Object getSecurityContext();
+
+ // Metadata access
+ Map getHeaders();
+ ICapability[] getCapabilities();
+ IRequirement[] getRequirements();
+ IRequirement[] getDynamicRequirements();
+ R4Library[] getNativeLibraries();
+
+ // Run-time data access.
+ String getId();
+ String getSymbolicName();
+ IWire[] getWires();
+ boolean isResolved();
+
+ // Content access.
+ IContent getContent();
+ Class getClassByDelegation(String name) throws ClassNotFoundException;
+ URL getResourceByDelegation(String name);
+ Enumeration getResourcesByDelegation(String name);
+ Class getClassFromModule(String name) throws ClassNotFoundException;
+ URL getResourceFromModule(String name);
+ Enumeration getResourcesFromModule(String name);
+ URL getResourceFromContent(String name);
+
+ // TODO: ML - For expediency, the index argument was added to these methods
+ // but it is not clear that this makes sense in the long run. This needs to
+ // be readdressed in the future, perhaps by the spec to clearly indicate
+ // how resources on the bundle class path are searched, which is why we
+ // need the index number in the first place -- to differentiate among
+ // resources with the same name on the bundle class path. This was previously
+ // handled as part of the resource path, but that approach is not spec
+ // compliant.
+ boolean hasInputStream(int index, String urlPath)
+ throws IOException;
+ InputStream getInputStream(int index, String urlPath)
+ throws IOException;
+}
\ No newline at end of file
Modified: felix/trunk/framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java?rev=732800&r1=732799&r2=732800&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/moduleloader/ModuleEvent.java Thu Jan 8 11:35:07 2009
@@ -44,9 +44,9 @@
* @param mgr the source of the event.
* @param module the subject of the event.
**/
- public ModuleEvent(IModuleFactory factory, IModule module)
+ public ModuleEvent(IModule module)
{
- super(factory);
+ super(module);
m_module = module;
}