parent
e0d52fb515
commit
4bb8ff29d8
|
@ -0,0 +1,95 @@
|
||||||
|
|
||||||
|
package net.sourceforge.tuned;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.ReadableByteChannel;
|
||||||
|
|
||||||
|
|
||||||
|
public class ByteBufferOutputStream extends OutputStream {
|
||||||
|
|
||||||
|
private ByteBuffer buffer;
|
||||||
|
|
||||||
|
private final float loadFactor;
|
||||||
|
|
||||||
|
|
||||||
|
public ByteBufferOutputStream(int initialCapacity) {
|
||||||
|
this(initialCapacity, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ByteBufferOutputStream(int initialCapacity, float loadFactor) {
|
||||||
|
if (initialCapacity <= 0)
|
||||||
|
throw new IllegalArgumentException("initialCapacity must be greater than 0");
|
||||||
|
|
||||||
|
if (loadFactor <= 0 || Float.isNaN(loadFactor))
|
||||||
|
throw new IllegalArgumentException("loadFactor must be greater than 0");
|
||||||
|
|
||||||
|
this.buffer = ByteBuffer.allocate(initialCapacity);
|
||||||
|
this.loadFactor = loadFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void write(int b) throws IOException {
|
||||||
|
ensureCapacity(buffer.position() + 1);
|
||||||
|
buffer.put((byte) b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void write(byte[] src) throws IOException {
|
||||||
|
ensureCapacity(buffer.position() + src.length);
|
||||||
|
buffer.put(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void write(byte[] src, int offset, int length) throws IOException {
|
||||||
|
ensureCapacity(buffer.position() + length);
|
||||||
|
buffer.put(src, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized void ensureCapacity(int minCapacity) {
|
||||||
|
if (minCapacity <= buffer.capacity())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// calculate new buffer size with load factor
|
||||||
|
int newCapacity = (int) (buffer.capacity() * (1 + loadFactor));
|
||||||
|
|
||||||
|
// ensure minCapacity
|
||||||
|
if (newCapacity < minCapacity)
|
||||||
|
newCapacity = minCapacity;
|
||||||
|
|
||||||
|
// create new buffer with increased capacity
|
||||||
|
ByteBuffer newBuffer = ByteBuffer.allocate(newCapacity);
|
||||||
|
|
||||||
|
// copy current data to new buffer
|
||||||
|
buffer.flip();
|
||||||
|
newBuffer.put(buffer);
|
||||||
|
|
||||||
|
buffer = newBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized ByteBuffer getByteBuffer() {
|
||||||
|
ByteBuffer result = buffer.duplicate();
|
||||||
|
|
||||||
|
// flip buffer so it can be read
|
||||||
|
result.flip();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized int transferFrom(ReadableByteChannel channel) throws IOException {
|
||||||
|
// make sure buffer is not at its limit
|
||||||
|
ensureCapacity(buffer.position() + 1);
|
||||||
|
|
||||||
|
return channel.read(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,19 +2,18 @@
|
||||||
package net.sourceforge.tuned;
|
package net.sourceforge.tuned;
|
||||||
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.ReadableByteChannel;
|
||||||
import java.nio.channels.WritableByteChannel;
|
import java.nio.channels.WritableByteChannel;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -36,38 +35,29 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Void> {
|
||||||
DONE
|
DONE
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int BUFFER_SIZE = 4 * 1024;
|
|
||||||
|
|
||||||
private URL url;
|
private URL url;
|
||||||
private ByteBuffer postdata;
|
|
||||||
|
|
||||||
private long size = -1;
|
private long size = -1;
|
||||||
private long bytesRead = 0;
|
private long bytesRead = 0;
|
||||||
private DownloadState state = DownloadState.PENDING;
|
private DownloadState state = DownloadState.PENDING;
|
||||||
|
|
||||||
private final Map<String, String> requestHeaders = new HashMap<String, String>();
|
private Map<String, String> postParameters;
|
||||||
private final Map<String, String> responseHeaders = new HashMap<String, String>();
|
private Map<String, String> requestHeaders;
|
||||||
|
private Map<String, List<String>> responseHeaders;
|
||||||
|
|
||||||
|
|
||||||
public DownloadTask(URL url) {
|
public DownloadTask(URL url) {
|
||||||
this(url, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public DownloadTask(URL url, Map<String, String> postParameters) {
|
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
|
||||||
if (postParameters != null) {
|
|
||||||
this.postdata = encodeParameters(postParameters);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected HttpURLConnection createConnection() throws Exception {
|
protected HttpURLConnection createConnection() throws Exception {
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
|
||||||
for (String key : requestHeaders.keySet()) {
|
if (requestHeaders != null) {
|
||||||
connection.addRequestProperty(key, requestHeaders.get(key));
|
for (Entry<String, String> entry : requestHeaders.entrySet()) {
|
||||||
|
connection.addRequestProperty(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
|
@ -80,33 +70,28 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Void> {
|
||||||
|
|
||||||
HttpURLConnection connection = createConnection();
|
HttpURLConnection connection = createConnection();
|
||||||
|
|
||||||
if (postdata != null) {
|
if (postParameters != null) {
|
||||||
connection.setRequestMethod("POST");
|
connection.setRequestMethod("POST");
|
||||||
connection.setDoOutput(true);
|
connection.setDoOutput(true);
|
||||||
WritableByteChannel out = Channels.newChannel(connection.getOutputStream());
|
WritableByteChannel out = Channels.newChannel(connection.getOutputStream());
|
||||||
out.write(postdata);
|
out.write(encodeParameters(postParameters));
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
size = connection.getContentLength();
|
size = connection.getContentLength();
|
||||||
|
|
||||||
for (String key : connection.getHeaderFields().keySet()) {
|
responseHeaders = connection.getHeaderFields();
|
||||||
responseHeaders.put(key, connection.getHeaderField(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
setDownloadState(DownloadState.DOWNLOADING);
|
setDownloadState(DownloadState.DOWNLOADING);
|
||||||
|
|
||||||
InputStream in = connection.getInputStream();
|
ReadableByteChannel in = Channels.newChannel(connection.getInputStream());
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max((int) size, BUFFER_SIZE));
|
ByteBufferOutputStream buffer = new ByteBufferOutputStream((int) (size > 0 ? size : 32 * 1024));
|
||||||
|
|
||||||
byte[] buffer = new byte[BUFFER_SIZE];
|
int count = 0;
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (((len = in.read(buffer)) >= 0) && !isCancelled()) {
|
while (!isCancelled() && ((count = buffer.transferFrom(in)) >= 0)) {
|
||||||
out.write(buffer, 0, len);
|
bytesRead += count;
|
||||||
|
|
||||||
bytesRead += len;
|
|
||||||
|
|
||||||
firePropertyChange(DOWNLOAD_PROGRESS, null, bytesRead);
|
firePropertyChange(DOWNLOAD_PROGRESS, null, bytesRead);
|
||||||
|
|
||||||
|
@ -116,17 +101,19 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Void> {
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// IOException (Premature EOF) is always thrown when the size of
|
// IOException (Premature EOF) is always thrown when the size of
|
||||||
// the response body is not known in advance, so we ignore it
|
// the response body is not known in advance, so we ignore it, if that is the case
|
||||||
if (isDownloadSizeKnown())
|
if (isDownloadSizeKnown())
|
||||||
throw e;
|
throw e;
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
in.close();
|
in.close();
|
||||||
out.close();
|
buffer.close();
|
||||||
|
|
||||||
|
// download either finished or an exception is thrown
|
||||||
|
setDownloadState(DownloadState.DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
setDownloadState(DownloadState.DONE);
|
return buffer.getByteBuffer();
|
||||||
return ByteBuffer.wrap(out.toByteArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,13 +148,28 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setRequestHeader(String name, String value) {
|
public void setRequestHeaders(Map<String, String> requestHeaders) {
|
||||||
requestHeaders.put(name, value);
|
this.requestHeaders = new HashMap<String, String>(requestHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Map<String, String> getResponseHeaders() {
|
public void setPostParameters(Map<String, String> postParameters) {
|
||||||
return Collections.unmodifiableMap(responseHeaders);
|
this.postParameters = new HashMap<String, String>(postParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String, List<String>> getResponseHeaders() {
|
||||||
|
return responseHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String, String> getPostParameters() {
|
||||||
|
return postParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String, String> getRequestHeaders() {
|
||||||
|
return requestHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue