|
From: <ka...@us...> - 2010-07-11 12:16:50
|
Revision: 3372
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3372&view=rev
Author: kappa1
Date: 2010-07-11 12:13:34 +0000 (Sun, 11 Jul 2010)
Log Message:
-----------
Appletloader: Initial implementation of a proper caching system. Files will only be downloaded if lastModified time is different from when files were downloaded previously. al_cache parameter is used to disable and enable this caching (default: true). This caching will not be used if al_version parameter is used.
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
Modified: trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2010-07-10 11:56:55 UTC (rev 3371)
+++ trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2010-07-11 12:13:34 UTC (rev 3372)
@@ -48,6 +48,8 @@
import java.io.FilePermission;
import java.io.IOException;
import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -69,6 +71,7 @@
import java.security.SecureClassLoader;
import java.security.cert.Certificate;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.jar.JarEntry;
@@ -107,6 +110,7 @@
* <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_cache - [boolean] Whether to use cache system. If al_version is used then cache is not used. <i>Default: true</i>.</li>
* <li>al_debug - [boolean] Whether to enable debug mode. <i>Default: false</i>.</li>
* <li>al_prepend_host - [boolean] Whether to limit caching to this domain, disable if your applet is hosted on multple domains and needs to share the cache. <i>Default: true</i>.</li>
* <ul>
@@ -220,6 +224,15 @@
/** whether to prepend host to cache path */
protected boolean prependHost;
+ /** Used to store file names with lastModified time */
+ protected HashMap filesLastModified;
+
+ /** Sizes of files to download */
+ protected int[] fileSizes;
+
+ /** whether to use caching system, only download files that have changed */
+ protected boolean cacheEnabled;
+
/** String to display as a subtask */
protected String subtaskMessage = "";
@@ -262,7 +275,10 @@
return;
}
}
-
+
+ // whether to use cache system
+ cacheEnabled = getBooleanParameter("al_cache", true);
+
// whether to run in debug mode
debugMode = getBooleanParameter("al_debug", false);
@@ -479,7 +495,7 @@
og.dispose();
- // finally draw it all
+ // finally draw it all centred
g.drawImage(offscreen, (getWidth() - offscreen.getWidth(null))/2, (getHeight() - offscreen.getHeight(null))/2, null);
}
@@ -528,7 +544,7 @@
case STATE_DETERMINING_PACKAGES:
return "Determining packages to load";
case STATE_CHECKING_CACHE:
- return "Checking cache for existing files";
+ return "Calculate download size and check cache";
case STATE_DOWNLOADING:
return "Downloading packages";
case STATE_EXTRACTING_PACKAGES:
@@ -681,11 +697,12 @@
if (!dir.exists()) {
dir.mkdirs();
}
- dir = new File(dir, "version");
+
+ File versionFile = new File(dir, "version");
+
+ // if specified applet version already available don't download anything
+ boolean versionAvailable = false;
- // if applet already available don't download anything
- boolean cacheAvailable = false;
-
// version of applet
String version = getParameter("al_version");
float latestVersion = 0;
@@ -696,10 +713,10 @@
latestVersion = Float.parseFloat(version);
// if version file exists
- if (dir.exists()) {
+ if (versionFile.exists()) {
// compare to new version
- if (latestVersion <= readVersionFile(dir)) {
- cacheAvailable = true;
+ if (latestVersion <= readVersionFile(versionFile)) {
+ versionAvailable = true;
percentage = 90;
if(debugMode) {
@@ -711,9 +728,12 @@
}
// if jars not available or need updating download them
- if (!cacheAvailable) {
+ if (!versionAvailable) {
+ // get jars file sizes and check cache
+ getJarInfo(dir); // 5-15%
+
// downloads jars from the server
- downloadJars(path); // 10-55%
+ downloadJars(path); // 15-55%
// Extract Pack and LZMA files
extractJars(path); // 55-65%
@@ -721,11 +741,14 @@
// Extracts Native Files
extractNatives(path); // 65-85%
- // add version information once jars downloaded successfully
+ // save version information once jars downloaded successfully
if (version != null) {
percentage = 90;
writeVersionFile(dir, latestVersion);
}
+
+ // save file names with last modified info once downloaded successfully
+ writeCacheFile(new File(dir, "cache"), filesLastModified);
}
// add the downloaded jars and natives to classpath
@@ -771,8 +794,35 @@
dos.writeFloat(version);
dos.close();
}
+
+ /**
+ * read the current cache file
+ *
+ * @param file the file to read
+ * @return the hashmap containing the files names and lastModified times
+ * @throws Exception if it fails to read hashmap
+ */
+ protected HashMap readCacheFile(File file) throws Exception {
+ ObjectInputStream dis = new ObjectInputStream(new FileInputStream(file));
+ HashMap hashMap = (HashMap)dis.readObject();
+ dis.close();
+ return hashMap;
+ }
/**
+ * write out cache file of applet
+ *
+ * @param file the file to write out to
+ * @param filesLastModified the hashmap containing files names and lastModified times
+ * @throws Exception if it fails to write file
+ */
+ protected void writeCacheFile(File file, HashMap filesLastModified) throws Exception {
+ ObjectOutputStream dos = new ObjectOutputStream(new FileOutputStream(file));
+ dos.writeObject(filesLastModified);
+ dos.close();
+ }
+
+ /**
* Edits the ClassPath at runtime to include the jars
* that have just been downloaded and then adds the
* lwjgl natives folder property.
@@ -848,7 +898,7 @@
* Due to the way applets on plugin1 work, one jvm must
* be used for all applets. We need to use multiple
* classloaders in the same jvm due to LWJGL's static
- * nature. I order to solver this we simply remove the
+ * nature. I order to solve this we simply remove the
* natives from a previous classloader allowing a new
* classloader to use those natives in the same jvm.
*
@@ -913,23 +963,33 @@
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
+ * This method will get the files sizes of the files to download.
+ * It wil further get the lastModified time of files
+ * and save it in a hashmap, if cache is enabled it will mark
+ * those files that have not changed since last download to not
+ * redownloaded.
*
- * @param path location of the directory to save to
- * @throws Exception if download fails
+ * @param dir - location to read cache file from
+ * @throws Exception - if fails to get infomation
*/
- protected void downloadJars(String path) throws Exception {
+ protected void getJarInfo(File dir) throws Exception {
- state = STATE_DOWNLOADING;
-
+ filesLastModified = new HashMap();
+
+ // store file sizes and mark which files not to download
+ fileSizes = new int[urlList.length];
+
URLConnection urlconnection;
- // store file sizes, used for download verification
- int[] fileSizes = new int[urlList.length];
+ File cacheFile = new File(dir, "cache");
+ // if cache file exists, load it
+ if (cacheFile.exists()) {
+ filesLastModified = readCacheFile(cacheFile);
+ }
+
// calculate total size of jars to download
for (int i = 0; i < urlList.length; i++) {
urlconnection = urlList[i].openConnection();
@@ -937,16 +997,57 @@
if (urlconnection instanceof HttpURLConnection) {
((HttpURLConnection) urlconnection).setRequestMethod("HEAD");
}
+
fileSizes[i] = urlconnection.getContentLength();
- totalSizeDownload += fileSizes[i];
+
+ long lastModified = urlconnection.getLastModified();
+ String fileName = getFileName(urlList[i]);
+
+
+ if (cacheEnabled && lastModified != 0 &&
+ filesLastModified.containsKey(fileName)) {
+ long savedLastModified = (Long)filesLastModified.get(fileName);
+
+ // if lastModifed time is the same, don't redownload
+ if (savedLastModified == lastModified) {
+ fileSizes[i] = -2; // mark it to not redownload
+ }
+ }
+
+ if (fileSizes[i] >= 0) {
+ totalSizeDownload += fileSizes[i];
+ }
+
+ // put key and value in the hashmap
+ filesLastModified.put(fileName, lastModified);
+
+ // update progress bar
+ percentage = 5 + (int)(10 * i/(float)urlList.length);
}
+ }
+
+ /**
+ * 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 {
- int initialPercentage = percentage = 10;
+ state = STATE_DOWNLOADING;
+ URLConnection urlconnection;
+
+ int initialPercentage = percentage = 15;
+
// download each jar
byte buffer[] = new byte[65536];
for (int i = 0; i < urlList.length; i++) {
+ // skip file if marked as -2 (already downloaded and not changed)
+ if (fileSizes[i] == -2) continue;
+
int unsuccessfulAttempts = 0;
int maxUnsuccessfulAttempts = 3;
boolean downloadFile = true;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|