GlueGen v2.6.0-rc-20250712
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: module: %s -> %s%n", nativeJarBasename, nativeJarURI);
218 }
219
220 try {
221 ok = TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI, nativeLibraryPath);
222 } catch(final Exception e) {
223 if(DEBUG) {
224 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: Caught %s%n", e.getMessage());
225 e.printStackTrace();
226 }
227 }
228 }
229 if (!ok) {
230 final ClassLoader cl = classFromJavaJar.getClassLoader();
231 {
232 // Attempt-2 a 'one big-fat jar file' layout, containing java classes
233 // and all native platform libraries under 'natives/os.and.arch' per platform!
234 final URL nativeLibraryURI = cl.getResource(nativeLibraryPath);
235 if (null != nativeLibraryURI) {
236 final Uri nativeJarURI = JarUtil.getJarFileUri( jarSubUriRoot.getEncoded().concat(jarBasename) );
237 try {
238 if( TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI, nativeLibraryPath) ) {
239 ok = true;
240 if (DEBUG) {
241 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: fat: %s -> %s%n", jarBasename, nativeJarURI);
242 }
243 }
244 } catch(final Exception e) {
245 if(DEBUG) {
246 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: Caught %s%n", e.getMessage());
247 e.printStackTrace();
248 }
249 }
250 }
251 }
252 if (!ok) {
253 // Attempt-3 to find via ClassLoader and Native-Jar-Tag,
254 // assuming one slim native jar file per 'os.and.arch'
255 // and native platform libraries under 'natives/os.and.arch'!
256 final String moduleName;
257 {
258 final String packageName = classFromJavaJar.getPackage().getName();
259 final int idx = packageName.lastIndexOf('.');
260 if( 0 <= idx ) {
261 moduleName = packageName.substring(idx+1);
262 } else {
263 moduleName = packageName;
264 }
265 }
266 final String os_and_arch_dot = PlatformPropsImpl.os_and_arch.replace('-', '.');
267 final String nativeJarTagClassName = nativeJarTagPackage + "." + moduleName + "." + os_and_arch_dot + ".TAG"; // TODO: sync with gluegen-cpptasks-base.xml
268 try {
269 if(DEBUG) {
270 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: ClassLoader/TAG: Locating module %s, os.and.arch %s: %s%n",
271 moduleName, os_and_arch_dot, nativeJarTagClassName);
272 }
273 final Uri nativeJarTagClassJarURI = JarUtil.getJarUri(nativeJarTagClassName, cl);
274 if (DEBUG) {
275 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: ClassLoader/TAG: %s -> %s%n", nativeJarTagClassName, nativeJarTagClassJarURI);
276 }
277 ok = TempJarCache.addNativeLibs(classFromJavaJar, nativeJarTagClassJarURI, nativeLibraryPath);
278 } catch (final Exception e ) {
279 if(DEBUG) {
280 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: Caught %s%n", e.getMessage());
281 e.printStackTrace();
282 }
283 }
284 }
285 }
286
287 if (DEBUG || PERF) {
288 final long tNow = System.currentTimeMillis() - t0;
289 final long tTotal, tCount;
290 synchronized(perfSync) {
291 tCount = perfCount+1;
292 tTotal = perfTotal + tNow;
293 perfTotal = tTotal;
294 perfCount = tCount;
295 }
296 final double tAvrg = tTotal / (double)tCount;
297 System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl.X: %s / %s -> ok: %b; duration: now %d ms, total %d ms (count %d, avrg %.3f ms)%n",
298 jarBasename, nativeJarBasename, ok, tNow, tTotal, tCount, tAvrg);
299 }
300 return ok;
301 }
302
303 /**
304 * Loads and adds a JAR file's native library to the TempJarCache,
305 * calling {@link JNILibLoaderBase#addNativeJarLibs(Class[], String)}
306 * with default JOGL deployment configuration:
307 * <pre>
308 return JNILibLoaderBase.addNativeJarLibs(classesFromJavaJars, "-all");
309 * </pre>
310 * If <code>Class1.class</code> is contained in a JAR file which name includes <code>singleJarMarker</code> <i>-all</i>,
311 * implementation will attempt to resolve the native JAR file as follows:
312 * <ul>
313 * <li><i>ClassJar-all</i>.jar to <i>ClassJar-all</i>-natives-<i>os.and.arch</i>.jar</li>
314 * </ul>
315 * Otherwise the native JAR files will be resolved for each class's JAR file:
316 * <ul>
317 * <li><i>ClassJar1</i>.jar to <i>ClassJar1</i>-natives-<i>os.and.arch</i>.jar</li>
318 * <li><i>ClassJar2</i>.jar to <i>ClassJar2</i>-natives-<i>os.and.arch</i>.jar</li>
319 * <li>..</li>
320 * </ul>
321 */
322
323 public static final boolean addNativeJarLibsJoglCfg(final Class<?>[] classesFromJavaJars) {
324 return addNativeJarLibs(classesFromJavaJars, "-all");
325 }
326
327 /**
328 * Loads and adds a JAR file's native library to the TempJarCache.<br>
329 * The native library JAR file's URI is derived as follows:
330 * <ul>
331 * <li> [1] <code>GLProfile.class</code> -> </li>
332 * <li> [2] <code>http://lala/gluegen-rt.jar</code> -> </li>
333 * <li> [3] <code>http://lala/gluegen-rt</code> -> </li>
334 * <li> [4] <code>http://lala/gluegen-rt-natives-'os.and.arch'.jar</code> </li>
335 * </ul>
336 * Where:
337 * <ul>
338 * <li> [1] is one of <code>classesFromJavaJars</code></li>
339 * <li> [2] is it's complete URI</li>
340 * <li> [3] is it's <i>base URI</i></li>
341 * <li> [4] is the derived native JAR filename</li>
342 * </ul>
343 * <p>
344 * Generic description:
345 * <pre>
346 final Class<?>[] classesFromJavaJars = new Class<?>[] { Class1.class, Class2.class };
347 JNILibLoaderBase.addNativeJarLibs(classesFromJavaJars, "-all");
348 * </pre>
349 * If <code>Class1.class</code> is contained in a JAR file which name includes <code>singleJarMarker</code>, here <i>-all</i>,
350 * implementation will attempt to resolve the native JAR file as follows:
351 * <ul>
352 * <li><i>ClassJar-all</i>.jar to <i>ClassJar-all</i>-natives-<i>os.and.arch</i>.jar</li>
353 * </ul>
354 * Otherwise the native JAR files will be resolved for each class's JAR file:
355 * <ul>
356 * <li><i>Class1Jar</i>.jar to <i>Class1Jar</i>-natives-<i>os.and.arch</i>.jar</li>
357 * <li><i>Class2Jar</i>.jar to <i>Class2Jar</i>-natives-<i>os.and.arch</i>.jar</li>
358 * </ul>
359 * </p>
360 * <p>
361 * Examples:
362 * </p>
363 * <p>
364 * JOCL:
365 * <pre>
366 // only: jocl.jar -> jocl-natives-<i>os.and.arch</i>.jar
367 addNativeJarLibs(new Class<?>[] { JOCLJNILibLoader.class }, null, null );
368 * </pre>
369 * </p>
370 * <p>
371 * JOGL:
372 * <pre>
373 final ClassLoader cl = GLProfile.class.getClassLoader();
374 // jogl-all.jar -> jogl-all-natives-<i>os.and.arch</i>.jar
375 // jogl-all-noawt.jar -> jogl-all-noawt-natives-<i>os.and.arch</i>.jar
376 // jogl-all-mobile.jar -> jogl-all-mobile-natives-<i>os.and.arch</i>.jar
377 // jogl-all-android.jar -> jogl-all-android-natives-<i>os.and.arch</i>.jar
378 // nativewindow.jar -> nativewindow-natives-<i>os.and.arch</i>.jar
379 // jogl.jar -> jogl-natives-<i>os.and.arch</i>.jar
380 // newt.jar -> newt-natives-<i>os.and.arch</i>.jar (if available)
381 final String newtFactoryClassName = "com.jogamp.newt.NewtFactory";
382 final Class<?>[] classesFromJavaJars = new Class<?>[] { NWJNILibLoader.class, GLProfile.class, null };
383 if( ReflectionUtil.isClassAvailable(newtFactoryClassName, cl) ) {
384 classesFromJavaJars[2] = ReflectionUtil.getClass(newtFactoryClassName, false, cl);
385 }
386 JNILibLoaderBase.addNativeJarLibs(classesFromJavaJars, "-all");
387 * </pre>
388 * </p>
389 *
390 * @param classesFromJavaJars For each given Class, load the native library JAR.
391 * @param singleJarMarker Optional string marker like "-all" to identify the single 'all-in-one' JAR file
392 * after which processing of the class array shall stop.
393 *
394 * @return true if either the 'all-in-one' native JAR or all native JARs loaded successful or were loaded already,
395 * false in case of an error
396 */
397 public static boolean addNativeJarLibs(final Class<?>[] classesFromJavaJars, final String singleJarMarker) {
398 if(DEBUG) {
399 final StringBuilder msg = new StringBuilder();
400 msg.append("JNILibLoaderBase: addNativeJarLibs(").append(PlatformPropsImpl.NEWLINE);
401 msg.append(" classesFromJavaJars = ").append(Arrays.asList(classesFromJavaJars)).append(PlatformPropsImpl.NEWLINE);
402 msg.append(" singleJarMarker = ").append(singleJarMarker).append(PlatformPropsImpl.NEWLINE);
403 msg.append(")");
404 System.err.println(msg.toString());
405 }
406
407 boolean ok = false;
408 if ( TempJarCache.isInitialized(true) ) {
409 ok = addNativeJarLibsWithTempJarCache(classesFromJavaJars, singleJarMarker);
410 } else if(DEBUG) {
411 System.err.println("JNILibLoaderBase: addNativeJarLibs0: disabled due to uninitialized TempJarCache");
412 }
413 return ok;
414 }
415
416 private static boolean addNativeJarLibsWithTempJarCache(final Class<?>[] classesFromJavaJars, final String singleJarMarker) {
417 boolean ok;
418 int count = 0;
419 try {
420 boolean done = false;
421 ok = true;
422
423 for (int i = 0; i < classesFromJavaJars.length; ++i) {
424 final Class<?> c = classesFromJavaJars[i];
425 if (c == null) {
426 continue;
427 }
428
429 final ClassLoader cl = c.getClassLoader();
430 final Uri classJarURI = JarUtil.getJarUri(c.getName(), cl);
431 final Uri.Encoded jarName = JarUtil.getJarBasename(classJarURI);
432
433 if (jarName == null) {
434 continue;
435 }
436
437 final Uri.Encoded jarBasename = jarName.substring(0, jarName.indexOf(".jar"));
438
439 if(DEBUG) {
440 System.err.printf("JNILibLoaderBase: jarBasename: %s%n", jarBasename);
441 }
442
443 /**
444 * If a jar marker was specified, and the basename contains the
445 * marker, we're done.
446 */
447
448 if (singleJarMarker != null) {
449 if (jarBasename.indexOf(singleJarMarker) >= 0) {
450 done = true;
451 }
452 }
453
454 final Uri.Encoded nativeJarBasename =
455 Uri.Encoded.cast( String.format((Locale)null, "%s-natives-%s.jar", jarBasename.get(), PlatformPropsImpl.os_and_arch) );
456
457 ok = JNILibLoaderBase.addNativeJarLibsImpl(c, classJarURI, jarName, nativeJarBasename);
458 if (ok) {
459 count++;
460 }
461 if (DEBUG && done) {
462 System.err.printf("JNILibLoaderBase: addNativeJarLibs0: done: %s%n", jarBasename);
463 }
464 }
465 } catch (final Exception x) {
466 System.err.printf("JNILibLoaderBase: Caught %s: %s%n", x.getClass().getSimpleName(), x.getMessage());
467 if(DEBUG) {
468 x.printStackTrace();
469 }
470 ok = false;
471 }
472 if(DEBUG) {
473 System.err.printf("JNILibLoaderBase: addNativeJarLibsWhenInitialized: count %d, ok %b%n", count, ok);
474 }
475 return ok;
476 }
477
478 /**
479 * Loads the library specified by libname, using the {@link LoaderAction} set by {@link #setLoadingAction(LoaderAction)}.<br>
480 * The implementation should ignore, if the library has been loaded already.<br>
481 * @param libname the library to load
482 * @param ignoreError if true, errors during loading the library should be ignored
483 * @param cl optional ClassLoader, used to locate the library
484 * @return true if library loaded successful
485 */
486 protected static synchronized boolean loadLibrary(final String libname, final boolean ignoreError, final ClassLoader cl) {
487 if (loaderAction != null) {
488 return loaderAction.loadLibrary(libname, ignoreError, cl);
489 }
490 return false;
491 }
492
493 /**
494 * Loads the library specified by libname, using the {@link LoaderAction} set by {@link #setLoadingAction(LoaderAction)}.<br>
495 * Optionally preloads the libraries specified by preload.<br>
496 * The implementation should ignore, if any library has been loaded already.<br>
497 * @param libname the library to load
498 * @param preload the libraries to load before loading the main library if not null
499 * @param preloadIgnoreError if true, errors during loading the preload-libraries should be ignored
500 * @param cl optional ClassLoader, used to locate the library
501 */
502 protected static synchronized void loadLibrary(final String libname, final String[] preload, final boolean preloadIgnoreError, final ClassLoader cl) {
503 if (loaderAction != null) {
504 loaderAction.loadLibrary(libname, preload, preloadIgnoreError, cl);
505 }
506 }
507
508 // private static final Class<?> customLauncherClass; // FIXME: remove
509 private static final Method customLoadLibraryMethod;
510
511 static {
512 final String sunAppletLauncherProperty = "sun.jnlp.applet.launcher";
513 final String sunAppletLauncherClassName = "org.jdesktop.applet.util.JNLPAppletLauncher";
514
515 final Method loadLibraryMethod = SecurityUtil.doPrivileged(new PrivilegedAction<Method>() {
516 @Override
517 public Method run() {
518 // FIXME: remove
519 final boolean usingJNLPAppletLauncher = PropertyAccess.getBooleanProperty(sunAppletLauncherProperty, true);
520
521 Class<?> launcherClass = null;
522 Method loadLibraryMethod = null;
523
524 if (usingJNLPAppletLauncher) {
525 try {
526 launcherClass = Class.forName(sunAppletLauncherClassName);
527 } catch (final ClassNotFoundException cnfe) {
528 // oops .. look like JNLPAppletLauncher doesn't exist, despite property
529 // this may happen if a previous applet was using JNLPAppletLauncher in the same JVM
530 System.err.println("JNILibLoaderBase: <"+sunAppletLauncherClassName+"> not found, despite enabled property <"+sunAppletLauncherProperty+">, JNLPAppletLauncher was probably used before");
531 System.setProperty(sunAppletLauncherProperty, Boolean.FALSE.toString());
532 } catch (final LinkageError le) {
533 throw le;
534 }
535 if(null != launcherClass) {
536 try {
537 loadLibraryMethod = launcherClass.getDeclaredMethod("loadLibrary", new Class[] { String.class });
538 } catch (final NoSuchMethodException ex) {
539 if(DEBUG) {
540 ex.printStackTrace();
541 }
542 launcherClass = null;
543 }
544 }
545 }
546 if(null==launcherClass) {
547 final String launcherClassName = PropertyAccess.getProperty("jnlp.launcher.class", false);
548 if(null!=launcherClassName) {
549 try {
550 launcherClass = Class.forName(launcherClassName);
551 loadLibraryMethod = launcherClass.getDeclaredMethod("loadLibrary", new Class[] { String.class });
552 } catch (final ClassNotFoundException ex) {
553 if(DEBUG) {
554 ex.printStackTrace();
555 }
556 } catch (final NoSuchMethodException ex) {
557 if(DEBUG) {
558 ex.printStackTrace();
559 }
560 launcherClass = null;
561 }
562 }
563 }
564 return loadLibraryMethod;
565 } } );
566 customLoadLibraryMethod = loadLibraryMethod;
567 }
568
569 private static void loadLibraryInternal(final String libraryName, final ClassLoader cl) {
570 // Note: special-casing JAWT which is built in to the JDK
571 int mode = 0; // 1 - custom, 2 - System.load( TempJarCache ), 3 - System.loadLibrary( name ), 4 - System.load( enumLibNames )
572 if (null!=customLoadLibraryMethod && !libraryName.equals("jawt")) {
573 // FIXME: remove
574 if(DEBUG) {
575 System.err.println("JNILibLoaderBase: customLoad("+libraryName+") - mode 1");
576 }
577 try {
578 customLoadLibraryMethod.invoke(null, new Object[] { libraryName });
579 mode = 1;
580 } catch (final Exception e) {
581 Throwable t = e;
582 if (t instanceof InvocationTargetException) {
583 t = ((InvocationTargetException) t).getTargetException();
584 }
585 if (t instanceof Error) {
586 throw (Error) t;
587 }
588 if (t instanceof RuntimeException) {
589 throw (RuntimeException) t;
590 }
591 // Throw UnsatisfiedLinkError for best compatibility with System.loadLibrary()
592 throw (UnsatisfiedLinkError) new UnsatisfiedLinkError("can not load library "+libraryName).initCause(e);
593 }
594 } else {
595 // System.err.println("sun.boot.library.path=" + Debug.getProperty("sun.boot.library.path", false));
596 final String libraryPath = NativeLibrary.findLibrary(libraryName, cl); // implicit TempJarCache usage if used/initialized
597 if(DEBUG) {
598 System.err.println("JNILibLoaderBase: loadLibraryInternal("+libraryName+"), TempJarCache: "+libraryPath);
599 }
600 if(null != libraryPath) {
601 if(DEBUG) {
602 System.err.println("JNILibLoaderBase: System.load("+libraryPath+") - mode 2");
603 }
604 System.load(libraryPath);
605 mode = 2;
606 } else {
607 if(DEBUG) {
608 System.err.println("JNILibLoaderBase: System.loadLibrary("+libraryName+") - mode 3: SystemEnvLibraryPaths: "+NativeLibrary.getSystemEnvLibraryPaths());
609 }
610 try {
611 System.loadLibrary(libraryName);
612 mode = 3;
613 } catch (final UnsatisfiedLinkError ex1) {
614 if(DEBUG) {
615 System.err.println("ERROR mode 3 - "+ex1.getMessage());
616 }
617 final List<NativeLibrary.LibPath> possiblePaths = NativeLibrary.enumerateLibraryPaths(libraryName, libraryName, libraryName, cl);
618 // Iterate down these and see which one if any we can actually find.
619 for (final Iterator<NativeLibrary.LibPath> iter = possiblePaths.iterator(); 0 == mode && iter.hasNext(); ) {
620 final NativeLibrary.LibPath path = iter.next();
621 if (DEBUG) {
622 System.err.println("JNILibLoaderBase: System.load("+path+") - mode 4");
623 }
624 try {
625 System.load(path.path);
626 mode = 4;
627 } catch (final UnsatisfiedLinkError ex2) {
628 if(DEBUG) {
629 System.err.println("n/a - "+ex2.getMessage());
630 }
631 if(!iter.hasNext()) {
632 // Avoid misleading final exception, use our own
633 throw new UnsatisfiedLinkError("Couldn't load library '"+libraryName+
634 "' generically including "+NativeLibrary.getSystemEnvLibraryPaths()+ // mode 3
635 ", nor as "+possiblePaths); // mode 4
636 }
637 }
638 }
639 }
640 }
641 }
642 if(DEBUG) {
643 System.err.println("JNILibLoaderBase: loadLibraryInternal("+libraryName+"): OK - mode "+mode);
644 }
645 }
646}
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.