The great big resource manager revamp: the resource manager now supports

the JNLP versioned resource protocol so that it can download jardiffs
instead of whole new jar files when a resource bundle is updated.
Unversioned http downloads (which we'll probably continue to use for the
dynamically generated island bundles) are currently not working.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2739 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2003-08-05 01:33:20 +00:00
parent 0e5cb7fa89
commit 636b792051
6 changed files with 593 additions and 199 deletions
@@ -0,0 +1,153 @@
//
// $Id: Downloader.java,v 1.1 2003/08/05 01:33:20 mdb Exp $
package com.threerings.resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import com.threerings.resource.DownloadManager.DownloadDescriptor;
import com.threerings.resource.DownloadManager.DownloadObserver;
/**
* Does something extraordinary.
*/
public abstract class Downloader
{
/**
* Provides this downloader with a reference to the download
* descriptor it needs to do its business.
*/
public void init (DownloadDescriptor ddesc)
{
_desc = ddesc;
_desc.destFileSize = _desc.destFile.length();
_desc.destLastModified = _desc.destFile.lastModified();
}
/**
* Returns a reference to the descriptor we are downloading.
*/
public DownloadDescriptor getDescriptor ()
{
return _desc;
}
/**
* Requests that this downloader determine whether it needs to be
* updated and if so, it should add its total download requirement to
* {@link ProgressInfo#totalSize} the supplied {@link ProgressInfo}
* record.
*
* @return true if this downloader needs be updated, false if not.
*/
public abstract boolean checkUpdate (ProgressInfo info)
throws IOException;
/**
* Compares the supplied size and last modified time with the size and
* last modified time of our local copy of the file.
*/
protected boolean compareWithLocal (long fileSize, long lastModified)
{
// check to see whether we have a local copy at all, and if so,
// whether its file size or last-modified time differs from the
// source file modulo a delta to account for inexactness on the
// part of the file-system (thanks Microsoft)
return ((!_desc.destFile.exists()) ||
(_desc.destFileSize != fileSize) ||
(_desc.destLastModified < (lastModified - DELTA)) ||
(_desc.destLastModified > (lastModified + DELTA)));
}
/**
* Processes a single download descriptor.
*/
public void processDownload (DownloadManager dmgr, DownloadObserver obs,
ProgressInfo pinfo, byte[] buffer)
throws IOException
{
// download the resource bundle from the specified URL
URLConnection ucon = _desc.sourceURL.openConnection();
// prepare to read the data from the URL into the cache file
Log.info("Downloading file [url=" + _desc.sourceURL + "].");
downloadContent(dmgr, obs, pinfo, buffer, ucon, _desc.destFile);
// if we have a last modified time, we want to adjust our cache
// file accordingly
if (_desc.lastModified != 0) {
if (!_desc.destFile.setLastModified(_desc.lastModified)) {
Log.warning("Failed to set last-modified date " +
"[file=" + _desc.destFile + "].");
}
}
}
/**
* Downloads the content from the supplied URL connection into the
* specified destination file, informing the supplied download manager
* and observer of our progress along the way.
*/
protected void downloadContent (DownloadManager dmgr, DownloadObserver obs,
ProgressInfo pinfo, byte[] buffer,
URLConnection ucon, File destFile)
throws IOException
{
InputStream in = ucon.getInputStream();
FileOutputStream out = new FileOutputStream(destFile);
int read;
// read in the file data
while ((read = in.read(buffer)) != -1) {
// write it out to our local copy
out.write(buffer, 0, read);
// report our progress to the download observer as a
// percentage of the total file data to be transferred
pinfo.currentSize += read;
// update our percent completion; if we're totally done, hold
// off on notifying the observer until the download manager
// finishes fiddling to ensure that any action the observer
// may take on the downloaded files can be safely undertaken
int pctdone = pinfo.getPercentDone();
pinfo.complete = (pctdone >= 100);
if (pinfo.complete) {
continue;
}
// update the transfer rate to reflect the bit of data we just
// transferred
long now = System.currentTimeMillis();
pinfo.updateXferRate(now);
// notify the progress observer if it's been sufficiently long
// since our last notification
if ((now - pinfo.lastUpdate) >= UPDATE_DELAY) {
pinfo.lastUpdate = now;
long remaining = pinfo.getXferTimeRemaining();
dmgr.notifyProgress(obs, pctdone, remaining);
}
}
// close the streams
in.close();
out.close();
}
/** The descriptor that we're downloading. */
protected DownloadDescriptor _desc;
/** The last-modified difference in milliseconds allowed between the
* source and destination file without considering the destination
* file to be out of date. */
protected static final long DELTA = 5000L;
/** The delay in milliseconds between notifying progress observers of
* file download progress. */
protected static final long UPDATE_DELAY = 2500L;
}