11package ca .weblite .nativeutils ;
22
3- import java .io .File ;
43import java .io .FileNotFoundException ;
5- import java .io .FileOutputStream ;
64import java .io .IOException ;
75import java .io .InputStream ;
86import java .io .OutputStream ;
7+ import java .nio .file .Files ;
8+ import java .nio .file .Path ;
9+ import java .nio .file .StandardOpenOption ;
910
1011/**
1112 * Simple library class for working with JNI (Java Native Interface)
@@ -24,96 +25,81 @@ private NativeUtils() {
2425 }
2526
2627 /**
27- * <p>loadLibraryFromJar.</p>
28+ * Loads a library from current JAR archive, using the class loader of the {@code NativeUtils}
29+ * class to find the resource in the JAR.
2830 *
2931 * @param path a {@link java.lang.String} object.
3032 * @throws java.io.IOException if any.
33+ * @throws UnsatisfiedLinkError if loading the native library fails.
3134 */
3235 public static void loadLibraryFromJar (String path ) throws IOException {
3336 loadLibraryFromJar (path , NativeUtils .class );
3437 }
3538
3639 /**
37- * Loads library from current JAR archive
40+ * Loads a library from current JAR archive.
3841 *
3942 * The file from JAR is copied into system temporary directory and then loaded. The temporary file is deleted after exiting.
4043 * Method uses String as filename because the pathname is "abstract", not system-dependent.
4144 *
4245 * @throws java.lang.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)).
43- * @throws java.lang.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)).
44- * @throws java.lang.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)).
4546 * @param path a {@link java.lang.String} object.
46- * @param source a {@link java.lang. Class} object.
47+ * @param source {@code Class} whose class loader should be used to look up the resource in the JAR file
4748 * @throws java.io.IOException if any.
49+ * @throws UnsatisfiedLinkError if loading the native library fails.
4850 */
49- public static void loadLibraryFromJar (String path , Class source ) throws IOException {
50-
51-
51+ public static void loadLibraryFromJar (String path , Class <?> source ) throws IOException , UnsatisfiedLinkError {
5252 // Finally, load the library
53- System .load (loadFileFromJar (path , source ).getAbsolutePath ());
53+ System .load (extractFromJar (path , source ).toAbsolutePath (). toString ());
5454 }
5555
5656 /**
57- * <p>loadFileFromJar.</p>
57+ * Extracts a resource from the JAR and stores it as temporary file
58+ * in the file system.
5859 *
59- * @param path a {@ link java.lang. String} object.
60- * @param source a {@link java.lang. Class} object.
61- * @return a {@link java.io.File} object.
60+ * @param path path of the resource, must begin with {@code '/'}, see {@ link Class#getResourceAsStream( String)}
61+ * @param source {@code Class} whose class loader should be used to look up the resource in the JAR file
62+ * @return file path of the temporary file extracted from this JAR
6263 * @throws java.io.IOException if any.
6364 */
64- public static File loadFileFromJar (String path , Class source ) throws IOException {
65+ public static Path extractFromJar (String path , Class <?> source ) throws IOException {
6566 if (!path .startsWith ("/" )) {
6667 throw new IllegalArgumentException ("The path has to be absolute (start with '/')." );
6768 }
6869
69- // Obtain filename from path
70- String [] parts = path .split ("/" );
71- String filename = (parts .length > 1 ) ? parts [parts .length - 1 ] : null ;
70+ String filename = path .substring (path .lastIndexOf ('/' ) + 1 );
7271
73- // Split filename to prexif and suffix (extension)
74- String prefix = "" ;
75- String suffix = null ;
76- if (filename != null ) {
77- parts = filename .split ("\\ ." , 2 );
78- prefix = parts [0 ];
79- suffix = (parts .length > 1 ) ? "." +parts [parts .length - 1 ] : null ; // Thanks, davs! :-)
72+ // Split filename to prefix and suffix (extension)
73+ String prefix ;
74+ String suffix ;
75+ int lastDot = filename .lastIndexOf ('.' );
76+ if (lastDot == -1 ) {
77+ // No file extension; use complete filename as prefix
78+ prefix = filename ;
79+ suffix = null ;
80+ } else {
81+ prefix = filename .substring (0 , lastDot );
82+ suffix = filename .substring (lastDot );
8083 }
8184
8285 // Check if the filename is okay
83- if (filename == null || prefix .length () < 3 ) {
86+ if (prefix .length () < 3 ) {
8487 throw new IllegalArgumentException ("The filename has to be at least 3 characters long." );
8588 }
8689
8790 // Prepare temporary file
88- File temp = File .createTempFile (prefix , suffix );
89- temp .deleteOnExit ();
90-
91- if (!temp .exists ()) {
92- throw new FileNotFoundException ("File " + temp .getAbsolutePath () + " does not exist." );
93- }
94-
95- // Prepare buffer for data copying
96- byte [] buffer = new byte [1024 ];
97- int readBytes ;
91+ Path temp = Files .createTempFile (prefix , suffix );
92+ temp .toFile ().deleteOnExit ();
9893
9994 // Open and check input stream
10095 InputStream is = source .getResourceAsStream (path );
10196 if (is == null ) {
10297 throw new FileNotFoundException ("File " + path + " was not found inside JAR." );
10398 }
10499
105- // Open output stream and copy data between source file in JAR and the temporary file
106- OutputStream os = new FileOutputStream (temp );
107- try {
108- while ((readBytes = is .read (buffer )) != -1 ) {
109- os .write (buffer , 0 , readBytes );
110- }
111- } finally {
112- // If read/write fails, close streams safely before throwing an exception
113- os .close ();
114- is .close ();
100+ try (is ; OutputStream out = Files .newOutputStream (temp , StandardOpenOption .WRITE , StandardOpenOption .TRUNCATE_EXISTING )) {
101+ is .transferTo (out );
115102 }
116103 return temp ;
117-
118104 }
119105}
0 commit comments