Moved native library verification to the resolver, since the spec
says they are resolve-time checks, not install-time checks. Also
fixed a bug in OS version parsing. (FELIX-1360)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@794305 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java b/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
index 277088b..8b9c185 100644
--- a/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
@@ -207,35 +207,6 @@
: ManifestParser.parseDelimitedString(mp.getActivationIncludeDirective(), ",");
m_symbolicName = mp.getSymbolicName();
m_isExtension = mp.isExtension();
-
- // Verify that all native libraries exist in advance; this will
- // throw an exception if the native library does not exist.
- try
- {
- for (int i = 0;
- (m_nativeLibraries != null) && (i < m_nativeLibraries.length);
- i++)
- {
- String entryName = m_nativeLibraries[i].getEntryName();
- if (entryName != null)
- {
- if (!m_content.hasEntry(entryName))
- {
- throw new BundleException("Native library does not exist: " + entryName);
- }
- }
- }
- }
- finally
- {
- // We close the module content here to make sure it is closed
- // to avoid having to close it if there is an exception during
- // the entire module creation process.
-// TODO: REFACTOR - If we do the above check here, then we open the module's content
-// immediately every time, which means we must close it here so we don't have
-// to remember to close it if there are other failures during module init.
- m_content.close();
- }
}
//
@@ -336,21 +307,37 @@
public synchronized R4Library[] getNativeLibraries()
{
- List nativeList = (m_nativeLibraries == null)
- ? new ArrayList() : new ArrayList(Arrays.asList(m_nativeLibraries));
- for (int fragIdx = 0;
- (m_fragments != null) && (fragIdx < m_fragments.length);
- fragIdx++)
+ R4Library[] result = null;
+ if (m_isResolved)
{
- R4Library[] libs = m_fragments[fragIdx].getNativeLibraries();
- for (int reqIdx = 0;
- (libs != null) && (reqIdx < libs.length);
- reqIdx++)
+ List nativeList = (m_nativeLibraries == null)
+ ? new ArrayList() : new ArrayList(Arrays.asList(m_nativeLibraries));
+ for (int fragIdx = 0;
+ (m_fragments != null) && (fragIdx < m_fragments.length);
+ fragIdx++)
{
- nativeList.add(libs[reqIdx]);
+ R4Library[] libs = m_fragments[fragIdx].getNativeLibraries();
+ for (int reqIdx = 0;
+ (libs != null) && (reqIdx < libs.length);
+ reqIdx++)
+ {
+ nativeList.add(libs[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
+ : (R4Library[]) nativeList.toArray(new R4Library[nativeList.size()]);
}
- return (R4Library[]) nativeList.toArray(new R4Library[nativeList.size()]);
+ else
+ {
+ result = m_nativeLibraries;
+ }
+
+ return result;
}
public int getDeclaredActivationPolicy()
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
index d3a8bb7..2e690b3 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
@@ -30,6 +30,7 @@
import org.apache.felix.framework.util.manifestparser.Capability;
import org.apache.felix.framework.util.manifestparser.R4Attribute;
import org.apache.felix.framework.util.manifestparser.R4Directive;
+import org.apache.felix.framework.util.manifestparser.R4Library;
import org.apache.felix.framework.util.manifestparser.Requirement;
import org.apache.felix.moduleloader.ICapability;
import org.apache.felix.moduleloader.IModule;
@@ -345,6 +346,38 @@
return;
}
+ // First, try to resolve any native code, since the module is
+ // not resolvable if its native code cannot be loaded.
+ R4Library[] libs = targetModule.getNativeLibraries();
+ if (libs != null)
+ {
+ String msg = null;
+ // Verify that all native libraries exist in advance; this will
+ // throw an exception if the native library does not exist.
+ for (int libIdx = 0; (msg == null) && (libIdx < libs.length); libIdx++)
+ {
+ String entryName = libs[libIdx].getEntryName();
+ if (entryName != null)
+ {
+ if (!targetModule.getContent().hasEntry(entryName))
+ {
+ msg = "Native library does not exist: " + entryName;
+ }
+ }
+ }
+ // If we have a zero-length native library array, then
+ // this means no native library class could be selected
+ // so we should fail to resolve.
+ if (libs.length == 0)
+ {
+ msg = "No matching native libraries found.";
+ }
+ if (msg != null)
+ {
+ throw new ResolveException(msg, targetModule, null);
+ }
+ }
+
// List to hold the resolving candidate sets for the target
// module's requirements.
List candSetList = new ArrayList();
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
index 548f51f..f0e2bd7 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
@@ -331,27 +331,40 @@
* <p>
* This method returns the selected native library metadata from
* the manifest. The information is not the raw metadata from the
- * manifest, but is native library metadata clause selected according
+ * manifest, but is the native library clause selected according
* to the OSGi native library clause selection policy. The metadata
* returned by this method will be attached directly to a module and
* used for finding its native libraries at run time. To inspect the
* raw native library metadata refer to <tt>getLibraryClauses()</tt>.
* </p>
- * @return an array of selected library metadata objects from the manifest.
- * @throws BundleException if any problems arise.
+ * <p>
+ * This method returns one of three values:
+ * </p>
+ * <ul>
+ * <li><tt>null</tt> - if the are no native libraries for this module;
+ * this may also indicate the native libraries are optional and
+ * did not match the current platform.</li>
+ * <li>Zero-length <tt>R4Library</tt> array - if no matching native library
+ * clause was found; this bundle should not resolve.</li>
+ * <li>Nonzero-length <tt>R4Library</tt> array - the native libraries
+ * associated with the matching native library clause.</li>
+ * </ul>
+ *
+ * @return <tt>null</tt> if there are no native libraries, a zero-length
+ * array if no libraries matched, or an array of selected libraries.
**/
- public R4Library[] getLibraries() throws BundleException
+ public R4Library[] getLibraries()
{
- R4LibraryClause clause = getSelectedLibraryClause();
-
- if (clause != null)
+ R4Library[] libs = null;
+ try
{
- String[] entries = clause.getLibraryEntries();
- R4Library[] libraries = new R4Library[entries.length];
- int current = 0;
- try
+ R4LibraryClause clause = getSelectedLibraryClause();
+ if (clause != null)
{
- for (int i = 0; i < libraries.length; i++)
+ String[] entries = clause.getLibraryEntries();
+ libs = new R4Library[entries.length];
+ int current = 0;
+ for (int i = 0; i < libs.length; i++)
{
String name = getName(entries[i]);
boolean found = false;
@@ -361,26 +374,25 @@
}
if (!found)
{
- libraries[current++] = new R4Library(
+ libs[current++] = new R4Library(
clause.getLibraryEntries()[i],
clause.getOSNames(), clause.getProcessors(), clause.getOSVersions(),
clause.getLanguages(), clause.getSelectionFilter());
}
}
- if (current < libraries.length)
+ if (current < libs.length)
{
R4Library[] tmp = new R4Library[current];
- System.arraycopy(libraries, 0, tmp, 0, current);
- libraries = tmp;
+ System.arraycopy(libs, 0, tmp, 0, current);
+ libs = tmp;
}
- return libraries;
- }
- catch (Exception ex)
- {
- throw new BundleException("Unable to create library", ex);
}
}
- return null;
+ catch (Exception ex)
+ {
+ libs = new R4Library[0];
+ }
+ return libs;
}
private String getName(String path)
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java
index 0053541..91cb625 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java
@@ -500,42 +500,13 @@
{
// Header: 'Bundle-NativeCode', Parameter: 'osversion'
// Standardized 'osversion': major.minor.micro, only digits
- String VERSION_DELIM = ".";
- String QUALIFIER_DELIM = "-";
- int major = 0;
- int minor = 0;
- int micro = 0;
try
{
- StringTokenizer st = new StringTokenizer(value, VERSION_DELIM, true);
- major = Integer.parseInt(st.nextToken());
-
- if (st.hasMoreTokens())
- {
- st.nextToken(); // consume delimiter
- minor = Integer.parseInt(st.nextToken());
-
- if (st.hasMoreTokens())
- {
- st.nextToken(); // consume delimiter
- String microStr = st.nextToken();
- if (microStr.indexOf(QUALIFIER_DELIM) < 0)
- {
- micro = Integer.parseInt(microStr);
- }
- else
- {
- micro = Integer.parseInt(microStr.substring(0, microStr
- .indexOf(QUALIFIER_DELIM)));
- }
- }
- }
+ return VersionRange.parse(value).toString();
}
catch (Exception ex)
{
return Version.emptyVersion.toString();
}
-
- return major + "." + minor + "." + micro;
}
}
\ No newline at end of file