Applied patches (FELIX-466 and FELIX-467) to improve how Felix finds resources
when getResources() is called.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@615256 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java
index 785386e..bd37810 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ContentClassLoader.java
@@ -1,4 +1,4 @@
-/*
+/*
* 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
@@ -46,7 +46,7 @@
Class dexFileClass = Class.forName("android.dalvik.DexFile");
dexFileClassConstructor = dexFileClass.getConstructor(
new Class[] { java.io.File.class });
- dexFileClassLoadClass = dexFileClass.getMethod("loadClass",
+ dexFileClassLoadClass = dexFileClass.getMethod("loadClass",
new Class[] { String.class, ClassLoader.class });
}
catch (Exception ex)
@@ -99,7 +99,7 @@
// Make sure the class was not already loaded.
synchronized (this)
- {
+ {
clazz = findLoadedClass(name);
}
@@ -138,7 +138,7 @@
String actual = name.replace('.', '/') + ".class";
byte[] bytes = null;
-
+
IContent content = null;
// Check the module class path.
for (int i = 0;
@@ -194,7 +194,7 @@
// If we can load the class from a dex file do so
if (content instanceof JarContent)
{
- try
+ try
{
clazz = getDexFileClass((JarContent) content, name, this);
}
@@ -237,7 +237,7 @@
Object dexFile = null;
- if (!m_jarContentToDexFile.containsKey(content))
+ if (!m_jarContentToDexFile.containsKey(content))
{
try
{
@@ -253,10 +253,10 @@
{
dexFile = m_jarContentToDexFile.get(content);
}
-
+
if (dexFile != null)
{
- return (Class) m_dexFileClassLoadClass.invoke(dexFile,
+ return (Class) m_dexFileClassLoadClass.invoke(dexFile,
new Object[] { name.replace('.','/'), loader });
}
return null;
@@ -290,12 +290,28 @@
protected URL findResource(String name)
{
- return m_contentLoader.getResource(name);
+ // Ask the search policy for the resource.
+ try
+ {
+ return m_contentLoader.getSearchPolicy().findResource(name);
+ }
+ catch (ResourceNotFoundException ex)
+ {
+ }
+ return null;
}
protected Enumeration findResources(String name)
{
- return m_contentLoader.getResources(name);
+ // Ask the search policy for the resources.
+ try
+ {
+ return m_contentLoader.getSearchPolicy().findResources(name);
+ }
+ catch (ResourceNotFoundException ex)
+ {
+ }
+ return null;
}
protected String findLibrary(String name)
@@ -307,4 +323,4 @@
{
return m_contentLoader.toString();
}
-}
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
index c9e9f9e..af22f6f 100755
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
@@ -32,6 +32,7 @@
import java.util.StringTokenizer;
import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.util.CompoundEnumeration;
import org.apache.felix.framework.util.SecurityManagerEx;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.Capability;
@@ -222,6 +223,8 @@
throws ResourceNotFoundException
{
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.
@@ -278,21 +281,20 @@
// 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 not found.
- if (m_bootPkgs[i].startsWith("java.") || (urls != null))
+ // search; otherwise, continue to look locally.
+ if (m_bootPkgs[i].startsWith("java."))
{
return urls;
}
- else
- {
- break;
- }
+
+ enums.add(urls);
+ break;
}
}
}
// Look in the module's imports.
- // We delegate to the module's wires to the resources.
+ // 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.
@@ -302,37 +304,63 @@
IWire[] wires = module.getWires();
for (int i = 0; (wires != null) && (i < wires.length); i++)
{
- // If we find the class or resource, then return it.
- urls = wires[i].getResources(name);
- if (urls != null)
+ if (wires[i] instanceof R4Wire)
{
- return urls;
+ // If we find the class or resource, then return it.
+ urls = wires[i].getResources(name);
+ if (urls != null)
+ {
+ enums.add(urls);
+ return new CompoundEnumeration((Enumeration[])
+ enums.toArray(new Enumeration[enums.size()]));
+ }
}
}
- // If not found, try the module's own class path.
+ // 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)
+ {
+ // If we find the class or resource, then add it.
+ urls = wires[i].getResources(name);
+ 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 = module.getContentLoader().getResources(name);
if (urls != null)
{
- return urls;
+ enums.add(urls);
}
-
- // If still 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 = attemptDynamicImport(module, pkgName);
- if (wire != null)
+ else
{
- urls = wire.getResources(name);
+ // 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 = attemptDynamicImport(module, pkgName);
+ if (wire != null)
+ {
+ urls = wire.getResources(name);
+
+ if (urls != null)
+ {
+ enums.add(urls);
+ }
+ }
}
- if (urls == null)
- {
- throw new ResourceNotFoundException(name);
- }
-
- return urls;
+ return new CompoundEnumeration((Enumeration[])
+ enums.toArray(new Enumeration[enums.size()]));
}
private Object findClassOrResource(IModule module, String name, boolean isClass)
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java
index 38c165d..1f18f79 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireModule.java
@@ -23,6 +23,7 @@
import org.apache.felix.framework.searchpolicy.R4SearchPolicyCore.ResolvedPackage;
import org.apache.felix.framework.searchpolicy.R4SearchPolicyCore.PackageSource;
+import org.apache.felix.framework.util.CompoundEnumeration;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.Capability;
import org.apache.felix.moduleloader.*;
@@ -127,6 +128,9 @@
return url;
}
}
+
+ // Don't throw ResourceNotFoundException because module
+ // dependencies support split packages.
}
return null;
@@ -137,8 +141,37 @@
*/
public Enumeration getResources(String name) throws ResourceNotFoundException
{
-// TODO: RB - Implement R4WireModule.getResources()
- return null;
+ // List to hold all enumerations from all package sources.
+ List enums = new ArrayList();
+
+ // Get the package of the target class.
+ String pkgName = Util.getResourcePackage(name);
+
+ // See if we have a resolved package for the resource's package.
+ // If so, loop through all package sources and aggregate any
+ // matching resource enumerations.
+ ResolvedPackage rp = (ResolvedPackage) m_pkgMap.get(pkgName);
+ if (rp != null)
+ {
+ 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);
+ if (urls != null)
+ {
+ enums.add(urls);
+ }
+ }
+
+ // Don't throw ResourceNotFoundException because module
+ // dependencies support split packages.
+ }
+
+ return (enums.size() == 0)
+ ? null
+ : new CompoundEnumeration(
+ (Enumeration[]) enums.toArray(new Enumeration[enums.size()]));
+
}
public String toString()
diff --git a/framework/src/main/java/org/apache/felix/framework/util/CompoundEnumeration.java b/framework/src/main/java/org/apache/felix/framework/util/CompoundEnumeration.java
new file mode 100644
index 0000000..e73a9f6
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/util/CompoundEnumeration.java
@@ -0,0 +1,91 @@
+package org.apache.felix.framework.util;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+public class CompoundEnumeration implements Enumeration
+{
+ private Enumeration[] m_enums = null;
+ private int index = 0;
+
+ public CompoundEnumeration(Enumeration[] enums)
+ {
+ m_enums = enums;
+ }
+
+ public boolean hasMoreElements()
+ {
+ // if the current enum is null that means this enum is finished
+ if (currentEnumeration() == null)
+ {
+ // No next enum
+ return false;
+ }
+ // If the current enum has more elements, lets go
+ return currentEnumeration().hasMoreElements();
+ }
+
+ private Enumeration findNextEnumeration(boolean moveCursor)
+ {
+ return findNextEnumeration(index, moveCursor);
+ }
+
+ private Enumeration findNextEnumeration(int cursor, boolean moveCursor)
+ {
+ // next place in the array
+ int next = cursor + 1;
+ // If the cursor is still in the array
+ if (next < m_enums.length)
+ {
+
+ // If there is something in that place
+ // AND the enum is not empty
+ if (m_enums[next] != null &&
+ m_enums[next].hasMoreElements())
+ {
+ // OK
+ if (moveCursor)
+ {
+ index = next;
+ }
+ return m_enums[next];
+ }
+ // Try next element
+ return findNextEnumeration(next, moveCursor);
+ }
+ // No more elements available
+ return null;
+ }
+
+ public Object nextElement()
+ {
+ // ask for the next element of the current enum.
+ if (currentEnumeration() != null)
+ {
+ return currentEnumeration().nextElement();
+ }
+
+ // no more elements in this Enum
+ // We must throw a NoSuchElementException
+ throw new NoSuchElementException("No more elements");
+ }
+
+ private Enumeration currentEnumeration()
+ {
+ if (m_enums != null)
+ {
+ if (index < m_enums.length)
+ {
+ Enumeration e = m_enums[index];
+ if (e == null || !e.hasMoreElements())
+ {
+ // the current enum is null or empty
+ // we probably want to switch to the next one
+ e = findNextEnumeration(true);
+ }
+ return e;
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file