summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--make/build-test.xml2
-rw-r--r--make/build.xml20
-rwxr-xr-xmake/scripts/adb-install-all-armv7.sh2
-rw-r--r--src/java/com/jogamp/common/jvm/JNILibLoaderBase.java182
-rw-r--r--src/java/com/jogamp/common/os/Platform.java43
-rw-r--r--src/java/com/jogamp/common/util/IOUtil.java12
-rw-r--r--src/java/com/jogamp/common/util/JarUtil.java287
-rw-r--r--src/java/com/jogamp/common/util/cache/TempJarCache.java174
-rw-r--r--src/junit/com/jogamp/common/util/TestJarUtil.java4
-rw-r--r--src/junit/com/jogamp/common/util/TestTempJarCache.java4
10 files changed, 474 insertions, 256 deletions
diff --git a/make/build-test.xml b/make/build-test.xml
index 7540c1c..a5417b6 100644
--- a/make/build-test.xml
+++ b/make/build-test.xml
@@ -86,7 +86,7 @@
</path>
<property name="junit.run.jars" value="${junit.jar}${path.separator}${ant.jar}${path.separator}${TestJarsInJar.jar}${path.separator}${gluegen.root}/${rootrel.build}/gluegen.jar${path.separator}${build_t}/gluegen-test.jar"/>
<property name="junit.run.remote.jars" value="${junit.jar}${path.separator}${env.TARGET_ANT_HOME}/lib/ant.jar${path.separator}${env.TARGET_ANT_HOME}/lib/ant-junit.jar${path.separator}${gluegen.root}/make/lib/TestJarsInJar.jar${path.separator}${gluegen.root}/${rootrel.build}/gluegen.jar${path.separator}${build_t}/gluegen-test.jar"/>
- <property name="junit.run.remote.apks" value="${gluegen.root}/${rootrel.build}/jogamp.android-launcher.apk${path.separator}${ant-junit-all.apk}${path.separator}${gluegen.root}/${rootrel.build}/gluegen-rt-android-${android.abi}.apk${path.separator}${build_t}/gluegen-test.apk${path.separator}${gluegen.root}/make/lib/TestJarsInJar.apk"/>
+ <property name="junit.run.remote.apks" value="${gluegen.root}/${rootrel.build}/jogamp-android-launcher.apk${path.separator}${ant-junit-all.apk}${path.separator}${gluegen.root}/${rootrel.build}/gluegen-rt-android-${android.abi}.apk${path.separator}${build_t}/gluegen-test.apk${path.separator}${gluegen.root}/make/lib/TestJarsInJar.apk"/>
<property name="stub.includes.dir" value="stub_includes" /> <!-- NOTE: this MUST be relative for FileSet -->
diff --git a/make/build.xml b/make/build.xml
index 9b4e316..671e3c3 100644
--- a/make/build.xml
+++ b/make/build.xml
@@ -141,7 +141,7 @@
<property name="archive" value="${build}/${archive.name}" />
<!-- the launcher is compiled and packaged explicit - if android -->
- <property name="jogamp.android-launcher.classes" value="jogamp/android/launcher/**"/>
+ <property name="jogamp-android-launcher.classes" value="jogamp/android/launcher/**"/>
<!-- optional android classes - if android -->
<property name="java.part.android" value="jogamp/common/os/android/**"/>
@@ -150,7 +150,7 @@
<property name="gluegen-rt.classes" value="com/jogamp/gluegen/runtime/**"/>
<property name="jogamp.common.classes" value="com/jogamp/common/** jogamp/common/**"/>
- <property name="gluegen.excludes.all" value="${gluegen.excludes.nsig} ${jogamp.android-launcher.classes}" />
+ <property name="gluegen.excludes.all" value="${gluegen.excludes.nsig} ${jogamp-android-launcher.classes}" />
</target>
@@ -709,7 +709,7 @@
<jar destfile="${build}/gluegen.jar" manifest="${build}/Manifest.temp">
<fileset dir="${classes}">
<include name="**/*.class" />
- <exclude name="${jogamp.android-launcher.classes}" />
+ <exclude name="${jogamp-android-launcher.classes}" />
<exclude name="${java.part.android}" />
</fileset>
<fileset dir="resources/assets">
@@ -734,7 +734,7 @@
<include name="com/jogamp/gluegen/runtime/*.class" />
<include name="com/jogamp/common/**" />
<include name="jogamp/common/**" />
- <exclude name="${jogamp.android-launcher.classes}" />
+ <exclude name="${jogamp-android-launcher.classes}" />
<exclude name="${java.part.android}" />
</fileset>
<fileset dir="resources/assets">
@@ -793,7 +793,7 @@
<include name="com/jogamp/gluegen/runtime/*.class" />
<include name="com/jogamp/common/**" />
<include name="jogamp/common/**" />
- <exclude name="${jogamp.android-launcher.classes}" />
+ <exclude name="${jogamp-android-launcher.classes}" />
</fileset>
<fileset dir="resources/assets">
<include name="**" />
@@ -812,14 +812,14 @@
<srcfiles dir= "." includes="*.xml"/>
<srcfiles dir= "resources/android" includes="**/*.xml"/>
<srcfiles dir= "${src.java}/jogamp/android/launcher" includes="**"/>
- <mapper type="merge" to="${build}/jogamp.android-launcher.jar"/>
+ <mapper type="merge" to="${build}/jogamp-android-launcher.jar"/>
</uptodate>
</target>
<target name="android-launcher.build" depends="gluegen.cpptasks.detect.os,gluegen.build.check.android-launcher" if="isAndroid" unless="gluegen.build.skip.android-launcher">
<javac destdir="${classes}"
includeAntRuntime="false"
- includes="${jogamp.android-launcher.classes}"
+ includes="${jogamp-android-launcher.classes}"
excludes="${jogamp.common.classes}"
memoryMaximumSize="${javac.memorymax}"
encoding="UTF-8"
@@ -842,16 +842,16 @@
</filterset>
</copy>
- <jar destfile="${build}/jogamp.android-launcher.jar" manifest="${build}/Manifest-android-launcher.temp">
+ <jar destfile="${build}/jogamp-android-launcher.jar" manifest="${build}/Manifest-android-launcher.temp">
<fileset dir="${classes}">
- <include name="${jogamp.android-launcher.classes}" />
+ <include name="${jogamp-android-launcher.classes}" />
</fileset>
</jar>
<aapt.signed
assetsdir="resources/assets-launcher"
jarbuilddir="${build}"
- jarbasename="jogamp.android-launcher"
+ jarbasename="jogamp-android-launcher"
nativebuilddir="${build}"
nativebasename="non-existing"
androidmanifest.path="resources/android/AndroidManifest-Launcher.xml"
diff --git a/make/scripts/adb-install-all-armv7.sh b/make/scripts/adb-install-all-armv7.sh
index 6f271eb..9a0e4f7 100755
--- a/make/scripts/adb-install-all-armv7.sh
+++ b/make/scripts/adb-install-all-armv7.sh
@@ -1,2 +1,2 @@
-adb $* install ../build-android-armv7/jogamp.android-launcher.apk
+adb $* install ../build-android-armv7/jogamp-android-launcher.apk
adb $* install ../build-android-armv7/gluegen-rt-android-armeabi-v7a.apk
diff --git a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
index 60f3060..b09a2f1 100644
--- a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
+++ b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
@@ -39,11 +39,13 @@
package com.jogamp.common.jvm;
+import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.Arrays;
import java.util.HashSet;
import com.jogamp.common.os.NativeLibrary;
@@ -141,76 +143,176 @@ public class JNILibLoaderBase {
loaderAction = action;
}
+ /* pp */ static final boolean addNativeJarLibsImpl(Class<?> classFromJavaJar, URL classJarURL, String nativeJarBasename, StringBuilder msg)
+ throws IOException, IllegalArgumentException, SecurityException
+ {
+ msg.setLength(0); // reset
+ msg.append("addNativeJarLibsImpl(classFromJavaJar ").append(classFromJavaJar).append(", classJarURL ").append(classJarURL).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 URL jarUrlRoot = JarUtil.getURLDirname( JarUtil.getJarSubURL( classJarURL ) );
+ msg.append(" + ").append(jarUrlRoot);
+ final URL nativeJarURL = JarUtil.getJarFileURL(jarUrlRoot, nativeJarName);
+ msg.append(" -> ").append(nativeJarURL);
+ if(DEBUG) {
+ System.err.println(msg.toString());
+ }
+ TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURL);
+ ok = true;
+ }
+ return ok;
+ }
+
/**
+ * Loads and adds a JAR file's native library to the TempJarCache.<br>
+ * The native library JAR file's URL is derived as follows:
+ * <ul>
+ * <li> [1] <code>GLProfile.class</code> -> </li>
+ * <li> [2] <code>http://lala/</code> -> </li>
+ * <li> [4] <code>http://lala/'nativeJarBaseName'-'os.and.arch'.jar</code> </li>
+ * </ul>
+ * Where:
+ * <ul>
+ * <li> [1] is the <code>classFromJavaJar</code></li>
+ * <li> [2] is it's <i>URL path</i></li>
+ * <li> [4] is the derived native JAR filename</li>
+ * </ul>
*
* @param classFromJavaJar GLProfile
- * @param nativeJarBaseName jogl-all
+ * @param nativeJarBasename jogl-all
* @return true if the native JAR file loaded successful or were loaded already, false in case of an error
*/
- public static final boolean addNativeJarLibs(Class<?> classFromJavaJar, String nativeJarBaseName) {
+ public static final boolean addNativeJarLibs(Class<?> classFromJavaJar, String nativeJarBasename) {
if(TempJarCache.isInitialized()) {
- final String nativeJarName = nativeJarBaseName+"-natives-"+PlatformPropsImpl.os_and_arch+".jar";
- final ClassLoader cl = classFromJavaJar.getClassLoader();
+ final StringBuilder msg = new StringBuilder();
try {
- URL jarUrlRoot = JarUtil.getURLDirname( JarUtil.getJarSubURL( classFromJavaJar.getName(), cl ) );
- if(DEBUG) {
- System.err.println("JNILibLoaderBase: addNativeJarLibs: "+nativeJarBaseName+": url-root "+jarUrlRoot);
- }
- URL nativeJarURL = JarUtil.getJarFileURL(jarUrlRoot, nativeJarName);
- if(DEBUG) {
- System.err.println("JNILibLoaderBase: addNativeJarLibs: "+nativeJarBaseName+": nativeJarURL "+nativeJarURL);
- }
- TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURL, cl);
- return true;
+ final URL classJarURL = JarUtil.getJarURL(classFromJavaJar.getName(), classFromJavaJar.getClassLoader());
+ return addNativeJarLibsImpl(classFromJavaJar, classJarURL, nativeJarBasename, msg);
} catch (Exception e0) {
// IllegalArgumentException, IOException
- System.err.println("Catched: "+e0.getMessage());
+ System.err.println("Catched "+e0.getClass().getSimpleName()+": "+e0.getMessage()+", while "+msg.toString());
if(DEBUG) {
e0.printStackTrace();
}
- }
+ }
+ } else if(DEBUG) {
+ System.err.println("JNILibLoaderBase: addNativeJarLibs1: disabled due to uninitialized TempJarCache");
}
return false;
}
/**
- * @param classFromJavaJar A class file to determine the base URL of the native JAR files, eg.: GLProfile.class
- * @param allNativeJarBaseName Attempt to use the 'all' native JAR variant first, if exists. Eg. "jogl-all"
- * @param atomicNativeJarBaseNames Fallback to use all the atomic native JAR files, eg. [ "nativewindow", "jogl", "newt" ]
- * @return true if either the 'all' native JAR or all of the atomic native JARs loaded successful or were loaded already,
+ * Loads and adds a JAR file's native library to the TempJarCache.<br>
+ * The native library JAR file's URL is derived as follows:
+ * <ul>
+ * <li> [1] <code>GLProfile.class</code> -> </li>
+ * <li> [2] <code>http://lala/gluegen-rt.jar</code> -> </li>
+ * <li> [3] <code>http://lala/gluegen-rt</code> -> </li>
+ * <li> [4] <code>http://lala/gluegen-rt-natives-'os.and.arch'.jar</code> </li>
+ * </ul>
+ * Where:
+ * <ul>
+ * <li> [1] is one of <code>classesFromJavaJars</code></li>
+ * <li> [2] is it's complete URL</li>
+ * <li> [3] is it's <i>base URL</i></li>
+ * <li> [4] is the derived native JAR filename</li>
+ * </ul>
+ *
+ * Examples:<br>
+ * <br>
+ * JOCL:
+ * <pre>
+ // only: jocl.jar -> jocl-natives-'os.and.arch'.jar
+ addNativeJarLibs(new Class<?>[] { JOCLJNILibLoader.class }, null, null );
+ * </pre>
+ *
+ * Newt Only:
+ * <pre>
+ // either: [jogl-all.jar, jogl-all-noawt.jar, jogl-all-mobile.jar] -> jogl-all-natives-<os.and.arch>.jar
+ // or: nativewindow-core.jar -> nativewindow-natives-<os.and.arch>.jar,
+ // newt-core.jar -> newt-natives-<os.and.arch>.jar
+ JNILibLoaderBase.addNativeJarLibs(new Class<?>[] { NWJNILibLoader.class, NEWTJNILibLoader.class }, "-all", new String[] { "-noawt", "-mobile", "-core" } );
+ * </pre>
+ *
+ * JOGL:
+ * <pre>
+ final ClassLoader cl = GLProfile.class.getClassLoader();
+ // either: [jogl-all.jar, jogl-all-noawt.jar, jogl-all-mobile.jar] -> jogl-all-natives-<os.and.arch>.jar
+ // or: nativewindow-core.jar -> nativewindow-natives-<os.and.arch>.jar,
+ // jogl-core.jar -> jogl-natives-<os.and.arch>.jar,
+ // (newt-core.jar -> newt-natives-<os.and.arch>.jar)? (if available)
+ final String newtFactoryClassName = "com.jogamp.newt.NewtFactory";
+ final Class<?>[] classesFromJavaJars = new Class<?>[] { NWJNILibLoader.class, GLProfile.class, null };
+ if( ReflectionUtil.isClassAvailable(newtFactoryClassName, cl) ) {
+ classesFromJavaJars[2] = ReflectionUtil.getClass(newtFactoryClassName, false, cl);
+ }
+ JNILibLoaderBase.addNativeJarLibs(classesFromJavaJars, "-all", new String[] { "-noawt", "-mobile", "-core" } );
+ * </pre>
+ *
+ * @param classesFromJavaJars For each given Class, load the native library JAR.
+ * @param singleJarMarker Optional string marker like "-all" to identify the single 'all-in-one' JAR file
+ * after which processing of the class array shall stop.
+ * @param stripBasenameSuffixes Optional substrings to be stripped of the <i>base URL</i>
+ *
+ * @return true if either the 'all-in-one' native JAR or all native JARs loaded successful or were loaded already,
* false in case of an error
*/
- public static boolean addNativeJarLibs(Class<?> classFromJavaJar, String allNativeJarBaseName, String[] atomicNativeJarBaseNames) {
- boolean res = false;
+ public static boolean addNativeJarLibs(Class<?>[] classesFromJavaJars, String singleJarMarker, String[] stripBasenameSuffixes) {
+ if(DEBUG) {
+ System.err.println("JNILibLoaderBase: addNativeJarLibs0(classesFromJavaJars "+Arrays.asList(classesFromJavaJars)+", singleJarMarker "+singleJarMarker+", stripBasenameSuffixes "+Arrays.asList(stripBasenameSuffixes));
+ }
+ boolean ok = false;
if(TempJarCache.isInitialized()) {
- final ClassLoader cl = classFromJavaJar.getClassLoader();
- try {
- final String jarName = JarUtil.getJarBasename(classFromJavaJar.getName(), cl);
- if(jarName!=null) {
- if(!res && null != allNativeJarBaseName) {
- // all-in-one variant 1st
- res = JNILibLoaderBase.addNativeJarLibs(classFromJavaJar, allNativeJarBaseName);
- }
- if(!res && null != atomicNativeJarBaseNames) {
- // atomic variant
- res = true;
- for(int i=0; res && i<atomicNativeJarBaseNames.length; i++) {
- final String atomicNativeJarBaseName = atomicNativeJarBaseNames[i];
- if(null != atomicNativeJarBaseName && atomicNativeJarBaseName.length()>0) {
- res = JNILibLoaderBase.addNativeJarLibs(classFromJavaJar, atomicNativeJarBaseName);
- }
+ final StringBuilder msg = new StringBuilder();
+ int count = 0;
+ try {
+ boolean done = false;
+ ok = true;
+ for(int i=0; !done && ok && i<classesFromJavaJars.length && null!=classesFromJavaJars[i]; i++) {
+ final ClassLoader cl = classesFromJavaJars[i].getClassLoader();
+ final URL classJarURL = JarUtil.getJarURL(classesFromJavaJars[i].getName(), cl);
+ final String jarName = JarUtil.getJarBasename(classJarURL);
+ ok = null != jarName;
+ if(ok) {
+ final String jarBasename = jarName.substring(0, jarName.indexOf(".jar")); // ".jar" already validated w/ JarUtil.getJarBasename(..)
+ final String nativeJarBasename = stripName(jarBasename, stripBasenameSuffixes);
+ done = null != singleJarMarker && jarBasename.indexOf(singleJarMarker) >= 0; // done if single-jar ('all' variant)
+ ok = JNILibLoaderBase.addNativeJarLibsImpl(classesFromJavaJars[i], classJarURL, nativeJarBasename, msg);
+ if(ok) { count++; }
+ if(DEBUG && done) {
+ System.err.println("JNILibLoaderBase: addNativeJarLibs0: end after all-in-one JAR: "+jarBasename);
}
}
}
} catch (Exception e0) {
// IllegalArgumentException, IOException
- System.err.println("Catched: "+e0.getMessage());
+ System.err.println("Catched "+e0.getClass().getSimpleName()+": "+e0.getMessage()+", while "+msg.toString());
if(DEBUG) {
e0.printStackTrace();
}
+ ok = false;
}
+ if(DEBUG) {
+ System.err.println("JNILibLoaderBase: addNativeJarLibs0(..) done, count "+count+", ok "+ok);
+ }
+ } else if(DEBUG) {
+ System.err.println("JNILibLoaderBase: addNativeJarLibs0: disabled due to uninitialized TempJarCache");
}
- return res;
+ return ok;
+ }
+
+ private static final String stripName(String name, String[] suffixes) {
+ if(null != suffixes) {
+ for(int i=0; i<suffixes.length && null != suffixes[i]; i++) {
+ int idx = name.indexOf(suffixes[i]);
+ if(0 < idx) {
+ return name.substring(0, idx);
+ }
+ }
+ }
+ return name;
}
/**
diff --git a/src/java/com/jogamp/common/os/Platform.java b/src/java/com/jogamp/common/os/Platform.java
index a42ab25..ba89474 100644
--- a/src/java/com/jogamp/common/os/Platform.java
+++ b/src/java/com/jogamp/common/os/Platform.java
@@ -162,9 +162,21 @@ public class Platform extends PlatformPropsImpl {
/** <code>true</code> if AWT is available and not in headless mode, otherwise <code>false</code>. */
public static final boolean AWT_AVAILABLE;
+ private static final URL platformClassJarURL;
+
static {
PlatformPropsImpl.initSingleton(); // just documenting the order of static initialization
-
+
+ {
+ URL _platformClassJarURL;
+ try {
+ _platformClassJarURL = JarUtil.getJarURL(Platform.class.getName(), Platform.class.getClassLoader());
+ } catch (Exception e) {
+ _platformClassJarURL = null;
+ }
+ platformClassJarURL = _platformClassJarURL;
+ }
+
USE_TEMP_JAR_CACHE = (OS_TYPE != OSType.ANDROID) && isRunningFromJarURL() &&
Debug.getBooleanProperty(useTempJarCachePropName, true, true);
@@ -209,35 +221,32 @@ public class Platform extends PlatformPropsImpl {
private Platform() {}
/**
- * Preemptively avoids initializing and using {@link TempJarCache} in case we are <b>not</b> running
- * from a Jar URL, ie. plain class files. Used to set {@link USE_TEMP_JAR_CACHE}.
- * <p>
- * Impact: Less overhead and more robustness.
- * </p>
- *
* @return true if we're running from a Jar URL, otherwise false
*/
- private static final boolean isRunningFromJarURL() {
- return JarUtil.hasJarURL(Platform.class.getName(), Platform.class.getClassLoader());
+ public static final boolean isRunningFromJarURL() {
+ return null != platformClassJarURL;
}
private static final void loadGlueGenRTImpl() {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
- final ClassLoader cl = Platform.class.getClassLoader();
if(USE_TEMP_JAR_CACHE && TempJarCache.initSingleton()) {
- final String nativeJarName = libBaseName+"-natives-"+os_and_arch+".jar";
+ String nativeJarName = null;
+ URL jarUrlRoot = null;
+ URL nativeJarURL = null;
try {
- final URL jarUrlRoot = JarUtil.getURLDirname(
- JarUtil.getJarSubURL(Platform.class.getName(), cl) );
- final URL nativeJarURL = JarUtil.getJarFileURL(jarUrlRoot, nativeJarName);
- TempJarCache.bootstrapNativeLib(Platform.class, libBaseName, nativeJarURL, cl);
+ final String jarName = JarUtil.getJarBasename(platformClassJarURL);
+ final String nativeJarBasename = jarName.substring(0, jarName.indexOf(".jar")); // ".jar" already validated w/ JarUtil.getJarBasename(..)
+ nativeJarName = nativeJarBasename+"-natives-"+PlatformPropsImpl.os_and_arch+".jar";
+ jarUrlRoot = JarUtil.getURLDirname( JarUtil.getJarSubURL(platformClassJarURL) );
+ nativeJarURL = JarUtil.getJarFileURL(jarUrlRoot, nativeJarName);
+ TempJarCache.bootstrapNativeLib(Platform.class, libBaseName, nativeJarURL);
} catch (Exception e0) {
// IllegalArgumentException, IOException
- System.err.println("Catched: "+e0.getMessage());
+ System.err.println("Catched "+e0.getClass().getSimpleName()+": "+e0.getMessage()+", while TempJarCache.bootstrapNativeLib() of "+nativeJarURL+" ("+jarUrlRoot+" + "+nativeJarName+")");
}
}
- DynamicLibraryBundle.GlueJNILibLoader.loadLibrary(libBaseName, false, cl);
+ DynamicLibraryBundle.GlueJNILibLoader.loadLibrary(libBaseName, false, Platform.class.getClassLoader());
return null;
}
});
diff --git a/src/java/com/jogamp/common/util/IOUtil.java b/src/java/com/jogamp/common/util/IOUtil.java
index 8c2a0c1..ffea7cb 100644
--- a/src/java/com/jogamp/common/util/IOUtil.java
+++ b/src/java/com/jogamp/common/util/IOUtil.java
@@ -338,19 +338,23 @@ public class IOUtil {
}
}
- public static String getClassFileName(String clazzBinName) throws IOException {
+ public static String getClassFileName(String clazzBinName) {
// or return clazzBinName.replace('.', File.separatorChar) + ".class"; ?
return clazzBinName.replace('.', '/') + ".class";
}
/**
* @param clazzBinName com.jogamp.common.util.cache.TempJarCache
- * @param cl
+ * @param cl ClassLoader to locate the JarFile
* @return jar:file:/usr/local/projects/JOGL/gluegen/build-x86_64/gluegen-rt.jar!/com/jogamp/common/util/cache/TempJarCache.class
- * @throws IOException
+ * @throws IOException if the jar file could not been found by the ClassLoader
*/
public static URL getClassURL(String clazzBinName, ClassLoader cl) throws IOException {
- return cl.getResource(getClassFileName(clazzBinName));
+ final URL url = cl.getResource(getClassFileName(clazzBinName));
+ if(null == url) {
+ throw new IOException("Cannot not find: "+clazzBinName);
+ }
+ return url;
}
/**
diff --git a/src/java/com/jogamp/common/util/JarUtil.java b/src/java/com/jogamp/common/util/JarUtil.java
index 85a10ce..84ec59d 100644
--- a/src/java/com/jogamp/common/util/JarUtil.java
+++ b/src/java/com/jogamp/common/util/JarUtil.java
@@ -35,6 +35,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.JarURLConnection;
+import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.Certificate;
@@ -81,125 +82,161 @@ public class JarUtil {
* </p>
*
* @param clazzBinName "com.jogamp.common.GlueGenVersion"
- * @param cl
+ * @param cl ClassLoader to locate the JarFile
* @return "jar:<i>sub_protocol</i>:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class"
- * @throws IllegalArgumentException if the URL doesn't match the expected formatting
- * @throws IOException
+ * @throws IllegalArgumentException if the URL doesn't match the expected formatting or null arguments
+ * @throws IOException if the class's Jar file could not been found by the ClassLoader
* @see {@link IOUtil#getClassURL(String, ClassLoader)}
*/
public static URL getJarURL(String clazzBinName, ClassLoader cl) throws IllegalArgumentException, IOException {
- URL url = IOUtil.getClassURL(clazzBinName, cl);
- if(null != url) {
- String urlS = url.toExternalForm();
- if(DEBUG) {
- System.out.println("getJarURL "+url+", extForm: "+urlS);
- }
- if(!urlS.startsWith("jar:")) {
- throw new IllegalArgumentException("JAR URL doesn't start with 'jar:', got <"+urlS+">");
- }
+ if(null == clazzBinName || null == cl) {
+ throw new IllegalArgumentException("null arguments: clazzBinName "+clazzBinName+", cl "+cl);
+ }
+ final URL url = IOUtil.getClassURL(clazzBinName, cl);
+ // test name ..
+ final String urlS = url.toExternalForm();
+ if(DEBUG) {
+ System.out.println("getJarURL "+url+", extForm: "+urlS);
+ }
+ if(!urlS.startsWith("jar:")) {
+ throw new IllegalArgumentException("JAR URL doesn't start with 'jar:', got <"+urlS+">");
}
return url;
}
/**
- * The Class's <code>"com.jogamp.common.GlueGenVersion"</code>
- * URL <code>jar:<i>sub_protocol</i>:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class"</code>
+ * The Class's Jar URL <code>jar:<i>sub_protocol</i>:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class</code>
* Jar basename <code>gluegen-rt.jar</code> will be returned.
* <p>
* <i>sub_protocol</i> may be "file", "http", etc..
* </p>
*
- * @param clazzBinName "com.jogamp.common.GlueGenVersion"
+ * @param classJarURL as retrieved w/ {@link #getJarURL(String, ClassLoader) getJarURL("com.jogamp.common.GlueGenVersion", cl)},
+ * i.e. <code>jar:<i>sub_protocol</i>:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class</code>
+ * @return <code>gluegen-rt.jar</code>
+ * @throws IllegalArgumentException if the URL doesn't match the expected formatting or is null
+ * @see {@link IOUtil#getClassURL(String, ClassLoader)}
+ */
+ public static String getJarBasename(URL classJarURL) throws IllegalArgumentException {
+ if(null == classJarURL) {
+ throw new IllegalArgumentException("URL is null");
+ }
+ String urlS = classJarURL.toExternalForm();
+ urlS = urlS.substring(4, urlS.length()); // exclude 'jar:'
+
+ // from
+ // file:/some/path/gluegen-rt.jar!/com/jogamp/common/util/cache/TempJarCache.class
+ // to
+ // file:/some/path/gluegen-rt.jar
+ int idx = urlS.lastIndexOf('!');
+ if (0 <= idx) {
+ urlS = urlS.substring(0, idx); // exclude '!/'
+ } else {
+ throw new IllegalArgumentException("JAR URL does not contain jar url terminator '!', in <"+classJarURL.toExternalForm()+">, got <"+urlS+">");
+ }
+
+ // from
+ // file:/some/path/gluegen-rt.jar
+ // to
+ // gluegen-rt.jar
+ idx = urlS.lastIndexOf('/');
+ if(0 > idx) {
+ // no abs-path, check for protocol terminator ':'
+ idx = urlS.lastIndexOf(':');
+ if(0 > idx) {
+ throw new IllegalArgumentException("JAR URL does not contain protocol terminator ':', in <"+classJarURL.toExternalForm()+">, got <"+urlS+">");
+ }
+ }
+ urlS = urlS.substring(idx+1); // just the jar name
+
+ if(0 >= urlS.lastIndexOf(".jar")) {
+ throw new IllegalArgumentException("No Jar name in <"+classJarURL.toExternalForm()+">, got <"+urlS+">");
+ }
+ if(DEBUG) {
+ System.out.println("getJarName res: "+urlS);
+ }
+ return urlS;
+ }
+
+ /**
+ * The Class's <code>com.jogamp.common.GlueGenVersion</code>
+ * URL <code>jar:<i>sub_protocol</i>:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class</code>
+ * Jar basename <code>gluegen-rt.jar</code> will be returned.
+ * <p>
+ * <i>sub_protocol</i> may be "file", "http", etc..
+ * </p>
+ *
+ * @param clazzBinName <code>com.jogamp.common.GlueGenVersion</code>
* @param cl
- * @return "gluegen-rt.jar"
+ * @return <code>gluegen-rt.jar</code>
* @throws IllegalArgumentException if the URL doesn't match the expected formatting
- * @throws IOException
+ * @throws IOException if the class's Jar file could not been found by the ClassLoader
* @see {@link IOUtil#getClassURL(String, ClassLoader)}
*/
public static String getJarBasename(String clazzBinName, ClassLoader cl) throws IllegalArgumentException, IOException {
- URL url = getJarURL(clazzBinName, cl);
- if(null != url) {
- String urlS = url.toExternalForm();
- urlS = urlS.substring(4, urlS.length()); // exclude 'jar:'
-
- // from
- // file:/some/path/gluegen-rt.jar!/com/jogamp/common/util/cache/TempJarCache.class
- // to
- // file:/some/path/gluegen-rt.jar
- int idx = urlS.lastIndexOf('!');
- if (0 <= idx) {
- urlS = urlS.substring(0, idx); // exclude '!/'
- } else {
- throw new IllegalArgumentException("JAR URL does not contain jar url terminator '!', in <"+url.toExternalForm()+">, got <"+urlS+">");
- }
-
- // from
- // file:/some/path/gluegen-rt.jar
- // to
- // gluegen-rt.jar
- idx = urlS.lastIndexOf('/');
- if(0 > idx) {
- // no abs-path, check for protocol terminator ':'
- idx = urlS.lastIndexOf(':');
- if(0 > idx) {
- throw new IllegalArgumentException("JAR URL does not contain protocol terminator ':', in <"+url.toExternalForm()+">, got <"+urlS+">");
- }
- }
- urlS = urlS.substring(idx+1); // just the jar name
-
- if(0 >= urlS.lastIndexOf(".jar")) {
- throw new IllegalArgumentException("No Jar name in <"+url.toExternalForm()+">, got <"+urlS+">");
- }
- if(DEBUG) {
- System.out.println("getJarName res: "+urlS);
- }
- return urlS;
+ return getJarBasename(getJarURL(clazzBinName, cl));
+ }
+
+ /**
+ * The Class's Jar URL <code>jar:<i>sub_protocol</i>:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class</code>
+ * Jar file's sub URL <code><i>sub_protocol</i>:/some/path/gluegen-rt.jar</code> will be returned.
+ * <p>
+ * <i>sub_protocol</i> may be "file", "http", etc..
+ * </p>
+ *
+ * @param classJarURL as retrieved w/ {@link #getJarURL(String, ClassLoader) getJarURL("com.jogamp.common.GlueGenVersion", cl)},
+ * i.e. <code>jar:<i>sub_protocol</i>:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class</code>
+ * @param cl
+ * @return <code><i>sub_protocol</i>:/some/path/gluegen-rt.jar</code>
+ * @throws IllegalArgumentException if the URL doesn't match the expected formatting or is null
+ * @throws MalformedURLException if the computed URL specifies an unknown protocol
+ * @see {@link IOUtil#getClassURL(String, ClassLoader)}
+ */
+ public static URL getJarSubURL(URL classJarURL) throws IllegalArgumentException, MalformedURLException {
+ if(null == classJarURL) {
+ throw new IllegalArgumentException("URL is null");
}
- return null;
+ String urlS = classJarURL.toExternalForm();
+ urlS = urlS.substring(4, urlS.length()); // exclude 'jar:'
+
+ // from
+ // file:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class
+ // to
+ // file:/some/path/gluegen-rt.jar
+ int idx = urlS.lastIndexOf('!');
+ if (0 <= idx) {
+ urlS = urlS.substring(0, idx); // exclude '!/'
+ } else {
+ throw new IllegalArgumentException("JAR URL does not contain jar url terminator '!', url <"+urlS+">");
+ }
+
+ if(0 >= urlS.lastIndexOf(".jar")) {
+ throw new IllegalArgumentException("No Jar name in <"+classJarURL.toExternalForm()+">, got <"+urlS+">");
+ }
+ if(DEBUG) {
+ System.out.println("getJarSubURL res: "+urlS);
+ }
+ return new URL(urlS);
}
/**
- * The Class's <code>"com.jogamp.common.GlueGenVersion"</code>
- * URL <code>jar:<i>sub_protocol</i>:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class"</code>
+ * The Class's <code>com.jogamp.common.GlueGenVersion</code>
+ * URL <code>jar:<i>sub_protocol</i>:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class</code>
* Jar file's sub URL <code><i>sub_protocol</i>:/some/path/gluegen-rt.jar</code> will be returned.
* <p>
* <i>sub_protocol</i> may be "file", "http", etc..
* </p>
*
- * @param clazzBinName "com.jogamp.common.GlueGenVersion"
+ * @param clazzBinName <code>com.jogamp.common.GlueGenVersion</code>
* @param cl
- * @return "<i>sub_protocol</i>:/some/path/gluegen-rt.jar"
+ * @return <code><i>sub_protocol</i>:/some/path/gluegen-rt.jar</code>
* @throws IllegalArgumentException if the URL doesn't match the expected formatting
- * @throws IOException
+ * @throws IOException if the class's Jar file could not been found by the ClassLoader
* @see {@link IOUtil#getClassURL(String, ClassLoader)}
*/
public static URL getJarSubURL(String clazzBinName, ClassLoader cl) throws IllegalArgumentException, IOException {
- URL url = getJarURL(clazzBinName, cl);
- if(null != url) {
- String urlS = url.toExternalForm();
- urlS = urlS.substring(4, urlS.length()); // exclude 'jar:'
-
- // from
- // file:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class
- // to
- // file:/some/path/gluegen-rt.jar
- int idx = urlS.lastIndexOf('!');
- if (0 <= idx) {
- urlS = urlS.substring(0, idx); // exclude '!/'
- } else {
- throw new IllegalArgumentException("JAR URL does not contain jar url terminator '!', url <"+urlS+">");
- }
-
- if(0 >= urlS.lastIndexOf(".jar")) {
- throw new IllegalArgumentException("No Jar name in <"+url.toExternalForm()+">, got <"+urlS+">");
- }
- if(DEBUG) {
- System.out.println("getJarSubURL res: "+urlS);
- }
- return new URL(urlS);
- }
- return null;
+ return getJarSubURL(getJarURL(clazzBinName, cl));
}
/**
@@ -213,20 +250,20 @@ public class JarUtil {
* @param clazzBinName "com.jogamp.common.GlueGenVersion"
* @param cl
* @return "jar:<i>sub_protocol</i>:/some/path/gluegen-rt.jar!/"
- * @throws IllegalArgumentException if the URL doesn't match the expected formatting
- * @throws IOException
+ * @throws IllegalArgumentException if the URL doesn't match the expected formatting or null arguments
+ * @throws IOException if the class's Jar file could not been found by the ClassLoader
* @see {@link IOUtil#getClassURL(String, ClassLoader)}
*/
public static URL getJarFileURL(String clazzBinName, ClassLoader cl) throws IllegalArgumentException, IOException {
+ if(null == clazzBinName || null == cl) {
+ throw new IllegalArgumentException("null arguments: clazzBinName "+clazzBinName+", cl "+cl);
+ }
URL url = getJarSubURL(clazzBinName, cl);
- if(null != url) {
- url = new URL("jar:"+url.toExternalForm()+"!/");
- if(DEBUG) {
- System.out.println("getJarFileURL res: "+url);
- }
- return url;
+ url = new URL("jar:"+url.toExternalForm()+"!/");
+ if(DEBUG) {
+ System.out.println("getJarFileURL res: "+url);
}
- return null;
+ return url;
}
/**
@@ -238,10 +275,13 @@ public class JarUtil {
*
* @param aURL "<i>protocol</i>:/some/path/gluegen-rt.jar"
* @return "<i>protocol</i>:/some/path/"
- * @throws IllegalArgumentException if the URL doesn't match the expected formatting
- * @throws IOException
+ * @throws IllegalArgumentException if the URL doesn't match the expected formatting, or is null
+ * @throws MalformedURLException
*/
- public static URL getURLDirname(URL aURL) throws IllegalArgumentException, IOException {
+ public static URL getURLDirname(URL aURL) throws IllegalArgumentException, MalformedURLException {
+ if(null == aURL) {
+ throw new IllegalArgumentException("URL is null");
+ }
String urlS = aURL.toExternalForm();
if(DEBUG) {
System.out.println("getURLDirname "+aURL+", extForm: "+urlS);
@@ -270,11 +310,12 @@ public class JarUtil {
* @param baseUrl file:/some/path/
* @param jarFileName gluegen-rt.jar
* @return jar:file:/some/path/gluegen-rt.jar!/
- * @throws IOException
+ * @throws MalformedURLException
+ * @throws IllegalArgumentException null arguments
*/
- public static URL getJarFileURL(URL baseUrl, String jarFileName) throws IOException {
- if(null == jarFileName) {
- throw new IllegalArgumentException("jarFileName is null");
+ public static URL getJarFileURL(URL baseUrl, String jarFileName) throws IOException, MalformedURLException {
+ if(null == baseUrl || null == jarFileName) {
+ throw new IllegalArgumentException("null arguments: baseUrl "+baseUrl+", jarFileName "+jarFileName);
}
return new URL("jar:"+baseUrl.toExternalForm()+jarFileName+"!/");
}
@@ -282,9 +323,10 @@ public class JarUtil {
/**
* @param jarSubUrl file:/some/path/gluegen-rt.jar
* @return jar:file:/some/path/gluegen-rt.jar!/
- * @throws IOException
+ * @throws MalformedURLException
+ * @throws IllegalArgumentException null arguments
*/
- public static URL getJarFileURL(URL jarSubUrl) throws IOException {
+ public static URL getJarFileURL(URL jarSubUrl) throws MalformedURLException, IllegalArgumentException {
if(null == jarSubUrl) {
throw new IllegalArgumentException("jarSubUrl is null");
}
@@ -295,9 +337,10 @@ public class JarUtil {
* @param jarFileURL jar:file:/some/path/gluegen-rt.jar!/
* @param jarEntry com/jogamp/common/GlueGenVersion.class
* @return jar:file:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class
- * @throws IOException
+ * @throws MalformedURLException
+ * @throws IllegalArgumentException null arguments
*/
- public static URL getJarEntryURL(URL jarFileURL, String jarEntry) throws IOException {
+ public static URL getJarEntryURL(URL jarFileURL, String jarEntry) throws MalformedURLException, IllegalArgumentException {
if(null == jarEntry) {
throw new IllegalArgumentException("jarEntry is null");
}
@@ -308,33 +351,35 @@ public class JarUtil {
* @param clazzBinName com.jogamp.common.util.cache.TempJarCache
* @param cl domain
* @return JarFile containing the named class within the given ClassLoader
- * @throws IOException
+ * @throws IOException if the class's Jar file could not been found by the ClassLoader
+ * @throws IllegalArgumentException null arguments
* @see {@link #getJarFileURL(String, ClassLoader)}
*/
- public static JarFile getJarFile(String clazzBinName, ClassLoader cl) throws IOException {
- return getJarFile(getJarFileURL(clazzBinName, cl), cl);
+ public static JarFile getJarFile(String clazzBinName, ClassLoader cl) throws IOException, IllegalArgumentException {
+ return getJarFile(getJarFileURL(clazzBinName, cl));
}
/**
* @param jarFileURL jar:file:/some/path/gluegen-rt.jar!/
- * @param cl domain
* @return JarFile as named by URL within the given ClassLoader
- * @throws IOException
+ * @throws IllegalArgumentException null arguments
+ * @throws IOException if the Jar file could not been found
*/
- public static JarFile getJarFile(URL jarFileUrl, ClassLoader cl) throws IOException {
+ public static JarFile getJarFile(URL jarFileUrl) throws IOException, IllegalArgumentException {
+ if(null == jarFileUrl) {
+ throw new IllegalArgumentException("null jarFileUrl");
+ }
if(DEBUG) {
System.out.println("getJarFile: "+jarFileUrl);
}
- if(null != jarFileUrl) {
- URLConnection urlc = jarFileUrl.openConnection();
- if(urlc instanceof JarURLConnection) {
- JarURLConnection jarConnection = (JarURLConnection)jarFileUrl.openConnection();
- JarFile jarFile = jarConnection.getJarFile();
- if(DEBUG) {
- System.out.println("getJarFile res: "+jarFile.getName());
- }
- return jarFile;
- }
+ URLConnection urlc = jarFileUrl.openConnection();
+ if(urlc instanceof JarURLConnection) {
+ JarURLConnection jarConnection = (JarURLConnection)jarFileUrl.openConnection();
+ JarFile jarFile = jarConnection.getJarFile();
+ if(DEBUG) {
+ System.out.println("getJarFile res: "+jarFile.getName());
+ }
+ return jarFile;
}
if(DEBUG) {
System.out.println("getJarFile res: NULL");
diff --git a/src/java/com/jogamp/common/util/cache/TempJarCache.java b/src/java/com/jogamp/common/util/cache/TempJarCache.java
index e4a77fe..6f24c68 100644
--- a/src/java/com/jogamp/common/util/cache/TempJarCache.java
+++ b/src/java/com/jogamp/common/util/cache/TempJarCache.java
@@ -39,9 +39,7 @@ import java.net.URL;
import java.security.cert.Certificate;
import java.util.Enumeration;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
-import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -62,10 +60,24 @@ public class TempJarCache {
// unpacked library file in nativeTmpDir.
private static Map<String, String> nativeLibMap;
- // Set of native jar files added
- private static Set<URL> nativeLibJars;
- private static Set<URL> classFileJars;
- private static Set<URL> resourceFileJars;
+ public enum LoadState {
+ LOOKED_UP, LOADED;
+
+ public boolean compliesWith(LoadState o2) {
+ return null != o2 ? compareTo(o2) >= 0 : false;
+ }
+ }
+ private static boolean testLoadState(LoadState has, LoadState exp) {
+ if(null == has) {
+ return null == exp;
+ }
+ return has.compliesWith(exp);
+ }
+
+ // Set of jar files added
+ private static Map<URL, LoadState> nativeLibJars;
+ private static Map<URL, LoadState> classFileJars;
+ private static Map<URL, LoadState> resourceFileJars;
private static TempFileCache tmpFileCache;
@@ -92,9 +104,9 @@ public class TempJarCache {
if(!staticInitError) {
// Initialize the collections of resources
nativeLibMap = new HashMap<String, String>();
- nativeLibJars = new HashSet<URL>();
- classFileJars = new HashSet<URL>();
- resourceFileJars = new HashSet<URL>();
+ nativeLibJars = new HashMap<URL, LoadState>();
+ classFileJars = new HashMap<URL, LoadState>();
+ resourceFileJars = new HashMap<URL, LoadState>();
}
if(DEBUG) {
System.err.println("TempJarCache.initSingleton(): ok "+(false==staticInitError)+", "+ tmpFileCache.getTempDir());
@@ -163,28 +175,28 @@ public class TempJarCache {
return tmpFileCache;
}
- public static boolean containsNativeLibs(URL jarURL) throws IOException {
+ public synchronized static boolean checkNativeLibs(URL jarURL, LoadState exp) throws IOException {
checkInitialized();
if(null == jarURL) {
throw new IllegalArgumentException("jarURL is null");
}
- return nativeLibJars.contains(jarURL);
+ return testLoadState(nativeLibJars.get(jarURL), exp);
}
- public static boolean containsClasses(URL jarURL) throws IOException {
+ public synchronized static boolean checkClasses(URL jarURL, LoadState exp) throws IOException {
checkInitialized();
if(null == jarURL) {
throw new IllegalArgumentException("jarURL is null");
}
- return classFileJars.contains(jarURL);
+ return testLoadState(classFileJars.get(jarURL), exp);
}
- public static boolean containsResources(URL jarURL) throws IOException {
+ public synchronized static boolean checkResources(URL jarURL, LoadState exp) throws IOException {
checkInitialized();
if(null == jarURL) {
throw new IllegalArgumentException("jarURL is null");
}
- return resourceFileJars.contains(jarURL);
+ return testLoadState(resourceFileJars.get(jarURL), exp);
}
/**
@@ -192,20 +204,23 @@ public class TempJarCache {
*
* @param certClass if class is certified, the JarFile entries needs to have the same certificate
* @param jarURL
- *
- * @throws IOException
+ * @throws IOException if the <code>jarURL</code> could not be loaded or a previous load attempt failed
* @throws SecurityException
*/
- public static final void addNativeLibs(Class<?> certClass, URL jarURL, ClassLoader cl) throws IOException, SecurityException {
- if(!containsNativeLibs(jarURL)) {
- final JarFile jarFile = JarUtil.getJarFile(jarURL, cl);
+ public synchronized static final void addNativeLibs(Class<?> certClass, URL jarURL) throws IOException, SecurityException {
+ final LoadState nativeLibJarsLS = nativeLibJars.get(jarURL);
+ if( !testLoadState(nativeLibJarsLS, LoadState.LOOKED_UP) ) {
+ nativeLibJars.put(jarURL, LoadState.LOOKED_UP);
+ final JarFile jarFile = JarUtil.getJarFile(jarURL);
if(DEBUG) {
System.err.println("TempJarCache: addNativeLibs: "+jarURL+": nativeJar "+jarFile.getName());
}
validateCertificates(certClass, jarFile);
JarUtil.extract(tmpFileCache.getTempDir(), nativeLibMap, jarFile,
true, false, false);
- nativeLibJars.add(jarURL);
+ nativeLibJars.put(jarURL, LoadState.LOADED);
+ } else if( !testLoadState(nativeLibJarsLS, LoadState.LOADED) ) {
+ throw new IOException("TempJarCache: addNativeLibs: "+jarURL+", previous load attempt failed");
}
}
@@ -217,20 +232,23 @@ public class TempJarCache {
*
* @param certClass if class is certified, the JarFile entries needs to have the same certificate
* @param jarFile
- *
- * @throws IOException
+ * @throws IOException if the <code>jarURL</code> could not be loaded or a previous load attempt failed
* @throws SecurityException
*/
- public static final void addClasses(Class<?> certClass, URL jarURL, ClassLoader cl) throws IOException, SecurityException {
- if(!containsClasses(jarURL)) {
- final JarFile jarFile = JarUtil.getJarFile(jarURL, cl);
+ public synchronized static final void addClasses(Class<?> certClass, URL jarURL) throws IOException, SecurityException {
+ final LoadState classFileJarsLS = classFileJars.get(jarURL);
+ if( !testLoadState(classFileJarsLS, LoadState.LOOKED_UP) ) {
+ classFileJars.put(jarURL, LoadState.LOOKED_UP);
+ final JarFile jarFile = JarUtil.getJarFile(jarURL);
if(DEBUG) {
System.err.println("TempJarCache: addClasses: "+jarURL+": nativeJar "+jarFile.getName());
}
validateCertificates(certClass, jarFile);
JarUtil.extract(tmpFileCache.getTempDir(), null, jarFile,
false, true, false);
- classFileJars.add(jarURL);
+ classFileJars.put(jarURL, LoadState.LOADED);
+ } else if( !testLoadState(classFileJarsLS, LoadState.LOADED) ) {
+ throw new IOException("TempJarCache: addClasses: "+jarURL+", previous load attempt failed");
}
}
@@ -239,21 +257,24 @@ public class TempJarCache {
*
* @param certClass if class is certified, the JarFile entries needs to have the same certificate
* @param jarFile
- *
* @return
- * @throws IOException
+ * @throws IOException if the <code>jarURL</code> could not be loaded or a previous load attempt failed
* @throws SecurityException
*/
- public static final void addResources(Class<?> certClass, URL jarURL, ClassLoader cl) throws IOException, SecurityException {
- if(!containsResources(jarURL)) {
- final JarFile jarFile = JarUtil.getJarFile(jarURL, cl);
+ public synchronized static final void addResources(Class<?> certClass, URL jarURL) throws IOException, SecurityException {
+ final LoadState resourceFileJarsLS = resourceFileJars.get(jarURL);
+ if( !testLoadState(resourceFileJarsLS, LoadState.LOOKED_UP) ) {
+ resourceFileJars.put(jarURL, LoadState.LOOKED_UP);
+ final JarFile jarFile = JarUtil.getJarFile(jarURL);
if(DEBUG) {
System.err.println("TempJarCache: addResources: "+jarURL+": nativeJar "+jarFile.getName());
}
validateCertificates(certClass, jarFile);
JarUtil.extract(tmpFileCache.getTempDir(), null, jarFile,
false, false, true);
- resourceFileJars.add(jarURL);
+ resourceFileJars.put(jarURL, LoadState.LOADED);
+ } else if( !testLoadState(resourceFileJarsLS, LoadState.LOADED) ) {
+ throw new IOException("TempJarCache: addResources: "+jarURL+", previous load attempt failed");
}
}
@@ -266,41 +287,62 @@ public class TempJarCache {
*
* @param certClass if class is certified, the JarFile entries needs to have the same certificate
* @param jarFile
- *
- * @throws IOException
+ * @throws IOException if the <code>jarURL</code> could not be loaded or a previous load attempt failed
* @throws SecurityException
*/
- public static final void addAll(Class<?> certClass, URL jarURL, ClassLoader cl) throws IOException, SecurityException {
+ public synchronized static final void addAll(Class<?> certClass, URL jarURL) throws IOException, SecurityException {
checkInitialized();
if(null == jarURL) {
throw new IllegalArgumentException("jarURL is null");
}
- if(!nativeLibJars.contains(jarURL) ||
- !classFileJars.contains(jarURL) ||
- !resourceFileJars.contains(jarURL)) {
- final JarFile jarFile = JarUtil.getJarFile(jarURL, cl);
+ final LoadState nativeLibJarsLS = nativeLibJars.get(jarURL);
+ final LoadState classFileJarsLS = classFileJars.get(jarURL);
+ final LoadState resourceFileJarsLS = resourceFileJars.get(jarURL);
+ if( !testLoadState(nativeLibJarsLS, LoadState.LOOKED_UP) ||
+ !testLoadState(classFileJarsLS, LoadState.LOOKED_UP) ||
+ !testLoadState(resourceFileJarsLS, LoadState.LOOKED_UP) ) {
+
+ final boolean extractNativeLibraries = !testLoadState(nativeLibJarsLS, LoadState.LOADED);
+ final boolean extractClassFiles = !testLoadState(classFileJarsLS, LoadState.LOADED);
+ final boolean extractOtherFiles = !testLoadState(resourceFileJarsLS, LoadState.LOOKED_UP);
+
+ // mark looked-up (those who are not loaded)
+ if(extractNativeLibraries) {
+ nativeLibJars.put(jarURL, LoadState.LOOKED_UP);
+ }
+ if(extractClassFiles) {
+ classFileJars.put(jarURL, LoadState.LOOKED_UP);
+ }
+ if(extractOtherFiles) {
+ resourceFileJars.put(jarURL, LoadState.LOOKED_UP);
+ }
+
+ final JarFile jarFile = JarUtil.getJarFile(jarURL);
if(DEBUG) {
System.err.println("TempJarCache: addAll: "+jarURL+": nativeJar "+jarFile.getName());
}
- final boolean extractNativeLibraries = !nativeLibJars.contains(jarURL);
- final boolean extractClassFiles = !classFileJars.contains(jarURL);
- final boolean extractOtherFiles = !resourceFileJars.contains(jarURL);
validateCertificates(certClass, jarFile);
JarUtil.extract(tmpFileCache.getTempDir(), nativeLibMap, jarFile,
extractNativeLibraries, extractClassFiles, extractOtherFiles);
+
+ // mark loaded (those were just loaded)
if(extractNativeLibraries) {
- nativeLibJars.add(jarURL);
+ nativeLibJars.put(jarURL, LoadState.LOADED);
}
if(extractClassFiles) {
- classFileJars.add(jarURL);
+ classFileJars.put(jarURL, LoadState.LOADED);
}
if(extractOtherFiles) {
- resourceFileJars.add(jarURL);
+ resourceFileJars.put(jarURL, LoadState.LOADED);
}
+ } else if( !testLoadState(nativeLibJarsLS, LoadState.LOADED) ||
+ !testLoadState(classFileJarsLS, LoadState.LOADED) ||
+ !testLoadState(resourceFileJarsLS, LoadState.LOADED) ) {
+ throw new IOException("TempJarCache: addAll: "+jarURL+", previous load attempt failed");
}
}
- public static final String findLibrary(String libName) {
+ public synchronized static final String findLibrary(String libName) {
checkInitialized();
// try with mapped library basename first
String path = nativeLibMap.get(libName);
@@ -331,7 +373,7 @@ public class TempJarCache {
return null;
} */
- public static final String findResource(String name) {
+ public synchronized static final String findResource(String name) {
checkInitialized();
final File f = new File(tmpFileCache.getTempDir(), name);
if(f.exists()) {
@@ -340,7 +382,7 @@ public class TempJarCache {
return null;
}
- public static final URL getResource(String name) throws MalformedURLException {
+ public synchronized static final URL getResource(String name) throws MalformedURLException {
checkInitialized();
final File f = new File(tmpFileCache.getTempDir(), name);
if(f.exists()) {
@@ -360,13 +402,20 @@ public class TempJarCache {
* @throws IOException
* @throws SecurityException
*/
- public static final void bootstrapNativeLib(Class<?> certClass, String libBaseName, URL jarURL, ClassLoader cl)
+ public synchronized static final void bootstrapNativeLib(Class<?> certClass, String libBaseName, URL jarURL)
throws IOException, SecurityException {
checkInitialized();
- if(!nativeLibJars.contains(jarURL) && !nativeLibMap.containsKey(libBaseName) ) {
- final JarFile jarFile = JarUtil.getJarFile(jarURL, cl);
+ boolean ok = false;
+ int countEntries = 0;
+ final LoadState nativeLibJarsLS = nativeLibJars.get(jarURL);
+ if( !testLoadState(nativeLibJarsLS, LoadState.LOOKED_UP) && !nativeLibMap.containsKey(libBaseName) ) {
if(DEBUG) {
- System.err.println("TempJarCache: bootstrapNativeLib: "+jarURL+": nativeJar "+jarFile.getName()+" - libBaseName: "+libBaseName);
+ System.err.println("TempJarCache: bootstrapNativeLib(certClass: "+certClass+", libBaseName "+libBaseName+", jarURL "+jarURL+")");
+ }
+ nativeLibJars.put(jarURL, LoadState.LOOKED_UP);
+ final JarFile jarFile = JarUtil.getJarFile(jarURL);
+ if(DEBUG) {
+ System.err.println("TempJarCache: bootstrapNativeLib: nativeJar "+jarFile.getName());
}
validateCertificates(certClass, jarFile);
final Enumeration<JarEntry> entries = jarFile.entries();
@@ -385,18 +434,27 @@ public class TempJarCache {
try {
final byte[] buf = new byte[ 2048 ];
while (true) {
- int count;
- if ((count = in.read(buf)) == -1) { break; }
- out.write(buf, 0, count);
- numBytes += count;
+ int countBytes;
+ if ((countBytes = in.read(buf)) == -1) { break; }
+ out.write(buf, 0, countBytes);
+ numBytes += countBytes;
}
} finally { in.close(); out.close(); }
if (numBytes>0) {
nativeLibMap.put(libBaseName, destFile.getAbsolutePath());
- nativeLibJars.add(jarURL);
+ nativeLibJars.put(jarURL, LoadState.LOADED);
+ ok = true;
+ countEntries++;
}
}
}
+ } else if( testLoadState(nativeLibJarsLS, LoadState.LOADED) ) {
+ ok = true; // already loaded
+ } else {
+ throw new IOException("TempJarCache: bootstrapNativeLib: "+jarURL+", previous load attempt failed");
+ }
+ if(DEBUG) {
+ System.err.println("TempJarCache: bootstrapNativeLib() done, count "+countEntries+", ok "+ok);
}
}
diff --git a/src/junit/com/jogamp/common/util/TestJarUtil.java b/src/junit/com/jogamp/common/util/TestJarUtil.java
index ea6cebf..cb1cc45 100644
--- a/src/junit/com/jogamp/common/util/TestJarUtil.java
+++ b/src/junit/com/jogamp/common/util/TestJarUtil.java
@@ -137,7 +137,7 @@ public class TestJarUtil extends JunitTracer {
final ClassLoader rootCL = this.getClass().getClassLoader();
// Get containing JAR file "TestJarsInJar.jar" and add it to the TempJarCache
- TempJarCache.addAll(GlueGenVersion.class, JarUtil.getJarFileURL("ClassInJar0", rootCL), rootCL);
+ TempJarCache.addAll(GlueGenVersion.class, JarUtil.getJarFileURL("ClassInJar0", rootCL));
// Fetch and load the contained "ClassInJar1.jar"
final URL ClassInJar1_jarFileURL = JarUtil.getJarFileURL(TempJarCache.getResource("ClassInJar1.jar"));
@@ -158,7 +158,7 @@ public class TestJarUtil extends JunitTracer {
final ClassLoader rootCL = this.getClass().getClassLoader();
// Get containing JAR file "TestJarsInJar.jar" and add it to the TempJarCache
- TempJarCache.addAll(GlueGenVersion.class, JarUtil.getJarFileURL("ClassInJar0", rootCL), rootCL);
+ TempJarCache.addAll(GlueGenVersion.class, JarUtil.getJarFileURL("ClassInJar0", rootCL));
// Fetch and load the contained "ClassInJar1.jar"
final URL ClassInJar2_jarFileURL = JarUtil.getJarFileURL(TempJarCache.getResource("sub/ClassInJar2.jar"));
diff --git a/src/junit/com/jogamp/common/util/TestTempJarCache.java b/src/junit/com/jogamp/common/util/TestTempJarCache.java
index d97894c..5467e4c 100644
--- a/src/junit/com/jogamp/common/util/TestTempJarCache.java
+++ b/src/junit/com/jogamp/common/util/TestTempJarCache.java
@@ -172,7 +172,7 @@ public class TestTempJarCache extends JunitTracer {
if(AndroidVersion.isAvailable) { System.err.println("n/a on Android"); return; }
final ClassLoader cl = getClass().getClassLoader();
- TempJarCache.addAll(GlueGenVersion.class, JarUtil.getJarFileURL(GlueGenVersion.class.getName(), cl), cl);
+ TempJarCache.addAll(GlueGenVersion.class, JarUtil.getJarFileURL(GlueGenVersion.class.getName(), cl));
File f0 = new File(TempJarCache.getTempFileCache().getTempDir(), "META-INF/MANIFEST.MF");
Assert.assertTrue(f0.exists());
@@ -201,7 +201,7 @@ public class TestTempJarCache extends JunitTracer {
URL nativeJarURL = JarUtil.getJarFileURL(jarUrlRoot, nativeJarName);
- TempJarCache.addNativeLibs(TempJarCache.class, nativeJarURL, cl);
+ TempJarCache.addNativeLibs(TempJarCache.class, nativeJarURL);
String libFullPath = TempJarCache.findLibrary(libBaseName);
Assert.assertNotNull(libFullPath);
Assert.assertEquals(libBaseName, NativeLibrary.isValidNativeLibraryName(libFullPath, true));