diff options
Diffstat (limited to 'src/classes/com')
-rw-r--r-- | src/classes/com/sun/opengl/impl/NativeLibLoader.java | 11 | ||||
-rw-r--r-- | src/classes/com/sun/opengl/impl/x11/DRIHack.java | 39 | ||||
-rwxr-xr-x | src/classes/com/sun/opengl/util/JOGLAppletLauncher.java | 304 |
3 files changed, 181 insertions, 173 deletions
diff --git a/src/classes/com/sun/opengl/impl/NativeLibLoader.java b/src/classes/com/sun/opengl/impl/NativeLibLoader.java index 25c52e594..aa5c4e236 100644 --- a/src/classes/com/sun/opengl/impl/NativeLibLoader.java +++ b/src/classes/com/sun/opengl/impl/NativeLibLoader.java @@ -133,17 +133,6 @@ public class NativeLibLoader { }); } - // See DRIHack.java in com/sun/opengl/impl/x11/ for description of - // why this is needed - public static void loadDRIHack() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - loadLibrary("jogl_drihack", null, false, false); - return null; - } - }); - } - public static void loadCgImpl() { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { diff --git a/src/classes/com/sun/opengl/impl/x11/DRIHack.java b/src/classes/com/sun/opengl/impl/x11/DRIHack.java index 18bf3d5e8..f6579238e 100644 --- a/src/classes/com/sun/opengl/impl/x11/DRIHack.java +++ b/src/classes/com/sun/opengl/impl/x11/DRIHack.java @@ -41,6 +41,7 @@ package com.sun.opengl.impl.x11; import java.io.*; import java.security.*; +import com.sun.gluegen.runtime.*; import com.sun.opengl.impl.*; /** @@ -70,19 +71,15 @@ import com.sun.opengl.impl.*; * necessary in any other situation than with the DRI drivers. Another * solution is to force the first load of libGL.so.1.2 to be done * dynamically with RTLD_GLOBAL before libjogl.so is loaded and causes - * libGL.so.1.2 to be loaded again. This requires the C APIs dlopen - * and dlclose to be made available before libjogl.so is loaded. This - * is the solution currently chosen and is called the "DRI hack" - * because again it is needed only in this situation. + * libGL.so.1.2 to be loaded again. The NativeLibrary class in the + * GlueGen runtime has this property, and we use it to implement this + * workaround. */ public class DRIHack { - public static native long dlopen(String name); - public static native int dlclose(long handle); - private static final boolean DEBUG = Debug.debug("DRIHack"); private static boolean driHackNeeded; - private static long libGLHandle; + private static NativeLibrary oglLib; public static void begin() { AccessController.doPrivileged(new PrivilegedAction() { @@ -102,34 +99,30 @@ public class DRIHack { System.err.println("Beginning DRI hack"); } - NativeLibLoader.loadDRIHack(); // Try a few different variants for best robustness // In theory probably only the first is necessary - libGLHandle = dlopen("libGL.so.1"); - if (DEBUG && libGLHandle != 0) System.err.println(" Found libGL.so.1"); - if (libGLHandle == 0) { - libGLHandle = dlopen("libGL.so.1.2"); - if (DEBUG && libGLHandle != 0) System.err.println(" Found libGL.so.1.2"); - } + oglLib = NativeLibrary.open("GL", null); + if (DEBUG && oglLib != null) System.err.println(" Found libGL.so"); // Allow ATI's fglrx to supersede version in /usr/lib - if (libGLHandle == 0) { - libGLHandle = dlopen("/usr/lib/ati-fglrx/libGL.so.1.2"); - if (DEBUG && libGLHandle != 0) System.err.println(" Found /usr/lib/ati-fglrx/libGL.so.1.2"); + if (oglLib == null) { + oglLib = NativeLibrary.open("/usr/lib/ati-fglrx/libGL.so.1.2", null); + if (DEBUG && oglLib != null) System.err.println(" Found /usr/lib/ati-fglrx/libGL.so.1.2"); } - if (libGLHandle == 0) { - libGLHandle = dlopen("/usr/lib/libGL.so.1"); - if (DEBUG && libGLHandle != 0) System.err.println(" Found /usr/lib/libGL.so.1"); + if (oglLib == null) { + oglLib = NativeLibrary.open("/usr/lib/libGL.so.1", null); + if (DEBUG && oglLib != null) System.err.println(" Found /usr/lib/libGL.so.1"); } } } public static void end() { - if (libGLHandle != 0) { + if (oglLib != null) { if (DEBUG) { System.err.println("Ending DRI hack"); } - dlclose(libGLHandle); + oglLib.close(); + oglLib = null; } } } diff --git a/src/classes/com/sun/opengl/util/JOGLAppletLauncher.java b/src/classes/com/sun/opengl/util/JOGLAppletLauncher.java index 303985b69..2f3237275 100755 --- a/src/classes/com/sun/opengl/util/JOGLAppletLauncher.java +++ b/src/classes/com/sun/opengl/util/JOGLAppletLauncher.java @@ -53,6 +53,7 @@ import java.applet.AppletContext; import java.io.*; import java.net.*; import java.security.cert.*; +import java.text.*; import java.util.*; import java.util.jar.*; import javax.swing.*; @@ -65,13 +66,15 @@ import javax.media.opengl.*; * It may also be used to deploy signed applets in which case * multiple security dialogs will be displayed. <p> * - * On the server side the codebase must contain jogl.jar and all of - * the jogl-natives-*.jar files from the standard JOGL distribution. - * This is the location from which the JOGL library used by the - * applet is downloaded. The codebase additionally contains the jar - * file of the user's potentially untrusted applet. The jogl.jar and - * all jogl-natives jars must be signed by the same entity, which is - * typically Sun Microsystems, Inc. + * On the server side the codebase must contain jogl.jar , + * gluegen-rt.jar, and all of the jogl-natives-*.jar and + * gluegen-rt-natives-*.jar files from the standard JOGL distribution + * (provided in jogl-[version]-webstart.zip). This is the location + * from which the JOGL library used by the applet is downloaded. The + * codebase additionally contains the jar file of the user's + * potentially untrusted applet. All of the JOGL and GlueGen-related + * jars must be signed by the same entity, which is typically Sun + * Microsystems, Inc. * * Sample applet code: * <pre> @@ -79,12 +82,12 @@ import javax.media.opengl.*; * width=600 * height=400 * codebase="/lib" - * archive="jogl.jar,your_applet.jar"> + * archive="jogl.jar,gluegen-rt.jar,your_applet.jar"> * <param name="subapplet.classname" VALUE="untrusted.JOGLApplet"> * <param name="subapplet.displayname" VALUE="My JOGL Applet"> * <param name="progressbar" value="true"> - * <param name="cache_archive" VALUE="jogl.jar,your_applet.jar"> - * <param name="cache_archive_ex" VALUE="jogl.jar;preload,your_applet.jar;preload"> + * <param name="cache_archive" VALUE="jogl.jar,gluegen-rt.jar,your_applet.jar"> + * <param name="cache_archive_ex" VALUE="jogl.jar;preload,gluegen-rt.jar;preload,your_applet.jar;preload"> * </applet> * </pre> * <p> @@ -108,8 +111,8 @@ import javax.media.opengl.*; * this applet launcher, the first question to ask the end user is * whether jogl.jar and any associated DLLs, .so's, etc. are installed * directly in to the JRE. The applet launcher has been tested - * primarily under Mozilla and Firefox; there may be problems when - * running under, for example, Opera. <p> + * primarily under Mozilla, Firefox and Internet Explorer; there may + * be problems when running under, for example, Opera. <p> * * @author Lilian Chamontin * @author Kenneth Russell @@ -126,37 +129,37 @@ public class JOGLAppletLauncher extends Applet { private static class NativeLibInfo { private String osName; private String osArch; - private String nativeJar; + private String osNameAndArchPair; private String nativePrefix; private String nativeSuffix; - public NativeLibInfo(String osName, String osArch, String nativeJar, String nativePrefix, String nativeSuffix) { + public NativeLibInfo(String osName, String osArch, String osNameAndArchPair, String nativePrefix, String nativeSuffix) { this.osName = osName; this.osArch = osArch; - this.nativeJar = nativeJar; + this.osNameAndArchPair = osNameAndArchPair; this.nativePrefix = nativePrefix; this.nativeSuffix = nativeSuffix; } public boolean matchesOSAndArch(String osName, String osArch) { - if (osName.startsWith(this.osName)) { + if (osName.toLowerCase().startsWith(this.osName)) { if ((this.osArch == null) || - (osArch.startsWith(this.osArch))) { + (osArch.toLowerCase().startsWith(this.osArch))) { return true; } } return false; } - public boolean matchesNativeLib(String nativeLibraryName) { - if (nativeLibraryName.toLowerCase().endsWith(nativeSuffix)) { + public boolean matchesNativeLib(String fileName) { + if (fileName.toLowerCase().endsWith(nativeSuffix)) { return true; } return false; } - public String getNativeJarName() { - return nativeJar; + public String formatNativeJarName(String nativeJarPattern) { + return MessageFormat.format(nativeJarPattern, new Object[] { osNameAndArchPair }); } public String getNativeLibName(String baseName) { @@ -166,16 +169,20 @@ public class JOGLAppletLauncher extends Applet { public boolean isMacOS() { return (osName.equals("mac")); } + + public boolean mayNeedDRIHack() { + return (!isMacOS() && !osName.equals("win")); + } } private static final NativeLibInfo[] allNativeLibInfo = { - new NativeLibInfo("win", "x86", "jogl-natives-windows-i586.jar", "", ".dll"), - new NativeLibInfo("mac", "ppc", "jogl-natives-macosx-ppc.jar", "lib", ".jnilib"), - new NativeLibInfo("mac", "i386", "jogl-natives-macosx-universal.jar", "lib", ".jnilib"), - new NativeLibInfo("linux", "i386", "jogl-natives-linux-i586.jar", "lib", ".so"), - new NativeLibInfo("linux", "x86", "jogl-natives-linux-i586.jar", "lib", ".so"), - new NativeLibInfo("sunos", "sparc", "jogl-natives-solaris-sparc.jar", "lib", ".so"), - new NativeLibInfo("sunos", "x86", "jogl-natives-solaris-i586.jar", "lib", ".so") + new NativeLibInfo("win", "x86", "windows-i586", "", ".dll"), + new NativeLibInfo("mac", "ppc", "macosx-ppc", "lib", ".jnilib"), + new NativeLibInfo("mac", "i386", "macosx-universal", "lib", ".jnilib"), + new NativeLibInfo("linux", "i386", "linux-i586", "lib", ".so"), + new NativeLibInfo("linux", "x86", "linux-i586", "lib", ".so"), + new NativeLibInfo("sunos", "sparc", "solaris-sparc", "lib", ".so"), + new NativeLibInfo("sunos", "x86", "solaris-i586", "lib", ".so") }; private NativeLibInfo nativeLibInfo; @@ -183,10 +190,6 @@ public class JOGLAppletLauncher extends Applet { // The signatures of these native libraries are checked before // installing them. private String[] nativeLibNames; - // Whether the "DRI hack" native library is present and whether we - // therefore might need to run the DRIHack during loading of the - // native libraries - private boolean driHackPresent; /** The applet we have to start */ private Applet subApplet; @@ -236,8 +239,8 @@ public class JOGLAppletLauncher extends Applet { this.installDirectory = codeBase.replace(':', '_') .replace('.', '_').replace('/', '_').replace('~','_'); // clean up the name - String osName = System.getProperty("os.name").toLowerCase(); - String osArch = System.getProperty("os.arch").toLowerCase(); + String osName = System.getProperty("os.name"); + String osArch = System.getProperty("os.arch"); if (checkOSAndArch(osName, osArch)) { this.isInitOk = true; } else { @@ -245,12 +248,30 @@ public class JOGLAppletLauncher extends Applet { } } - private void displayMessage(String message){ - progressBar.setString(message); + private void displayMessage(final String message){ + SwingUtilities.invokeLater(new Runnable() { + public void run() { + progressBar.setString(message); + } + }); + } + + private void displayError(final String errorMessage){ + // Print message to Java console too in case it's truncated in the applet's display + System.err.println(errorMessage); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + progressBar.setString("Error : " + errorMessage); + } + }); } - private void displayError(String errorMessage){ - progressBar.setString("Error : " + errorMessage); + private void setProgress(final int value) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + progressBar.setValue(value); + } + }); } private void initLoaderLayout(){ @@ -368,110 +389,110 @@ public class JOGLAppletLauncher extends Applet { } } - String nativeJarName = nativeLibInfo.getNativeJarName(); + String[] nativeJarNames = new String[] { + nativeLibInfo.formatNativeJarName("jogl-natives-{0}.jar"), + nativeLibInfo.formatNativeJarName("gluegen-rt-natives-{0}.jar") + }; - URL nativeLibURL; - URLConnection urlConnection; - String path = getCodeBase().toExternalForm() + nativeJarName; - try { - nativeLibURL = new URL(path); - urlConnection = nativeLibURL.openConnection(); - } catch (Exception e){ - e.printStackTrace(); - displayError("Couldn't access the native lib URL : " + path); - return; - } + for (int n = 0; n < nativeJarNames.length; n++) { + String nativeJarName = nativeJarNames[n]; - // the timestamp used to determine if we have to download the native jar again - // don't rely on the OS's timestamp to cache this - long lastModified = getTimestamp(installDir, urlConnection.getLastModified()); - if (lastModified != urlConnection.getLastModified()) { - displayMessage("Updating local version of the native libraries"); - // first download the full jar locally - File localJarFile = new File(installDir, nativeJarName); + URL nativeLibURL; + URLConnection urlConnection; + String path = getCodeBase().toExternalForm() + nativeJarName; try { - saveNativesJarLocally(localJarFile, urlConnection); - } catch (IOException ioe) { - ioe.printStackTrace(); - displayError("Unable to install the native file locally"); - return; + nativeLibURL = new URL(path); + urlConnection = nativeLibURL.openConnection(); + } catch (Exception e){ + e.printStackTrace(); + displayError("Couldn't access the native lib URL : " + path); + return; } - try { - JarFile jf = new JarFile(localJarFile); - - // Iterate the entries finding all candidate libraries that need - // to have their signatures verified - if (!findNativeEntries(jf)) { - displayError("native libraries not found in jar file"); - return; - } - - byte[] buf = new byte[8192]; - - // Go back and verify the signatures - for (int i = 0; i < nativeLibNames.length; i++) { - JarEntry entry = jf.getJarEntry(nativeLibNames[i]); - if (entry == null) { - displayError("error looking up jar entry " + nativeLibNames[i]); - return; - } - if (!checkNativeCertificates(jf, entry, buf)) { - displayError("Native library " + nativeLibNames[i] + " isn't properly signed or has other errors"); - return; - } - } - - // Now install the native library files - progressBar.setValue(0); - for (int i = 0; i < nativeLibNames.length; i++) { - displayMessage("Installing native files"); - if (!installFile(installDir, jf, nativeLibNames[i], buf)) { - return; - } - int percent = (100 * (i + 1) / nativeLibNames.length); - progressBar.setValue(percent); - } - - // At this point we can delete the jar file we just downloaded - jf.close(); - localJarFile.delete(); - - // If installation succeeded, write a timestamp for all of the - // files to be checked next time - try { - File timestampFile = new File(installDir, "timestamp"); - timestampFile.delete(); - BufferedWriter writer = new BufferedWriter(new FileWriter(timestampFile)); - writer.write("" + urlConnection.getLastModified()); - writer.flush(); - writer.close(); - } catch (Exception e) { - displayError("Error writing time stamp for native libraries"); - return; - } - - } catch (Exception e) { - displayError("Error opening jar file " + localJarFile.getName() + " for reading"); - return; - } - } else { - // Still need to discover whether DRI hack is installed - File[] files = installDir.listFiles(); - for (int i = 0; i < files.length; i++) { - if (files[i].getName().indexOf("jogl_drihack") >= 0) { - driHackPresent = true; - } + // the timestamp used to determine if we have to download the native jar again + // don't rely on the OS's timestamp to cache this + long lastModified = getTimestamp(installDir, nativeJarName, urlConnection.getLastModified()); + if (lastModified != urlConnection.getLastModified()) { + displayMessage("Updating local version of the native libraries"); + // first download the full jar locally + File localJarFile = new File(installDir, nativeJarName); + try { + saveNativesJarLocally(localJarFile, urlConnection); + } catch (IOException ioe) { + ioe.printStackTrace(); + displayError("Unable to install the native file locally"); + return; + } + + try { + JarFile jf = new JarFile(localJarFile); + + // Iterate the entries finding all candidate libraries that need + // to have their signatures verified + if (!findNativeEntries(jf)) { + displayError("native libraries not found in jar file"); + return; + } + + byte[] buf = new byte[8192]; + + // Go back and verify the signatures + for (int i = 0; i < nativeLibNames.length; i++) { + JarEntry entry = jf.getJarEntry(nativeLibNames[i]); + if (entry == null) { + displayError("error looking up jar entry " + nativeLibNames[i]); + return; + } + if (!checkNativeCertificates(jf, entry, buf)) { + displayError("Native library " + nativeLibNames[i] + " isn't properly signed or has other errors"); + return; + } + } + + // Now install the native library files + setProgress(0); + for (int i = 0; i < nativeLibNames.length; i++) { + displayMessage("Installing native files from " + nativeJarName); + if (!installFile(installDir, jf, nativeLibNames[i], buf)) { + return; + } + int percent = (100 * (i + 1) / nativeLibNames.length); + setProgress(percent); + } + + // At this point we can delete the jar file we just downloaded + jf.close(); + localJarFile.delete(); + + // If installation succeeded, write a timestamp for all of the + // files to be checked next time + try { + File timestampFile = new File(installDir, "timestamp"); + timestampFile.delete(); + BufferedWriter writer = new BufferedWriter(new FileWriter(timestampFile)); + writer.write("" + urlConnection.getLastModified()); + writer.flush(); + writer.close(); + } catch (Exception e) { + displayError("Error writing time stamp for native libraries"); + return; + } + + } catch (Exception e) { + displayError("Error opening jar file " + localJarFile.getName() + " for reading"); + return; + } } } loadNativesAndStart(installDir); } - private long getTimestamp(File installDir, long timestamp) { + private long getTimestamp(File installDir, String nativeJarName, long timestamp) { // Avoid returning valid value if timestamp file doesn't exist try { - BufferedReader reader = new BufferedReader(new FileReader(new File(installDir, "timestamp"))); + String timestampName = "timestamp-" + nativeJarName.replace('.', '-'); + BufferedReader reader = new BufferedReader(new FileReader(new File(installDir, timestampName))); try { StreamTokenizer tokenizer = new StreamTokenizer(reader); // Avoid screwing up by not being able to read full longs @@ -497,7 +518,7 @@ public class JOGLAppletLauncher extends Applet { BufferedOutputStream out = null;; InputStream in = null; displayMessage("Downloading native library"); - progressBar.setValue(0); + setProgress(0); try { out = new BufferedOutputStream(new FileOutputStream(localJarFile)); @@ -510,7 +531,7 @@ public class JOGLAppletLauncher extends Applet { out.write(buffer, 0, len); sum += len; int percent = (100 * sum / totalLength); - progressBar.setValue(percent); + setProgress(percent); } out.close(); in.close(); @@ -538,9 +559,6 @@ public class JOGLAppletLauncher extends Applet { JarEntry entry = (JarEntry) e.nextElement(); if (nativeLibInfo.matchesNativeLib(entry.getName())) { list.add(entry.getName()); - if (entry.getName().indexOf("jogl_drihack") >= 0) { - driHackPresent = true; - } } } if (list.isEmpty()) { @@ -632,13 +650,21 @@ public class JOGLAppletLauncher extends Applet { public void run() { displayMessage("Loading native libraries"); - // disable JOGL loading from elsewhere + // disable JOGL and GlueGen runtime library loading from elsewhere com.sun.opengl.impl.NativeLibLoader.disableLoading(); + com.sun.gluegen.runtime.NativeLibLoader.disableLoading(); + + // Open GlueGen runtime library optimistically. Note that + // currently we do not need this on any platform except X11 + // ones, because JOGL doesn't use the GlueGen NativeLibrary + // class anywhere except the DRIHack class, but if for + // example we add JOAL support then we will need this on + // every platform. + loadLibrary(nativeLibDir, "gluegen-rt"); Class driHackClass = null; - if (driHackPresent) { - // Load DRI hack library and run the DRI hack itself - loadLibrary(nativeLibDir, "jogl_drihack"); + if (nativeLibInfo.mayNeedDRIHack()) { + // Run the DRI hack try { driHackClass = Class.forName("com.sun.opengl.impl.x11.DRIHack"); driHackClass.getMethod("begin", new Class[] {}).invoke(null, new Object[] {}); @@ -650,7 +676,7 @@ public class JOGLAppletLauncher extends Applet { // Load core JOGL native library loadLibrary(nativeLibDir, "jogl"); - if (driHackPresent) { + if (nativeLibInfo.mayNeedDRIHack()) { // End DRI hack try { driHackClass.getMethod("end", new Class[] {}).invoke(null, new Object[] {}); |