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