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 
40 package com.sun.opengl.impl;
41 
42 import java.awt.Toolkit;
43 import java.lang.reflect.InvocationTargetException;
44 import java.lang.reflect.Method;
45 import java.security.AccessController;
46 import java.security.PrivilegedAction;
47 import java.util.HashSet;
48 
49 public class NativeLibLoader {
50   public interface LoaderAction {
51     /**
52      * Loads the library specified by libname. Optionally preloads the libraries specified by
53      * preload. The implementation should ignore, if the preload-libraries have already been
54      * loaded.
55      * @param libname the library to load
56      * @param preload the libraries to load before loading the main library
57      * @param doPreload true, iff the preload-libraries should be loaded
58      * @param ignoreError true, iff errors during loading the preload-libraries should be ignored
59      */
loadLibrary(String libname, String[] preload, boolean doPreload, boolean ignoreError)60     void loadLibrary(String libname, String[] preload,
61         boolean doPreload, boolean ignoreError);
62   }
63 
64   private static class DefaultAction implements LoaderAction {
loadLibrary(String libname, String[] preload, boolean doPreload, boolean ignoreError)65     public void loadLibrary(String libname, String[] preload,
66         boolean doPreload, boolean ignoreError) {
67       if (doPreload) {
68         for (int i=0; i<preload.length; i++) {
69           try {
70             loadLibraryInternal(preload[i]);
71           }
72           catch (UnsatisfiedLinkError e) {
73             if (!ignoreError && e.getMessage().indexOf("already loaded") < 0) {
74               throw e;
75             }
76           }
77         }
78       }
79 
80       loadLibraryInternal(libname);
81     }
82   }
83 
84   private static final HashSet loaded = new HashSet();
85   private static LoaderAction loaderAction = new DefaultAction();
86 
disableLoading()87   public static void disableLoading() {
88     setLoadingAction(null);
89   }
90 
enableLoading()91   public static void enableLoading() {
92     setLoadingAction(new DefaultAction());
93   }
94 
setLoadingAction(LoaderAction action)95   public static synchronized void setLoadingAction(LoaderAction action) {
96     loaderAction = action;
97   }
98 
loadLibrary(String libname, String[] preload, boolean doPreload, boolean ignoreError)99   private static synchronized void loadLibrary(String libname, String[] preload,
100       boolean doPreload, boolean ignoreError) {
101     if (loaderAction != null && !loaded.contains(libname))
102     {
103       loaderAction.loadLibrary(libname, preload, doPreload, ignoreError);
104       loaded.add(libname);
105     }
106   }
107 
loadCore()108   public static void loadCore() {
109     AccessController.doPrivileged(new PrivilegedAction() {
110       public Object run() {
111         loadLibrary("jogl", null, false, false);
112         return null;
113       }
114     });
115   }
116 
loadAWTImpl()117   public static void loadAWTImpl() {
118     AccessController.doPrivileged(new PrivilegedAction() {
119       public Object run() {
120         // Make sure that awt.dll is loaded before loading jawt.dll. Otherwise
121         // a Dialog with "awt.dll not found" might pop up.
122         // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4481947.
123         Toolkit.getDefaultToolkit();
124 
125         // Must pre-load JAWT on all non-Mac platforms to
126         // ensure references from jogl_awt shared object
127         // will succeed since JAWT shared object isn't in
128         // default library path
129         boolean isOSX = System.getProperty("os.name").equals("Mac OS X");
130         String[] preload = { "jawt" };
131 
132         loadLibrary("jogl_awt", preload, !isOSX, false);
133         return null;
134       }
135     });
136   }
137 
loadCgImpl()138   public static void loadCgImpl() {
139     AccessController.doPrivileged(new PrivilegedAction() {
140       public Object run() {
141         String[] preload = { "cg", "cgGL" };
142         loadLibrary("jogl_cg", preload, true, true);
143         return null;
144       }
145     });
146   }
147 
148   //----------------------------------------------------------------------
149   // Support for the new JNLPAppletLauncher
150   //
151 
152   private static boolean usingJNLPAppletLauncher;
153   private static Method  jnlpLoadLibraryMethod;
154 
155   static {
AccessController.doPrivileged(new PrivilegedAction() { public Object run() { String sunAppletLauncher = System.getProperty(R); usingJNLPAppletLauncher = Boolean.valueOf(sunAppletLauncher).booleanValue(); return null; } })156     AccessController.doPrivileged(new PrivilegedAction() {
157         public Object run() {
158           String sunAppletLauncher = System.getProperty("sun.jnlp.applet.launcher");
159           usingJNLPAppletLauncher = Boolean.valueOf(sunAppletLauncher).booleanValue();
160           return null;
161         }
162       });
163   }
164 
165   // I hate the amount of delegation currently in this class
loadLibraryInternal(String libraryName)166   private static void loadLibraryInternal(String libraryName) {
167     // Note: special-casing JAWT which is built in to the JDK
168     if (usingJNLPAppletLauncher && !libraryName.equals("jawt")) {
169         try {
170           if (jnlpLoadLibraryMethod == null) {
171             Class jnlpAppletLauncherClass = Class.forName("org.jdesktop.applet.util.JNLPAppletLauncher");
172             jnlpLoadLibraryMethod = jnlpAppletLauncherClass.getDeclaredMethod("loadLibrary", new Class[] { String.class });
173           }
174           jnlpLoadLibraryMethod.invoke(null, new Object[] { libraryName });
175         } catch (Exception e) {
176           Throwable t = e;
177           if (t instanceof InvocationTargetException) {
178             t = ((InvocationTargetException) t).getTargetException();
179           }
180           if (t instanceof Error)
181             throw (Error) t;
182           if (t instanceof RuntimeException) {
183             throw (RuntimeException) t;
184           }
185           // Throw UnsatisfiedLinkError for best compatibility with System.loadLibrary()
186           throw (UnsatisfiedLinkError) new UnsatisfiedLinkError().initCause(e);
187         }
188     } else {
189       System.loadLibrary(libraryName);
190     }
191   }
192 }
193