Fix NativeUtils. loading native Libraries from temp dir is possible
[splitter-ng] / Splitter-ng-plugin-bitsplitter / src / cz / adamh / utils / NativeUtils.java
1 package cz.adamh.utils;
2  
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.OutputStream;
9 import java.lang.reflect.Field;
10 import java.nio.file.Files;
11 import java.nio.file.Path;
12 import java.nio.file.Paths;
13 import java.util.Vector;
14  
15 /**
16  * Simple library class for working with JNI (Java Native Interface)
17  * 
18  * @see http://frommyplayground.com/how-to-load-native-jni-library-from-jar
19  *
20  * @author Adam Heirnich <adam@adamh.cz>, http://www.adamh.cz
21  */
22 public class NativeUtils {
23  
24         /**
25          * Private constructor - this class will never be instanced
26          */
27         private NativeUtils() {
28         }
29  
30         /**
31          * Loads library from current JAR archive
32          * 
33          * The file from JAR is copied into system temporary directory and then loaded. The temporary file is deleted after exiting.
34          * Method uses String as filename because the pathname is "abstract", not system-dependent.
35          * 
36          * @param filename The filename inside JAR as absolute path (beginning with '/'), e.g. /package/File.ext
37          * @throws IOException If temporary file creation or read/write operation fails
38          * @throws IllegalArgumentException If source file (param path) does not exist
39          * @throws IllegalArgumentException If the path is not absolute or if the filename is shorter than three characters (restriction of {@see File#createTempFile(java.lang.String, java.lang.String)}).
40          */
41         public static void loadLibraryFromJar(String path) throws IOException {
42  
43                 if (!path.startsWith("/")) {
44                         throw new IllegalArgumentException("The path to be absolute (start with '/').");
45                 }
46  
47                 // Obtain filename from path
48                 String[] parts = path.split("/");
49                 String filename = (parts.length > 1) ? parts[parts.length - 1] : null;
50  
51                 // Split filename to prexif and suffix (extension)
52                 String prefix = "";
53                 String suffix = null;
54                 if (filename != null) {
55                         parts = filename.split("\\.", 2);
56                         prefix = parts[0];
57                         suffix = (parts.length > 1) ? "."+parts[parts.length - 1] : null; // Thanks, davs! :-)
58                 }
59  
60                 // Check if the filename is okay
61                 if (filename == null || prefix.length() < 3) {
62                         throw new IllegalArgumentException("The filename has to be at least 3 characters long.");
63                 }
64  
65                 // Prepare temporary file
66                 String tempDir = System.getProperty("java.io.tmpdir");
67                 File temp = new File(tempDir+"/"+prefix+suffix);
68                 Files.createFile(temp.toPath());
69                 temp.deleteOnExit();
70                 
71                 // Prepare temporary file
72                 //File temp = File.createTempFile(prefix, suffix);
73                 //temp.deleteOnExit();
74                  
75                 if (!temp.exists()) {
76                         throw new FileNotFoundException("File " + temp.getAbsolutePath() + " does not exist.");
77                 }
78  
79                 // Prepare buffer for data copying
80                 byte[] buffer = new byte[1024];
81                 int readBytes;
82  
83                 // Open and check input stream
84                 InputStream is = NativeUtils.class.getResourceAsStream(path);
85                 if (is == null) {
86                         throw new FileNotFoundException("File " + path + " was not found inside JAR.");
87                 }
88  
89                 // Open output stream and copy data between source file in JAR and the temporary file
90                 OutputStream os = new FileOutputStream(temp);
91                 try {
92                         while ((readBytes = is.read(buffer)) != -1) {
93                                 os.write(buffer, 0, readBytes);
94                         }
95                 } finally {
96                         // If read/write fails, close streams safely before throwing an exception
97                         os.close();
98                         is.close();
99                 }
100  
101                 // Finally, load the library
102                 System.load(temp.getAbsolutePath());
103                 //System.out.println(temp.getAbsolutePath()+" geladen");
104
105         }
106 }