aboutsummaryrefslogtreecommitdiffstats
path: root/netx/net/sourceforge/jnlp/cache/NativeLibraryStorage.java
diff options
context:
space:
mode:
authorAdam Domurad <[email protected]>2013-06-03 10:34:36 -0400
committerAdam Domurad <[email protected]>2013-06-03 10:34:36 -0400
commit58464afe42ef3f0558da034bece3a7800f9104ff (patch)
tree8635f31393ee772b81e977af1549e4d242feccfe /netx/net/sourceforge/jnlp/cache/NativeLibraryStorage.java
parent1c3034421f64b802cef7b30c44b8524b36255e2f (diff)
Extract NativeLibraryStorage class from JNLPClassLoader
Diffstat (limited to 'netx/net/sourceforge/jnlp/cache/NativeLibraryStorage.java')
-rw-r--r--netx/net/sourceforge/jnlp/cache/NativeLibraryStorage.java162
1 files changed, 162 insertions, 0 deletions
diff --git a/netx/net/sourceforge/jnlp/cache/NativeLibraryStorage.java b/netx/net/sourceforge/jnlp/cache/NativeLibraryStorage.java
new file mode 100644
index 0000000..ef0bd82
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/cache/NativeLibraryStorage.java
@@ -0,0 +1,162 @@
+package net.sourceforge.jnlp.cache;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.util.FileUtils;
+
+/**
+ * Handles loading and access of native code loading through a JNLP application or applet.
+ * Stores native code in a temporary folder.
+ * Be sure to call cleanupTemporayFolder when finished with the object.
+ */
+public class NativeLibraryStorage {
+ private ResourceTracker tracker;
+ private List<File> nativeSearchDirectories = new ArrayList<File>();
+
+ /* Temporary directory to store native jar entries, added to our search path */
+ private File jarEntryDirectory = null;
+
+ public NativeLibraryStorage(ResourceTracker tracker) {
+ this.tracker = tracker;
+ }
+
+ /**
+ * Clean up our temporary folder if we created one.
+ */
+ public void cleanupTemporaryFolder() {
+ if (jarEntryDirectory != null) {
+ if (JNLPRuntime.isDebug()) {
+ System.out.println("Cleaning up native directory" + jarEntryDirectory.getAbsolutePath());
+ }
+ try {
+ FileUtils.recursiveDelete(jarEntryDirectory,
+ new File(System.getProperty("java.io.tmpdir")));
+ jarEntryDirectory = null;
+ } catch (IOException e) {
+ /*
+ * failed to delete a file in tmpdir, no big deal (as well the VM
+ * might be shutting down at this point so no much we can do)
+ */
+ }
+ }
+ }
+
+ /**
+ * Adds the {@link File} to the search path of this {@link NativeLibraryStorage}
+ * when trying to find a native library
+ */
+ public void addSearchDirectory(File directory) {
+ nativeSearchDirectories.add(directory);
+ }
+
+ public List<File> getSearchDirectories() {
+ return nativeSearchDirectories;
+ }
+
+ /**
+ * Looks in the search directories for 'fileName',
+ * returning a path to the found file if it exists.
+ * Returns null otherwise.
+ */
+ public File findLibrary(String fileName) {
+ for (File dir : getSearchDirectories()) {
+ File target = new File(dir, fileName);
+ if (target.exists())
+ return target;
+ }
+ return null;
+ }
+
+ /**
+ * Search for and enable any native code contained in a JAR by copying the
+ * native files into the filesystem. Called in the security context of the
+ * classloader.
+ */
+ public void addSearchJar(URL jarLocation) {
+ if (JNLPRuntime.isDebug())
+ System.out.println("Activate native: " + jarLocation);
+
+ File localFile = tracker.getCacheFile(jarLocation);
+ if (localFile == null)
+ return;
+
+ String[] librarySuffixes = { ".so", ".dylib", ".jnilib", ".framework", ".dll" };
+
+ try {
+ JarFile jarFile = new JarFile(localFile, false);
+ Enumeration<JarEntry> entries = jarFile.entries();
+
+ while (entries.hasMoreElements()) {
+ JarEntry e = entries.nextElement();
+
+ if (e.isDirectory()) {
+ continue;
+ }
+
+ String name = new File(e.getName()).getName();
+ boolean isLibrary = false;
+
+ for (String suffix : librarySuffixes) {
+ if (name.endsWith(suffix)) {
+ isLibrary = true;
+ break;
+ }
+ }
+ if (!isLibrary) {
+ continue;
+ }
+
+ ensureNativeStoreDirectory();
+
+ File outFile = new File(jarEntryDirectory, name);
+ if (!outFile.isFile()) {
+ FileUtils.createRestrictedFile(outFile, true);
+ }
+ CacheUtil.streamCopy(jarFile.getInputStream(e),
+ new FileOutputStream(outFile));
+ }
+
+ jarFile.close();
+ } catch (IOException ex) {
+ if (JNLPRuntime.isDebug())
+ ex.printStackTrace();
+ }
+ }
+
+ private void ensureNativeStoreDirectory() {
+ if (jarEntryDirectory == null) {
+ jarEntryDirectory = createNativeStoreDirectory();
+ addSearchDirectory(jarEntryDirectory);
+ }
+ }
+
+ /**
+ * Create a random base directory to store native code files in.
+ */
+ private static File createNativeStoreDirectory() {
+ final int rand = (int)((Math.random()*2 - 1) * Integer.MAX_VALUE);
+ File nativeDir = new File(System.getProperty("java.io.tmpdir")
+ + File.separator + "netx-native-"
+ + (rand & 0xFFFF));
+ File parent = nativeDir.getParentFile();
+ if (!parent.isDirectory() && !parent.mkdirs()) {
+ return null;
+ }
+
+ try {
+ FileUtils.createRestrictedDirectory(nativeDir);
+ return nativeDir;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+}