summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-10-01 13:16:59 +0200
committerSven Gothel <[email protected]>2013-10-01 13:16:59 +0200
commit4aa1478b2e4f1401b08d093461b37a14c9501c29 (patch)
treee609e8ad9633b69d431753650ec73080c2e11682
parent1a8d2c627dbab5234aea72a458c00b6bba28add0 (diff)
Bug 845: Add support for one big-fat jar file [java classes plus all native 'os.and.arch' libraries]
JNILibLoaderBase.addNativeJarLibsImpl(..): If the modules's jar file contains the folder 'natives/<os.and.arch>/' we assume a big-fat jar and attempt to load all native libraries from the same. The test for above folder is performed via the class ClassLoader's getResource(..) and is considered inexpensive. If the folder exists and native libraries could be loaded, the method returns successfull. Otherwise, the 'slim' jar file is attempted to be loaded, even if such folder exist.
-rw-r--r--src/java/com/jogamp/common/jvm/JNILibLoaderBase.java45
-rw-r--r--src/java/com/jogamp/common/util/JarUtil.java39
-rw-r--r--src/java/com/jogamp/common/util/cache/TempJarCache.java18
-rw-r--r--src/junit/com/jogamp/common/util/TestTempJarCache.java4
4 files changed, 73 insertions, 33 deletions
diff --git a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
index 022ec0e..f0ff69d 100644
--- a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
+++ b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
@@ -44,6 +44,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
@@ -153,22 +154,38 @@ public class JNILibLoaderBase {
msg.setLength(0); // reset
msg.append("addNativeJarLibsImpl(classFromJavaJar ").append(classFromJavaJar).append(", classJarURI ").append(classJarURI).append(", nativeJarBaseName ").append(nativeJarBasename).append("): ");
boolean ok = false;
- if(TempJarCache.isInitialized()) {
- final String nativeJarName = nativeJarBasename+"-natives-"+PlatformPropsImpl.os_and_arch+".jar";
- msg.append(nativeJarName);
- final URI jarSubURI = JarUtil.getJarSubURI( classJarURI );
- if(null == jarSubURI) {
- throw new IllegalArgumentException("JarSubURI is null of: "+classJarURI);
+ if(TempJarCache.isInitialized()) {
+ final String nativeLibraryPath = "natives/"+PlatformPropsImpl.os_and_arch+"/";
+ final ClassLoader cl = classFromJavaJar.getClassLoader();
+ final URL nativeLibraryURI = cl.getResource(nativeLibraryPath);
+ if( null != nativeLibraryURI ) {
+ // We probably have one big-fat jar file, containing java classes
+ // and all native platform libraries under 'natives/os.and.arch'!
+ if( TempJarCache.addNativeLibs(classFromJavaJar, classJarURI, nativeLibraryPath) ) {
+ ok = true;
+ msg.append(classJarURI).append(" (fat)");
+ if(DEBUG) {
+ System.err.println(msg.toString());
+ }
+ }
}
- final String jarUriRoot_s = IOUtil.getURIDirname( jarSubURI.toString() );
- msg.append(" + ").append(jarUriRoot_s);
- final URI nativeJarURI = JarUtil.getJarFileURI(jarUriRoot_s+nativeJarName);
- msg.append(" -> ").append(nativeJarURI);
- if(DEBUG) {
- System.err.println(msg.toString());
+ if( !ok ) {
+ // We assume one slim native jar file per 'os.and.arch'!
+ final String nativeJarName = nativeJarBasename+"-natives-"+PlatformPropsImpl.os_and_arch+".jar";
+ msg.append(nativeJarName);
+ final URI jarSubURI = JarUtil.getJarSubURI( classJarURI );
+ if(null == jarSubURI) {
+ throw new IllegalArgumentException("JarSubURI is null of: "+classJarURI);
+ }
+ final String jarUriRoot_s = IOUtil.getURIDirname( jarSubURI.toString() );
+ msg.append(" + ").append(jarUriRoot_s);
+ final URI nativeJarURI = JarUtil.getJarFileURI(jarUriRoot_s+nativeJarName);
+ msg.append(" -> ").append(nativeJarURI).append(" (slim)");
+ if(DEBUG) {
+ System.err.println(msg.toString());
+ }
+ ok = TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI, null /* nativeLibraryPath */);
}
- TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI);
- ok = true;
}
return ok;
}
diff --git a/src/java/com/jogamp/common/util/JarUtil.java b/src/java/com/jogamp/common/util/JarUtil.java
index 41d68d4..665e196 100644
--- a/src/java/com/jogamp/common/util/JarUtil.java
+++ b/src/java/com/jogamp/common/util/JarUtil.java
@@ -514,22 +514,23 @@ public class JarUtil {
* @param dest
* @param nativeLibMap
* @param jarFile
- * @param deepDirectoryTraversal
+ * @param nativeLibraryPath if not null, only extracts native libraries within this path.
* @param extractNativeLibraries
* @param extractClassFiles
* @param extractOtherFiles
+ * @param deepDirectoryTraversal
* @return
* @throws IOException
*/
public static final int extract(File dest, Map<String, String> nativeLibMap,
JarFile jarFile,
+ String nativeLibraryPath,
boolean extractNativeLibraries,
- boolean extractClassFiles,
- boolean extractOtherFiles) throws IOException {
+ boolean extractClassFiles, boolean extractOtherFiles) throws IOException {
if (DEBUG) {
System.err.println("JarUtil: extract: "+jarFile.getName()+" -> "+dest+
- ", extractNativeLibraries "+extractNativeLibraries+
+ ", extractNativeLibraries "+extractNativeLibraries+" ("+nativeLibraryPath+")"+
", extractClassFiles "+extractClassFiles+
", extractOtherFiles "+extractOtherFiles);
}
@@ -543,11 +544,29 @@ public class JarUtil {
// Match entries with correct prefix and suffix (ignoring case)
final String libBaseName = NativeLibrary.isValidNativeLibraryName(entryName, false);
final boolean isNativeLib = null != libBaseName;
- if(isNativeLib && !extractNativeLibraries) {
- if (DEBUG) {
- System.err.println("JarUtil: JarEntry : " + entryName + " native-lib skipped");
+ if(isNativeLib) {
+ if(!extractNativeLibraries) {
+ if (DEBUG) {
+ System.err.println("JarUtil: JarEntry : " + entryName + " native-lib skipped, skip all native libs");
+ }
+ continue;
+ }
+ if(null != nativeLibraryPath) {
+ final String nativeLibraryPathS;
+ final String dirnameS;
+ try {
+ nativeLibraryPathS = IOUtil.slashify(nativeLibraryPath, false /* startWithSlash */, true /* endWithSlash */);
+ dirnameS = IOUtil.getDirname(entryName);
+ } catch (URISyntaxException e) {
+ throw new IOException(e);
+ }
+ if( !nativeLibraryPathS.equals(dirnameS) ) {
+ if (DEBUG) {
+ System.err.println("JarUtil: JarEntry : " + entryName + " native-lib skipped, not in path: "+nativeLibraryPathS);
+ }
+ continue;
+ }
}
- continue;
}
final boolean isClassFile = entryName.endsWith(".class");
@@ -581,14 +600,14 @@ public class JarUtil {
if (DEBUG) {
System.err.println("JarUtil: MKDIR: " + entryName + " -> " + destFile );
}
- destFile.mkdir();
+ destFile.mkdirs();
} else {
final File destFolder = new File(destFile.getParent());
if(!destFolder.exists()) {
if (DEBUG) {
System.err.println("JarUtil: MKDIR (parent): " + entryName + " -> " + destFolder );
}
- destFolder.mkdir();
+ destFolder.mkdirs();
}
final InputStream in = new BufferedInputStream(jarFile.getInputStream(entry));
final OutputStream out = new BufferedOutputStream(new FileOutputStream(destFile));
diff --git a/src/java/com/jogamp/common/util/cache/TempJarCache.java b/src/java/com/jogamp/common/util/cache/TempJarCache.java
index 3943633..e2a33e0 100644
--- a/src/java/com/jogamp/common/util/cache/TempJarCache.java
+++ b/src/java/com/jogamp/common/util/cache/TempJarCache.java
@@ -197,12 +197,14 @@ public class TempJarCache {
*
* @param certClass if class is certified, the JarFile entries needs to have the same certificate
* @param jarURI
+ * @param nativeLibraryPath if not null, only extracts native libraries within this path.
+ * @return true if native libraries were added or previously loaded from given jarURI, otherwise false
* @throws IOException if the <code>jarURI</code> could not be loaded or a previous load attempt failed
* @throws SecurityException
* @throws URISyntaxException
* @throws IllegalArgumentException
*/
- public synchronized static final void addNativeLibs(Class<?> certClass, URI jarURI) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException {
+ public synchronized static final boolean addNativeLibs(Class<?> certClass, URI jarURI, String nativeLibraryPath) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException {
final LoadState nativeLibJarsLS = nativeLibJars.get(jarURI);
if( !testLoadState(nativeLibJarsLS, LoadState.LOOKED_UP) ) {
nativeLibJars.put(jarURI, LoadState.LOOKED_UP);
@@ -211,11 +213,13 @@ public class TempJarCache {
System.err.println("TempJarCache: addNativeLibs: "+jarURI+": nativeJar "+jarFile.getName());
}
validateCertificates(certClass, jarFile);
- JarUtil.extract(tmpFileCache.getTempDir(), nativeLibMap, jarFile, true, false, false);
+ final int num = JarUtil.extract(tmpFileCache.getTempDir(), nativeLibMap, jarFile, nativeLibraryPath, true, false, false);
nativeLibJars.put(jarURI, LoadState.LOADED);
- } else if( !testLoadState(nativeLibJarsLS, LoadState.LOADED) ) {
- throw new IOException("TempJarCache: addNativeLibs: "+jarURI+", previous load attempt failed");
+ return num > 0;
+ } else if( testLoadState(nativeLibJarsLS, LoadState.LOADED) ) {
+ return true;
}
+ throw new IOException("TempJarCache: addNativeLibs: "+jarURI+", previous load attempt failed");
}
/**
@@ -241,7 +245,7 @@ public class TempJarCache {
}
validateCertificates(certClass, jarFile);
JarUtil.extract(tmpFileCache.getTempDir(), null, jarFile,
- false, true, false);
+ null /* nativeLibraryPath */, false, true, false);
classFileJars.put(jarURI, LoadState.LOADED);
} else if( !testLoadState(classFileJarsLS, LoadState.LOADED) ) {
throw new IOException("TempJarCache: addClasses: "+jarURI+", previous load attempt failed");
@@ -269,7 +273,7 @@ public class TempJarCache {
}
validateCertificates(certClass, jarFile);
JarUtil.extract(tmpFileCache.getTempDir(), null, jarFile,
- false, false, true);
+ null /* nativeLibraryPath */, false, false, true);
resourceFileJars.put(jarURI, LoadState.LOADED);
} else if( !testLoadState(resourceFileJarsLS, LoadState.LOADED) ) {
throw new IOException("TempJarCache: addResources: "+jarURI+", previous load attempt failed");
@@ -323,7 +327,7 @@ public class TempJarCache {
}
validateCertificates(certClass, jarFile);
JarUtil.extract(tmpFileCache.getTempDir(), nativeLibMap, jarFile,
- extractNativeLibraries, extractClassFiles, extractOtherFiles);
+ null /* nativeLibraryPath */, extractNativeLibraries, extractClassFiles, extractOtherFiles);
// mark loaded (those were just loaded)
if(extractNativeLibraries) {
diff --git a/src/junit/com/jogamp/common/util/TestTempJarCache.java b/src/junit/com/jogamp/common/util/TestTempJarCache.java
index 29fe4c5..7ddf52a 100644
--- a/src/junit/com/jogamp/common/util/TestTempJarCache.java
+++ b/src/junit/com/jogamp/common/util/TestTempJarCache.java
@@ -147,7 +147,7 @@ public class TestTempJarCache extends JunitTracer {
if(AndroidVersion.isAvailable) { System.err.println("n/a on Android"); return; }
JarFile jarFile = JarUtil.getJarFile(GlueGenVersion.class.getName(), this.getClass().getClassLoader());
Assert.assertNotNull(jarFile);
- JarUtil.extract(fileCache.getTempDir(), null, jarFile, false, true, true);
+ JarUtil.extract(fileCache.getTempDir(), null, jarFile, null, false, true, true);
File f = new File(fileCache.getTempDir(), "META-INF/MANIFEST.MF");
Assert.assertTrue(f.exists());
f = new File(fileCache.getTempDir(), IOUtil.getClassFileName(GlueGenVersion.class.getName()));
@@ -207,7 +207,7 @@ public class TestTempJarCache extends JunitTracer {
URI nativeJarURI = JarUtil.getJarFileURI(jarUriRoot, nativeJarName);
- TempJarCache.addNativeLibs(TempJarCache.class, nativeJarURI);
+ TempJarCache.addNativeLibs(TempJarCache.class, nativeJarURI, null /* nativeLibraryPath */);
String libFullPath = TempJarCache.findLibrary(libBaseName);
Assert.assertNotNull(libFullPath);
Assert.assertEquals(libBaseName, NativeLibrary.isValidNativeLibraryName(libFullPath, true));