AppletLoader: apply arielsan's concurrent HTTP requests patch
This commit is contained in:
parent
dae790d54f
commit
08eb7c60d9
|
@ -74,8 +74,14 @@ import java.security.SecureClassLoader;
|
|||
import java.security.cert.Certificate;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
@ -199,7 +205,7 @@ public class AppletLoader extends Applet implements Runnable, AppletStub {
|
|||
public static final int STATE_DONE = 12;
|
||||
|
||||
/** used to calculate length of progress bar */
|
||||
protected int percentage;
|
||||
protected volatile int percentage;
|
||||
|
||||
/** current size of download in bytes */
|
||||
protected int currentSizeDownload;
|
||||
|
@ -285,6 +291,9 @@ public class AppletLoader extends Applet implements Runnable, AppletStub {
|
|||
/** messages to be passed via liveconnect in headless mode */
|
||||
protected String[] headlessMessage;
|
||||
|
||||
/** threads to use when fetching information of files to be downloaded */
|
||||
protected int concurrentLookupThreads;
|
||||
|
||||
/** whether a fatal error occurred */
|
||||
protected boolean fatalError;
|
||||
|
||||
|
@ -342,6 +351,9 @@ public class AppletLoader extends Applet implements Runnable, AppletStub {
|
|||
// whether to run in headless mode
|
||||
headless = getBooleanParameter("al_headless", false);
|
||||
|
||||
// obtain the number of concurrent lookup threads to use
|
||||
concurrentLookupThreads = getIntParameter("al_lookup_threads", 1); // defaults to 1
|
||||
|
||||
// get colors of applet
|
||||
bgColor = getColor("boxbgcolor", Color.white);
|
||||
setBackground(bgColor);
|
||||
|
@ -1327,8 +1339,6 @@ public class AppletLoader extends Applet implements Runnable, AppletStub {
|
|||
// store file sizes and mark which files not to download
|
||||
fileSizes = new int[urlList.length];
|
||||
|
||||
URLConnection urlconnection;
|
||||
|
||||
File timestampsFile = new File(dir, "timestamps");
|
||||
|
||||
// if timestamps file exists, load it
|
||||
|
@ -1337,39 +1347,76 @@ public class AppletLoader extends Applet implements Runnable, AppletStub {
|
|||
}
|
||||
|
||||
// calculate total size of jars to download
|
||||
for (int i = 0; i < urlList.length; i++) {
|
||||
urlconnection = urlList[i].openConnection();
|
||||
urlconnection.setDefaultUseCaches(false);
|
||||
if (urlconnection instanceof HttpURLConnection) {
|
||||
((HttpURLConnection) urlconnection).setRequestMethod("HEAD");
|
||||
}
|
||||
|
||||
fileSizes[i] = urlconnection.getContentLength();
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(concurrentLookupThreads);
|
||||
Queue<Future> requests = new LinkedList<Future>();
|
||||
|
||||
long lastModified = urlconnection.getLastModified();
|
||||
String fileName = getFileName(urlList[i]);
|
||||
// create unique object to sync code in requests
|
||||
final Object sync = new Integer(1);
|
||||
|
||||
for (int j = 0; j < urlList.length; j++) {
|
||||
final int i = j;
|
||||
|
||||
if (cacheEnabled && lastModified != 0 &&
|
||||
filesLastModified.containsKey(fileName)) {
|
||||
long savedLastModified = filesLastModified.get(fileName);
|
||||
Future request = executorService.submit(new Runnable() {
|
||||
|
||||
// if lastModifed time is the same, don't redownload
|
||||
if (savedLastModified == lastModified) {
|
||||
fileSizes[i] = -2; // mark it to not redownload
|
||||
}
|
||||
}
|
||||
public void run() {
|
||||
|
||||
if (fileSizes[i] >= 0) {
|
||||
totalSizeDownload += fileSizes[i];
|
||||
}
|
||||
try {
|
||||
|
||||
// put key and value in the hashmap
|
||||
filesLastModified.put(fileName, lastModified);
|
||||
URLConnection urlconnection = urlList[i].openConnection();
|
||||
urlconnection.setDefaultUseCaches(false);
|
||||
if (urlconnection instanceof HttpURLConnection) {
|
||||
((HttpURLConnection) urlconnection).setRequestMethod("HEAD");
|
||||
}
|
||||
|
||||
// update progress bar
|
||||
percentage = 5 + (int)(10 * i/(float)urlList.length);
|
||||
fileSizes[i] = urlconnection.getContentLength();
|
||||
|
||||
long lastModified = urlconnection.getLastModified();
|
||||
String fileName = getFileName(urlList[i]);
|
||||
|
||||
if (cacheEnabled && lastModified != 0 && filesLastModified.containsKey(fileName)) {
|
||||
long savedLastModified = 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) {
|
||||
synchronized (sync) {
|
||||
totalSizeDownload += fileSizes[i];
|
||||
}
|
||||
}
|
||||
|
||||
// put key and value in the hashmap
|
||||
filesLastModified.put(fileName, lastModified);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to fetch information for " + urlList[i], e);
|
||||
}
|
||||
}});
|
||||
|
||||
requests.add(request);
|
||||
}
|
||||
|
||||
while (!requests.isEmpty()) {
|
||||
Iterator<Future> iterator = requests.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Future request = iterator.next();
|
||||
if (request.isDone()) {
|
||||
request.get(); // will throw an exception if request thrown an exception.
|
||||
iterator.remove();
|
||||
|
||||
// update progress bar
|
||||
percentage = 5 + (int) (10 * (urlList.length - requests.size()) / (float) urlList.length);
|
||||
}
|
||||
}
|
||||
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2087,12 +2134,26 @@ public class AppletLoader extends Applet implements Runnable, AppletStub {
|
|||
*/
|
||||
protected boolean getBooleanParameter(String name, boolean defaultValue) {
|
||||
String parameter = getParameter(name);
|
||||
if(parameter != null) {
|
||||
if (parameter != null) {
|
||||
return Boolean.parseBoolean(parameter);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the int 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 int getIntParameter(String name, int defaultValue) {
|
||||
String parameter = getParameter(name);
|
||||
if (parameter != null) {
|
||||
return Integer.parseInt(parameter);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the error message and print debug information
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue