26
27 import java.io.File;
28 import java.net.URI;
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31 import java.util.HashSet;
32
33 public class NativeLibLoader {
34
35 private static final HashSet<String> loaded = new HashSet<String>();
36
37 public static synchronized void loadLibrary(String libname) {
38 if (!loaded.contains(libname)) {
39 loadLibraryInternal(libname);
40 loaded.add(libname);
41 }
42 }
43
44 private static boolean verbose = false;
45
46 private static File libDir = null;
47 private static String libPrefix = "";
48 private static String libSuffix = "";
49
50 static {
51 AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
52 verbose = Boolean.getBoolean("javafx.verbose");
53 return null;
54 });
55 }
56
57 private static String[] initializePath(String propname) {
58 String ldpath = System.getProperty(propname, "");
59 String ps = File.pathSeparator;
60 int ldlen = ldpath.length();
61 int i, j, n;
62 // Count the separators in the path
63 i = ldpath.indexOf(ps);
64 n = 0;
65 while (i >= 0) {
72
73 // Fill the array with paths from the ldpath
74 n = i = 0;
75 j = ldpath.indexOf(ps);
76 while (j >= 0) {
77 if (j - i > 0) {
78 paths[n++] = ldpath.substring(i, j);
79 } else if (j - i == 0) {
80 paths[n++] = ".";
81 }
82 i = j + 1;
83 j = ldpath.indexOf(ps, i);
84 }
85 paths[n] = ldpath.substring(i, ldlen);
86 return paths;
87 }
88
89 private static void loadLibraryInternal(String libraryName) {
90 // Look for the library in the same directory as the jar file
91 // containing this class.
92 // If that fails, then try System.loadLibrary as a last resort.
93 try {
94 loadLibraryFullPath(libraryName);
95 } catch (UnsatisfiedLinkError ex) {
96 // NOTE: First attempt to load the libraries from the java.library.path.
97 // This allows FX to find more recent versions of the shared libraries
98 // from java.library.path instead of ones that might be part of the JRE
99 //
100 String [] libPath = initializePath("java.library.path");
101 for (int i=0; i<libPath.length; i++) {
102 try {
103 String path = libPath[i];
104 if (!path.endsWith(File.separator)) path += File.separator;
105 String fileName = System.mapLibraryName(libraryName);
106 File libFile = new File(path + fileName);
107 System.load(libFile.getAbsolutePath());
108 if (verbose) {
109 System.err.println("Loaded " + libFile.getAbsolutePath()
110 + " from java.library.path");
111 }
112 return;
113 } catch (UnsatisfiedLinkError ex3) {
114 // Fail silently and try the next directory in java.library.path
115 }
116 }
117
118 // Try System.loadLibrary as a last resort. If it succeeds, then
119 // print a warning. If it fails, rethrow the exception from
120 // the earlier System.load()
121 try {
122 System.loadLibrary(libraryName);
123 if (verbose) {
124 System.err.println("WARNING: " + ex.toString());
125 System.err.println(" using System.loadLibrary("
126 + libraryName + ") as a fallback");
127 }
128 } catch (UnsatisfiedLinkError ex2) {
129 //On iOS we link all libraries staticaly. Presence of library
130 //is recognized by existence of JNI_OnLoad_libraryname() C function.
131 //If libraryname contains hyphen, it needs to be translated
132 //to underscore to form valid C function indentifier.
133 if ("iOS".equals(System.getProperty("os.name"))
134 && libraryName.contains("-")) {
135 libraryName = libraryName.replace("-", "_");
136 try {
137 System.loadLibrary(libraryName);
138 return;
139 } catch (UnsatisfiedLinkError ex3) {
140 throw ex3;
141 }
142 }
143 // Rethrow original exception
144 throw ex;
145 }
146 }
147 }
148
149 /**
150 * Load the native library from the same directory as the jar file
151 * containing this class.
152 */
153 private static void loadLibraryFullPath(String libraryName) {
154 try {
155 if (libDir == null) {
156 // Get the URL for this class, if it is a jar URL, then get the
157 // filename associated with it.
158 String theClassFile = "NativeLibLoader.class";
159 Class theClass = NativeLibLoader.class;
160 String classUrlString = theClass.getResource(theClassFile).toString();
161 if (!classUrlString.startsWith("jar:file:") || classUrlString.indexOf('!') == -1){
162 throw new UnsatisfiedLinkError("Invalid URL for class: " + classUrlString);
163 }
164 // Strip out the "jar:" and everything after and including the "!"
165 String tmpStr = classUrlString.substring(4, classUrlString.lastIndexOf('!'));
166 // Strip everything after the last "/" or "\" to get rid of the jar filename
167 int lastIndexOfSlash = Math.max(tmpStr.lastIndexOf('/'), tmpStr.lastIndexOf('\\'));
168
169 // Set the native directory based on the OS
170 String osName = System.getProperty("os.name");
171 String relativeDir = null;
172 if (osName.startsWith("Windows")) {
173 relativeDir = "../bin";
174 } else if (osName.startsWith("Mac")) {
175 relativeDir = ".";
176 } else if (osName.startsWith("Linux")) {
177 relativeDir = "./" + System.getProperty("os.arch");
178 }
179
180 // Location of native libraries relative to jar file
181 String libDirUrlString = tmpStr.substring(0, lastIndexOfSlash)
|
26
27 import java.io.File;
28 import java.net.URI;
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31 import java.util.HashSet;
32
33 public class NativeLibLoader {
34
35 private static final HashSet<String> loaded = new HashSet<String>();
36
37 public static synchronized void loadLibrary(String libname) {
38 if (!loaded.contains(libname)) {
39 loadLibraryInternal(libname);
40 loaded.add(libname);
41 }
42 }
43
44 private static boolean verbose = false;
45
46 private static boolean usingModules = false;
47 private static File libDir = null;
48 private static String libPrefix = "";
49 private static String libSuffix = "";
50
51 static {
52 AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
53 verbose = Boolean.getBoolean("javafx.verbose");
54 return null;
55 });
56 }
57
58 private static String[] initializePath(String propname) {
59 String ldpath = System.getProperty(propname, "");
60 String ps = File.pathSeparator;
61 int ldlen = ldpath.length();
62 int i, j, n;
63 // Count the separators in the path
64 i = ldpath.indexOf(ps);
65 n = 0;
66 while (i >= 0) {
73
74 // Fill the array with paths from the ldpath
75 n = i = 0;
76 j = ldpath.indexOf(ps);
77 while (j >= 0) {
78 if (j - i > 0) {
79 paths[n++] = ldpath.substring(i, j);
80 } else if (j - i == 0) {
81 paths[n++] = ".";
82 }
83 i = j + 1;
84 j = ldpath.indexOf(ps, i);
85 }
86 paths[n] = ldpath.substring(i, ldlen);
87 return paths;
88 }
89
90 private static void loadLibraryInternal(String libraryName) {
91 // Look for the library in the same directory as the jar file
92 // containing this class.
93 // If that fails, then try System.loadLibrary.
94 try {
95 // FIXME: We should eventually remove this legacy path, since
96 // it isn't applicable to Jigsaw.
97 loadLibraryFullPath(libraryName);
98 } catch (UnsatisfiedLinkError ex) {
99 if (verbose && !usingModules) {
100 System.err.println("WARNING: " + ex);
101 }
102
103 // NOTE: First attempt to load the libraries from the java.library.path.
104 // This allows FX to find more recent versions of the shared libraries
105 // from java.library.path instead of ones that might be part of the JRE
106 //
107 String [] libPath = initializePath("java.library.path");
108 for (int i=0; i<libPath.length; i++) {
109 try {
110 String path = libPath[i];
111 if (!path.endsWith(File.separator)) path += File.separator;
112 String fileName = System.mapLibraryName(libraryName);
113 File libFile = new File(path + fileName);
114 System.load(libFile.getAbsolutePath());
115 if (verbose) {
116 System.err.println("Loaded " + libFile.getAbsolutePath()
117 + " from java.library.path");
118 }
119 return;
120 } catch (UnsatisfiedLinkError ex3) {
121 // Fail silently and try the next directory in java.library.path
122 }
123 }
124
125 // Finally we will use System.loadLibrary.
126 try {
127 System.loadLibrary(libraryName);
128 if (verbose) {
129 System.err.println("System.loadLibrary("
130 + libraryName + ") succeeded");
131 }
132 } catch (UnsatisfiedLinkError ex2) {
133 //On iOS we link all libraries staticaly. Presence of library
134 //is recognized by existence of JNI_OnLoad_libraryname() C function.
135 //If libraryname contains hyphen, it needs to be translated
136 //to underscore to form valid C function indentifier.
137 if ("iOS".equals(System.getProperty("os.name"))
138 && libraryName.contains("-")) {
139 libraryName = libraryName.replace("-", "_");
140 try {
141 System.loadLibrary(libraryName);
142 return;
143 } catch (UnsatisfiedLinkError ex3) {
144 throw ex3;
145 }
146 }
147 // Rethrow exception
148 throw ex2;
149 }
150 }
151 }
152
153 /**
154 * Load the native library from the same directory as the jar file
155 * containing this class.
156 */
157 private static void loadLibraryFullPath(String libraryName) {
158 try {
159 if (usingModules) {
160 throw new UnsatisfiedLinkError("ignored");
161 }
162 if (libDir == null) {
163 // Get the URL for this class, if it is a jar URL, then get the
164 // filename associated with it.
165 String theClassFile = "NativeLibLoader.class";
166 Class theClass = NativeLibLoader.class;
167 String classUrlString = theClass.getResource(theClassFile).toString();
168 if (classUrlString.startsWith("jrt:")) {
169 // Suppress warning messages
170 usingModules = true;
171 throw new UnsatisfiedLinkError("ignored");
172 }
173 if (!classUrlString.startsWith("jar:file:") || classUrlString.indexOf('!') == -1) {
174 throw new UnsatisfiedLinkError("Invalid URL for class: " + classUrlString);
175 }
176 // Strip out the "jar:" and everything after and including the "!"
177 String tmpStr = classUrlString.substring(4, classUrlString.lastIndexOf('!'));
178 // Strip everything after the last "/" or "\" to get rid of the jar filename
179 int lastIndexOfSlash = Math.max(tmpStr.lastIndexOf('/'), tmpStr.lastIndexOf('\\'));
180
181 // Set the native directory based on the OS
182 String osName = System.getProperty("os.name");
183 String relativeDir = null;
184 if (osName.startsWith("Windows")) {
185 relativeDir = "../bin";
186 } else if (osName.startsWith("Mac")) {
187 relativeDir = ".";
188 } else if (osName.startsWith("Linux")) {
189 relativeDir = "./" + System.getProperty("os.arch");
190 }
191
192 // Location of native libraries relative to jar file
193 String libDirUrlString = tmpStr.substring(0, lastIndexOfSlash)
|