|
From: <ma...@us...> - 2007-06-10 20:30:06
|
Revision: 2848
http://svn.sourceforge.net/java-game-lib/?rev=2848&view=rev
Author: matzon
Date: 2007-06-10 13:30:03 -0700 (Sun, 10 Jun 2007)
Log Message:
-----------
initial checking on AppletLoader
Added Paths:
-----------
trunk/LWJGL/res/appletlogo.png
trunk/LWJGL/res/appletprogress.gif
trunk/LWJGL/src/java/org/lwjgl/test/applet/AppletLoaderTest.java
trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
Added: trunk/LWJGL/res/appletlogo.png
===================================================================
(Binary files differ)
Property changes on: trunk/LWJGL/res/appletlogo.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/LWJGL/res/appletprogress.gif
===================================================================
(Binary files differ)
Property changes on: trunk/LWJGL/res/appletprogress.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/LWJGL/src/java/org/lwjgl/test/applet/AppletLoaderTest.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/test/applet/AppletLoaderTest.java (rev 0)
+++ trunk/LWJGL/src/java/org/lwjgl/test/applet/AppletLoaderTest.java 2007-06-10 20:30:03 UTC (rev 2848)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2006 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions 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 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.test.applet;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Canvas;
+
+import org.lwjgl.opengl.AWTInputAdapter;
+
+public class AppletLoaderTest extends Applet {
+
+ Test test = null;
+
+ public void destroy() {
+ super.destroy();
+ System.out.println("*** destroy ***");
+ AWTInputAdapter.destroy();
+ }
+
+ public void start() {
+ super.start();
+ System.out.println("*** start ***");
+ }
+
+ public void stop() {
+ super.stop();
+ System.out.println("*** stop ***");
+ test.stop();
+ }
+
+ public void init() {
+ System.out.println("*** init ***");
+
+ setLayout(new BorderLayout());
+ try {
+ test = (Test) Class.forName(getParameter("test")).newInstance();
+ Canvas canvas = (Canvas) test;
+ canvas.setSize(getWidth(), getHeight());
+ add(canvas);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ test.start();
+ }
+}
Added: trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java (rev 0)
+++ trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2007-06-10 20:30:03 UTC (rev 2848)
@@ -0,0 +1,907 @@
+/*
+ * Copyright (c) 2002-2007 LWJGL Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions 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 'LWJGL' nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.lwjgl.util.applet;
+
+import java.applet.Applet;
+import java.applet.AppletStub;
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLConnection;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.security.cert.Certificate;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * <p>
+ * The AppletLoader enables deployment of LWJGL to applets in an easy
+ * and polished way. The loader will display a configurable logo and progressbar
+ * while the relevant jars (generic and native) are downloaded from a specified source.
+ * </p>
+ * <p>
+ * The downloaded are extracted to the users temporary directory - and if enabled, cached for
+ * faster loading in future uses.
+ * </p>
+ * <p>
+ * The following applet parameters are required:
+ * <ul>
+ * <li>al_main - [String] Full package and class the applet to instantiate and display when loaded.</li>
+ * <li>al_logo - [String Path of of the logo resource to paint while loading.</li>
+ * <li>al_progressbar - [String] Path of the progressbar resource to paint on top of the logo, width clipped by percentage.</li>
+ * <li>al_jars - [String] Comma seperated list of jars to download.</li>
+ * <li>al_windows - [String] Jar containing native files for windows.</li>
+ * <li>al_linux - [String] Jar containing native files for linux.</li>
+ * <li>al_mac - [String] Jar containing native files for mac.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Additionally the following parameters can be supplied to tweak the behaviour of the AppletLoader.
+ * <ul>
+ * <li>al_version - [int or float] Version of deployment. If this is specified, the jars will be cached and
+ * reused if the version matches. If version doesn't match all of the files are reloaded.</li>
+ * <li>al_bgcolor - [String] Hex formated color to use as background. <i>Default: ffffff</i>.</li>
+ * <li>al_fgcolor - [String] Hex formated color to use as foreground. <i>Default: 000000</i>.</li>
+ * <li>al_errorcolor - [String] Hex formated color to use as foreground color on error. <i>Default: ff0000</i>.</li>
+ * <li>al_debug - [boolean] Whether to enable debug mode. <i>Default: false</i>.</li>
+ * </ul>
+ * </p>
+ * @author kappaOne
+ * @author Brian Matzon <br...@ma...>
+ * @version $Revision$
+ * $Id$
+ */
+public class AppletLoader extends Applet implements Runnable, AppletStub {
+ /** initializing */
+ public static final int STATE_INIT = 1;
+
+ /** determining which packages that are required */
+ public static final int STATE_DETERMINING_PACKAGES = 2;
+
+ /** checking for already downloaded files */
+ public static final int STATE_CHECKING_CACHE = 3;
+
+ /** downloading packages */
+ public static final int STATE_DOWNLOADING = 4;
+
+ /** extracting packages */
+ public static final int STATE_EXTRACTING_PACKAGES = 5;
+
+ /** updating the classpath */
+ public static final int STATE_UPDATING_CLASSPATH = 6;
+
+ /** switching to real applet */
+ public static final int STATE_SWITCHING_APPLET = 7;
+
+ /** initializing real applet */
+ public static final int STATE_INITIALIZE_REAL_APPLET = 8;
+
+ /** stating real applet */
+ public static final int STATE_START_REAL_APPLET = 9;
+
+ /** done */
+ public static final int STATE_DONE = 10;
+
+ /** used to calculate length of progress bar */
+ protected int percentage;
+
+ /** current size of download in bytes */
+ protected int currentSizeDownload;
+
+ /** total size of download in bytes */
+ protected int totalSizeDownload;
+
+ /** current size of extracted in bytes */
+ protected int currentSizeExtract;
+
+ /** total size of extracted in bytes */
+ protected int totalSizeExtract;
+
+ /** logo to be shown while loading */
+ protected Image logo;
+
+ /** progressbar to render while loading */
+ protected Image progressbar;
+
+ /** offscreen image used */
+ protected Image offscreen;
+
+ /** background color of applet */
+ protected Color bgColor = Color.white;
+
+ /** Color to write errors in */
+ protected Color errorColor = Color.red;
+
+ /** color to write forground in */
+ protected Color fgColor = Color.black;
+
+ /** urls of the jars to download */
+ protected URL[] urlList;
+
+ /** list of jars to download */
+ protected String jarList;
+
+ /** actual thread that does the loading */
+ protected Thread loaderThread;
+
+ /** animation thread that renders our loaderscreen while loading */
+ protected Thread animationThread;
+
+ /** applet to load after all downloads are complete */
+ protected Applet lwjglApplet;
+
+ /** whether a fatal error occured */
+ protected boolean fatalError;
+
+ /** fatal error that occured */
+ protected String fatalErrorDescription;
+
+ /** whether we're running in debug mode */
+ protected boolean debugMode;
+
+ /** String to display as a subtask */
+ protected String subtaskMessage = "";
+
+ /** state of applet loader */
+ protected int state = STATE_INIT;
+
+ /** generic error message to display on error */
+ protected String[] genericErrorMessage = { "An error occured while loading the applet.",
+ "Plese contact support to resolve this issue.",
+ "<placeholder for error message>"};
+
+ /*
+ * @see java.applet.Applet#init()
+ */
+ public void init() {
+
+ // sanity check
+ String[] requiredArgs = {"al_main", "al_logo", "al_progressbar", "al_jars"};
+ for(int i=0; i<requiredArgs.length; i++) {
+ if(getParameter(requiredArgs[i]) == null) {
+ fatalErrorOccured("missing required applet parameter: " + requiredArgs[i]);
+ return;
+ }
+ }
+
+ // whether to run in debug mode
+ debugMode = getBooleanParameter("al_debug", false);
+
+ // get colors of applet
+ bgColor = getColor("al_bgcolor", Color.white);
+ fgColor = getColor("al_fgcolor", Color.black);
+ errorColor = getColor("al_errorcolor", Color.red);
+
+ // load logos
+ logo = getImage("/" + getParameter("al_logo"));
+ progressbar = getImage("/" + getParameter("al_progressbar"));
+
+ // jars to load
+ jarList = getParameter("al_jars");
+
+ //sanity check
+ if(logo == null || progressbar == null) {
+ fatalErrorOccured("Unable to load logo and progressbar images");
+ return;
+ }
+
+ // parse the urls for the jars into the url list
+ loadJarURLs();
+ }
+
+ /*
+ * @see java.applet.Applet#start()
+ */
+ public void start() {
+ if(loaderThread == null && !fatalError) {
+ loaderThread = new Thread(this);
+ loaderThread.setName("AppletLoader.loaderThread");
+ loaderThread.start();
+
+ animationThread = new Thread() {
+ public void run() {
+ while(state != STATE_DONE) {
+ repaint();
+ AppletLoader.this.sleep(100);
+ }
+ animationThread = null;
+ }
+ };
+ animationThread.setName("AppletLoader.animationthread");
+ animationThread.start();
+ }
+ }
+
+ /*
+ * @see java.applet.Applet#stop()
+ */
+ public void stop() {
+ if (lwjglApplet != null) {
+ lwjglApplet.stop();
+ }
+ super.stop();
+ }
+
+ /*
+ * @see java.applet.Applet#destroy()
+ */
+ public void destroy() {
+ if (lwjglApplet != null) {
+ lwjglApplet.destroy();
+ }
+
+ progressbar = null;
+ logo = null;
+
+ super.destroy();
+ }
+
+ /**
+ * Retrieves the applet that has been loaded. Usefull for liveconnect.
+ */
+ public Applet getApplet() {
+ return lwjglApplet;
+ }
+
+ /*
+ * @see java.applet.AppletStub#appletResize(int, int)
+ */
+ public void appletResize(int width, int height) {
+ /* uhm? */
+ }
+
+ /*
+ * @see java.awt.Container#update(java.awt.Graphics)
+ */
+ public final void update(Graphics g) {
+ paint(g);
+ }
+
+ /*
+ * @see java.awt.Container#paint(java.awt.Graphics)
+ */
+ public final synchronized void paint(Graphics g) {
+
+ // paint applet if available
+ if(lwjglApplet != null && state == STATE_DONE) {
+ lwjglApplet.paint(g);
+ return;
+ }
+
+ // create offscreen if missing
+ if (offscreen == null) {
+ offscreen = createImage(getWidth(), getHeight());
+ }
+
+ // draw everything onto an image before drawing to avoid flicker
+ Graphics og = offscreen.getGraphics();
+ FontMetrics fm = og.getFontMetrics();
+
+ // set background color
+ og.setColor(bgColor);
+ og.fillRect(0, 0, getWidth(), getHeight());
+
+ // get logo position so its in the middle of applet
+ int x = 0, y = 0;
+
+ if(logo != null && !fatalError) {
+ x = (getWidth() - logo.getWidth(this)) / 2;
+ y = (getHeight() - logo.getHeight(this)) / 2;
+ }
+
+ og.setColor(fgColor);
+ String message = null;
+
+ switch (state) {
+ case STATE_INIT:
+ message = "Initializing loader";
+ break;
+ case STATE_DETERMINING_PACKAGES:
+ message = "Determining packages to load";
+ break;
+ case STATE_CHECKING_CACHE:
+ message = "Checking cache for existing files";
+ break;
+ case STATE_DOWNLOADING:
+ message = "Downloading packages";
+ break;
+ case STATE_EXTRACTING_PACKAGES:
+ message = "Extracting downloaded packages";
+ break;
+ case STATE_UPDATING_CLASSPATH:
+ message = "Updating classpath";
+ break;
+ case STATE_SWITCHING_APPLET:
+ message = "Switching applet";
+ break;
+ case STATE_INITIALIZE_REAL_APPLET:
+ message = "Initializing real applet";
+ break;
+ case STATE_START_REAL_APPLET:
+ message = "Starting real applet";
+ break;
+ case STATE_DONE:
+ message = "Done loading";
+ break;
+ }
+
+ if (fatalError) {
+ genericErrorMessage[genericErrorMessage.length-1] = fatalErrorDescription;
+ for(int i=0; i<genericErrorMessage.length; i++) {
+ int messageX = (getWidth() - fm.stringWidth(genericErrorMessage[i])) / 2;
+ int messageY = (getHeight() - (fm.getHeight() * genericErrorMessage.length)) / 2;
+
+ og.setColor(errorColor);
+ og.drawString(genericErrorMessage[i], messageX, messageY + i*fm.getHeight());
+ }
+ } else {
+ og.setColor(fgColor);
+
+ // draw logo
+ og.drawImage(logo, x, y, null);
+
+ // draw message
+ int messageX = (getWidth() - fm.stringWidth(message)) / 2;
+ int messageY = y + logo.getHeight(null) + 20;
+ og.drawString(message, messageX, messageY);
+
+ // draw subtaskmessage, if any
+ if(subtaskMessage.length() > 0) {
+ messageX = (getWidth() - fm.stringWidth(subtaskMessage)) / 2;
+ og.drawString(subtaskMessage, messageX, messageY+20);
+ }
+
+ // draw loading bar, clipping it depending on percentage done
+ int barSize = (progressbar.getWidth(this) * percentage) / 100;
+ og.clipRect(0, 0, x + barSize, getHeight());
+ og.drawImage(progressbar, x, y, null);
+ }
+
+ og.dispose();
+
+ // finally draw it all
+ g.drawImage(offscreen, 0, 0, null);
+ }
+
+ /**
+ * Reads list of jars to download and adds the urls to urlList
+ * also finds out which OS you are on and adds appropriate native
+ * jar to the urlList
+ */
+ protected void loadJarURLs() {
+ state = STATE_DETERMINING_PACKAGES;
+
+ StringTokenizer jar = new StringTokenizer(jarList, ", ");
+
+ int jarCount = jar.countTokens() + 1;
+
+ urlList = new URL[jarCount];
+
+ try {
+ URL path = getCodeBase();
+
+ // set jars urls
+ for (int i = 0; i < jarCount - 1; i++) {
+ urlList[i] = new URL(path, jar.nextToken());
+ }
+
+ // native jar url
+ String osName = System.getProperty("os.name");
+ String nativeJar = null;
+
+ if (osName.startsWith("Win")) {
+ nativeJar = getParameter("al_windows");
+ } else if (osName.startsWith("Linux") || osName.startsWith("FreeBSD") || osName.startsWith("SunOS")) {
+ nativeJar = getParameter("al_linux");
+ } else if (osName.startsWith("Mac")) {
+ nativeJar = getParameter("al_mac");
+ } else {
+ fatalErrorOccured("OS (" + osName + ") not supported");
+ }
+
+ if (nativeJar == null) {
+ fatalErrorOccured("no lwjgl natives files found");
+ } else {
+ urlList[jarCount - 1] = new URL(path, nativeJar);
+ }
+
+ } catch (MalformedURLException e) {
+ fatalErrorOccured(e.getMessage());
+ }
+ }
+
+ /**
+ * 4 steps
+ *
+ * 1) check version of applet and decide whether to download jars
+ * 2) download the jars
+ * 3) extract natives
+ * 4) add to jars to class path
+ * 5) switch applets
+ *
+ */
+ public void run() {
+
+ state = STATE_CHECKING_CACHE;
+
+ percentage = 5;
+
+ try {
+ if(debugMode) {
+ sleep(2000);
+ }
+
+ // get path where applet will be stored
+ String path = (String) AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ return System.getProperty("java.io.tmpdir") + File.separator + getParameter("al_title") + File.separator;
+ }
+ });
+
+ File dir = new File(path);
+
+ // create directory
+ if (!dir.exists()) {
+ dir.mkdir();
+ }
+ dir = new File(dir, "version");
+
+ // if applet already available don't download anything
+ boolean cacheAvailable = false;
+
+ // version of applet
+ String version = getParameter("al_version");
+ float latestVersion = 0;
+
+ // if applet version specifed, check if you have latest version of applet
+ if (version != null) {
+
+ latestVersion = Float.parseFloat(version);
+
+ // if version file exists
+ if (dir.exists()) {
+ // compare to new version
+ if (latestVersion <= readVersionFile(dir)) {
+ cacheAvailable = true;
+ percentage = 90;
+ if(debugMode) {
+ sleep(2000);
+ }
+ }
+ }
+ }
+
+ // if jars not available or need updating download them
+ if (!cacheAvailable) {
+ // downloads jars from the server
+ downloadJars(path); // 10-65%
+
+ // Extracts Native Files
+ extractNatives(path); // 65-85%
+
+ // add version information once jars downloaded successfully
+ if (version != null) {
+ percentage = 90;
+ writeVersionFile(dir, latestVersion);
+ }
+ }
+
+ // add the downloaded jars and natives to classpath
+ updateClassPath(path);
+
+ // switch to LWJGL Applet
+ switchApplet();
+
+ state = STATE_DONE;
+ } catch (AccessControlException ace) {
+ fatalErrorOccured(ace.getMessage());
+ } catch (Exception e) {
+ fatalErrorOccured(e.getMessage());
+ } finally {
+ loaderThread = null;
+ }
+ }
+
+ /**
+ * read the current version file
+ *
+ * @param file the file to read
+ * @return the version value of saved file
+ * @throws Exception if it fails to read value
+ */
+ protected float readVersionFile(File file) throws Exception {
+ DataInputStream dis = new DataInputStream(new FileInputStream(file));
+ float version = dis.readFloat();
+ dis.close();
+ return version;
+ }
+
+ /**
+ * write out version file of applet
+ *
+ * @param file the file to write out to
+ * @param version the version of the applet as a float
+ * @throws Exception if it fails to write file
+ */
+ protected void writeVersionFile(File file, float version) throws Exception {
+ DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
+ dos.writeFloat(version);
+ dos.close();
+ }
+
+ /**
+ * Edits the ClassPath at runtime to include the jars
+ * that have just been downloaded and then adds the
+ * lwjgl natives folder property.
+ *
+ * @param path location where applet is stored
+ * @throws Exception if it fails to add classpath
+ */
+ protected void updateClassPath(String path) throws Exception {
+
+ state = STATE_UPDATING_CLASSPATH;
+
+ percentage = 95;
+
+ Class[] parameters = new Class[] { URL.class};
+
+ // modify class path by adding downloaded jars to it
+ for (int i = 0; i < urlList.length; i++) {
+ // get location of jar as a url
+ URL u = new URL("file:" + path + getFileName(urlList[i]));
+
+ // add to class path
+ Method method = URLClassLoader.class.getDeclaredMethod("addURL", parameters);
+ method.setAccessible(true);
+ method.invoke((URLClassLoader) ClassLoader.getSystemClassLoader(), new Object[] { u});
+ }
+
+ if(debugMode) {
+ sleep(2000);
+ }
+
+ // add natives files path to native class path
+ System.setProperty("org.lwjgl.librarypath", path + "natives");
+
+ // Make sure jinput knows about the new path too
+ System.setProperty("net.java.games.input.librarypath", path + "natives");
+
+ // replace security system to avoid bug where vm fails to
+ // recognise downloaded jars as signed, when they are
+ System.setSecurityManager(null);
+ }
+
+ /**
+ * replace the current applet with the lwjgl applet
+ * using AppletStub and initialise and start it
+ */
+ protected void switchApplet() throws Exception {
+
+ state = STATE_SWITCHING_APPLET;
+ percentage = 100;
+
+ if(debugMode) {
+ sleep(2000);
+ }
+
+ Class appletClass = Class.forName(getParameter("al_main"));
+ lwjglApplet = (Applet) appletClass.newInstance();
+
+ lwjglApplet.setStub(this);
+
+ setLayout(new GridLayout(1, 1));
+ add(lwjglApplet);
+ validate();
+
+ state = STATE_INITIALIZE_REAL_APPLET;
+ lwjglApplet.init();
+
+ state = STATE_START_REAL_APPLET;
+ lwjglApplet.start();
+ }
+
+ /**
+ * Will download the jars from the server using the list of urls
+ * in urlList, while at the same time updating progress bar
+ *
+ * @param path location of the directory to save to
+ * @throws Exception if download fails
+ */
+ protected void downloadJars(String path) throws Exception {
+
+ state = STATE_DOWNLOADING;
+
+ URLConnection urlconnection;
+
+ // calculate total size of jars to download
+ for (int i = 0; i < urlList.length; i++) {
+ urlconnection = urlList[i].openConnection();
+ totalSizeDownload += urlconnection.getContentLength();
+ }
+
+ int initialPercentage = percentage = 10;
+
+ // download each jar
+ byte buffer[] = new byte[65536];
+ for (int i = 0; i < urlList.length; i++) {
+ if(debugMode) {
+ sleep(2000);
+ }
+
+ urlconnection = urlList[i].openConnection();
+
+ String currentFile = getFileName(urlList[i]);
+ InputStream inputstream = urlconnection.getInputStream();
+ FileOutputStream fos = new FileOutputStream(path + currentFile);
+
+
+ int bufferSize;
+ while ((bufferSize = inputstream.read(buffer, 0, buffer.length)) != -1) {
+ if(debugMode) {
+ sleep(10);
+ }
+ fos.write(buffer, 0, bufferSize);
+ currentSizeDownload += bufferSize;
+ percentage = initialPercentage + ((currentSizeDownload * 55) / totalSizeDownload);
+ subtaskMessage = "Retrieving: " + currentFile + " " + ((currentSizeDownload * 100) / totalSizeDownload) + "%";
+ }
+ }
+ subtaskMessage = "";
+ }
+
+ /**
+ * This method will extract all file from the native jar and extract them
+ * to the subdirectory called "natives" in the local path, will also check
+ * to see if the native jar files is signed properly
+ *
+ * @param path base folder containing all downloaded jars
+ * @throws Exception if it fails to extract files
+ */
+ protected void extractNatives(String path) throws Exception {
+
+ state = STATE_EXTRACTING_PACKAGES;
+
+ int initialPercentage = percentage;
+
+ // get name of jar file with natives from urlList, it will be the last url
+ String nativeJar = getFileName(urlList[urlList.length - 1]);
+
+ // get the current certificate to compare against native files
+ Certificate[] certificate = AppletLoader.class.getProtectionDomain().getCodeSource().getCertificates();
+
+ // create native folder
+ File nativeFolder = new File(path + "natives");
+ if (!nativeFolder.exists()) {
+ nativeFolder.mkdir();
+ }
+
+ // open jar file
+ JarFile jarFile = new JarFile(path + nativeJar, true);
+
+ // get list of files in jar
+ Enumeration entities = jarFile.entries();
+
+ totalSizeExtract = 0;
+
+ // calculate the size of the files to extract for progress bar
+ while (entities.hasMoreElements()) {
+ JarEntry entry = (JarEntry) entities.nextElement();
+
+ // skip directories and anything in directories
+ // conveniently ignores the manifest
+ if (entry.isDirectory() || entry.getName().indexOf('/') != -1) {
+ continue;
+ }
+ totalSizeExtract += entry.getSize();
+ }
+
+ currentSizeExtract = 0;
+
+ // reset point to begining by getting list of file again
+ entities = jarFile.entries();
+
+ // extract all files from the jar
+ while (entities.hasMoreElements()) {
+ JarEntry entry = (JarEntry) entities.nextElement();
+
+ // skip directories and anything in directories
+ // conveniently ignores the manifest
+ if (entry.isDirectory() || entry.getName().indexOf('/') != -1) {
+ continue;
+ }
+
+ // check if native file already exists if so delete it to make room for new one
+ // useful when using the reload button on the browser
+ File f = new File(path + "natives" + File.separator + entry.getName());
+ if (f.exists()) {
+ if (!f.delete()) {
+ continue; // unable to delete file, it is in use, skip extracting it
+ }
+ }
+
+ if(debugMode) {
+ sleep(1000);
+ }
+
+ InputStream in = jarFile.getInputStream(jarFile.getEntry(entry.getName()));
+ OutputStream out = new FileOutputStream(path + "natives" + File.separator + entry.getName());
+
+ int bufferSize;
+ byte buffer[] = new byte[65536];
+
+ while ((bufferSize = in.read(buffer, 0, buffer.length)) != -1) {
+ if(debugMode) {
+ sleep(10);
+ }
+ out.write(buffer, 0, bufferSize);
+ currentSizeExtract += bufferSize;
+
+ // update progress bar
+ percentage = initialPercentage + ((currentSizeExtract * 20) / totalSizeExtract);
+ subtaskMessage = "Extracting: " + entry.getName() + " " + ((currentSizeExtract * 100) / totalSizeExtract) + "%";
+ }
+
+ // validate if the certificate for native file is correct
+ validateCertificateChain(certificate, entry.getCertificates());
+
+ in.close();
+ out.close();
+ }
+ subtaskMessage = "";
+
+ jarFile.close();
+ }
+
+ /**
+ * Validates the certificate chain for a single file
+ *
+ * @param ownCerts Chain of certificates to check against
+ * @param native_certs Chain of certificates to check
+ * @return true if the chains match
+ */
+ protected static void validateCertificateChain(Certificate[] ownCerts, Certificate[] native_certs) throws Exception {
+ if (native_certs == null)
+ throw new Exception("Unable to validate certificate chain. Native entry did not have a certificate chain at all");
+
+ if (ownCerts.length != native_certs.length)
+ throw new Exception("Unable to validate certificate chain. Chain differs in length [" + ownCerts.length + " vs " + native_certs.length + "]");
+
+ for (int i = 0; i < ownCerts.length; i++) {
+ if (!ownCerts[i].equals(native_certs[i])) {
+ throw new Exception("Certificate mismatch: " + ownCerts[i] + " != " + native_certs[i]);
+ }
+ }
+ }
+
+ /**
+ * Get Image from path provided
+ *
+ * @param s location of the image
+ * @return the Image file
+ */
+ protected Image getImage(String s) {
+ try {
+ DataInputStream datainputstream = new DataInputStream(getClass().getResourceAsStream(s));
+ byte abyte0[] = new byte[datainputstream.available()];
+ datainputstream.readFully(abyte0);
+ datainputstream.close();
+ return Toolkit.getDefaultToolkit().createImage(abyte0);
+ } catch (Exception e) {
+ /* */
+ }
+ return null;
+ }
+
+
+ /**
+ * Get file name portion of URL.
+ *
+ * @param url Get file name from this url
+ * @return file name as string
+ */
+ protected String getFileName(URL url) {
+ String fileName = url.getFile();
+ return fileName.substring(fileName.lastIndexOf('/') + 1);
+ }
+
+ /**
+ * Retrieves the color
+ *
+ * @param color Color to load
+ * @param defaultColor Default color to use if no color to load
+ * @return Color to use
+ */
+ protected Color getColor(String color, Color defaultColor) {
+ String param_color = getParameter(color);
+ if (param_color != null) {
+ return new Color(Integer.parseInt(param_color, 16));
+ }
+ return defaultColor;
+ }
+
+ /**
+ * Retrieves the boolean value for the applet
+ * @param name Name of parameter
+ * @param defaultValue default value to return if no such parameter
+ * @return value of parameter or defaultValue
+ */
+ protected boolean getBooleanParameter(String name, boolean defaultValue) {
+ String parameter = getParameter(name);
+ if(parameter != null) {
+ return Boolean.parseBoolean(parameter);
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Sets the state of the loaded and prints some debug information
+ *
+ * @param error Error message to print
+ * @param state State to enter
+ */
+ protected void fatalErrorOccured(String error) {
+ fatalError = true;
+ fatalErrorDescription = "Fatal error occured (" + state + "): " + error;
+ System.out.println(fatalErrorDescription);
+ repaint();
+ }
+
+ /**
+ * Utility method for sleeping
+ * @param ms milliseconds to sleep
+ */
+ protected void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (Exception e) {
+ /* ignored */
+ }
+ }
+}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|