Move all content path handling to the bundle revision implementation
to avoid duplication of code. (FELIX-2950)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1102834 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
index 33ecf5e..349a0ce 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
@@ -33,7 +33,6 @@
import org.apache.felix.framework.resolver.Content;
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.manifestparser.ManifestParser;
import org.apache.felix.framework.util.manifestparser.R4Library;
import org.osgi.framework.Bundle;
@@ -73,7 +72,7 @@
private final Bundle m_bundle;
- private Content[] m_contentPath;
+ private List<Content> m_contentPath;
private boolean m_isActivationTriggered = false;
private ProtectionDomain m_protectionDomain = null;
private final static SecureAction m_secureAction = new SecureAction();
@@ -85,9 +84,6 @@
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();
-
/**
* This constructor is used by the extension manager, since it needs
* a constructor that does not throw an exception.
@@ -346,6 +342,21 @@
if (wiring != null)
{
+ // If the wiring has fragments, then close the old content path,
+ // since it'll need to be recalculated to include fragments.
+ if (wiring.getFragments() != null)
+ {
+ for (int i = 0; (m_contentPath != null) && (i < m_contentPath.size()); i++)
+ {
+ // Don't close this module's content, if it is on the content path.
+ if (m_content != m_contentPath.get(i))
+ {
+ m_contentPath.get(i).close();
+ }
+ }
+ m_contentPath = null;
+ }
+
m_wiring = wiring;
}
}
@@ -379,7 +390,7 @@
return m_content;
}
- private synchronized Content[] getContentPath()
+ synchronized List<Content> getContentPath()
{
if (m_contentPath == null)
{
@@ -396,15 +407,32 @@
return m_contentPath;
}
- private Content[] initializeContentPath() throws Exception
+ private List<Content> initializeContentPath() throws Exception
{
- List contentList = new ArrayList();
- calculateContentPath(this, m_content, contentList, true);
- return (Content[]) contentList.toArray(new Content[contentList.size()]);
+ List<Content> contentList = new ArrayList();
+ calculateContentPath(this, getContent(), contentList, true);
+
+ List<BundleRevision> fragments = null;
+ List<Content> fragmentContents = null;
+ if (m_wiring != null)
+ {
+ fragments = m_wiring.getFragments();
+ fragmentContents = m_wiring.getFragmentContents();
+ }
+ if (fragments != null)
+ {
+ for (int i = 0; i < fragments.size(); i++)
+ {
+ calculateContentPath(
+ fragments.get(i), fragmentContents.get(i), contentList, false);
+ }
+ }
+ return contentList;
}
private List calculateContentPath(
- BundleRevision revision, Content content, List contentList, boolean searchFragments)
+ BundleRevision revision, Content content, List<Content> contentList,
+ boolean searchFragments)
throws Exception
{
// Creating the content path entails examining the bundle's
@@ -446,6 +474,19 @@
// Try to find the embedded class path entry in the current
// content.
Content embeddedContent = content.getEntryAsContent(classPathStrings.get(i));
+ // If the embedded class path entry was not found, it might be
+ // in one of the fragments if the current content is the bundle,
+ // so try to search the fragments if necessary.
+ List<Content> fragmentContents = (m_wiring == null)
+ ? null : m_wiring.getFragmentContents();
+ for (int fragIdx = 0;
+ searchFragments && (embeddedContent == null)
+ && (fragmentContents != null) && (fragIdx < fragmentContents.size());
+ fragIdx++)
+ {
+ embeddedContent =
+ fragmentContents.get(fragIdx).getEntryAsContent(classPathStrings.get(i));
+ }
// If we found the embedded content, then add it to the
// class path content list.
if (embeddedContent != null)
@@ -456,7 +497,7 @@
{
// TODO: FRAMEWORK - Per the spec, this should fire a FrameworkEvent.INFO event;
// need to create an "Eventer" class like "Logger" perhaps.
- m_logger.log(m_bundle, Logger.LOG_INFO,
+ m_logger.log(getBundle(), Logger.LOG_INFO,
"Class path entry not found: "
+ classPathStrings.get(i));
}
@@ -493,12 +534,12 @@
}
// Check the module class path.
- Content[] contentPath = getContentPath();
+ List<Content> contentPath = getContentPath();
for (int i = 0;
(url == null) &&
- (i < contentPath.length); i++)
+ (i < contentPath.size()); i++)
{
- if (contentPath[i].hasEntry(name))
+ if (contentPath.get(i).hasEntry(name))
{
url = createURL(i + 1, name);
}
@@ -514,10 +555,10 @@
// 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();
+ final List<Content> contentPath = getContentPath();
if (name.equals("/"))
{
- for (int i = 0; i < contentPath.length; i++)
+ for (int i = 0; i < contentPath.size(); i++)
{
l.add(createURL(i + 1, name));
}
@@ -531,9 +572,9 @@
}
// Check the module class path.
- for (int i = 0; i < contentPath.length; i++)
+ for (int i = 0; i < contentPath.size(); i++)
{
- if (contentPath[i].hasEntry(name))
+ if (contentPath.get(i).hasEntry(name))
{
// Use the class path index + 1 for creating the path so
// that we can differentiate between module content URLs
@@ -591,7 +632,7 @@
{
return m_content.hasEntry(urlPath);
}
- return getContentPath()[index - 1].hasEntry(urlPath);
+ return getContentPath().get(index - 1).hasEntry(urlPath);
}
public InputStream getInputStream(int index, String urlPath)
@@ -605,7 +646,7 @@
{
return m_content.getEntryAsStream(urlPath);
}
- return getContentPath()[index - 1].getEntryAsStream(urlPath);
+ return getContentPath().get(index - 1).getEntryAsStream(urlPath);
}
public URL getLocalURL(int index, String urlPath)
@@ -618,7 +659,7 @@
{
return m_content.getEntryAsURL(urlPath);
}
- return getContentPath()[index - 1].getEntryAsURL(urlPath);
+ return getContentPath().get(index - 1).getEntryAsURL(urlPath);
}
private URL createURL(int port, String path)
@@ -658,9 +699,9 @@
m_logger.log(Logger.LOG_ERROR, "Error releasing revision: " + ex.getMessage(), ex);
}
m_content.close();
- for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
+ for (int i = 0; (m_contentPath != null) && (i < m_contentPath.size()); i++)
{
- m_contentPath[i].close();
+ m_contentPath.get(i).close();
}
m_contentPath = null;
}
@@ -670,21 +711,4 @@
{
return m_id;
}
-
- static URL convertToLocalUrl(URL url)
- {
- if (url.getProtocol().equals("bundle"))
- {
- try
- {
- url = ((URLHandlersBundleURLConnection)
- url.openConnection()).getLocalURL();
- }
- catch (IOException ex)
- {
- // Ignore and add original url.
- }
- }
- return url;
- }
}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
index 5b193e3..201f94a 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
@@ -51,7 +51,6 @@
import org.apache.felix.framework.util.SecureAction;
import org.apache.felix.framework.util.SecurityManagerEx;
import org.apache.felix.framework.util.Util;
-import org.apache.felix.framework.util.manifestparser.ManifestParser;
import org.apache.felix.framework.util.manifestparser.R4Library;
import org.apache.felix.framework.wiring.BundleCapabilityImpl;
import org.apache.felix.framework.wiring.BundleRequirementImpl;
@@ -83,8 +82,7 @@
private final List<BundleRequirement> m_resolvedReqs;
private final List<BundleRequirement> m_resolvedDynamicReqs;
private final List<R4Library> m_resolvedNativeLibs;
- private final Content[] m_contentPath;
- private final Content[] m_fragmentContents;
+ private final List<Content> m_fragmentContents;
private BundleClassLoader m_classLoader;
private boolean m_isActivationTriggered = false;
@@ -154,7 +152,7 @@
// We need to sort the fragments and add ourself as a dependent of each one.
// We also need to create an array of fragment contents to attach to our
// content path.
- Content[] fragmentContents = null;
+ List<Content> fragmentContents = null;
if (fragments != null)
{
// Sort fragments according to ID order, if necessary.
@@ -170,20 +168,17 @@
}
fragments = new ArrayList(sorted.values());
}
- fragmentContents = new Content[fragments.size()];
+ fragmentContents = new ArrayList<Content>(fragments.size());
for (int i = 0; (fragments != null) && (i < fragments.size()); i++)
{
- fragmentContents[i] =
+ fragmentContents.add(
((BundleRevisionImpl) fragments.get(i)).getContent()
- .getEntryAsContent(FelixConstants.CLASS_PATH_DOT);
+ .getEntryAsContent(FelixConstants.CLASS_PATH_DOT));
}
}
m_fragments = fragments;
m_fragmentContents = fragmentContents;
- // Recalculate the content path for the new fragments.
- m_contentPath = initializeContentPath();
-
List<BundleCapability> capList = (m_revision.getDeclaredCapabilities(null) == null)
? new ArrayList<BundleCapability>()
: new ArrayList<BundleCapability>(m_revision.getDeclaredCapabilities(null));
@@ -308,111 +303,16 @@
public void dispose()
{
- for (int i = 0; (m_contentPath != null) && (i < m_contentPath.length); i++)
+ if (m_fragmentContents != null)
{
- m_contentPath[i].close();
- }
- for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
- {
- m_fragmentContents[i].close();
+ for (Content content : m_fragmentContents)
+ {
+ content.close();
+ }
}
m_classLoader = null;
}
- private Content[] initializeContentPath() throws Exception
- {
- List contentList = new ArrayList();
- calculateContentPath(m_revision, m_revision.getContent(), contentList, true);
- for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
- {
- calculateContentPath(m_fragments.get(i), m_fragmentContents[i], contentList, false);
- }
- return (Content[]) contentList.toArray(new Content[contentList.size()]);
- }
-
- private List calculateContentPath(
- BundleRevision revision, Content content, List contentList, boolean searchFragments)
- throws Exception
- {
- // Creating the content path entails examining the bundle's
- // class path to determine whether the bundle JAR file itself
- // is on the bundle's class path and then creating content
- // objects for everything on the class path.
-
- // Create a list to contain the content path for the specified content.
- List localContentList = new ArrayList();
-
- // Find class path meta-data.
- String classPath = (String) ((BundleRevisionImpl) revision)
- .getHeaders().get(FelixConstants.BUNDLE_CLASSPATH);
- // Parse the class path into strings.
- List<String> classPathStrings = ManifestParser.parseDelimitedString(
- classPath, FelixConstants.CLASS_PATH_SEPARATOR);
-
- if (classPathStrings == null)
- {
- classPathStrings = new ArrayList<String>(0);
- }
-
- // Create the bundles class path.
- for (int i = 0; i < classPathStrings.size(); i++)
- {
- // Remove any leading slash, since all bundle class path
- // entries are relative to the root of the bundle.
- classPathStrings.set(i, (classPathStrings.get(i).startsWith("/"))
- ? classPathStrings.get(i).substring(1)
- : classPathStrings.get(i));
-
- // Check for the bundle itself on the class path.
- if (classPathStrings.get(i).equals(FelixConstants.CLASS_PATH_DOT))
- {
- localContentList.add(content);
- }
- else
- {
- // Try to find the embedded class path entry in the current
- // content.
- Content embeddedContent = content.getEntryAsContent(classPathStrings.get(i));
- // If the embedded class path entry was not found, it might be
- // in one of the fragments if the current content is the bundle,
- // so try to search the fragments if necessary.
- for (int fragIdx = 0;
- searchFragments && (embeddedContent == null)
- && (m_fragmentContents != null) && (fragIdx < m_fragmentContents.length);
- fragIdx++)
- {
- embeddedContent =
- m_fragmentContents[fragIdx].getEntryAsContent(classPathStrings.get(i));
- }
- // If we found the embedded content, then add it to the
- // class path content list.
- if (embeddedContent != null)
- {
- localContentList.add(embeddedContent);
- }
- else
- {
-// TODO: FRAMEWORK - Per the spec, this should fire a FrameworkEvent.INFO event;
-// need to create an "Eventer" class like "Logger" perhaps.
- m_logger.log(m_revision.getBundle(), Logger.LOG_INFO,
- "Class path entry not found: "
- + classPathStrings.get(i));
- }
- }
- }
-
- // If there is nothing on the class path, then include
- // "." by default, as per the spec.
- if (localContentList.isEmpty())
- {
- localContentList.add(content);
- }
-
- // Now add the local contents to the global content list and return it.
- contentList.addAll(localContentList);
- return contentList;
- }
-
// TODO: OSGi R4.3 - This really shouldn't be public, but it is needed by the
// resolver to determine if a bundle can dynamically import.
public synchronized boolean hasPackageSource(String pkgName)
@@ -427,11 +327,16 @@
return m_importedPkgs.get(pkgName);
}
- public List<BundleRevision> getFragments()
+ List<BundleRevision> getFragments()
{
return m_fragments;
}
+ List<Content> getFragmentContents()
+ {
+ return m_fragmentContents;
+ }
+
public boolean isCurrent()
{
throw new UnsupportedOperationException("Not supported yet.");
@@ -576,19 +481,6 @@
// Class loader implementation methods.
//
- public URL getLocalURL(int index, String urlPath)
- {
- if (urlPath.startsWith("/"))
- {
- urlPath = urlPath.substring(1);
- }
- if (index == 0)
- {
- return m_revision.getContent().getEntryAsURL(urlPath);
- }
- return m_contentPath[index - 1].getEntryAsURL(urlPath);
- }
-
private URL createURL(int port, String path)
{
// Add a slash if there is one already, otherwise
@@ -615,37 +507,6 @@
return null;
}
- URL getResourceLocal(String name)
- {
- URL url = null;
-
- // Remove leading slash, if present, but special case
- // "/" so that it returns a root URL...this isn't very
- // clean or meaninful, but the Spring guys want it.
- if (name.equals("/"))
- {
- // Just pick a class path index since it doesn't really matter.
- url = createURL(1, name);
- }
- else if (name.startsWith("/"))
- {
- name = name.substring(1);
- }
-
- // Check the module class path.
- for (int i = 0;
- (url == null) &&
- (i < m_contentPath.length); i++)
- {
- if (m_contentPath[i].hasEntry(name))
- {
- url = createURL(i + 1, name);
- }
- }
-
- return url;
- }
-
public Enumeration getResourcesByDelegation(String name)
{
Set requestSet = (Set) m_cycleCheck.get();
@@ -685,7 +546,7 @@
// The spec states that if the bundle cannot be resolved, then
// only the local bundle's resources should be searched. So we
// will ask the module's own class path.
- return getResourcesLocal(name);
+ return m_revision.getResourcesLocal(name);
}
// Get the package of the target class/resource.
@@ -762,7 +623,7 @@
// 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);
+ urls = m_revision.getResourcesLocal(name);
if ((urls != null) && (urls.hasMoreElements()))
{
completeUrlList.add(urls);
@@ -798,45 +659,6 @@
completeUrlList.toArray(new Enumeration[completeUrlList.size()]));
}
- private Enumeration getResourcesLocal(String name)
- {
- List l = new ArrayList();
-
- // Special case "/" so that it returns a root URLs for
- // each bundle class path entry...this isn't very
- // clean or meaningful, but the Spring guys want it.
- if (name.equals("/"))
- {
- for (int i = 0; i < m_contentPath.length; i++)
- {
- l.add(createURL(i + 1, name));
- }
- }
- else
- {
- // Remove leading slash, if present.
- if (name.startsWith("/"))
- {
- name = name.substring(1);
- }
-
- // Check the module class path.
- for (int i = 0; i < m_contentPath.length; i++)
- {
- if (m_contentPath[i].hasEntry(name))
- {
- // Use the class path index + 1 for creating the path so
- // that we can differentiate between module content URLs
- // (where the path will start with 0) and module class
- // path URLs.
- l.add(createURL(i + 1, name));
- }
- }
- }
-
- return Collections.enumeration(l);
- }
-
private ClassLoader determineParentClassLoader()
{
// Determine the class loader's parent based on the
@@ -1056,7 +878,7 @@
{
result = (isClass)
? (Object) ((BundleClassLoader) getClassLoader()).findClass(name)
- : (Object) getResourceLocal(name);
+ : (Object) m_revision.getResourceLocal(name);
// If still not found, then try the revision's dynamic imports.
if (result == null)
@@ -1083,7 +905,7 @@
// The spec states that if the bundle cannot be resolved, then
// only the local bundle's resources should be searched. So we
// will ask the module's own class path.
- URL url = getResourceLocal(name);
+ URL url = m_revision.getResourceLocal(name);
if (url != null)
{
return url;
@@ -1469,7 +1291,7 @@
@Override
protected Enumeration findResources(String name)
{
- return BundleWiringImpl.this.getResourcesLocal(name);
+ return m_revision.getResourcesLocal(name);
}
}
@@ -1557,13 +1379,14 @@
byte[] bytes = null;
// Check the bundle class path.
+ List<Content> contentPath = m_revision.getContentPath();
Content content = null;
for (int i = 0;
(bytes == null) &&
- (i < m_contentPath.length); i++)
+ (i < contentPath.size()); i++)
{
- bytes = m_contentPath[i].getEntryAsBytes(actual);
- content = m_contentPath[i];
+ bytes = contentPath.get(i).getEntryAsBytes(actual);
+ content = contentPath.get(i);
}
if (bytes != null)
@@ -1780,7 +1603,7 @@
@Override
protected URL findResource(String name)
{
- return BundleWiringImpl.this.getResourceLocal(name);
+ return m_revision.getResourceLocal(name);
}
// The findResources() method should only look at the revision itself, but
@@ -1838,10 +1661,10 @@
// If not found, then search fragments in order.
for (int i = 0;
(result == null) && (m_fragmentContents != null)
- && (i < m_fragmentContents.length);
+ && (i < m_fragmentContents.size());
i++)
{
- result = m_fragmentContents[i].getEntryAsNativeLibrary(
+ result = m_fragmentContents.get(i).getEntryAsNativeLibrary(
libs.get(libIdx).getEntryName());
}
}
diff --git a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
index cdae317..ff0c411 100644
--- a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
+++ b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
@@ -834,11 +834,5 @@
{
// Nothing needed here.
}
-
- @Override
- public URL getLocalURL(int index, String urlPath)
- {
- return getClass().getClassLoader().getResource(urlPath);
- }
}
}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index 079c1e9..2d8437c 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -876,24 +876,27 @@
AdminPermission.EXECUTE));
}
- // Spec says stop() on SystemBundle should return immediately and
- // shutdown framework on another thread.
- new Thread(new Runnable() {
- public void run()
- {
- try
+ if ((getState() & (Bundle.INSTALLED | Bundle.RESOLVED)) == 0)
+ {
+ // Spec says stop() on SystemBundle should return immediately and
+ // shutdown framework on another thread.
+ new Thread(new Runnable() {
+ public void run()
{
- stopBundle(Felix.this, true);
+ try
+ {
+ stopBundle(Felix.this, true);
+ }
+ catch (BundleException ex)
+ {
+ m_logger.log(
+ Logger.LOG_ERROR,
+ "Exception trying to stop framework.",
+ ex);
+ }
}
- catch (BundleException ex)
- {
- m_logger.log(
- Logger.LOG_ERROR,
- "Exception trying to stop framework.",
- ex);
- }
- }
- }, "FelixShutdown").start();
+ }, "FelixShutdown").start();
+ }
}
public void stop(int options) throws BundleException