X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=getdown%2Fsrc%2Fgetdown%2Fcore%2Fsrc%2Fmain%2Fjava%2Fcom%2Fthreerings%2Fgetdown%2Fnet%2FHTTPDownloader.java;fp=getdown%2Fsrc%2Fgetdown%2Fcore%2Fsrc%2Fmain%2Fjava%2Fcom%2Fthreerings%2Fgetdown%2Fnet%2FHTTPDownloader.java;h=a7a3287a95ecb81393539aadd7fd99968263acf2;hb=890092d4ca9b8c17a3f356eeb12f49440d5fc51c;hp=0000000000000000000000000000000000000000;hpb=15c6c6724878a5445e9f5bc6594719dbe81c1735;p=jalview.git diff --git a/getdown/src/getdown/core/src/main/java/com/threerings/getdown/net/HTTPDownloader.java b/getdown/src/getdown/core/src/main/java/com/threerings/getdown/net/HTTPDownloader.java new file mode 100644 index 0000000..a7a3287 --- /dev/null +++ b/getdown/src/getdown/core/src/main/java/com/threerings/getdown/net/HTTPDownloader.java @@ -0,0 +1,115 @@ +// +// Getdown - application installer, patcher and launcher +// Copyright (C) 2004-2018 Getdown authors +// https://github.com/threerings/getdown/blob/master/LICENSE + +package com.threerings.getdown.net; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; + +import com.threerings.getdown.data.Resource; +import com.threerings.getdown.util.ConnectionUtil; + +import static com.threerings.getdown.Log.log; + +/** + * Implements downloading files over HTTP + */ +public class HTTPDownloader extends Downloader +{ + public HTTPDownloader (Proxy proxy) + { + _proxy = proxy; + } + + @Override protected long checkSize (Resource rsrc) throws IOException + { + URLConnection conn = ConnectionUtil.open(_proxy, rsrc.getRemote(), 0, 0); + try { + // if we're accessing our data via HTTP, we only need a HEAD request + if (conn instanceof HttpURLConnection) { + HttpURLConnection hcon = (HttpURLConnection)conn; + hcon.setRequestMethod("HEAD"); + hcon.connect(); + // make sure we got a satisfactory response code + if (hcon.getResponseCode() != HttpURLConnection.HTTP_OK) { + throw new IOException("Unable to check up-to-date for " + + rsrc.getRemote() + ": " + hcon.getResponseCode()); + } + } + return conn.getContentLength(); + + } finally { + // let it be known that we're done with this connection + conn.getInputStream().close(); + } + } + + @Override protected void download (Resource rsrc) throws IOException + { + // TODO: make FileChannel download impl (below) robust and allow apps to opt-into it via a + // system property + if (true) { + // download the resource from the specified URL + URLConnection conn = ConnectionUtil.open(_proxy, rsrc.getRemote(), 0, 0); + conn.connect(); + + // make sure we got a satisfactory response code + if (conn instanceof HttpURLConnection) { + HttpURLConnection hcon = (HttpURLConnection)conn; + if (hcon.getResponseCode() != HttpURLConnection.HTTP_OK) { + throw new IOException("Unable to download resource " + rsrc.getRemote() + ": " + + hcon.getResponseCode()); + } + } + long actualSize = conn.getContentLength(); + log.info("Downloading resource", "url", rsrc.getRemote(), "size", actualSize); + long currentSize = 0L; + byte[] buffer = new byte[4*4096]; + try (InputStream in = conn.getInputStream(); + FileOutputStream out = new FileOutputStream(rsrc.getLocalNew())) { + + // TODO: look to see if we have a download info file + // containing info on potentially partially downloaded data; + // if so, use a "Range: bytes=HAVE-" header. + + // read in the file data + int read; + while ((read = in.read(buffer)) != -1) { + // abort the download if the downloader is aborted + if (_state == State.ABORTED) { + break; + } + // write it out to our local copy + out.write(buffer, 0, read); + // note that we've downloaded some data + currentSize += read; + reportProgress(rsrc, currentSize, actualSize); + } + } + + } else { + log.info("Downloading resource", "url", rsrc.getRemote(), "size", "unknown"); + File localNew = rsrc.getLocalNew(); + try (ReadableByteChannel rbc = Channels.newChannel(rsrc.getRemote().openStream()); + FileOutputStream fos = new FileOutputStream(localNew)) { + // TODO: more work is needed here, transferFrom can fail to transfer the entire + // file, in which case it's not clear what we're supposed to do.. call it again? + // will it repeatedly fail? + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + reportProgress(rsrc, localNew.length(), localNew.length()); + } + } + } + + protected final Proxy _proxy; +}