GlueGen v2.6.0-rc-20250822
GlueGen, Native Binding Generator for Java™ (public API).
JNILibLoaderBase.java
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * - Redistribution of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistribution in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * Neither the name of Sun Microsystems, Inc. or the names of
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * This software is provided "AS IS," without a warranty of any kind. ALL
20 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
23 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
24 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
25 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
26 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
27 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
28 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
29 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
30 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31 *
32 * You acknowledge that this software is not designed or intended for use
33 * in the design, construction, operation or maintenance of any nuclear
34 * facility.
35 *
36 * Sun gratefully acknowledges that this software was originally authored
37 * and developed by Kenneth Bradley Russell and Christopher John Kline.
38 */
39
40package com.jogamp.common.jvm;
41
42import java.io.IOException;
43import java.lang.reflect.InvocationTargetException;
44import java.lang.reflect.Method;
45import java.net.URISyntaxException;
46import java.net.URL;
47import java.security.PrivilegedAction;
48import java.util.Arrays;
49import java.util.HashSet;
50import java.util.Iterator;
51import java.util.List;
52import java.util.Locale;
53
54import com.jogamp.common.net.Uri;
55import com.jogamp.common.os.NativeLibrary;
56import com.jogamp.common.util.JarUtil;
57import com.jogamp.common.util.PropertyAccess;
58import com.jogamp.common.util.SecurityUtil;
59import com.jogamp.common.util.cache.TempJarCache;
60
61import jogamp.common.Debug;
62import jogamp.common.os.PlatformPropsImpl;
63
64public class JNILibLoaderBase {
65 public static final boolean DEBUG;
66 protected static final boolean PERF;
67
68 static {
69 Debug.initSingleton();
70 DEBUG = Debug.debug("JNILibLoader");
71 PERF = DEBUG || PropertyAccess.isPropertyDefined("jogamp.debug.JNILibLoader.Perf", true);
72 }
73
74 private static final Object perfSync = new Object();
75 private static long perfTotal = 0;
76 private static long perfCount = 0;
77
78 public interface LoaderAction {
79 /**
80 * Loads the library specified by libname.<br>
81 * The implementation should ignore, if the library has been loaded already.<br>
82 * @param libname the library to load
83 * @param ignoreError if true, errors during loading the library should be ignored
84 * @param cl optional ClassLoader, used to locate the library
85 * @return true if library loaded successful
86 */
87 boolean loadLibrary(String libname, boolean ignoreError, ClassLoader cl);
88
89 /**
90 * Loads the library specified by libname.<br>
91 * Optionally preloads the libraries specified by preload.<br>
92 * The implementation should ignore, if any library has been loaded already.<br>
93 * @param libname the library to load
94 * @param preload the libraries to load before loading the main library if not null
95 * @param preloadIgnoreError if true, errors during loading the preload-libraries should be ignored
96 * @param cl optional ClassLoader, used to locate the library
97 */
98 void loadLibrary(String libname, String[] preload, boolean preloadIgnoreError, ClassLoader cl);
99 }
100
101 private static class DefaultAction implements LoaderAction {
102 @Override
103 public boolean loadLibrary(final String libname, final boolean ignoreError, final ClassLoader cl) {
104 boolean res = true;
105 if(!isLoaded(libname)) {
106 try {
107 loadLibraryInternal(libname, cl);
108 addLoaded(libname);
109 if(DEBUG) {
110 System.err.println("JNILibLoaderBase: loaded "+libname);
111 }
112 } catch (final UnsatisfiedLinkError e) {
113 res = false;
114 if(DEBUG) {
115 e.printStackTrace();
116 }
117 if (!ignoreError && e.getMessage().indexOf("already loaded") < 0) {
118 throw e;
119 }
120 }
121 }
122 return res;
123 }
124
125 @Override
126 public void loadLibrary(final String libname, final String[] preload, final boolean preloadIgnoreError, final ClassLoader cl) {
127 if(!isLoaded(libname)) {
128 if (null!=preload) {
129 for (int i=0; i<preload.length; i++) {
130 loadLibrary(preload[i], preloadIgnoreError, cl);
131 }
132 }
133 loadLibrary(libname, false, cl);
134 }
135 }
136 }
137
138 private static final HashSet<String> loaded = new HashSet<String>();
139 private static LoaderAction loaderAction = new DefaultAction();
140
141 public static boolean isLoaded(final String libName) {
142 return loaded.contains(libName);
143 }
144
145 public static void addLoaded(final String libName) {
146 loaded.add(libName);
147 if(DEBUG) {
148 System.err.println("JNILibLoaderBase: Loaded Native Library: "+libName);
149 }
150 }
151
152 public static void disableLoading() {
153 setLoadingAction(null);
154 }
155
156 public static void enableLoading() {
157 setLoadingAction(new DefaultAction());
158 }
159
160 public static synchronized void setLoadingAction(final LoaderAction action) {
161 loaderAction = action;
162 }
163
164 private static final String nativeJarTagPackage = "jogamp.nativetag"; // TODO: sync with gluegen-cpptasks-base.xml
165
166 /**
167 *
168 * @param classFromJavaJar
169 * @param classJarUri
170 * @param jarBasename jar basename w/ suffix
171 * @param nativeJarBasename native jar basename w/ suffix
172 * @return
173 * @throws IOException
174 * @throws SecurityException
175 * @throws URISyntaxException
176 */
177 private static final boolean addNativeJarLibsImpl(final Class<?> classFromJavaJar, final Uri classJarUri,
178 final Uri.Encoded jarBasename, final Uri.Encoded nativeJarBasename)
179 throws IOException, SecurityException, URISyntaxException
180 {
181 if (DEBUG) {
182 final StringBuilder msg = new StringBuilder();
183 msg.append("JNILibLoaderBase: addNativeJarLibsImpl(").append(PlatformPropsImpl.NEWLINE);
184 msg.append(" classFromJavaJar = ").append(classFromJavaJar).append(PlatformPropsImpl.NEWLINE);
185 msg.append(" classJarURI = ").append(classJarUri).append(PlatformPropsImpl.NEWLINE);
186 msg.append(" jarBasename = ").append(jarBasename).append(PlatformPropsImpl.NEWLINE);
187 msg.append(" os.and.arch = ").append(PlatformPropsImpl.os_and_arch).append(PlatformPropsImpl.NEWLINE);
188 msg.append(" nativeJarBasename = ").append(nativeJarBasename).append(PlatformPropsImpl.NEWLINE);
189 msg.append(")");
190 System.err.println(msg.toString());
191 }
192 final long t0 = PERF ? System.currentTimeMillis() : 0; // 'Platform.currentTimeMillis()' not yet available!
193
194 boolean ok = false;
195
196 final Uri jarSubURI = classJarUri.getContainedUri();
197 if (null == jarSubURI) {
198 throw new IllegalArgumentException("JarSubURI is null of: "+classJarUri);
199 }
200
201 final Uri jarSubUriRoot = jarSubURI.getDirectory();
202
203 if (DEBUG) {
204 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: initial: %s -> %s%n", jarSubURI, jarSubUriRoot);
205 }
206
207 final String nativeLibraryPath = String.format((Locale)null, "natives/%s/", PlatformPropsImpl.os_and_arch);
208 if (DEBUG) {
209 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: nativeLibraryPath: %s%n", nativeLibraryPath);
210 }
211 {
212 // Attempt-1 a 'one slim native jar file' per 'os.and.arch' layout
213 // with native platform libraries under 'natives/os.and.arch'!
214 final Uri nativeJarURI = JarUtil.getJarFileUri( jarSubUriRoot.getEncoded().concat(nativeJarBasename) );
215
216 if (DEBUG) {
217 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl-1: module: %s -> %s%n", nativeJarBasename, nativeJarURI);
218 }
219
220 try {
221 ok = TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI, nativeLibraryPath);
222 if (DEBUG) {
223 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl-1: OK "+ok+": %s -> %s%n", nativeJarURI, nativeLibraryPath);
224 }
225 } catch(final Exception e) {
226 if(DEBUG) {
227 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl-1: Caught %s%n", e.getMessage());
228 e.printStackTrace();
229 }
230 }
231 }
232 if (!ok) {
233 final ClassLoader cl = classFromJavaJar.getClassLoader();
234 {
235 // Attempt-2 a 'one big-fat jar file' layout, containing java classes
236 // and all native platform libraries under 'natives/os.and.arch' per platform!
237 final URL nativeLibraryURI = cl.getResource(nativeLibraryPath);
238 if (null != nativeLibraryURI) {
239 final Uri nativeJarURI = JarUtil.getJarFileUri( jarSubUriRoot.getEncoded().concat(jarBasename) );
240 try {
241 ok = TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI, nativeLibraryPath);
242 if (DEBUG) {
243 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl-2: OK "+ok+", fat: %s -> %s%n", nativeJarURI, nativeLibraryPath);
244 }
245 } catch(final Exception e) {
246 if(DEBUG) {
247 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl-2: Caught %s%n", e.getMessage());
248 e.printStackTrace();
249 }
250 }
251 } else if (DEBUG) {
252 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl-2: CL couldn't locate %s in %s%n", nativeLibraryPath, jarBasename);
253 }
254 }
255 if (!ok) {
256 // Attempt-3 to find via ClassLoader and Native-Jar-Tag,
257 // assuming one slim native jar file per 'os.and.arch'
258 // and native platform libraries under 'natives/os.and.arch'!
259 final String moduleName;
260 {
261 final String packageName = classFromJavaJar.getPackage().getName();
262 final int idx = packageName.lastIndexOf('.');
263 if( 0 <= idx ) {
264 moduleName = packageName.substring(idx+1);
265 } else {
266 moduleName = packageName;
267 }
268 }
269 final String os_and_arch_dot = PlatformPropsImpl.os_and_arch.replace('-', '.');
270 final String nativeJarTagClassName = nativeJarTagPackage + "." + moduleName + "." + os_and_arch_dot + ".TAG"; // TODO: sync with gluegen-cpptasks-base.xml
271 try {
272 if(DEBUG) {
273 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl-3: ClassLoader/TAG: Locating module %s, os.and.arch %s: %s%n",
274 moduleName, os_and_arch_dot, nativeJarTagClassName);
275 }
276 final Uri nativeJarTagClassJarURI = JarUtil.getJarUri(nativeJarTagClassName, cl);
277 if (DEBUG) {
278 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl-3: ClassLoader/TAG: %s -> %s%n", nativeJarTagClassName, nativeJarTagClassJarURI);
279 }
280 ok = TempJarCache.addNativeLibs(classFromJavaJar, nativeJarTagClassJarURI, nativeLibraryPath);
281 if (DEBUG) {
282 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl-3: OK "+ok+": %s -> %s%n", nativeJarTagClassJarURI, nativeLibraryPath);
283 }
284 } catch (final Exception e ) {
285 if(DEBUG) {
286 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl-3: Caught %s%n", e.getMessage());
287 e.printStackTrace();
288 }
289 }
290 }
291 }
292
293 if (DEBUG || PERF) {
294 final long tNow = System.currentTimeMillis() - t0;
295 final long tTotal, tCount;
296 synchronized(perfSync) {
297 tCount = perfCount+1;
298 tTotal = perfTotal + tNow;
299 perfTotal = tTotal;
300 perfCount = tCount;
301 }
302 final double tAvrg = tTotal / (double)tCount;
303 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl.X: %s / %s -> ok: %b; duration: now %d ms, total %d ms (count %d, avrg %.3f ms)%n",
304 jarBasename, nativeJarBasename, ok, tNow, tTotal, tCount, tAvrg);
305 }
306 return ok;
307 }
308
309 /**
310 * Loads and adds a JAR file's native library to the TempJarCache,
311 * calling {@link JNILibLoaderBase#addNativeJarLibs(Class[], String)}
312 * with default JOGL deployment configuration:
313 * <pre>
314 return JNILibLoaderBase.addNativeJarLibs(classesFromJavaJars, "-all");
315 * </pre>
316 * If <code>Class1.class</code> is contained in a JAR file which name includes <code>singleJarMarker</code> <i>-all</i>,
317 * implementation will attempt to resolve the native JAR file as follows:
318 * <ul>
319 * <li><i>ClassJar-all</i>.jar to <i>ClassJar-all</i>-natives-<i>os.and.arch</i>.jar</li>
320 * </ul>
321 * Otherwise the native JAR files will be resolved for each class's JAR file:
322 * <ul>
323 * <li><i>ClassJar1</i>.jar to <i>ClassJar1</i>-natives-<i>os.and.arch</i>.jar</li>
324 * <li><i>ClassJar2</i>.jar to <i>ClassJar2</i>-natives-<i>os.and.arch</i>.jar</li>
325 * <li>..</li>
326 * </ul>
327 */
328
329 public static final boolean addNativeJarLibsJoglCfg(final Class<?>[] classesFromJavaJars) {
330 return addNativeJarLibs(classesFromJavaJars, "-all");
331 }
332
333 /**
334 * Loads and adds a JAR file's native library to the TempJarCache.<br>
335 * The native library JAR file's URI is derived as follows:
336 * <ul>
337 * <li> [1] <code>GLProfile.class</code> -> </li>
338 * <li> [2] <code>http://lala/gluegen-rt.jar</code> -> </li>
339 * <li> [3] <code>http://lala/gluegen-rt</code> -> </li>
340 * <li> [4] <code>http://lala/gluegen-rt-natives-'os.and.arch'.jar</code> </li>
341 * </ul>
342 * Where:
343 * <ul>
344 * <li> [1] is one of <code>classesFromJavaJars</code></li>
345 * <li> [2] is it's complete URI</li>
346 * <li> [3] is it's <i>base URI</i></li>
347 * <li> [4] is the derived native JAR filename</li>
348 * </ul>
349 * <p>
350 * Generic description:
351 * <pre>
352 final Class<?>[] classesFromJavaJars = new Class<?>[] { Class1.class, Class2.class };
353 JNILibLoaderBase.addNativeJarLibs(classesFromJavaJars, "-all");
354 * </pre>
355 * If <code>Class1.class</code> is contained in a JAR file which name includes <code>singleJarMarker</code>, here <i>-all</i>,
356 * implementation will attempt to resolve the native JAR file as follows:
357 * <ul>
358 * <li><i>ClassJar-all</i>.jar to <i>ClassJar-all</i>-natives-<i>os.and.arch</i>.jar</li>
359 * </ul>
360 * Otherwise the native JAR files will be resolved for each class's JAR file:
361 * <ul>
362 * <li><i>Class1Jar</i>.jar to <i>Class1Jar</i>-natives-<i>os.and.arch</i>.jar</li>
363 * <li><i>Class2Jar</i>.jar to <i>Class2Jar</i>-natives-<i>os.and.arch</i>.jar</li>
364 * </ul>
365 * </p>
366 * <p>
367 * Examples:
368 * </p>
369 * <p>
370 * JOCL:
371 * <pre>
372 // only: jocl.jar -> jocl-natives-<i>os.and.arch</i>.jar
373 addNativeJarLibs(new Class<?>[] { JOCLJNILibLoader.class }, null, null );
374 * </pre>
375 * </p>
376 * <p>
377 * JOGL:
378 * <pre>
379 final ClassLoader cl = GLProfile.class.getClassLoader();
380 // jogl-all.jar -> jogl-all-natives-<i>os.and.arch</i>.jar
381 // jogl-all-noawt.jar -> jogl-all-noawt-natives-<i>os.and.arch</i>.jar
382 // jogl-all-mobile.jar -> jogl-all-mobile-natives-<i>os.and.arch</i>.jar
383 // jogl-all-android.jar -> jogl-all-android-natives-<i>os.and.arch</i>.jar
384 // nativewindow.jar -> nativewindow-natives-<i>os.and.arch</i>.jar
385 // jogl.jar -> jogl-natives-<i>os.and.arch</i>.jar
386 // newt.jar -> newt-natives-<i>os.and.arch</i>.jar (if available)
387 final String newtFactoryClassName = "com.jogamp.newt.NewtFactory";
388 final Class<?>[] classesFromJavaJars = new Class<?>[] { NWJNILibLoader.class, GLProfile.class, null };
389 if( ReflectionUtil.isClassAvailable(newtFactoryClassName, cl) ) {
390 classesFromJavaJars[2] = ReflectionUtil.getClass(newtFactoryClassName, false, cl);
391 }
392 JNILibLoaderBase.addNativeJarLibs(classesFromJavaJars, "-all");
393 * </pre>
394 * </p>
395 *
396 * @param classesFromJavaJars For each given Class, load the native library JAR.
397 * @param singleJarMarker Optional string marker like "-all" to identify the single 'all-in-one' JAR file
398 * after which processing of the class array shall stop.
399 *
400 * @return true if either the 'all-in-one' native JAR or all native JARs loaded successful or were loaded already,
401 * false in case of an error
402 */
403 public static boolean addNativeJarLibs(final Class<?>[] classesFromJavaJars, final String singleJarMarker) {
404 if(DEBUG) {
405 final StringBuilder msg = new StringBuilder();
406 msg.append("JNILibLoaderBase: addNativeJarLibs(").append(PlatformPropsImpl.NEWLINE);
407 msg.append(" classesFromJavaJars = ").append(Arrays.asList(classesFromJavaJars)).append(PlatformPropsImpl.NEWLINE);
408 msg.append(" singleJarMarker = ").append(singleJarMarker).append(PlatformPropsImpl.NEWLINE);
409 msg.append(")");
410 System.err.println(msg.toString());
411 }
412
413 boolean ok = false;
414 if ( TempJarCache.isInitialized(true) ) {
415 ok = addNativeJarLibsWithTempJarCache(classesFromJavaJars, singleJarMarker);
416 } else if(DEBUG) {
417 System.err.println("JNILibLoaderBase: addNativeJarLibs0: disabled due to uninitialized TempJarCache");
418 }
419 return ok;
420 }
421
422 private static boolean addNativeJarLibsWithTempJarCache(final Class<?>[] classesFromJavaJars, final String singleJarMarker) {
423 boolean ok;
424 int count = 0;
425 try {
426 boolean done = false;
427 ok = true;
428
429 for (int i = 0; i < classesFromJavaJars.length; ++i) {
430 final Class<?> c = classesFromJavaJars[i];
431 if (c == null) {
432 continue;
433 }
434
435 final ClassLoader cl = c.getClassLoader();
436 final Uri classJarURI = JarUtil.getJarUri(c.getName(), cl);
437 final Uri.Encoded jarName = JarUtil.getJarBasename(classJarURI);
438
439 if (jarName == null) {
440 continue;
441 }
442
443 final Uri.Encoded jarBasename = jarName.substring(0, jarName.indexOf(".jar"));
444
445 if(DEBUG) {
446 System.err.printf("JNILibLoaderBase: jarBasename: %s%n", jarBasename);
447 }
448
449 /**
450 * If a jar marker was specified, and the basename contains the
451 * marker, we're done.
452 */
453
454 if (singleJarMarker != null) {
455 if (jarBasename.indexOf(singleJarMarker) >= 0) {
456 done = true;
457 }
458 }
459
460 final Uri.Encoded nativeJarBasename =
461 Uri.Encoded.cast( String.format((Locale)null, "%s-natives-%s.jar", jarBasename.get(), PlatformPropsImpl.os_and_arch) );
462
463 ok = JNILibLoaderBase.addNativeJarLibsImpl(c, classJarURI, jarName, nativeJarBasename);
464 if (ok) {
465 count++;
466 }
467 if (DEBUG && done) {
468 System.err.printf("JNILibLoaderBase: addNativeJarLibs0: done: %s%n", jarBasename);
469 }
470 }
471 } catch (final Exception x) {
472 System.err.printf("JNILibLoaderBase: Caught %s: %s%n", x.getClass().getSimpleName(), x.getMessage());
473 if(DEBUG) {
474 x.printStackTrace();
475 }
476 ok = false;
477 }
478 if(DEBUG) {
479 System.err.printf("JNILibLoaderBase: addNativeJarLibsWhenInitialized: count %d, ok %b%n", count, ok);
480 }
481 return ok;
482 }
483
484 /**
485 * Loads the library specified by libname, using the {@link LoaderAction} set by {@link #setLoadingAction(LoaderAction)}.<br>
486 * The implementation should ignore, if the library has been loaded already.<br>
487 * @param libname the library to load
488 * @param ignoreError if true, errors during loading the library should be ignored
489 * @param cl optional ClassLoader, used to locate the library
490 * @return true if library loaded successful
491 */
492 protected static synchronized boolean loadLibrary(final String libname, final boolean ignoreError, final ClassLoader cl) {
493 if (loaderAction != null) {
494 return loaderAction.loadLibrary(libname, ignoreError, cl);
495 }
496 return false;
497 }
498
499 /**
500 * Loads the library specified by libname, using the {@link LoaderAction} set by {@link #setLoadingAction(LoaderAction)}.<br>
501 * Optionally preloads the libraries specified by preload.<br>
502 * The implementation should ignore, if any library has been loaded already.<br>
503 * @param libname the library to load
504 * @param preload the libraries to load before loading the main library if not null
505 * @param preloadIgnoreError if true, errors during loading the preload-libraries should be ignored
506 * @param cl optional ClassLoader, used to locate the library
507 */
508 protected static synchronized void loadLibrary(final String libname, final String[] preload, final boolean preloadIgnoreError, final ClassLoader cl) {
509 if (loaderAction != null) {
510 loaderAction.loadLibrary(libname, preload, preloadIgnoreError, cl);
511 }
512 }
513
514 // private static final Class<?> customLauncherClass; // FIXME: remove
515 private static final Method customLoadLibraryMethod;
516
517 static {
518 final String sunAppletLauncherProperty = "sun.jnlp.applet.launcher";
519 final String sunAppletLauncherClassName = "org.jdesktop.applet.util.JNLPAppletLauncher";
520
521 final Method loadLibraryMethod = SecurityUtil.doPrivileged(new PrivilegedAction<Method>() {
522 @Override
523 public Method run() {
524 // FIXME: remove
525 final boolean usingJNLPAppletLauncher = PropertyAccess.getBooleanProperty(sunAppletLauncherProperty, true);
526
527 Class<?> launcherClass = null;
528 Method loadLibraryMethod = null;
529
530 if (usingJNLPAppletLauncher) {
531 try {
532 launcherClass = Class.forName(sunAppletLauncherClassName);
533 } catch (final ClassNotFoundException cnfe) {
534 // oops .. look like JNLPAppletLauncher doesn't exist, despite property
535 // this may happen if a previous applet was using JNLPAppletLauncher in the same JVM
536 System.err.println("JNILibLoaderBase: <"+sunAppletLauncherClassName+"> not found, despite enabled property <"+sunAppletLauncherProperty+">, JNLPAppletLauncher was probably used before");
537 System.setProperty(sunAppletLauncherProperty, Boolean.FALSE.toString());
538 } catch (final LinkageError le) {
539 throw le;
540 }
541 if(null != launcherClass) {
542 try {
543 loadLibraryMethod = launcherClass.getDeclaredMethod("loadLibrary", new Class[] { String.class });
544 } catch (final NoSuchMethodException ex) {
545 if(DEBUG) {
546 ex.printStackTrace();
547 }
548 launcherClass = null;
549 }
550 }
551 }
552 if(null==launcherClass) {
553 final String launcherClassName = PropertyAccess.getProperty("jnlp.launcher.class", false);
554 if(null!=launcherClassName) {
555 try {
556 launcherClass = Class.forName(launcherClassName);
557 loadLibraryMethod = launcherClass.getDeclaredMethod("loadLibrary", new Class[] { String.class });
558 } catch (final ClassNotFoundException ex) {
559 if(DEBUG) {
560 ex.printStackTrace();
561 }
562 } catch (final NoSuchMethodException ex) {
563 if(DEBUG) {
564 ex.printStackTrace();
565 }
566 launcherClass = null;
567 }
568 }
569 }
570 return loadLibraryMethod;
571 } } );
572 customLoadLibraryMethod = loadLibraryMethod;
573 }
574
575 private static void loadLibraryInternal(final String libraryName, final ClassLoader cl) {
576 // Note: special-casing JAWT which is built in to the JDK
577 int mode = 0; // 1 - custom, 2 - System.load( TempJarCache ), 3 - System.loadLibrary( name ), 4 - System.load( enumLibNames )
578 if (null!=customLoadLibraryMethod && !libraryName.equals("jawt")) {
579 // FIXME: remove
580 if(DEBUG) {
581 System.err.println("JNILibLoaderBase: customLoad("+libraryName+") - mode 1");
582 }
583 try {
584 customLoadLibraryMethod.invoke(null, new Object[] { libraryName });
585 mode = 1;
586 } catch (final Exception e) {
587 Throwable t = e;
588 if (t instanceof InvocationTargetException) {
589 t = ((InvocationTargetException) t).getTargetException();
590 }
591 if (t instanceof Error) {
592 throw (Error) t;
593 }
594 if (t instanceof RuntimeException) {
595 throw (RuntimeException) t;
596 }
597 // Throw UnsatisfiedLinkError for best compatibility with System.loadLibrary()
598 throw (UnsatisfiedLinkError) new UnsatisfiedLinkError("can not load library "+libraryName).initCause(e);
599 }
600 } else {
601 // System.err.println("sun.boot.library.path=" + Debug.getProperty("sun.boot.library.path", false));
602 final String libraryPath = NativeLibrary.findLibrary(libraryName, cl); // implicit TempJarCache usage if used/initialized
603 if(DEBUG) {
604 System.err.println("JNILibLoaderBase: loadLibraryInternal("+libraryName+"), TempJarCache: "+libraryPath);
605 }
606 if(null != libraryPath) {
607 if(DEBUG) {
608 System.err.println("JNILibLoaderBase: System.load("+libraryPath+") - mode 2");
609 }
610 System.load(libraryPath);
611 mode = 2;
612 } else {
613 if(DEBUG) {
614 System.err.println("JNILibLoaderBase: System.loadLibrary("+libraryName+") - mode 3: SystemEnvLibraryPaths: "+NativeLibrary.getSystemEnvLibraryPaths());
615 }
616 try {
617 System.loadLibrary(libraryName);
618 mode = 3;
619 } catch (final UnsatisfiedLinkError ex1) {
620 if(DEBUG) {
621 System.err.println("ERROR mode 3 - "+ex1.getMessage());
622 }
623 final List<NativeLibrary.LibPath> possiblePaths = NativeLibrary.enumerateLibraryPaths(libraryName, libraryName, libraryName, cl);
624 // Iterate down these and see which one if any we can actually find.
625 for (final Iterator<NativeLibrary.LibPath> iter = possiblePaths.iterator(); 0 == mode && iter.hasNext(); ) {
626 final NativeLibrary.LibPath path = iter.next();
627 if (DEBUG) {
628 System.err.println("JNILibLoaderBase: System.load("+path+") - mode 4");
629 }
630 try {
631 System.load(path.path);
632 mode = 4;
633 } catch (final UnsatisfiedLinkError ex2) {
634 if(DEBUG) {
635 System.err.println("n/a - "+ex2.getMessage());
636 }
637 if(!iter.hasNext()) {
638 // Avoid misleading final exception, use our own
639 throw new UnsatisfiedLinkError("Couldn't load library '"+libraryName+
640 "' generically including "+NativeLibrary.getSystemEnvLibraryPaths()+ // mode 3
641 ", nor as "+possiblePaths); // mode 4
642 }
643 }
644 }
645 }
646 }
647 }
648 if(DEBUG) {
649 System.err.println("JNILibLoaderBase: loadLibraryInternal("+libraryName+"): OK - mode "+mode);
650 }
651 }
652}
static final boolean addNativeJarLibsJoglCfg(final Class<?>[] classesFromJavaJars)
Loads and adds a JAR file's native library to the TempJarCache, calling JNILibLoaderBase#addNativeJar...
static synchronized void loadLibrary(final String libname, final String[] preload, final boolean preloadIgnoreError, final ClassLoader cl)
Loads the library specified by libname, using the LoaderAction set by setLoadingAction(LoaderAction).
static boolean addNativeJarLibs(final Class<?>[] classesFromJavaJars, final String singleJarMarker)
Loads and adds a JAR file's native library to the TempJarCache.
static boolean isLoaded(final String libName)
static void addLoaded(final String libName)
static synchronized void setLoadingAction(final LoaderAction action)
static synchronized boolean loadLibrary(final String libname, final boolean ignoreError, final ClassLoader cl)
Loads the library specified by libname, using the LoaderAction set by setLoadingAction(LoaderAction).
Immutable RFC3986 encoded string.
Definition: Uri.java:296
This class implements an immutable Uri as defined by RFC 2396.
Definition: Uri.java:160
Helper routines for accessing properties.
static final boolean getBooleanProperty(final String property, final boolean jnlpAlias)
static final boolean isPropertyDefined(final String property, final boolean jnlpAlias)
static< T > T doPrivileged(final PrivilegedAction< T > o)
Call wrapper for java.security.AccessController#doPrivileged(PrivilegedAction).
Static Jar file cache handler using an underlying instance of TempFileCache, see getTempFileCache().
static boolean isInitialized(final boolean forExecutables)
boolean loadLibrary(String libname, boolean ignoreError, ClassLoader cl)
Loads the library specified by libname.
void loadLibrary(String libname, String[] preload, boolean preloadIgnoreError, ClassLoader cl)
Loads the library specified by libname.