diff options
author | Sven Gothel <[email protected]> | 2019-04-03 01:00:29 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2019-04-03 01:00:29 +0200 |
commit | 1157b913a068167062c853b4b525954b223a5509 (patch) | |
tree | 8cab1fcdc3d512a6c94c77692b9d7695f9739c9c /src/java/com/jogamp/common | |
parent | ecb65c39a6902158ed824348a23dbbcb42a85f01 (diff) |
Bug 1367: Make TempFileCache & TempJarCache even if temp folder can't handle executables
Diffstat (limited to 'src/java/com/jogamp/common')
6 files changed, 130 insertions, 40 deletions
diff --git a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java index 4e62d54..eee65d8 100644 --- a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java +++ b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java @@ -405,7 +405,7 @@ public class JNILibLoaderBase { } boolean ok = false; - if (TempJarCache.isInitialized()) { + if ( TempJarCache.isInitialized(true) ) { ok = addNativeJarLibsWithTempJarCache(classesFromJavaJars, singleJarMarker); } else if(DEBUG) { System.err.println("JNILibLoaderBase: addNativeJarLibs0: disabled due to uninitialized TempJarCache"); diff --git a/src/java/com/jogamp/common/os/NativeLibrary.java b/src/java/com/jogamp/common/os/NativeLibrary.java index 2ba2581..7c6aeca 100644 --- a/src/java/com/jogamp/common/os/NativeLibrary.java +++ b/src/java/com/jogamp/common/os/NativeLibrary.java @@ -643,7 +643,7 @@ public final class NativeLibrary implements DynamicLookupHelper { } public static final String findLibrary(final String libName, final ClassLoader loader) { String res = null; - if(TempJarCache.isInitialized()) { + if( TempJarCache.isInitialized(true) ) { res = TempJarCache.findLibrary(libName); if (DEBUG) { System.err.println("NativeLibrary.findLibrary(<"+libName+">) (TempJarCache): "+res); diff --git a/src/java/com/jogamp/common/os/Platform.java b/src/java/com/jogamp/common/os/Platform.java index 2e63550..535b8a9 100644 --- a/src/java/com/jogamp/common/os/Platform.java +++ b/src/java/com/jogamp/common/os/Platform.java @@ -306,7 +306,7 @@ public class Platform extends PlatformPropsImpl { PropertyAccess.getBooleanProperty(useTempJarCachePropName, true, true); // load GluegenRT native library - if(_USE_TEMP_JAR_CACHE[0] && TempJarCache.initSingleton()) { + if(_USE_TEMP_JAR_CACHE[0] && TempJarCache.initSingleton() && TempJarCache.isInitialized(true) ) { try { JNILibLoaderBase.addNativeJarLibs(new Class<?>[] { jogamp.common.Debug.class }, null); } catch (final Exception e0) { diff --git a/src/java/com/jogamp/common/util/cache/TempCacheReg.java b/src/java/com/jogamp/common/util/cache/TempCacheReg.java index 47ef584..b7c275c 100644 --- a/src/java/com/jogamp/common/util/cache/TempCacheReg.java +++ b/src/java/com/jogamp/common/util/cache/TempCacheReg.java @@ -31,7 +31,11 @@ public class TempCacheReg { public static boolean isTempFileCacheUsed() { return null != System.getProperty(TempFileCache.tmpRootPropName); } - public static boolean isTempJarCacheUsed() { - return TempJarCache.isInitialized(); + /** + * @param forExecutables if {@code true}, method also tests whether {@link TempJarCache}'s underlying cache is suitable to load native libraries or launch executables + * @return true if {@link TempJarCache} has been properly initialized, ie. is in use. Otherwise returns false. + */ + public static boolean isTempJarCacheUsed(final boolean forExecutables) { + return TempJarCache.isInitialized(forExecutables); } } diff --git a/src/java/com/jogamp/common/util/cache/TempFileCache.java b/src/java/com/jogamp/common/util/cache/TempFileCache.java index 44c7a11..0547f9a 100644 --- a/src/java/com/jogamp/common/util/cache/TempFileCache.java +++ b/src/java/com/jogamp/common/util/cache/TempFileCache.java @@ -45,6 +45,9 @@ public class TempFileCache { // Flag indicating that we got a fatal error in the static initializer. private static boolean staticInitError = false; + // Flag indicating that the temp root folder can be used for executable files + private static boolean staticTempIsExecutable = true; + private static final String tmpDirPrefix = "file_cache"; // Lifecycle: For one user's JVMs, ClassLoader and time. @@ -80,10 +83,19 @@ public class TempFileCache { try { _tmpBaseDir = new File(IOUtil.getTempDir(true /* executable */), tmpDirPrefix); _tmpBaseDir = IOUtil.testDir(_tmpBaseDir, true /* create */, false /* executable */); // executable already checked + staticTempIsExecutable = true; } catch (final Exception ex) { System.err.println("Warning: Caught Exception while retrieving executable temp base directory:"); ex.printStackTrace(); - staticInitError = true; + staticTempIsExecutable = false; + try { + _tmpBaseDir = new File(IOUtil.getTempDir(false /* executable */), tmpDirPrefix); + _tmpBaseDir = IOUtil.testDir(_tmpBaseDir, true /* create */, false /* executable */); + } catch (final Exception ex2) { + System.err.println("Warning: Caught Exception while retrieving non-executable temp base directory:"); + ex2.printStackTrace(); + staticInitError = true; + } } tmpBaseDir = _tmpBaseDir; @@ -92,7 +104,7 @@ public class TempFileCache { System.err.println("TempFileCache: Static Initialization ---------------------------------------------- OK: "+(!staticInitError)); System.err.println("TempFileCache: Thread: "+Thread.currentThread().getName()+ ", CL 0x"+Integer.toHexString(TempFileCache.class.getClassLoader().hashCode())+ - ", tempBaseDir "+tmpBaseDirAbsPath); + ", tempBaseDir "+tmpBaseDirAbsPath+", executable "+staticTempIsExecutable); } if(!staticInitError) { @@ -102,6 +114,7 @@ public class TempFileCache { System.err.println("Warning: Caught Exception due to initializing TmpRoot:"); ex.printStackTrace(); staticInitError = true; + staticTempIsExecutable = false; } } if (DEBUG) { @@ -414,7 +427,7 @@ public class TempFileCache { path.delete(); } - /** Create the <code>individualTmpDir</code>. */ + /** Create the {@link #getTempDir()} */ public TempFileCache () { if (DEBUG) { System.err.println("TempFileCache: new TempFileCache() --------------------- (static ok: "+(!staticInitError)+")"); @@ -434,7 +447,7 @@ public class TempFileCache { } } - /** Delete the <code>individualTmpDir</code> recursively and remove it's reference. */ + /** Delete the {@link #getTempDir()} recursively and remove it's reference. */ public void destroy() { if (DEBUG) { System.err.println("TempFileCache: destroy() --------------------- (static ok: "+(!staticInitError)+")"); @@ -454,15 +467,20 @@ public class TempFileCache { } /** - * @return true is static and object initialization was successful + * @param forExecutables if {@code true}, method also tests whether the underlying {@link #getBaseDir()} is suitable to load native libraries or launch executables + * @return true if static and object initialization was successful + * @see #isTempExecutable() + * @see #isValid() */ - public boolean isValid() { return !staticInitError && !initError; } + public boolean isValid(final boolean forExecutables) { + return !staticInitError && !initError && ( !forExecutables || staticTempIsExecutable ); + } /** - * Base temp directory used by TempFileCache. + * Base temp directory used by {@link TempFileCache}. * * <p> - * Lifecycle: For one user's JVMs, ClassLoader and time. + * Lifecycle: For one user's concurrently running JVMs and ClassLoader * </p> * * This is set to: @@ -472,11 +490,14 @@ public class TempFileCache { * * @return */ - public File getBaseDir() { return tmpBaseDir; } + public static File getBaseDir() { return tmpBaseDir; } /** * Root temp directory for this JVM instance. Used to store individual * directories. + * <p> + * This directory is a sub-folder to {@link #getBaseDir()}. + * </p> * * <p> * Lifecycle: For one user's concurrently running JVMs and ClassLoader @@ -498,15 +519,19 @@ public class TempFileCache { * * @return */ - public File getRootDir() { return tmpRootDir; } + public static File getRootDir() { return tmpRootDir; } /** * Temporary directory for individual files (eg. native libraries of one ClassLoader instance). - * The directory name is: + * <p> + * This directory is a sub-folder to {@link #getRootDir()}. + * </p> * * <p> - * Lifecycle: Within each JVM .. use case dependent, ie. per ClassLoader + * Lifecycle: Within each JVM .. use case dependent, ie. per ClassLoader <b>and</b> per {@link TempFileCache} instance! * </p> + * <p> + * The directory name is: * * <pre> * tmpRootDir/jlnMMMMM @@ -514,7 +539,7 @@ public class TempFileCache { * * where jlnMMMMM is the unique filename created by File.createTempFile() * without the ".tmp" extension. - * + * </p> * * @return */ diff --git a/src/java/com/jogamp/common/util/cache/TempJarCache.java b/src/java/com/jogamp/common/util/cache/TempJarCache.java index 2ff5140..c5cca3a 100644 --- a/src/java/com/jogamp/common/util/cache/TempJarCache.java +++ b/src/java/com/jogamp/common/util/cache/TempJarCache.java @@ -37,6 +37,7 @@ import java.util.jar.JarFile; import jogamp.common.Debug; +import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.net.Uri; import com.jogamp.common.os.NativeLibrary; import com.jogamp.common.util.JarUtil; @@ -74,6 +75,7 @@ public class TempJarCache { private static TempFileCache tmpFileCache; private static volatile boolean staticInitError = false; + private static volatile boolean staticTempIsExecutable = true; private static volatile boolean isInit = false; /** @@ -89,7 +91,8 @@ public class TempJarCache { if(!staticInitError) { tmpFileCache = new TempFileCache(); - staticInitError = !tmpFileCache.isValid(); + staticInitError = !tmpFileCache.isValid(false); + staticTempIsExecutable = tmpFileCache.isValid(true); } if(!staticInitError) { @@ -102,7 +105,7 @@ public class TempJarCache { if(DEBUG) { final File tempDir = null != tmpFileCache ? tmpFileCache.getTempDir() : null; final String tempDirAbsPath = null != tempDir ? tempDir.getAbsolutePath() : null; - System.err.println("TempJarCache.initSingleton(): ok "+(false==staticInitError)+", "+ tempDirAbsPath); + System.err.println("TempJarCache.initSingleton(): ok "+(false==staticInitError)+", "+ tempDirAbsPath+", executable "+staticTempIsExecutable); } isInit = true; } @@ -163,44 +166,77 @@ public class TempJarCache { } /** - * @return true if this class has been properly initialized, ie. is in use, otherwise false. + * @param forExecutables if {@code true}, method also tests whether the underlying cache is suitable to load native libraries or launch executables + * @return true if this class has been properly initialized, ie. is in use. Otherwise returns false. */ - public static boolean isInitialized() { - return isInitializedImpl() && !staticInitError; + public static boolean isInitialized(final boolean forExecutables) { + return isInitializedImpl() && !staticInitError && ( !forExecutables || staticTempIsExecutable ); } - /* package */ static void checkInitialized() { + /** + * @param forExecutables if {@code true}, method also tests whether the underlying cache is suitable to load native libraries or launch executables + */ + /* package */ static void checkInitialized(final boolean forExecutables) { if(!isInitializedImpl()) { - throw new RuntimeException("initSingleton() has to be called first."); + throw new JogampRuntimeException("initSingleton() has to be called first."); } if(staticInitError) { - throw new RuntimeException("initSingleton() failed."); + throw new JogampRuntimeException("initSingleton() failed."); + } + if( forExecutables && !staticTempIsExecutable ) { + throw new JogampRuntimeException("TempJarCache folder not suitable for executables"); } } + /** + * @return the underlying {@link TempFileCache} + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(false)} + */ public static TempFileCache getTempFileCache() { - checkInitialized(); + checkInitialized(false); return tmpFileCache; } + /** + * @param jarUri + * @param exp + * @return + * @throws IOException + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(false)} + */ public synchronized static boolean checkNativeLibs(final Uri jarUri, final LoadState exp) throws IOException { - checkInitialized(); + checkInitialized(false); if(null == jarUri) { throw new IllegalArgumentException("jarUri is null"); } return testLoadState(nativeLibJars.get(jarUri), exp); } + /** + * @param jarUri + * @param exp + * @return + * @throws IOException + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(false)} + */ public synchronized static boolean checkClasses(final Uri jarUri, final LoadState exp) throws IOException { - checkInitialized(); + checkInitialized(false); if(null == jarUri) { throw new IllegalArgumentException("jarUri is null"); } return testLoadState(classFileJars.get(jarUri), exp); } + /** + * + * @param jarUri + * @param exp + * @return + * @throws IOException + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(false)} + */ public synchronized static boolean checkResources(final Uri jarUri, final LoadState exp) throws IOException { - checkInitialized(); + checkInitialized(false); if(null == jarUri) { throw new IllegalArgumentException("jarUri is null"); } @@ -218,9 +254,10 @@ public class TempJarCache { * @throws SecurityException * @throws URISyntaxException * @throws IllegalArgumentException + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(true)} */ public synchronized static final boolean addNativeLibs(final Class<?> certClass, final Uri jarUri, final String nativeLibraryPath) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { - checkInitialized(); + checkInitialized(true); final LoadState nativeLibJarsLS = nativeLibJars.get(jarUri); if( !testLoadState(nativeLibJarsLS, LoadState.LOOKED_UP) ) { nativeLibJars.put(jarUri, LoadState.LOOKED_UP); @@ -253,9 +290,10 @@ public class TempJarCache { * @throws SecurityException * @throws URISyntaxException * @throws IllegalArgumentException + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(false)} */ public synchronized static final void addClasses(final Class<?> certClass, final Uri jarUri) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { - checkInitialized(); + checkInitialized(false); final LoadState classFileJarsLS = classFileJars.get(jarUri); if( !testLoadState(classFileJarsLS, LoadState.LOOKED_UP) ) { classFileJars.put(jarUri, LoadState.LOOKED_UP); @@ -282,9 +320,10 @@ public class TempJarCache { * @throws SecurityException * @throws URISyntaxException * @throws IllegalArgumentException + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(false)} */ public synchronized static final void addResources(final Class<?> certClass, final Uri jarUri) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { - checkInitialized(); + checkInitialized(false); final LoadState resourceFileJarsLS = resourceFileJars.get(jarUri); if( !testLoadState(resourceFileJarsLS, LoadState.LOOKED_UP) ) { resourceFileJars.put(jarUri, LoadState.LOOKED_UP); @@ -314,9 +353,10 @@ public class TempJarCache { * @throws SecurityException * @throws URISyntaxException * @throws IllegalArgumentException + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(false)} */ public synchronized static final void addAll(final Class<?> certClass, final Uri jarUri) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { - checkInitialized(); + checkInitialized(false); if(null == jarUri) { throw new IllegalArgumentException("jarUri is null"); } @@ -327,7 +367,7 @@ public class TempJarCache { !testLoadState(classFileJarsLS, LoadState.LOOKED_UP) || !testLoadState(resourceFileJarsLS, LoadState.LOOKED_UP) ) { - final boolean extractNativeLibraries = !testLoadState(nativeLibJarsLS, LoadState.LOADED); + final boolean extractNativeLibraries = staticTempIsExecutable && !testLoadState(nativeLibJarsLS, LoadState.LOADED); final boolean extractClassFiles = !testLoadState(classFileJarsLS, LoadState.LOADED); final boolean extractOtherFiles = !testLoadState(resourceFileJarsLS, LoadState.LOOKED_UP); @@ -367,8 +407,18 @@ public class TempJarCache { } } + /** + * If {@link #isInitialized(boolean) isInitialized(true)} is false due to lack of executable support only, + * this method always returns false. + * @param libName + * @return the found native library path within this cache or null if not found + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(false)} + */ public synchronized static final String findLibrary(final String libName) { - checkInitialized(); + checkInitialized(false); + if( !staticTempIsExecutable ) { + return null; + } // try with mapped library basename first String path = nativeLibMap.get(libName); if(null == path) { @@ -398,9 +448,14 @@ public class TempJarCache { return null; } */ - /** Similar to {@link ClassLoader#getResource(String)}. */ + /** + * Similar to {@link ClassLoader#getResource(String)}. + * @param name + * @return + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(false)} + */ public synchronized static final String findResource(final String name) { - checkInitialized(); + checkInitialized(false); final File f = new File(tmpFileCache.getTempDir(), name); if(f.exists()) { return f.getAbsolutePath(); @@ -408,9 +463,15 @@ public class TempJarCache { return null; } - /** Similar to {@link ClassLoader#getResource(String)}. */ + /** + * Similar to {@link ClassLoader#getResource(String)}. + * @param name + * @return + * @throws URISyntaxException + * @throws JogampRuntimeException if not {@link #isInitialized(boolean) isInitialized(false)} + */ public synchronized static final Uri getResourceUri(final String name) throws URISyntaxException { - checkInitialized(); + checkInitialized(false); final File f = new File(tmpFileCache.getTempDir(), name); if(f.exists()) { return Uri.valueOf(f); |