diff options
Diffstat (limited to 'src/classes/com/sun/opengl/util/JOGLAppletLauncher.java')
-rwxr-xr-x | src/classes/com/sun/opengl/util/JOGLAppletLauncher.java | 1080 |
1 files changed, 0 insertions, 1080 deletions
diff --git a/src/classes/com/sun/opengl/util/JOGLAppletLauncher.java b/src/classes/com/sun/opengl/util/JOGLAppletLauncher.java deleted file mode 100755 index c82aaf9c6..000000000 --- a/src/classes/com/sun/opengl/util/JOGLAppletLauncher.java +++ /dev/null @@ -1,1080 +0,0 @@ -/* This java class is distributed under the BSD license. - * - * Copyright 2005 Lilian Chamontin. - * contact lilian.chamontin at f r e e . f r - */ - -/* - * Portions Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - */ - -package com.sun.opengl.util; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Graphics; -import java.awt.Label; -import java.awt.Panel; -import java.applet.Applet; -import java.applet.AppletStub; -import java.applet.AppletContext; -import java.io.*; -import java.net.*; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.*; -import java.text.*; -import java.util.*; -import java.util.jar.*; -import javax.swing.*; - -import javax.media.opengl.*; - - -/** This class enables deployment of high-end applets which use OpenGL - * for 3D graphics via JOGL and (optionally) OpenAL for spatialized - * audio via JOAL. The applet being deployed may be either signed or - * unsigned; if it is unsigned, it runs inside the security sandbox, - * and if it is signed, the user receives a security dialog to accept - * the certificate for the applet as well as for JOGL and JOAL. <P> - * - * The steps for deploying such applets are straightforward. First, - * the "archive" parameter to the applet tag must contain jogl.jar - * and gluegen-rt.jar, as well as any jar files associated with your - * applet (in this case, "your_applet.jar"). <P> - * - * Second, the codebase directory on the server, which contains the - * applet's jar files, must also contain jogl.jar, gluegen-rt.jar, - * and all of the jogl-natives-*.jar and gluegen-rt-natives-*.jar - * files from the standard JOGL and GlueGen runtime distributions - * (provided in jogl-[version]-webstart.zip from the <a - * href="http://jogl.dev.java.net/servlets/ProjectDocumentList">JOGL - * release builds</a> and gluegen-rt-[version]-webstart.zip from the - * <a - * href="http://gluegen.dev.java.net/servlets/ProjectDocumentList">GlueGen - * runtime release builds</a>). Note that the codebase of the applet - * is currently the location from which the JOGL native library used - * by the applet is downloaded. All of the JOGL and GlueGen-related - * jars must be signed by the same entity, which is typically Sun - * Microsystems, Inc. <P> - * - * To deploy an applet using both JOGL and JOAL, simply add joal.jar - * to the list of jars in the archive tag of the applet, and put - * joal.jar and the joal-natives-*.jar signed jars into the same - * codebase directory on the web server. These signed jars are - * supplied in the joal-[version]-webstart.zip archive from the <a - * href="http://joal.dev.java.net/servlets/ProjectDocumentList">JOAL - * release builds</a>. <P> - * - * Sample applet code: - * <pre> - * <applet code="com.sun.opengl.util.JOGLAppletLauncher" - * width=600 - * height=400 - * codebase="/lib" - * 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,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> - * - * There are some limitations with this approach. It is not possible - * to specify e.g. -Dsun.java2d.noddraw=true or - * -Dsun.java2d.opengl=true for better control over the Java2D - * pipeline as it is with Java Web Start. However, the - * JOGLAppletLauncher tries to force the use of - * -Dsun.java2d.noddraw=true on Windows platforms for best robustness - * by detecting if it has not been set and asking the user whether it - * can update the Java Plug-In configuration automatically. If the - * user agrees to this, a browser restart is required in order for the - * change to take effect, though it is permanent for subsequent - * browser restarts. <P> - * - * The behavior of the noddraw-related dialog box can be changed via - * two applet parameters. The <CODE>jogl.silent.noddraw.check</CODE> - * parameter, if set to <CODE>"true"</CODE>, silences the two dialog - * boxes associated with this check, forcing it to always be performed - * and deployment.properties to be silently updated if necessary - * (unless the user previously saw such a dialog box and dismissed it - * by saying "No, Don't Ask Again"). The noddraw check can be disabled - * completely by setting the <CODE>jogl.disable.noddraw.check</CODE> - * applet parameter to <CODE>"true"</CODE>. <P> - * - * The JOGL (and optionally JOAL) natives are cached in the user's - * home directory (the value of the "user.home" system property in - * Java) under the directory .jogl_ext. The Java Plug-In is - * responsible for performing all other jar caching. If the JOGL - * installation is updated on the server, the .jogl_ext cache will - * automatically be updated. <p> - * - * This technique requires that JOGL has not been installed in to the - * JRE under e.g. jre/lib/ext. If problems are seen when deploying - * 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, Firefox and Internet Explorer; there may - * be problems when running under, for example, Opera. <p> - * - * It has been discovered that the Talkback agent in Mozilla / Firefox - * has bad interactions with OpenGL applets. For highest performance, - * we recommend disabling the Talkback agent; find talkback.exe, run - * it, and follow the directions for turning it off. Please see - * <a href="http://www.javagaming.org/forums/index.php?topic=12200.30">this - * thread</a> on the javagaming.org forums and - * <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=326381">this - * thread</a> on the Mozilla bug reporting database. <p> - * - * @author Lilian Chamontin - * @author Kenneth Russell - */ -public class JOGLAppletLauncher extends Applet { - static { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (Exception ignore) { - } - } - - // metadata for native libraries - private static class NativeLibInfo { - private String osName; - private String osArch; - private String osNameAndArchPair; - private String nativePrefix; - private String nativeSuffix; - - public NativeLibInfo(String osName, String osArch, String osNameAndArchPair, String nativePrefix, String nativeSuffix) { - this.osName = osName; - this.osArch = osArch; - this.osNameAndArchPair = osNameAndArchPair; - this.nativePrefix = nativePrefix; - this.nativeSuffix = nativeSuffix; - } - - public boolean matchesOSAndArch(String osName, String osArch) { - if (osName.toLowerCase().startsWith(this.osName)) { - if ((this.osArch == null) || - (osArch.toLowerCase().equals(this.osArch))) { - return true; - } - } - return false; - } - - public boolean matchesNativeLib(String fileName) { - if (fileName.toLowerCase().endsWith(nativeSuffix)) { - return true; - } - return false; - } - - public String formatNativeJarName(String nativeJarPattern) { - return MessageFormat.format(nativeJarPattern, new Object[] { osNameAndArchPair }); - } - - public String getNativeLibName(String baseName) { - return nativePrefix + baseName + nativeSuffix; - } - - public boolean isMacOS() { - return (osName.equals("mac")); - } - - public boolean mayNeedDRIHack() { - return (!isMacOS() && !osName.equals("win")); - } - } - - private static final NativeLibInfo[] allNativeLibInfo = { - new NativeLibInfo("win", "x86", "windows-i586", "", ".dll"), - new NativeLibInfo("win", "amd64", "windows-amd64", "", ".dll"), - new NativeLibInfo("win", "x86_64","windows-amd64", "", ".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("linux", "amd64", "linux-amd64", "lib", ".so"), - new NativeLibInfo("linux", "x86_64","linux-amd64", "lib", ".so"), - new NativeLibInfo("sunos", "sparc", "solaris-sparc", "lib", ".so"), - new NativeLibInfo("sunos", "sparcv9","solaris-sparcv9", "lib", ".so"), - new NativeLibInfo("sunos", "x86", "solaris-i586", "lib", ".so"), - new NativeLibInfo("sunos", "amd64", "solaris-amd64", "lib", ".so"), - new NativeLibInfo("sunos", "x86_64","solaris-amd64", "lib", ".so") - }; - - private NativeLibInfo nativeLibInfo; - // Library names computed once the jar comes down. - // The signatures of these native libraries are checked before - // installing them. - private String[] nativeLibNames; - - /** The applet we have to start */ - private Applet subApplet; - - private String subAppletClassName; // from applet PARAM - private String subAppletDisplayName; // from applet PARAM - /** URL string to an image used while installing */ - private String subAppletImageName; // from applet PARAM - - private String installDirectory; // (defines a private directory for native libs) - - private JPanel loaderPanel = new JPanel(new BorderLayout()); - - private JProgressBar progressBar = new JProgressBar(0,100); - - private boolean isInitOk = false; - - /** false once start() has been invoked */ - private boolean firstStart = true; - - /** true if start() has passed successfully */ - private boolean joglStarted = false; - - /** Indicates whether JOAL is present */ - private boolean haveJOAL = false; - - // Helpers for question about whether to update deployment.properties - private static final String JRE_PREFIX = "deployment.javapi.jre."; - private static final String NODDRAW_PROP = "-Dsun.java2d.noddraw=true"; - private static final String DONT_ASK = ".dont_ask"; - - public JOGLAppletLauncher() { - } - - private static String md2Hash(String str) { - // Helps hash the jars in the "archive" tag into a hex value to - // avoid having too-long path names in the install directory's - // path name but also to have unique directories for each - // different archive set used (also meaning for each class loader - // loading something via the JOGLAppletLauncher) -- note that this - // is somewhat dependent on the Sun implementation of applets and - // their class loaders - MessageDigest md2 = null; - try { - md2 = MessageDigest.getInstance("MD2"); - } catch (NoSuchAlgorithmException e) { - return ""; - } - byte[] digest = md2.digest(str.getBytes()); - if (digest == null || (digest.length == 0)) - return ""; - StringBuffer res = new StringBuffer(); - for (int i = 0; i < digest.length; i++) { - res.append(Integer.toHexString(digest[i] & 0xFF)); - } - return res.toString(); - } - - /** Applet initialization */ - public void init() { - - this.subAppletClassName = getParameter("subapplet.classname"); - if (subAppletClassName == null){ - displayError("Init failed : Missing subapplet.classname argument"); - return; - } - this.subAppletDisplayName = getParameter("subapplet.displayname"); - if (subAppletDisplayName == null){ - subAppletDisplayName = "Applet"; - } - - this.subAppletImageName = getParameter("subapplet.image"); - - initLoaderLayout(); - validate(); - - String extForm = getCodeBase().toExternalForm(); - String codeBase = extForm.substring(extForm.indexOf(":") + 3); // minus http:// or https:// - - this.installDirectory = codeBase.replace(':', '_') - .replace('.', '_').replace('/', '_').replace('~','_') // clean up the name - + md2Hash(getParameter("archive")); // make it unique across different applet class loaders - - String osName = System.getProperty("os.name"); - String osArch = System.getProperty("os.arch"); - if (checkOSAndArch(osName, osArch)) { - this.isInitOk = true; - } else { - displayError("Init failed : Unsupported os / arch ( " + osName + " / " + osArch + " )"); - } - } - - 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 setProgress(final int value) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - progressBar.setValue(value); - } - }); - } - - private void initLoaderLayout(){ - setLayout(new BorderLayout()); - progressBar.setBorderPainted(true); - progressBar.setStringPainted(true); - progressBar.setString("Loading..."); - boolean includeImage = false; - ImageIcon image = null; - if (subAppletImageName != null){ - try { - image = new ImageIcon(new URL(subAppletImageName)); - includeImage = true; - } catch (MalformedURLException ex) { - ex.printStackTrace(); - // not blocking - } - } - if (includeImage){ - add(loaderPanel, BorderLayout.SOUTH); - loaderPanel.add(new JLabel(image), BorderLayout.CENTER); - loaderPanel.add(progressBar, BorderLayout.SOUTH); - } else { - add(loaderPanel, BorderLayout.SOUTH); - loaderPanel.add(progressBar, BorderLayout.CENTER); - } - } - - - /** start asynchroneous loading of libraries if needed */ - public void start(){ - if (isInitOk){ - if (firstStart) { - firstStart = false; - String userHome = System.getProperty("user.home"); - - try { - // We need to load in the jogl package so that we can query the version information - ClassLoader classloader = getClass().getClassLoader(); - classloader.loadClass("javax.media.opengl.GL"); - Package p = Package.getPackage("javax.media.opengl"); - - String installDirName = userHome + File.separator + ".jogl_ext" - + File.separator + installDirectory + File.separator + p.getImplementationVersion().replace(':', '_'); - - final File installDir = new File(installDirName); - - Thread refresher = new Thread() { - public void run() { - refreshJOGL(installDir); - } - }; - refresher.setPriority(Thread.NORM_PRIORITY - 1); - refresher.start(); - } - catch (ClassNotFoundException e) { - System.err.println("Unable to load javax.media.opengl package"); - System.exit(0); - } - - } else if (joglStarted) { - checkNoDDrawAndUpdateDeploymentProperties(); - // we have to start again the applet (start can be called multiple times, - // e.g once per tabbed browsing - subApplet.start(); - } - } - } - - public void stop(){ - if (subApplet != null){ - subApplet.stop(); - } - } - - public void destroy(){ - if (subApplet != null){ - subApplet.destroy(); - } - } - - - /** Helper method to make it easier to call methods on the - sub-applet from JavaScript. */ - public Applet getSubApplet() { - return subApplet; - } - - private boolean checkOSAndArch(String osName, String osArch) { - for (int i = 0; i < allNativeLibInfo.length; i++) { - NativeLibInfo info = allNativeLibInfo[i]; - if (info.matchesOSAndArch(osName, osArch)) { - nativeLibInfo = info; - return true; - } - } - return false; - } - - // Get a "boolean" parameter, assuming that anything non-null aside - // from "false" is true - private boolean getBooleanParameter(String parameterName) { - String val = getParameter(parameterName); - if (val == null) - return false; - return !val.toLowerCase().equals("false"); - } - - private void checkNoDDrawAndUpdateDeploymentProperties() { - if (getBooleanParameter("jogl.disable.noddraw.check")) - return; - if (System.getProperty("os.name").toLowerCase().startsWith("windows") && - !"true".equalsIgnoreCase(System.getProperty("sun.java2d.noddraw"))) { - if (!SwingUtilities.isEventDispatchThread()) { - try { - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - updateDeploymentPropertiesImpl(); - } - }); - } catch (Exception e) { - } - } else { - updateDeploymentPropertiesImpl(); - } - } - } - - private void updateDeploymentPropertiesImpl() { - String userHome = System.getProperty("user.home"); - File dontAskFile = new File(userHome + File.separator + ".jogl_ext" + - File.separator + DONT_ASK); - if (dontAskFile.exists()) - return; // User asked us not to prompt again - - int option = 0; - - if (!getBooleanParameter("jogl.silent.noddraw.check")) { - option = JOptionPane.showOptionDialog(null, - "For best robustness of JOGL applets on Windows,\n" + - "we recommend disabling Java2D's use of DirectDraw.\n" + - "This setting will affect all applets, but is unlikely\n" + - "to slow other applets down significantly. May we update\n" + - "your deployment.properties to turn off DirectDraw for\n" + - "applets? You can change this back later if necessary\n" + - "using the Java Control Panel, Java tab, under Java\n" + - "Applet Runtime Settings.", - "Update deployment.properties?", - JOptionPane.YES_NO_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE, - null, - new Object[] { - "Yes", - "No", - "No, Don't Ask Again" - }, - "Yes"); - } - - if (option < 0 || - option == 1) - return; // No - - if (option == 2) { - try { - dontAskFile.createNewFile(); - } catch (IOException e) { - } - return; // No, Don't Ask Again - } - - try { - // Must update deployment.properties - File propsDir = new File(System.getProperty("user.home") + File.separator + - "Application Data/Sun/Java/Deployment"); - if (!propsDir.exists()) - // Don't know what's going on or how to set this permanently - return; - - File propsFile = new File(propsDir, "deployment.properties"); - if (!propsFile.exists()) - // Don't know what's going on or how to set this permanently - return; - - Properties props = new Properties(); - InputStream input = new BufferedInputStream(new FileInputStream(propsFile)); - props.load(input); - input.close(); - // Search through the keys looking for JRE versions - Set/*<String>*/ jreVersions = new HashSet/*<String>*/(); - for (Iterator/*<String>*/ iter = props.keySet().iterator(); iter.hasNext(); ) { - String key = (String) iter.next(); - if (key.startsWith(JRE_PREFIX)) { - int idx = key.lastIndexOf("."); - if (idx >= 0 && idx > JRE_PREFIX.length()) { - String jreVersion = key.substring(JRE_PREFIX.length(), idx); - jreVersions.add(jreVersion); - } - } - } - - // Make sure the currently-running JRE shows up in this set to - // avoid repeated displays of the dialog. It might not in some - // upgrade scenarios where there was a pre-existing - // deployment.properties and the new Java Control Panel hasn't - // been run yet. - jreVersions.add(System.getProperty("java.version")); - - // OK, now that we know all JRE versions covered by the - // deployment.properties, check out the args for each and update - // them - for (Iterator/*<String>*/ iter = jreVersions.iterator(); iter.hasNext(); ) { - String version = (String) iter.next(); - String argKey = JRE_PREFIX + version + ".args"; - String argVal = props.getProperty(argKey); - if (argVal == null) { - argVal = NODDRAW_PROP; - } else if (argVal.indexOf(NODDRAW_PROP) < 0) { - argVal = argVal + " " + NODDRAW_PROP; - } - props.setProperty(argKey, argVal); - } - - OutputStream output = new BufferedOutputStream(new FileOutputStream(propsFile)); - props.store(output, null); - output.close(); - - if (!getBooleanParameter("jogl.silent.noddraw.check")) { - // Tell user we're done - JOptionPane.showMessageDialog(null, - "For best robustness, we recommend you now exit and\n" + - "restart your web browser. (Note: clicking \"OK\" will\n" + - "not exit your browser.)", - "Browser Restart Recommended", - JOptionPane.INFORMATION_MESSAGE); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** This method is executed from outside the Event Dispatch Thread, and installs - * the required native libraries in the local folder. - */ - private void refreshJOGL(final File installDir) { - try { - Class subAppletClass = Class.forName(subAppletClassName); - // this will block until the applet jar is downloaded - } catch (ClassNotFoundException cnfe){ - displayError("Start failed : class not found : " + subAppletClassName); - return; - } - - if (!installDir.exists()){ - if (!installDir.mkdirs()) { - displayError("Unable to create directories for target: " + installDir); - return; - } - } - - // See whether JOAL is present - try { - Class alClass = Class.forName("net.java.games.joal.AL", false, this.getClass().getClassLoader()); - haveJOAL = true; - // Note: it seems that some JRE implementations can throw - // SecurityException as well as ClassNotFoundException, at least - // if the OpenAL classes are not present and the web server - // redirects elsewhere - } catch (Exception e) { - } - - String[] nativeJarNames = new String[] { - nativeLibInfo.formatNativeJarName("jogl-natives-{0}.jar"), - nativeLibInfo.formatNativeJarName("gluegen-rt-natives-{0}.jar"), - (haveJOAL ? nativeLibInfo.formatNativeJarName("joal-natives-{0}.jar") : null) - }; - - for (int n = 0; n < nativeJarNames.length; n++) { - String nativeJarName = nativeJarNames[n]; - - if (nativeJarName == null) - continue; - - 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; - } - - // 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, getTimestampFileName(nativeJarName)); - 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 String getTimestampFileName(String nativeJarName) { - return "timestamp-" + nativeJarName.replace('.', '-'); - } - - private long getTimestamp(File installDir, String nativeJarName, long timestamp) { - // Avoid returning valid value if timestamp file doesn't exist - try { - String timestampName = getTimestampFileName(nativeJarName); - 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 - tokenizer.resetSyntax(); - tokenizer.wordChars('0', '9'); - tokenizer.wordChars('-', '-'); - tokenizer.nextToken(); - String tok = tokenizer.sval; - if (tok != null) { - return Long.parseLong(tok); - } - } catch (Exception e) { - } finally { - reader.close(); - } - } catch (Exception e) { - } - return ((timestamp == 0) ? 1 : 0); - } - - private void saveNativesJarLocally(File localJarFile, - URLConnection urlConnection) throws IOException { - BufferedOutputStream out = null;; - InputStream in = null; - displayMessage("Downloading native library"); - setProgress(0); - try { - out = new BufferedOutputStream(new - FileOutputStream(localJarFile)); - int totalLength = urlConnection.getContentLength(); - in = urlConnection.getInputStream(); - byte[] buffer = new byte[1024]; - int len; - int sum = 0; - while ( (len = in.read(buffer)) > 0) { - out.write(buffer, 0, len); - sum += len; - int percent = (100 * sum / totalLength); - setProgress(percent); - } - out.close(); - in.close(); - } finally { - // close the files - if (out != null) { - try { - out.close(); - } catch (IOException ignore) { - } - } - if (in != null) { - try { - in.close(); - } catch (IOException ignore) { - } - } - } - } - - private boolean findNativeEntries(JarFile jf) { - List list = new ArrayList(); - Enumeration e = jf.entries(); - while (e.hasMoreElements()) { - JarEntry entry = (JarEntry) e.nextElement(); - if (nativeLibInfo.matchesNativeLib(entry.getName())) { - list.add(entry.getName()); - } - } - if (list.isEmpty()) { - return false; - } - nativeLibNames = (String[]) list.toArray(new String[0]); - return true; - } - - /** checking the native certificates with the jogl ones (all must match)*/ - private boolean checkNativeCertificates(JarFile jar, JarEntry entry, byte[] buf){ - // API states that we must read all of the data from the entry's - // InputStream in order to be able to get its certificates - try { - InputStream is = jar.getInputStream(entry); - int totalLength = (int) entry.getSize(); - int len; - while ((len = is.read(buf)) > 0) { - } - is.close(); - Certificate[] nativeCerts = entry.getCertificates(); - // locate the JOGL certificates - Certificate[] joglCerts = GLDrawableFactory.class.getProtectionDomain(). - getCodeSource().getCertificates(); - - if (nativeCerts == null || nativeCerts.length == 0) { - return false; - } - int checked = 0; - for (int i = 0; i < joglCerts.length; i++) { - for (int j = 0; j < nativeCerts.length; j++) { - if (nativeCerts[j].equals(joglCerts[i])){ - checked++; - break; - } - } - } - return (checked == joglCerts.length); - } catch (Exception e) { - return false; - } - } - - private boolean installFile(File installDir, - JarFile jar, - String fileName, - byte[] buf) { - try { - JarEntry entry = jar.getJarEntry(fileName); - if (entry == null) { - displayError("Error finding native library " + fileName); - return false; - } - InputStream is = jar.getInputStream(entry); - int totalLength = (int) entry.getSize(); - BufferedOutputStream out = null; - File outputFile = new File(installDir, fileName); - boolean exists = false; - try { - exists = outputFile.exists(); - out = new BufferedOutputStream(new FileOutputStream(outputFile)); - } catch (Exception e) { - if (exists) { - // It's possible the files were updated on the web server - // but we still have them loaded in this process; skip this - // update - return true; - } else { - displayError("Error opening file " + fileName + " for writing"); - return false; - } - } - int len; - try { - while ( (len = is.read(buf)) > 0) { - out.write(buf, 0, len); - } - } catch (IOException ioe) { - displayError("Error writing file " + fileName + " to disk"); - ioe.printStackTrace(); - outputFile.delete(); - return false; - } - out.flush(); - out.close(); - is.close(); - return true; - } catch (Exception e2) { - e2.printStackTrace(); - displayError("Error writing file " + fileName + " to disk"); - return false; - } - } - - /** last step before launch : System.load() the natives and init()/start() the child applet */ - private void loadNativesAndStart(final File nativeLibDir) { - // back to the EDT - SwingUtilities.invokeLater(new Runnable() { - public void run() { - displayMessage("Loading native libraries"); - - // 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 (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[] {}); - } catch (Exception e) { - e.printStackTrace(); - } - } - - // Load core JOGL native library - loadLibrary(nativeLibDir, "jogl"); - - if (nativeLibInfo.mayNeedDRIHack()) { - // End DRI hack - try { - driHackClass.getMethod("end", new Class[] {}).invoke(null, new Object[] {}); - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (!nativeLibInfo.isMacOS()) { // borrowed from NativeLibLoader - // Must pre-load JAWT on all non-Mac platforms to - // ensure references from jogl_awt shared object - // will succeed since JAWT shared object isn't in - // default library path - try { - System.loadLibrary("jawt"); - } catch (UnsatisfiedLinkError ex) { - // Accessibility technologies load JAWT themselves; safe to continue - // as long as JAWT is loaded by any loader - if (ex.getMessage().indexOf("already loaded") == -1) { - displayError("Unable to load JAWT"); - throw ex; - } - } - } - - // Load AWT-specific native code - loadLibrary(nativeLibDir, "jogl_awt"); - - if (haveJOAL) { - // Turn off the System.loadLibrary call of the joal_native - // library. It will still need to load the OpenAL library - // internally via another mechanism. - try { - Class c = Class.forName("net.java.games.joal.impl.NativeLibLoader"); - c.getMethod("disableLoading", new Class[] {}).invoke(null, new Object[] {}); - } catch (Exception e) { - e.printStackTrace(); - } - - // Append the installed native library directory to - // java.library.path. This is the most convenient way to - // make this directory available to the NativeLibrary code, - // which needs it for loading OpenAL if present. - String javaLibPath = System.getProperty("java.library.path"); - String absPath = nativeLibDir.getAbsolutePath(); - boolean shouldSet = false; - if (javaLibPath == null) { - javaLibPath = absPath; - shouldSet = true; - } else if (javaLibPath.indexOf(absPath) < 0) { - javaLibPath = javaLibPath + File.pathSeparator + absPath; - shouldSet = true; - } - if (shouldSet) { - System.setProperty("java.library.path", javaLibPath); - } - - // Load core JOAL native library - loadLibrary(nativeLibDir, "joal_native"); - } - - displayMessage("Starting applet " + subAppletDisplayName); - - // start the subapplet - startSubApplet(); - } - }); - } - - private void loadLibrary(File installDir, String libName) { - String nativeLibName = nativeLibInfo.getNativeLibName(libName); - try { - System.load(new File(installDir, nativeLibName).getPath()); - } catch (UnsatisfiedLinkError ex) { - // Note: if we have loaded this particular copy of the - // JOGL-related native library in another class loader, the - // steps taken above to ensure the installation directory name - // was unique have failed. We can't continue properly in this - // case, so just print and re-throw the exception. - ex.printStackTrace(); - throw ex; - } - } - - /** The true start of the sub applet (invoked in the EDT) */ - private void startSubApplet(){ - try { - subApplet = (Applet)Class.forName(subAppletClassName).newInstance(); - subApplet.setStub(new AppletStubProxy()); - } catch (ClassNotFoundException cnfe) { - cnfe.printStackTrace(); - displayError("Class not found (" + subAppletClassName + ")"); - return; - } catch (Exception ex) { - ex.printStackTrace(); - displayError("Unable to start " + subAppletDisplayName); - return; - } - - add(subApplet, BorderLayout.CENTER); - - try { - subApplet.init(); - remove(loaderPanel); - validate(); - checkNoDDrawAndUpdateDeploymentProperties(); - subApplet.start(); - joglStarted = true; - } catch (Exception ex){ - ex.printStackTrace(); - } - - } - - /** a proxy to allow the subApplet to work like a real applet */ - class AppletStubProxy implements AppletStub { - public boolean isActive() { - return JOGLAppletLauncher.this.isActive(); - } - - public URL getDocumentBase() { - return JOGLAppletLauncher.this.getDocumentBase(); - } - - public URL getCodeBase() { - return JOGLAppletLauncher.this.getCodeBase(); - } - - public String getParameter(String name) { - return JOGLAppletLauncher.this.getParameter(name); - } - - public AppletContext getAppletContext() { - return JOGLAppletLauncher.this.getAppletContext(); - } - - public void appletResize(int width, int height) { - JOGLAppletLauncher.this.resize(width, height); - } - } -} - |