* Add new but currently unused native extraction engine which supports user-specified native libraries as well as deferred extraction of libraries.experimental
parent
e90ff15688
commit
948fdb21eb
@ -1,100 +1,113 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 jMonkeyEngine |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* * Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* |
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package com.jme3.system; |
||||
|
||||
public enum Platform { |
||||
|
||||
/** |
||||
* Microsoft Windows 32 bit |
||||
*/ |
||||
Windows32, |
||||
|
||||
/** |
||||
* Microsoft Windows 64 bit |
||||
*/ |
||||
Windows64, |
||||
|
||||
/** |
||||
* Linux 32 bit |
||||
*/ |
||||
Linux32, |
||||
|
||||
/** |
||||
* Linux 64 bit |
||||
*/ |
||||
Linux64, |
||||
|
||||
/** |
||||
* Apple Mac OS X 32 bit |
||||
*/ |
||||
MacOSX32, |
||||
|
||||
/** |
||||
* Apple Mac OS X 64 bit |
||||
*/ |
||||
MacOSX64, |
||||
|
||||
/** |
||||
* Apple Mac OS X 32 bit PowerPC |
||||
*/ |
||||
MacOSX_PPC32, |
||||
|
||||
/** |
||||
* Apple Mac OS X 64 bit PowerPC |
||||
*/ |
||||
MacOSX_PPC64, |
||||
|
||||
/** |
||||
* Android ARM5 |
||||
*/ |
||||
Android_ARM5, |
||||
|
||||
/** |
||||
* Android ARM6 |
||||
*/ |
||||
Android_ARM6, |
||||
|
||||
/** |
||||
* Android ARM7 |
||||
*/ |
||||
Android_ARM7, |
||||
|
||||
/** |
||||
* Android x86 |
||||
*/ |
||||
Android_X86, |
||||
|
||||
iOS_X86, |
||||
|
||||
iOS_ARM; |
||||
|
||||
/* |
||||
* Copyright (c) 2009-2012 jMonkeyEngine |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* * Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* |
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package com.jme3.system; |
||||
|
||||
public enum Platform { |
||||
|
||||
/** |
||||
* Microsoft Windows 32 bit |
||||
*/ |
||||
Windows32, |
||||
|
||||
/** |
||||
* Microsoft Windows 64 bit |
||||
*/ |
||||
Windows64(true), |
||||
|
||||
/** |
||||
* Linux 32 bit |
||||
*/ |
||||
Linux32, |
||||
|
||||
/** |
||||
* Linux 64 bit |
||||
*/ |
||||
Linux64(true), |
||||
|
||||
/** |
||||
* Apple Mac OS X 32 bit |
||||
*/ |
||||
MacOSX32, |
||||
|
||||
/** |
||||
* Apple Mac OS X 64 bit |
||||
*/ |
||||
MacOSX64(true), |
||||
|
||||
/** |
||||
* Apple Mac OS X 32 bit PowerPC |
||||
*/ |
||||
MacOSX_PPC32, |
||||
|
||||
/** |
||||
* Apple Mac OS X 64 bit PowerPC |
||||
*/ |
||||
MacOSX_PPC64(true), |
||||
|
||||
/** |
||||
* Android ARM5 |
||||
*/ |
||||
Android_ARM5, |
||||
|
||||
/** |
||||
* Android ARM6 |
||||
*/ |
||||
Android_ARM6, |
||||
|
||||
/** |
||||
* Android ARM7 |
||||
*/ |
||||
Android_ARM7, |
||||
|
||||
/** |
||||
* Android x86 |
||||
*/ |
||||
Android_X86, |
||||
|
||||
iOS_X86, |
||||
|
||||
iOS_ARM; |
||||
|
||||
private final boolean is64bit; |
||||
|
||||
public boolean is64Bit() { |
||||
return is64bit; |
||||
} |
||||
|
||||
private Platform(boolean is64bit) { |
||||
this.is64bit = is64bit; |
||||
} |
||||
|
||||
private Platform() { |
||||
this(false); |
||||
} |
||||
} |
@ -0,0 +1,137 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 jMonkeyEngine |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* * Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* |
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package com.jme3.system; |
||||
|
||||
/** |
||||
* Holds information about a native library for a particular platform. |
||||
* |
||||
* @author Kirill Vainer |
||||
*/ |
||||
final class NativeLibrary { |
||||
|
||||
private final String name; |
||||
private final Platform platform; |
||||
private final boolean isJNI; |
||||
private final String pathInNativesJar; |
||||
|
||||
/** |
||||
* Key for map to find a library for a name and platform. |
||||
*/ |
||||
static final class Key { |
||||
|
||||
private final String name; |
||||
private final Platform platform; |
||||
|
||||
public Key(String name, Platform platform) { |
||||
this.name = name; |
||||
this.platform = platform; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int hash = 5; |
||||
hash = 79 * hash + this.name.hashCode(); |
||||
hash = 79 * hash + this.platform.hashCode(); |
||||
return hash; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
final Key other = (Key) obj; |
||||
if (!this.name.equals(other.name)) { |
||||
return false; |
||||
} |
||||
if (this.platform != other.platform) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* The name of the library. |
||||
* Generally only used as a way to uniquely identify the library. |
||||
* |
||||
* @return name of the library. |
||||
*/ |
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
/** |
||||
* The OS + architecture combination for which this library |
||||
* should be extracted. |
||||
* |
||||
* @return platform associated to this native library |
||||
*/ |
||||
public Platform getPlatform() { |
||||
return platform; |
||||
} |
||||
|
||||
/** |
||||
* If this library is a JNI library. |
||||
* |
||||
* @return True if JNI library, false if native code (e.g. C/C++) library. |
||||
*/ |
||||
public boolean isJNI() { |
||||
return isJNI; |
||||
} |
||||
|
||||
/** |
||||
* Path inside the natives jar or classpath where the library is located. |
||||
* |
||||
* This library must be compatible with the {@link #getPlatform() platform} |
||||
* which this library is associated with. |
||||
* |
||||
* @return path to the library in the classpath |
||||
*/ |
||||
public String getPathInNativesJar() { |
||||
return pathInNativesJar; |
||||
} |
||||
|
||||
/** |
||||
* Create a new NativeLibrary. |
||||
*/ |
||||
public NativeLibrary(String name, Platform platform, String pathInNativesJar, boolean isJNI) { |
||||
this.name = name; |
||||
this.platform = platform; |
||||
this.pathInNativesJar = pathInNativesJar; |
||||
this.isJNI = isJNI; |
||||
} |
||||
|
||||
/** |
||||
* Create a new NativeLibrary. |
||||
*/ |
||||
public NativeLibrary(String name, Platform platform, String pathInNativesJar) { |
||||
this(name, platform, pathInNativesJar, true); |
||||
} |
||||
} |
@ -0,0 +1,410 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 jMonkeyEngine |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* * Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* |
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package com.jme3.system; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import java.net.MalformedURLException; |
||||
import java.net.URL; |
||||
import java.net.URLConnection; |
||||
import java.util.HashMap; |
||||
import java.util.logging.Level; |
||||
import java.util.logging.Logger; |
||||
|
||||
/** |
||||
* Utility class to register, extract, and load native libraries. |
||||
* <br> |
||||
* Register your own libraries via the |
||||
* {@link #registerNativeLibrary(java.lang.String, com.jme3.system.Platform, java.lang.String, boolean) } |
||||
* method, for each platform. |
||||
* You can then extract this library (depending on platform), by |
||||
* using {@link #loadNativeLibrary(java.lang.String, boolean) }. |
||||
* <br> |
||||
* Example:<br> |
||||
* <code><pre> |
||||
* NativeLibraryLoader.registerNativeLibrary("mystuff", Platform.Windows32, "native/windows/mystuff.dll"); |
||||
* NativeLibraryLoader.registerNativeLibrary("mystuff", Platform.Windows64, "native/windows/mystuff64.dll"); |
||||
* NativeLibraryLoader.registerNativeLibrary("mystuff", Platform.Linux32, "native/linux/libmystuff.so"); |
||||
* NativeLibraryLoader.registerNativeLibrary("mystuff", Platform.Linux64, "native/linux/libmystuff64.so"); |
||||
* NativeLibraryLoader.registerNativeLibrary("mystuff", Platform.MacOSX32, "native/macosx/libmystuff.jnilib"); |
||||
* NativeLibraryLoader.registerNativeLibrary("mystuff", Platform.MacOSX64, "native/macosx/libmystuff.jnilib"); |
||||
* </pre></code> |
||||
* <br> |
||||
* This will register the library. Load it via: <br> |
||||
* <code><pre> |
||||
* NativeLibraryLoader.loadNativeLibrary("mystuff", true); |
||||
* </pre></code> |
||||
* It will load the right library automatically based on the platform. |
||||
* |
||||
* @author Kirill Vainer |
||||
*/ |
||||
public final class NativeLibraryLoader { |
||||
|
||||
private static final Logger logger = Logger.getLogger(NativeLibraryLoader.class.getName()); |
||||
private static final byte[] buf = new byte[1024 * 100]; |
||||
private static File extractionFolderOverride = null; |
||||
private static File extractionFolder = null; |
||||
|
||||
private static final HashMap<NativeLibrary.Key, NativeLibrary> nativeLibraryMap |
||||
= new HashMap<NativeLibrary.Key, NativeLibrary>(); |
||||
|
||||
/** |
||||
* Register a new known library. |
||||
* |
||||
* This simply registers a known library, the actual extraction and loading |
||||
* is performed by calling {@link #loadNativeLibrary(java.lang.String, boolean) }. |
||||
* |
||||
* @param name The name / ID of the library (not OS or architecture specific). |
||||
* @param platform The platform for which the in-natives-jar path has |
||||
* been specified for. |
||||
* @param path The path inside the natives-jar or classpath |
||||
* corresponding to this library. Must be compatible with the platform |
||||
* argument. |
||||
* @param isJNI True if this is a JNI library, false if this is a regular |
||||
* native (C/C++) library. |
||||
*/ |
||||
public static void registerNativeLibrary(String name, Platform platform, |
||||
String path, boolean isJNI) { |
||||
nativeLibraryMap.put(new NativeLibrary.Key(name, platform), |
||||
new NativeLibrary(name, platform, path, isJNI)); |
||||
} |
||||
|
||||
/** |
||||
* Register a new known JNI library. |
||||
* |
||||
* This simply registers a known library, the actual extraction and loading |
||||
* is performed by calling {@link #loadNativeLibrary(java.lang.String, boolean) }. |
||||
* |
||||
* This method should be called several times for each library name, |
||||
* each time specifying a different platform + path combination. |
||||
* |
||||
* @param name The name / ID of the library (not OS or architecture specific). |
||||
* @param platform The platform for which the in-natives-jar path has |
||||
* been specified for. |
||||
* @param path The path inside the natives-jar or classpath |
||||
* corresponding to this library. Must be compatible with the platform |
||||
* argument. |
||||
*/ |
||||
public static void registerNativeLibrary(String name, Platform platform, |
||||
String path) { |
||||
registerNativeLibrary(name, platform, path, true); |
||||
} |
||||
|
||||
static { |
||||
// LWJGL
|
||||
registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl.dll"); |
||||
registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl64.dll"); |
||||
registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl.so"); |
||||
registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl64.so"); |
||||
registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.jnilib"); |
||||
registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.jnilib"); |
||||
|
||||
// OpenAL
|
||||
registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll", false); |
||||
registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL64.dll", false); |
||||
registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal.so", false); |
||||
registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal64.so", false); |
||||
registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", false); |
||||
registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", false); |
||||
|
||||
// BulletJme
|
||||
registerNativeLibrary("bulletjme", Platform.Windows32, "native/windows/x86/bulletjme.dll", false); |
||||
registerNativeLibrary("bulletjme", Platform.Windows64, "native/windows/x86_64/bulletjme.dll", false); |
||||
registerNativeLibrary("bulletjme", Platform.Linux32, "native/linux/x86/libbulletjme.so", false); |
||||
registerNativeLibrary("bulletjme", Platform.Linux64, "native/linux/x86_64/libbulletjme.so", false); |
||||
registerNativeLibrary("bulletjme", Platform.MacOSX32, "native/macosx/x86/libbulletjme.jnilib", false); |
||||
registerNativeLibrary("bulletjme", Platform.MacOSX64, "native/macosx/x86_64/libbulletjme.jnilib", false); |
||||
|
||||
// JInput
|
||||
registerNativeLibrary("jinput", Platform.Windows32, "native/windows/jinput-raw.dll"); |
||||
registerNativeLibrary("jinput", Platform.Windows64, "native/windows/jinput-raw_64.dll"); |
||||
registerNativeLibrary("jinput", Platform.Linux32, "native/windows/libjinput-linux.so"); |
||||
registerNativeLibrary("jinput", Platform.Linux64, "native/windows/libjinput-linux64.so"); |
||||
registerNativeLibrary("jinput", Platform.MacOSX32, "native/macosx/libjinput-osx.jnilib"); |
||||
registerNativeLibrary("jinput", Platform.MacOSX64, "native/macosx/libjinput-osx.jnilib"); |
||||
|
||||
// JInput Auxiliary (only required on Windows)
|
||||
registerNativeLibrary("jinput-dx8", Platform.Windows32, "native/windows/jinput-dx8.dll"); |
||||
registerNativeLibrary("jinput-dx8", Platform.Windows64, "native/windows/jinput-dx8_64.dll"); |
||||
registerNativeLibrary("jinput-dx8", Platform.Linux32, null); |
||||
registerNativeLibrary("jinput-dx8", Platform.Linux64, null); |
||||
registerNativeLibrary("jinput-dx8", Platform.MacOSX32, null); |
||||
registerNativeLibrary("jinput-dx8", Platform.MacOSX64, null); |
||||
} |
||||
|
||||
private NativeLibraryLoader() { |
||||
} |
||||
|
||||
/** |
||||
* Specify a custom location where native libraries should |
||||
* be extracted to. Ensure this is a unique path not used |
||||
* by other applications to extract their libraries. |
||||
* |
||||
* @param path Path where to extract native libraries. |
||||
*/ |
||||
public static void setCustomExtractionFolder(String path) { |
||||
extractionFolderOverride = new File(path).getAbsoluteFile(); |
||||
} |
||||
|
||||
public static File getExtractionFolder() { |
||||
if (extractionFolderOverride != null) { |
||||
return extractionFolderOverride; |
||||
} |
||||
if (extractionFolder == null) { |
||||
File workingFolder = new File("").getAbsoluteFile(); |
||||
if (!workingFolder.canWrite()) { |
||||
setExtractionDirToStorageDir(); |
||||
} else { |
||||
try { |
||||
File file = new File(workingFolder + File.separator + ".jmetestwrite"); |
||||
file.createNewFile(); |
||||
file.delete(); |
||||
extractionFolder = workingFolder; |
||||
} catch (Exception e) { |
||||
setExtractionDirToStorageDir(); |
||||
} |
||||
} |
||||
} |
||||
return extractionFolder; |
||||
} |
||||
|
||||
private static void setExtractionDirToStorageDir() { |
||||
logger.log(Level.WARNING, "Working directory is not writable. Using home directory instead."); |
||||
extractionFolder = new File(JmeSystem.getStorageFolder(), |
||||
"natives_" + Integer.toHexString(computeNativesHash())); |
||||
if (!extractionFolder.exists()) { |
||||
extractionFolder.mkdir(); |
||||
} |
||||
} |
||||
|
||||
private static int computeNativesHash() { |
||||
URLConnection conn = null; |
||||
try { |
||||
String classpath = System.getProperty("java.class.path"); |
||||
URL url = Thread.currentThread().getContextClassLoader().getResource("com/jme3/system/Natives.class"); |
||||
|
||||
StringBuilder sb = new StringBuilder(url.toString()); |
||||
if (sb.indexOf("jar:") == 0) { |
||||
sb.delete(0, 4); |
||||
sb.delete(sb.indexOf("!"), sb.length()); |
||||
sb.delete(sb.lastIndexOf("/") + 1, sb.length()); |
||||
} |
||||
try { |
||||
url = new URL(sb.toString()); |
||||
} catch (MalformedURLException ex) { |
||||
throw new UnsupportedOperationException(ex); |
||||
} |
||||
|
||||
conn = url.openConnection(); |
||||
int hash = classpath.hashCode() ^ (int) conn.getLastModified(); |
||||
return hash; |
||||
} catch (IOException ex) { |
||||
throw new UnsupportedOperationException(ex); |
||||
} finally { |
||||
if (conn != null) { |
||||
try { |
||||
conn.getInputStream().close(); |
||||
conn.getOutputStream().close(); |
||||
} catch (IOException ex) { } |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* First extracts the native library and then loads it. |
||||
* |
||||
* @param name The name of the library to load. |
||||
* @param isRequired If true and the library fails to load, throw exception. If |
||||
* false, do nothing if it fails to load. |
||||
*/ |
||||
public static void loadNativeLibrary(String name, boolean isRequired) { |
||||
if (JmeSystem.isLowPermissions()) { |
||||
throw new UnsupportedOperationException("JVM is running under " |
||||
+ "reduced permissions. Cannot load native libraries."); |
||||
} |
||||
|
||||
Platform platform = JmeSystem.getPlatform(); |
||||
NativeLibrary library = nativeLibraryMap.get(new NativeLibrary.Key(name, platform)); |
||||
|
||||
if (library == null) { |
||||
// No library exists for this platform.
|
||||
if (isRequired) { |
||||
throw new UnsatisfiedLinkError( |
||||
"The required native library '" + name + "'" |
||||
+ " is not available for your OS: " + platform); |
||||
} else { |
||||
logger.log(Level.FINE, "The optional native library ''{0}''" + |
||||
" is not available for your OS: {1}", |
||||
new Object[]{name, platform}); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
String pathInJar = library.getPathInNativesJar(); |
||||
|
||||
if (pathInJar == null) { |
||||
// This platform does not require the native library to be loaded.
|
||||
return; |
||||
} |
||||
|
||||
String fileNameInJar; |
||||
if (pathInJar.contains("/")) { |
||||
fileNameInJar = pathInJar.substring(pathInJar.lastIndexOf("/") + 1); |
||||
} else { |
||||
fileNameInJar = pathInJar; |
||||
} |
||||
|
||||
URL url = Thread.currentThread().getContextClassLoader().getResource(pathInJar); |
||||
|
||||
if (url == null) { |
||||
// Try the root of the classpath as well.
|
||||
url = Thread.currentThread().getContextClassLoader().getResource(fileNameInJar); |
||||
} |
||||
|
||||
if (url == null) { |
||||
// Attempt to load it as a system library.
|
||||
try { |
||||
System.loadLibrary(name); |
||||
logger.log(Level.FINE, "Loaded system installed " + |
||||
"version of native library: {0}", name); |
||||
} catch (UnsatisfiedLinkError e) { |
||||
if (isRequired) { |
||||
throw new UnsatisfiedLinkError( |
||||
"The required native library '" + name + "'" |
||||
+ " was not found in the classpath via '" + pathInJar + "'"); |
||||
} else { |
||||
logger.log(Level.FINE, "The optional native library ''{0}''" + |
||||
" was not found in the classpath via ''{1}''", |
||||
new Object[]{name, pathInJar}); |
||||
} |
||||
} |
||||
|
||||
return; |
||||
} |
||||
|
||||
// The library has been found and is ready to be extracted.
|
||||
// Determine what filename it should be extracted as.
|
||||
String loadedAsFileName; |
||||
if (library.isJNI()) { |
||||
String nameWithArch; |
||||
|
||||
// Append "64" to path
|
||||
// so that we don't overwrite the 32-bit version.
|
||||
if (platform.is64Bit()) { |
||||
nameWithArch = name + "64"; |
||||
} else { |
||||
nameWithArch = name; |
||||
} |
||||
|
||||
// JNI libraries on Mac / JDK6 use jnilib extension.
|
||||
// JNI libraries on Mac / JDK7 use dylib extension.
|
||||
loadedAsFileName = System.mapLibraryName(nameWithArch); |
||||
} else { |
||||
// Not a JNI library.
|
||||
// Just use the original filename as it is in the JAR.
|
||||
loadedAsFileName = fileNameInJar; |
||||
} |
||||
|
||||
File extactionDirectory = getExtractionFolder(); |
||||
URLConnection conn; |
||||
InputStream in; |
||||
|
||||
try { |
||||
conn = url.openConnection(); |
||||
in = conn.getInputStream(); |
||||
} catch (IOException ex) { |
||||
// Maybe put more detail here? Not sure..
|
||||
throw new UnsatisfiedLinkError("Failed to open file: '" + url + |
||||
"'. Error: " + ex); |
||||
} |
||||
|
||||
File targetFile = new File(extactionDirectory, loadedAsFileName); |
||||
OutputStream out = null; |
||||
try { |
||||
if (targetFile.exists()) { |
||||
// OK, compare last modified date of this file to
|
||||
// file in jar
|
||||
long targetLastModified = targetFile.lastModified(); |
||||
long sourceLastModified = conn.getLastModified(); |
||||
|
||||
// Allow ~1 second range for OSes that only support low precision
|
||||
if (targetLastModified + 1000 > sourceLastModified) { |
||||
logger.log(Level.FINE, "Not copying library {0}. " + |
||||
"Latest already extracted.", |
||||
loadedAsFileName); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
out = new FileOutputStream(targetFile); |
||||
int len; |
||||
while ((len = in.read(buf)) > 0) { |
||||
out.write(buf, 0, len); |
||||
} |
||||
|
||||
in.close(); |
||||
in = null; |
||||
out.close(); |
||||
out = null; |
||||
|
||||
// NOTE: On OSes that support "Date Created" property,
|
||||
// this will cause the last modified date to be lower than
|
||||
// date created which makes no sense
|
||||
targetFile.setLastModified(conn.getLastModified()); |
||||
} catch (IOException ex) { |
||||
if (ex.getMessage().contains("used by another process")) { |
||||
return; |
||||
} else { |
||||
throw new UnsatisfiedLinkError("Failed to extract native " |
||||
+ "library to: " + targetFile); |
||||
} |
||||
} finally { |
||||
// Not sure if we always want to load it.
|
||||
// Maybe specify this as a per library setting.
|
||||
System.load(targetFile.getAbsolutePath()); |
||||
|
||||
if(in != null){ |
||||
try { in.close(); } catch (IOException ex) { } |
||||
} |
||||
if(out != null){ |
||||
try { out.close(); } catch (IOException ex) { } |
||||
} |
||||
} |
||||
|
||||
logger.log(Level.FINE, "Loaded native library from ''{0}'' into ''{1}''", |
||||
new Object[]{url, targetFile}); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,57 @@ |
||||
/* |
||||
* Copyright (c) 2009-2012 jMonkeyEngine |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* * Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* |
||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package jme3test.app; |
||||
|
||||
import com.jme3.system.NativeLibraryLoader; |
||||
import com.jme3.util.JmeFormatter; |
||||
import java.util.logging.ConsoleHandler; |
||||
import java.util.logging.Handler; |
||||
import java.util.logging.Level; |
||||
import java.util.logging.Logger; |
||||
|
||||
/** |
||||
* Try to load some natives. |
||||
* |
||||
* @author Kirill Vainer |
||||
*/ |
||||
public class TestNativeLoader { |
||||
|
||||
public static void main(String[] args) { |
||||
Logger.getLogger("").getHandlers()[0].setLevel(Level.ALL); |
||||
Logger.getLogger("").setLevel(Level.ALL); |
||||
|
||||
NativeLibraryLoader.loadNativeLibrary("lwjgl", true); |
||||
NativeLibraryLoader.loadNativeLibrary("jinput", true); |
||||
NativeLibraryLoader.loadNativeLibrary("openal", true); |
||||
NativeLibraryLoader.loadNativeLibrary("bulletjme", false); |
||||
} |
||||
} |
Loading…
Reference in new issue