aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKoushik Dutta <koushd@gmail.com>2013-03-23 02:44:30 -0700
committerKoushik Dutta <koushd@gmail.com>2013-03-23 02:44:30 -0700
commita9f3cb26f3065b7c931857ad4a117face4e68ad1 (patch)
tree5c3f63532e193aa115bbb8bfb9aa3e9ff22c1c74
parentb8349e870e13195cc8c683c9c7d616dc1cf5dd45 (diff)
downloadAndroidAsync-a9f3cb26f3065b7c931857ad4a117face4e68ad1.tar.gz
AndroidAsync-a9f3cb26f3065b7c931857ad4a117face4e68ad1.tar.bz2
AndroidAsync-a9f3cb26f3065b7c931857ad4a117face4e68ad1.zip
further refactorings to fixup caching. implement conditional caching (304 not modified)
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java7
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/AsyncSocketWrapper.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/DataEmitterWrapper.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/DataWrapperSocket.java2
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java7
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/SimpleWrapperSocket.java7
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/Util.java15
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/WrapperSocket.java5
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java69
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClientMiddleware.java32
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java10
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java33
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java65
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java418
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/SimpleMiddleware.java24
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/Util.java31
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/libcore/ResponseHeaders.java8
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/libcore/ResponseSource.java2
-rw-r--r--AndroidAsyncSample/src/com/koushikdutta/async/sample/MainActivity.java58
19 files changed, 547 insertions, 256 deletions
diff --git a/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java b/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java
index 2d981ff..8ece9bf 100644
--- a/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java
+++ b/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java
@@ -24,7 +24,7 @@ import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.callback.WritableCallback;
-public class AsyncSSLSocket implements WrapperSocket, IAsyncSSLSocket {
+public class AsyncSSLSocket implements AsyncSocketWrapper, IAsyncSSLSocket {
AsyncSocket mSocket;
BufferedDataEmitter mEmitter;
BufferedDataSink mSink;
@@ -388,6 +388,11 @@ public class AsyncSSLSocket implements WrapperSocket, IAsyncSSLSocket {
return mSocket;
}
+ @Override
+ public DataEmitter getDataEmitter() {
+ return mSocket;
+ }
+
X509Certificate[] peerCertificates;
@Override
public X509Certificate[] getPeerCertificates() {
diff --git a/AndroidAsync/src/com/koushikdutta/async/AsyncSocketWrapper.java b/AndroidAsync/src/com/koushikdutta/async/AsyncSocketWrapper.java
new file mode 100644
index 0000000..c8bcdfa
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/AsyncSocketWrapper.java
@@ -0,0 +1,5 @@
+package com.koushikdutta.async;
+
+public interface AsyncSocketWrapper extends AsyncSocket, DataEmitterWrapper {
+ public AsyncSocket getSocket();
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/DataEmitterWrapper.java b/AndroidAsync/src/com/koushikdutta/async/DataEmitterWrapper.java
new file mode 100644
index 0000000..5b9beee
--- /dev/null
+++ b/AndroidAsync/src/com/koushikdutta/async/DataEmitterWrapper.java
@@ -0,0 +1,5 @@
+package com.koushikdutta.async;
+
+public interface DataEmitterWrapper extends DataEmitter {
+ public DataEmitter getDataEmitter();
+}
diff --git a/AndroidAsync/src/com/koushikdutta/async/DataWrapperSocket.java b/AndroidAsync/src/com/koushikdutta/async/DataWrapperSocket.java
index abd676f..6164faf 100644
--- a/AndroidAsync/src/com/koushikdutta/async/DataWrapperSocket.java
+++ b/AndroidAsync/src/com/koushikdutta/async/DataWrapperSocket.java
@@ -5,7 +5,7 @@ import java.nio.ByteBuffer;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.WritableCallback;
-public class DataWrapperSocket extends FilteredDataEmitter implements WrapperSocket {
+public class DataWrapperSocket extends FilteredDataEmitter implements AsyncSocketWrapper {
private AsyncSocket mSocket;
public void setSocket(AsyncSocket socket) {
mSocket = socket;
diff --git a/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java b/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java
index 496004a..eac9b5b 100644
--- a/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java
@@ -1,10 +1,13 @@
package com.koushikdutta.async;
+import junit.framework.Assert;
+
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.DataCallback;
-public class FilteredDataEmitter implements DataEmitter, DataCallback {
+public class FilteredDataEmitter implements DataEmitter, DataCallback, DataEmitterWrapper {
DataEmitter mEmitter;
+ @Override
public DataEmitter getDataEmitter() {
return mEmitter;
}
@@ -20,6 +23,8 @@ public class FilteredDataEmitter implements DataEmitter, DataCallback {
}
mEmitter = emitter;
mEmitter.setDataCallback(this);
+// mEndCallback = mEmitter.getEndCallback();
+// Assert.assertNull(mEndCallback);
mEmitter.setEndCallback(new CompletedCallback() {
@Override
public void onCompleted(Exception ex) {
diff --git a/AndroidAsync/src/com/koushikdutta/async/SimpleWrapperSocket.java b/AndroidAsync/src/com/koushikdutta/async/SimpleWrapperSocket.java
index 6adfb2c..0ed6c32 100644
--- a/AndroidAsync/src/com/koushikdutta/async/SimpleWrapperSocket.java
+++ b/AndroidAsync/src/com/koushikdutta/async/SimpleWrapperSocket.java
@@ -6,7 +6,7 @@ import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.callback.WritableCallback;
-public class SimpleWrapperSocket implements WrapperSocket {
+public class SimpleWrapperSocket implements AsyncSocketWrapper {
AsyncSocket socket;
public void setSocket(AsyncSocket socket) {
this.socket = socket;
@@ -101,4 +101,9 @@ public class SimpleWrapperSocket implements WrapperSocket {
public AsyncSocket getSocket() {
return socket;
}
+
+ @Override
+ public DataEmitter getDataEmitter() {
+ return socket;
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/Util.java b/AndroidAsync/src/com/koushikdutta/async/Util.java
index beced7e..13436cf 100644
--- a/AndroidAsync/src/com/koushikdutta/async/Util.java
+++ b/AndroidAsync/src/com/koushikdutta/async/Util.java
@@ -169,11 +169,22 @@ public class Util {
public static AsyncSocket getWrappedSocket(AsyncSocket socket, Class wrappedClass) {
if (wrappedClass.isInstance(socket))
return socket;
- while (socket instanceof WrapperSocket) {
- socket = ((WrapperSocket)socket).getSocket();
+ while (socket instanceof AsyncSocketWrapper) {
+ socket = ((AsyncSocketWrapper)socket).getSocket();
if (wrappedClass.isInstance(socket))
return socket;
}
return null;
}
+
+ public static DataEmitter getWrappedDataEmitter(DataEmitter emitter, Class wrappedClass) {
+ if (wrappedClass.isInstance(emitter))
+ return emitter;
+ while (emitter instanceof DataEmitterWrapper) {
+ emitter = ((AsyncSocketWrapper)emitter).getSocket();
+ if (wrappedClass.isInstance(emitter))
+ return emitter;
+ }
+ return null;
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/WrapperSocket.java b/AndroidAsync/src/com/koushikdutta/async/WrapperSocket.java
deleted file mode 100644
index 4d4eb39..0000000
--- a/AndroidAsync/src/com/koushikdutta/async/WrapperSocket.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.koushikdutta.async;
-
-public interface WrapperSocket extends AsyncSocket {
- public AsyncSocket getSocket();
-}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
index fef07a3..4cd4b48 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClient.java
@@ -8,7 +8,6 @@ import java.net.HttpURLConnection;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeoutException;
@@ -34,7 +33,9 @@ import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.ConnectCallback;
import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.callback.RequestCallback;
+import com.koushikdutta.async.http.AsyncHttpClientMiddleware.OnRequestCompleteData;
import com.koushikdutta.async.http.libcore.RawHeaders;
+import com.koushikdutta.async.http.libcore.ResponseHeaders;
import com.koushikdutta.async.stream.OutputStreamDataCallback;
public class AsyncHttpClient {
@@ -54,24 +55,6 @@ public class AsyncHttpClient {
mMiddleware.add(0, middleware);
}
}
-
- HashMap<String, Integer> protocolPort = new HashMap<String, Integer>();
-
- public void setProtocolPort(String protocol, int port) {
- protocolPort.put(protocol, port);
- }
-
- public int getProtocolPort(URI uri) {
- if (uri.getPort() == -1) {
- Integer mapped = protocolPort.get(uri.getScheme());
- if (mapped == null)
- return -1;
- return mapped;
- }
- else {
- return uri.getPort();
- }
- }
AsyncServer mServer;
public AsyncHttpClient(AsyncServer server) {
@@ -125,7 +108,8 @@ public class AsyncHttpClient {
return;
}
final URI uri = request.getUri();
- final Bundle state = new Bundle();
+ final OnRequestCompleteData data = new OnRequestCompleteData();
+ data.request = request;
final InternalConnectCallback socketConnected = new InternalConnectCallback() {
Object scheduled;
@@ -145,19 +129,37 @@ public class AsyncHttpClient {
}
@Override
- public void onConnectCompleted(Exception ex, AsyncSocket socket) {
+ public void onConnectCompleted(Exception ex, AsyncSocket _socket) {
if (cancel.isCanceled()) {
- if (socket != null)
- socket.close();
+ if (_socket != null)
+ _socket.close();
return;
}
+
+ data.socket = _socket;
+ for (AsyncHttpClientMiddleware middleware: mMiddleware) {
+ middleware.onSocket(data);
+ }
+
+ AsyncSocket socket = data.socket;
cancel.socket = socket;
+
if (ex != null) {
reportConnectedCompleted(cancel, ex, null, callback);
return;
}
final AsyncHttpResponseImpl ret = new AsyncHttpResponseImpl(request) {
+ @Override
+ public void setDataEmitter(DataEmitter emitter) {
+ data.bodyEmitter = emitter;
+ for (AsyncHttpClientMiddleware middleware: mMiddleware) {
+ middleware.onBodyDecoder(data);
+ }
+ mHeaders = data.headers;
+ super.setDataEmitter(data.bodyEmitter);
+ }
+
protected void onHeadersReceived() {
try {
if (cancel.isCanceled())
@@ -165,11 +167,14 @@ public class AsyncHttpClient {
if (scheduled != null)
mServer.removeAllCallbacks(scheduled);
- RawHeaders headers = getRawHeaders();
+ data.headers = mHeaders;
for (AsyncHttpClientMiddleware middleware: mMiddleware) {
- middleware.onHeadersReceived(state, getSocket(), request, getHeaders());
+ middleware.onHeadersReceived(data);
}
+ mHeaders = data.headers;
+ RawHeaders headers = mHeaders.getHeaders();
+
if ((headers.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM || headers.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP) && request.getFollowRedirect()) {
URI redirect = URI.create(headers.get("Location"));
@@ -209,8 +214,9 @@ public class AsyncHttpClient {
reportConnectedCompleted(cancel, ex, null, callback);
}
+ data.exception = ex;
for (AsyncHttpClientMiddleware middleware: mMiddleware) {
- middleware.onRequestComplete(state, socket, request, getHeaders(), ex);
+ middleware.onRequestComplete(data);
}
}
@@ -229,18 +235,13 @@ public class AsyncHttpClient {
}
};
- for (AsyncHttpClientMiddleware middleware: mMiddleware) {
- AsyncSocket newSocket = middleware.onSocket(state, socket, request);
- if (newSocket != null)
- socket = newSocket;
- }
-
ret.setSocket(socket);
}
};
-
+ data.connectCallback = socketConnected;
+
for (AsyncHttpClientMiddleware middleware: mMiddleware) {
- if (null != (cancel.socketCancelable = middleware.getSocket(state, request, socketConnected)))
+ if (null != (cancel.socketCancelable = middleware.getSocket(data)))
return;
}
Assert.fail();
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClientMiddleware.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClientMiddleware.java
index 8963629..847d57e 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClientMiddleware.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpClientMiddleware.java
@@ -4,12 +4,36 @@ import android.os.Bundle;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.Cancelable;
+import com.koushikdutta.async.DataEmitter;
import com.koushikdutta.async.callback.ConnectCallback;
import com.koushikdutta.async.http.libcore.ResponseHeaders;
public interface AsyncHttpClientMiddleware {
- public Cancelable getSocket(Bundle state, AsyncHttpRequest request, final ConnectCallback callback);
- public AsyncSocket onSocket(Bundle state, AsyncSocket socket, AsyncHttpRequest request);
- public void onHeadersReceived(Bundle state, AsyncSocket socket, AsyncHttpRequest request, ResponseHeaders headers);
- public void onRequestComplete(Bundle state, AsyncSocket socket, AsyncHttpRequest request, ResponseHeaders headers, Exception ex);
+ public static class GetSocketData {
+ Bundle state = new Bundle();
+ AsyncHttpRequest request;
+ ConnectCallback connectCallback;
+ }
+
+ public static class OnSocketData extends GetSocketData {
+ AsyncSocket socket;
+ }
+
+ public static class OnHeadersReceivedData extends OnSocketData {
+ ResponseHeaders headers;
+ }
+
+ public static class OnBodyData extends OnHeadersReceivedData {
+ DataEmitter bodyEmitter;
+ }
+
+ public static class OnRequestCompleteData extends OnBodyData {
+ Exception exception;
+ }
+
+ public Cancelable getSocket(GetSocketData data);
+ public void onSocket(OnSocketData data);
+ public void onHeadersReceived(OnHeadersReceivedData data);
+ public void onBodyDecoder(OnBodyData data);
+ public void onRequestComplete(OnRequestCompleteData data);
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
index 1997e19..151d19c 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
@@ -20,11 +20,6 @@ import com.koushikdutta.async.http.libcore.RawHeaders;
import com.koushikdutta.async.http.libcore.ResponseHeaders;
abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements AsyncHttpResponse {
- private RawHeaders mRawHeaders = new RawHeaders();
- public RawHeaders getRawHeaders() {
- return mRawHeaders;
- }
-
private AsyncHttpRequestBody mWriter;
public AsyncSocket getSocket() {
@@ -90,13 +85,14 @@ abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements Asyn
protected abstract void onHeadersReceived();
StringCallback mHeaderCallback = new StringCallback() {
+ private RawHeaders mRawHeaders = new RawHeaders();
@Override
public void onStringAvailable(String s) {
try {
if (mRawHeaders.getStatusLine() == null) {
mRawHeaders.setStatusLine(s);
}
- else if (!"\r".equals(s)){
+ else if (!"\r".equals(s)) {
mRawHeaders.addLine(s);
}
else {
@@ -137,7 +133,7 @@ abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements Asyn
private AsyncHttpRequest mRequest;
private AsyncSocket mSocket;
- private ResponseHeaders mHeaders;
+ ResponseHeaders mHeaders;
public AsyncHttpResponseImpl(AsyncHttpRequest request) {
mRequest = request;
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java
index c8844c1..1fe5c81 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLSocketMiddleware.java
@@ -1,27 +1,28 @@
package com.koushikdutta.async.http;
-import android.os.Bundle;
+import java.net.URI;
import com.koushikdutta.async.AsyncSSLSocket;
import com.koushikdutta.async.AsyncSocket;
-import com.koushikdutta.async.IAsyncSSLSocket;
+import com.koushikdutta.async.callback.ConnectCallback;
-public class AsyncSSLSocketMiddleware extends SimpleMiddleware {
- AsyncHttpClient mClient;
+public class AsyncSSLSocketMiddleware extends AsyncSocketMiddleware {
public AsyncSSLSocketMiddleware(AsyncHttpClient client) {
- mClient = client;
- mClient.setProtocolPort("https", 443);
+ super(client, "https", 443);
}
-
+
@Override
- public AsyncSocket onSocket(Bundle state, AsyncSocket socket, AsyncHttpRequest request) {
- if (!request.getUri().getScheme().equals("https"))
- return super.onSocket(state, socket, request);
-
- // don't wrap anything that is already an ssl socket
- if (com.koushikdutta.async.Util.getWrappedSocket(socket, IAsyncSSLSocket.class) != null)
- return super.onSocket(state, socket, request);
-
- return new AsyncSSLSocket(socket, request.getUri().getHost(), mClient.getProtocolPort(request.getUri()));
+ protected ConnectCallback wrapCallback(final ConnectCallback callback, final URI uri, final int port) {
+ return new ConnectCallback() {
+ @Override
+ public void onConnectCompleted(Exception ex, AsyncSocket socket) {
+ if (ex == null) {
+ callback.onConnectCompleted(ex, new AsyncSSLSocket(socket, uri.getHost(), port));
+ }
+ else {
+ callback.onConnectCompleted(ex, socket);
+ }
+ }
+ };
}
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java
index 87f4a39..cbf7031 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncSocketMiddleware.java
@@ -4,21 +4,36 @@ import java.net.URI;
import java.util.HashSet;
import java.util.Hashtable;
-import android.os.Bundle;
import android.util.Log;
-import com.koushikdutta.async.AsyncNetworkSocket;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.Cancelable;
import com.koushikdutta.async.SimpleCancelable;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.ConnectCallback;
-import com.koushikdutta.async.http.libcore.ResponseHeaders;
public class AsyncSocketMiddleware extends SimpleMiddleware {
- public AsyncSocketMiddleware(AsyncHttpClient client) {
+ String scheme;
+ int port;
+ public AsyncSocketMiddleware(AsyncHttpClient client, String scheme, int port) {
mClient = client;
- mClient.setProtocolPort("http", 80);
+ this.scheme = scheme;
+ this.port = port;
+ }
+
+ public int getSchemePort(URI uri) {
+ if (!uri.getScheme().equals(scheme))
+ return -1;
+ if (uri.getPort() == -1) {
+ return port;
+ }
+ else {
+ return uri.getPort();
+ }
+ }
+
+ public AsyncSocketMiddleware(AsyncHttpClient client) {
+ this(client, "http", 80);
}
AsyncHttpClient mClient;
@@ -29,13 +44,15 @@ public class AsyncSocketMiddleware extends SimpleMiddleware {
}
@Override
- public Cancelable getSocket(Bundle state, AsyncHttpRequest request, final ConnectCallback callback) {
- final URI uri = request.getUri();
- final int port = mClient.getProtocolPort(uri);
+ public Cancelable getSocket(final GetSocketData data) {
+ final URI uri = data.request.getUri();
+ final int port = getSchemePort(data.request.getUri());
if (port == -1) {
return null;
}
final String lookup = uri.getScheme() + "//" + uri.getHost() + ":" + port;
+
+ data.state.putBoolean(getClass().getCanonicalName() + ".owned", true);
HashSet<AsyncSocket> sockets = mSockets.get(lookup);
if (sockets != null) {
@@ -48,7 +65,7 @@ public class AsyncSocketMiddleware extends SimpleMiddleware {
@Override
public void run() {
Log.i("AsyncHttpSocket", "Reusing socket.");
- callback.onConnectCompleted(null, socket);
+ data.connectCallback.onConnectCompleted(null, socket);
}
});
// just a noop/dummy, as this can't actually be cancelled.
@@ -58,28 +75,30 @@ public class AsyncSocketMiddleware extends SimpleMiddleware {
}
}
- return mClient.getServer().connectSocket(uri.getHost(), port, callback);
+ return mClient.getServer().connectSocket(uri.getHost(), port, wrapCallback(data.connectCallback, uri, port));
}
@Override
- public void onRequestComplete(Bundle state, final AsyncSocket socket, AsyncHttpRequest request, ResponseHeaders headers, Exception ex) {
- if (com.koushikdutta.async.Util.getWrappedSocket(socket, AsyncNetworkSocket.class) == null) {
- Log.i("AsyncHttpSocket", getClass().getCanonicalName() + " Not keeping non-owned socket: " + state.getString("socket.owner"));
+ public void onRequestComplete(final OnRequestCompleteData data) {
+ if (!data.state.getBoolean(getClass().getCanonicalName() + ".owned", false)) {
+ Log.i("AsyncHttpSocket", getClass().getCanonicalName() + " Not keeping non-owned socket: " + data.state.getString("socket.owner"));
return;
}
- if (ex != null || !socket.isOpen()) {
- socket.close();
+ if (data.exception != null || !data.socket.isOpen()) {
+ data.socket.close();
return;
}
- String kas = headers.getConnection();
+ String kas = data.headers.getConnection();
if (kas == null || !"keep-alive".toLowerCase().equals(kas.toLowerCase())) {
- socket.close();
+ data.socket.close();
return;
}
- final URI uri = request.getUri();
- final int port = mClient.getProtocolPort(uri);
+ Log.i("AsynchttpSocket", "recycling");
+
+ final URI uri = data.request.getUri();
+ final int port = getSchemePort(data.request.getUri());
final String lookup = uri.getScheme() + "//" + uri.getHost() + ":" + port;
HashSet<AsyncSocket> sockets = mSockets.get(lookup);
if (sockets == null) {
@@ -88,14 +107,14 @@ public class AsyncSocketMiddleware extends SimpleMiddleware {
}
final HashSet<AsyncSocket> ss = sockets;
synchronized (sockets) {
- sockets.add(socket);
- socket.setClosedCallback(new CompletedCallback() {
+ sockets.add(data.socket);
+ data.socket.setClosedCallback(new CompletedCallback() {
@Override
public void onCompleted(Exception ex) {
synchronized (ss) {
- ss.remove(socket);
+ ss.remove(data.socket);
}
- socket.setClosedCallback(null);
+ data.socket.setClosedCallback(null);
}
});
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java b/AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java
index 1af857a..4171db0 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/ResponseCacheMiddleware.java
@@ -31,24 +31,26 @@ import java.util.Map;
import javax.net.ssl.SSLPeerUnverifiedException;
-import junit.framework.Assert;
-import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.Base64;
+import android.util.Log;
import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.ByteBufferList;
import com.koushikdutta.async.Cancelable;
import com.koushikdutta.async.DataEmitter;
+import com.koushikdutta.async.DataWrapperSocket;
+import com.koushikdutta.async.FilteredDataEmitter;
import com.koushikdutta.async.IAsyncSSLSocket;
import com.koushikdutta.async.SimpleCancelable;
-import com.koushikdutta.async.DataWrapperSocket;
import com.koushikdutta.async.callback.CompletedCallback;
-import com.koushikdutta.async.callback.ConnectCallback;
import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.callback.WritableCallback;
import com.koushikdutta.async.http.libcore.RawHeaders;
import com.koushikdutta.async.http.libcore.ResponseHeaders;
+import com.koushikdutta.async.http.libcore.ResponseSource;
import com.koushikdutta.async.util.cache.Charsets;
import com.koushikdutta.async.util.cache.DiskLruCache;
import com.koushikdutta.async.util.cache.StrictLineReader;
@@ -72,6 +74,7 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
ResponseCacheMiddleware ret = new ResponseCacheMiddleware();
ret.client = client;
ret.cache = DiskLruCache.open(cacheDir, VERSION, ENTRY_COUNT, size);
+ client.insertMiddleware(ret);
return ret;
}
@@ -105,73 +108,6 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
}
}
- private static class CachingSocket extends DataWrapperSocket {
- CacheRequestImpl cacheRequest;
- ByteArrayOutputStream outputStream;
- ByteBufferList cached;
-
- public CachingSocket() {
- reset();
- }
- @Override
- public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
- if (cached != null) {
- com.koushikdutta.async.Util.emitAllData(this, cached);
- // couldn't emit it all, so just wait for another day...
- if (cached.remaining() > 0)
- return;
- cached = null;
- }
-
- // write to cache... any data not consumed needs to be retained for the next callback
- OutputStream outputStream = this.outputStream;
- try {
- if (outputStream == null && cacheRequest != null)
- outputStream = cacheRequest.getBody();
- if (outputStream != null) {
- for (ByteBuffer b: bb) {
- outputStream.write(b.array(), b.arrayOffset() + b.position(), b.remaining());
- }
- }
- }
- catch (Exception e) {
- outputStream = null;
- abort();
- }
-
- super.onDataAvailable(emitter, bb);
-
- if (outputStream != null && bb.remaining() > 0) {
- cached = new ByteBufferList();
- cached.add(bb);
- bb.clear();
- }
- }
-
- public void abort() {
- if (cacheRequest != null) {
- cacheRequest.abort();
- cacheRequest = null;
- }
-
- outputStream = null;
- }
-
- public void commit() {
- if (cacheRequest != null) {
- try {
- cacheRequest.getBody().close();
- }
- catch (Exception e) {
- }
- }
- }
-
- public void reset() {
- outputStream = new ByteArrayOutputStream();
- cacheRequest = null;
- }
- }
private class CachedSocket implements AsyncSocket {
CacheResponse cacheResponse;
@@ -316,15 +252,37 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
}
}
-// private static final String LOGTAG = "AsyncHttpCache";
+ public static class CacheData implements Parcelable {
+ CacheResponse candidate;
+ ResponseHeaders cachedResponseHeaders;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+
+ }
+
+ private static final String LOGTAG = "AsyncHttpCache";
+ // step 1) see if we can serve request from the cache directly.
+ // also see if this can be turned into a conditional cache request.
@Override
- public Cancelable getSocket(Bundle state, AsyncHttpRequest request, final ConnectCallback callback) {
+ public Cancelable getSocket(final GetSocketData data) {
+ if (cache == null)
+ return null;
+
if (!caching)
return null;
+ if (data.request.getHeaders().isNoCache())
+ return null;
// Log.i(LOGTAG, "getting cache socket: " + request.getUri().toString());
- String key = uriToKey(request.getUri());
+ String key = uriToKey(data.request.getUri());
DiskLruCache.Snapshot snapshot;
Entry entry;
try {
@@ -339,106 +297,302 @@ public class ResponseCacheMiddleware extends SimpleMiddleware {
return null;
}
- if (!entry.matches(request.getUri(), request.getMethod(), request.getHeaders().getHeaders().toMultimap())) {
+ if (!entry.matches(data.request.getUri(), data.request.getMethod(), data.request.getHeaders().getHeaders().toMultimap())) {
snapshot.close();
return null;
}
+
+ ResponseSource responseSource = ResponseSource.NETWORK;
+
+ CacheResponse candidate = entry.isHttps() ? new EntrySecureCacheResponse(entry, snapshot) : new EntryCacheResponse(entry, snapshot);
+
+ Map<String, List<String>> responseHeadersMap;
+ InputStream cachedResponseBody;
+ try {
+ responseHeadersMap = candidate.getHeaders();
+ cachedResponseBody = candidate.getBody();
+ }
+ catch (Exception e) {
+ return null;
+ }
+ if (responseHeadersMap == null || cachedResponseBody == null) {
+ try {
+ cachedResponseBody.close();
+ }
+ catch (Exception e) {
+ }
+ return null;
+ }
+
+ RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(responseHeadersMap);
+ ResponseHeaders cachedResponseHeaders = new ResponseHeaders(data.request.getUri(), rawResponseHeaders);
-// Log.i(LOGTAG, "Serving from cache");
- final CachedSocket socket = entry.isHttps() ? new CachedSSLSocket(new EntrySecureCacheResponse(entry, snapshot)) : new CachedSocket(new EntryCacheResponse(entry, snapshot));
- client.getServer().post(new Runnable() {
- @Override
- public void run() {
- callback.onConnectCompleted(null, socket);
- socket.spewInternal();
+ ////
+ if (false) {
+ final CachedSocket ss = entry.isHttps() ? new CachedSSLSocket((EntrySecureCacheResponse)candidate) : new CachedSocket((EntryCacheResponse)candidate);
+
+ ss.pending.add(ByteBuffer.wrap(rawResponseHeaders.toHeaderString().getBytes()));
+
+ client.getServer().post(new Runnable() {
+ @Override
+ public void run() {
+ data.connectCallback.onConnectCompleted(null, ss);
+ ss.spewInternal();
+ }
+ });
+
+ if (true)
+ return new SimpleCancelable();
+ }
+ ///
+
+
+ long now = System.currentTimeMillis();
+ responseSource = cachedResponseHeaders.chooseResponseSource(now, data.request.getHeaders());
+
+ if (responseSource == ResponseSource.CACHE) {
+ final CachedSocket socket = entry.isHttps() ? new CachedSSLSocket((EntrySecureCacheResponse)candidate) : new CachedSocket((EntryCacheResponse)candidate);
+
+ client.getServer().post(new Runnable() {
+ @Override
+ public void run() {
+ data.connectCallback.onConnectCompleted(null, socket);
+ socket.spewInternal();
+ }
+ });
+ }
+ else if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
+ CacheData cacheData = new CacheData();
+ cacheData.cachedResponseHeaders = cachedResponseHeaders;
+ cacheData.candidate = candidate;
+ data.state.putParcelable("cache-data", cacheData);
+
+ return null;
+ }
+ else {
+ // NETWORK or other
+ try {
+ cachedResponseBody.close();
+ }
+ catch (Exception e) {
}
- });
+ return null;
+ }
+
return new SimpleCancelable();
}
- @Override
- public AsyncSocket onSocket(Bundle state, AsyncSocket socket, AsyncHttpRequest request) {
- if (!caching)
- return socket;
+ private static class BodyCacher extends FilteredDataEmitter implements Parcelable {
+ CacheRequestImpl cacheRequest;
+ ByteBufferList cached;
+
+ @Override
+ public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
+ if (cached != null) {
+ com.koushikdutta.async.Util.emitAllData(this, cached);
+ // couldn't emit it all, so just wait for another day...
+ if (cached.remaining() > 0)
+ return;
+ cached = null;
+ }
- // dont cache socket served from cache
- if (com.koushikdutta.async.Util.getWrappedSocket(socket, CachedSocket.class) != null)
- return socket;
+ // write to cache... any data not consumed needs to be retained for the next callback
+ try {
+ if (cacheRequest != null) {
+ OutputStream outputStream = cacheRequest.getBody();
+ if (outputStream != null) {
+ for (ByteBuffer b: bb) {
+ outputStream.write(b.array(), b.arrayOffset() + b.position(), b.remaining());
+ }
+ }
+ else {
+ abort();
+ }
+ }
+ }
+ catch (Exception e) {
+ abort();
+ }
+
+ super.onDataAvailable(emitter, bb);
+
+ if (cacheRequest != null && bb.remaining() > 0) {
+ cached = new ByteBufferList();
+ cached.add(bb);
+ bb.clear();
+ }
+ }
- if (cache == null)
- return socket;
+ public void abort() {
+ if (cacheRequest != null) {
+ cacheRequest.abort();
+ cacheRequest = null;
+ }
+ }
- if (!request.getMethod().equals(AsyncHttpGet.METHOD))
- return socket;
+ public void commit() {
+ if (cacheRequest != null) {
+ try {
+ cacheRequest.getBody().close();
+ }
+ catch (Exception e) {
+ }
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+ }
+
+ private static class BodySpewer extends FilteredDataEmitter {
+ CacheResponse cacheResponse;
+
+ void spewInternal() {
+ if (pending.remaining() > 0) {
+ com.koushikdutta.async.Util.emitAllData(BodySpewer.this, pending);
+ if (pending.remaining() > 0)
+ return;
+ }
+
+ // fill pending
+ try {
+ while (pending.remaining() == 0) {
+ ByteBuffer buffer = ByteBuffer.allocate(8192);
+ int read = cacheResponse.getBody().read(buffer.array());
+ if (read == -1) {
+ allowEnd = true;
+ report(null);
+ return;
+ }
+ buffer.limit(read);
+ pending.add(buffer);
+ com.koushikdutta.async.Util.emitAllData(BodySpewer.this, pending);
+ }
+ }
+ catch (IOException e) {
+ allowEnd = true;
+ report(e);
+ }
+ }
+
+ ByteBufferList pending = new ByteBufferList();
+ void spew() {
+ getServer().post(new Runnable() {
+ @Override
+ public void run() {
+ spewInternal();
+ }
+ });
+ }
- try {
- CachingSocket ret = new CachingSocket();
- ret.setSocket(socket);
- return ret;
+ boolean paused;
+ @Override
+ public void resume() {
+ paused = false;
+ spew();
}
- catch (Exception e) {
- return socket;
+
+ @Override
+ public boolean isPaused() {
+ return paused;
+ }
+
+ boolean allowEnd;
+ @Override
+ protected void report(Exception e) {
+ if (!allowEnd)
+ return;
+ super.report(e);
}
}
+
+ // step 3) if this is a conditional cache request, serve it from the cache if necessary
+ // otherwise, see if it is cacheable
@Override
- public void onHeadersReceived(Bundle state, AsyncSocket socket, AsyncHttpRequest request, ResponseHeaders headers) {
-// Log.i(LOGTAG, "headers: " + request.getUri().toString());
- CachingSocket caching = (CachingSocket)com.koushikdutta.async.Util.getWrappedSocket(socket, CachingSocket.class);
- if (caching == null)
+ public void onBodyDecoder(OnBodyData data) {
+ CacheData cacheData = data.state.getParcelable("cache-data");
+ if (cacheData != null) {
+ if (cacheData.cachedResponseHeaders.validate(data.headers)) {
+ data.headers = cacheData.cachedResponseHeaders.combine(data.headers);
+ data.headers.getHeaders().setStatusLine(cacheData.cachedResponseHeaders.getHeaders().getStatusLine());
+
+ BodySpewer bodySpewer = new BodySpewer();
+ bodySpewer.cacheResponse = cacheData.candidate;
+ bodySpewer.setDataEmitter(data.bodyEmitter);
+ data.bodyEmitter = bodySpewer;
+ bodySpewer.spew();
+ return;
+ }
+
+ // did not validate, so fall through and cache the response
+ data.state.remove("cache-data");
+ }
+
+ if (!caching)
return;
- if (!headers.isCacheable(request.getHeaders())) {
- caching.abort();
+ if (!data.headers.isCacheable(data.request.getHeaders()))
return;
- }
-
- String key = uriToKey(request.getUri());
- RawHeaders varyHeaders = request.getHeaders().getHeaders().getAll(headers.getVaryFields());
- Entry entry = new Entry(request.getUri(), varyHeaders, request, headers);
+
+ String key = uriToKey(data.request.getUri());
+ RawHeaders varyHeaders = data.request.getHeaders().getHeaders().getAll(data.headers.getVaryFields());
+ Entry entry = new Entry(data.request.getUri(), varyHeaders, data.request, data.headers);
DiskLruCache.Editor editor = null;
+ BodyCacher cacher = new BodyCacher();
try {
editor = cache.edit(key);
if (editor == null) {
-// Log.i(LOGTAG, "can't cache");
- caching.outputStream = null;
+ // Log.i(LOGTAG, "can't cache");
return;
}
entry.writeTo(editor);
- caching.cacheRequest = new CacheRequestImpl(editor);
- Assert.assertNotNull(caching.outputStream);
- byte[] bytes = caching.outputStream.toByteArray();
- caching.outputStream = null;
- caching.cacheRequest.getBody().write(bytes);
+
+
+ cacher.cacheRequest = new CacheRequestImpl(editor);
+ if (cacher.cacheRequest.getBody() == null)
+ return;
+// cacher.cacheData =
+ cacher.setDataEmitter(data.bodyEmitter);
+ data.bodyEmitter = cacher;
+
+ data.state.putParcelable("body-cacher", cacher);
}
catch (Exception e) {
-// Log.e(LOGTAG, "error", e);
- caching.outputStream = null;
- if (caching.cacheRequest != null)
- caching.cacheRequest.abort();
- caching.cacheRequest = null;
+ // Log.e(LOGTAG, "error", e);
+ if (cacher.cacheRequest != null)
+ cacher.cacheRequest.abort();
+ cacher.cacheRequest = null;
}
}
+
@Override
- public void onRequestComplete(Bundle state, AsyncSocket socket, AsyncHttpRequest request, ResponseHeaders headers, Exception ex) {
- CachingSocket caching = (CachingSocket)com.koushikdutta.async.Util.getWrappedSocket(socket, CachingSocket.class);
- if (caching == null)
+ public void onRequestComplete(OnRequestCompleteData data) {
+// CachingSocket caching = (CachingSocket)com.koushikdutta.async.Util.getWrappedSocket(data.socket, CachingSocket.class);
+// if (caching == null)
+// return;
+
+ BodyCacher cacher = data.state.getParcelable("body-cacher");
+ if (cacher == null)
return;
// Log.i(LOGTAG, "Cache done: " + ex);
try {
- if (ex != null)
- caching.abort();
+ if (data.exception != null)
+ cacher.abort();
else
- caching.commit();
+ cacher.commit();
}
catch (Exception e) {
}
-
- // reset for socket reuse
- caching.reset();
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/SimpleMiddleware.java b/AndroidAsync/src/com/koushikdutta/async/http/SimpleMiddleware.java
index ba60e58..1930016 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/SimpleMiddleware.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/SimpleMiddleware.java
@@ -1,28 +1,32 @@
package com.koushikdutta.async.http;
-import android.os.Bundle;
-
-import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.Cancelable;
-import com.koushikdutta.async.callback.ConnectCallback;
-import com.koushikdutta.async.http.libcore.ResponseHeaders;
public class SimpleMiddleware implements AsyncHttpClientMiddleware {
+
@Override
- public Cancelable getSocket(Bundle state, AsyncHttpRequest request, ConnectCallback callback) {
+ public Cancelable getSocket(GetSocketData data) {
return null;
}
@Override
- public AsyncSocket onSocket(Bundle state, AsyncSocket socket, AsyncHttpRequest request) {
- return null;
+ public void onSocket(OnSocketData data) {
+
}
@Override
- public void onHeadersReceived(Bundle state, AsyncSocket socket, AsyncHttpRequest request, ResponseHeaders headers) {
+ public void onHeadersReceived(OnHeadersReceivedData data) {
+
}
@Override
- public void onRequestComplete(Bundle state, AsyncSocket socket, AsyncHttpRequest request, ResponseHeaders headers, Exception ex) {
+ public void onBodyDecoder(OnBodyData data) {
+
}
+
+ @Override
+ public void onRequestComplete(OnRequestCompleteData data) {
+
+ }
+
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/Util.java b/AndroidAsync/src/com/koushikdutta/async/http/Util.java
index cafe9fc..67cdee7 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/Util.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/Util.java
@@ -1,6 +1,8 @@
package com.koushikdutta.async.http;
+import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.DataEmitter;
+import com.koushikdutta.async.FilteredDataEmitter;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.http.filter.ChunkedInputFilter;
import com.koushikdutta.async.http.filter.ContentLengthFilter;
@@ -74,15 +76,24 @@ public class Util {
chunker.setDataEmitter(emitter);
emitter = chunker;
}
- else if (server) {
- // if this is the server, and the client has not indicated a request body, the client is done
- emitter.getServer().post(new Runnable() {
- @Override
- public void run() {
- reporter.onCompleted(null);
- }
- });
- return emitter;
+ else {
+ if (server || headers.getStatusLine().contains("HTTP/1.1")) {
+ // if this is the server, and the client has not indicated a request body, the client is done
+ final AsyncServer srv = emitter.getServer();
+ final FilteredDataEmitter wrapped = new FilteredDataEmitter() {
+ {
+ srv.post(new Runnable() {
+ @Override
+ public void run() {
+ report(null);
+ }
+ });
+ }
+ };
+ wrapped.setDataEmitter(emitter);
+ emitter = wrapped;
+ return emitter;
+ }
}
if ("gzip".equals(headers.get("Content-Encoding"))) {
@@ -96,7 +107,7 @@ public class Util {
emitter = inflater;
}
- // conversely, if this is the client, and the server has not indicated a request body, we do not report
+ // conversely, if this is the client (http 1.0), and the server has not indicated a request body, we do not report
// the close/end event until the server actually closes the connection.
return emitter;
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/libcore/ResponseHeaders.java b/AndroidAsync/src/com/koushikdutta/async/http/libcore/ResponseHeaders.java
index 8f7bb65..30f0bf3 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/libcore/ResponseHeaders.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/libcore/ResponseHeaders.java
@@ -435,15 +435,15 @@ public final class ResponseHeaders {
return ResponseSource.CACHE;
}
- if (lastModified != null) {
+ if (etag != null) {
+ request.setIfNoneMatch(etag);
+ }
+ else if (lastModified != null) {
request.setIfModifiedSince(lastModified);
} else if (servedDate != null) {
request.setIfModifiedSince(servedDate);
}
- if (etag != null) {
- request.setIfNoneMatch(etag);
- }
return request.hasConditions()
? ResponseSource.CONDITIONAL_CACHE
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/libcore/ResponseSource.java b/AndroidAsync/src/com/koushikdutta/async/http/libcore/ResponseSource.java
index d1eaed4..3501b0f 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/libcore/ResponseSource.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/libcore/ResponseSource.java
@@ -16,7 +16,7 @@
package com.koushikdutta.async.http.libcore;
-enum ResponseSource {
+public enum ResponseSource {
/**
* Return the response from the cache immediately.
diff --git a/AndroidAsyncSample/src/com/koushikdutta/async/sample/MainActivity.java b/AndroidAsyncSample/src/com/koushikdutta/async/sample/MainActivity.java
index 115f312..4b2fe88 100644
--- a/AndroidAsyncSample/src/com/koushikdutta/async/sample/MainActivity.java
+++ b/AndroidAsyncSample/src/com/koushikdutta/async/sample/MainActivity.java
@@ -2,16 +2,22 @@ package com.koushikdutta.async.sample;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
+import android.net.http.HttpResponseCache;
import android.os.Bundle;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
@@ -35,11 +41,55 @@ public class MainActivity extends Activity {
ImageView desksms;
ImageView chart;
+ @SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
+ new Thread() {
+ public void run() {
+ try {
+ HttpResponseCache cache;
+ try {
+ File httpCacheDir = new File(getCacheDir(), "http");
+ long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
+ cache = HttpResponseCache.install(httpCacheDir, httpCacheSize);
+ }
+ catch (IOException e) {
+ Log.i("cache", "HTTP response cache installation failed:" + e);
+ return;
+ }
+ URL url = new URL("https://desksms.appspot.com");
+ URLConnection conn = url.openConnection();
+ for (String header: conn.getRequestProperties().keySet()) {
+ System.out.println(header + ": ");
+ for (String value: conn.getRequestProperties().get(header)) {
+ System.out.println(value);
+ }
+ }
+ for (String header: conn.getHeaderFields().keySet()) {
+ System.out.println(header + ": " + conn.getHeaderField(header));
+ }
+ InputStream in = conn.getInputStream();
+ int count = 0;
+ while (in.read() != -1) {
+ count++;
+ }
+ in.close();
+ System.out.println("count: " + count);
+
+ System.out.println("cache count: " + cache.getHitCount());
+ System.out.println("network count: " + cache.getNetworkCount());
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ };
+ }.start();
+
+
if (cacher == null) {
+
try {
cacher = ResponseCacheMiddleware.addCache(AsyncHttpClient.getDefaultInstance(), getFileStreamPath("asynccache"), 1024 * 1024 * 10);
cacher.setCaching(false);
@@ -149,8 +199,8 @@ public class MainActivity extends Activity {
chart.setImageBitmap(null);
getFile(rommanager, "https://raw.github.com/koush/AndroidAsync/master/rommanager.png", getFileStreamPath(randomFile()).getAbsolutePath());
- getFile(tether, "https://raw.github.com/koush/AndroidAsync/master/tether.png", getFileStreamPath(randomFile()).getAbsolutePath());
- getFile(desksms, "https://raw.github.com/koush/AndroidAsync/master/desksms.png", getFileStreamPath(randomFile()).getAbsolutePath());
- getChartFile();
+// getFile(tether, "https://raw.github.com/koush/AndroidAsync/master/tether.png", getFileStreamPath(randomFile()).getAbsolutePath());
+// getFile(desksms, "https://raw.github.com/koush/AndroidAsync/master/desksms.png", getFileStreamPath(randomFile()).getAbsolutePath());
+// getChartFile();
}
}