aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java4
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/LineEmitter.java39
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequestBody.java3
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java3
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/JSONRequestBody.java4
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/MultipartCallback.java2
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/MultipartFormDataBody.java98
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/UrlEncodedFormBody.java36
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/Util.java39
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedInputFilter.java6
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java11
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpRequestBodyBase.java8
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequestImpl.java9
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/BoundaryEmitter.java2
-rw-r--r--AndroidAsync/src/com/koushikdutta/async/http/server/UnknownRequestBody.java16
15 files changed, 152 insertions, 128 deletions
diff --git a/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java b/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java
index ee7c2bd..496004a 100644
--- a/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java
@@ -10,8 +10,8 @@ public class FilteredDataEmitter implements DataEmitter, DataCallback {
}
protected void report(Exception e) {
- if (mEndCallback != null)
- mEndCallback.onCompleted(e);
+ if (getEndCallback() != null)
+ getEndCallback().onCompleted(e);
}
public void setDataEmitter(DataEmitter emitter) {
diff --git a/AndroidAsync/src/com/koushikdutta/async/LineEmitter.java b/AndroidAsync/src/com/koushikdutta/async/LineEmitter.java
index 9694d5b..5bcf164 100644
--- a/AndroidAsync/src/com/koushikdutta/async/LineEmitter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/LineEmitter.java
@@ -4,34 +4,13 @@ import junit.framework.Assert;
import com.koushikdutta.async.callback.DataCallback;
-public class LineEmitter {
+public class LineEmitter implements DataCallback {
static public interface StringCallback {
public void onStringAvailable(String s);
}
StringBuilder data = new StringBuilder();
- public LineEmitter(final DataEmitter emitter) {
- emitter.setDataCallback(new DataCallback() {
- @Override
- public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
- while (bb.remaining() > 0) {
- byte b = bb.get();
- if (b == '\n') {
- Assert.assertNotNull(mLineCallback);
- mLineCallback.onStringAvailable(data.toString());
- if (emitter.getDataCallback() != this)
- return;
- data = new StringBuilder();
- }
- else {
- data.append((char)b);
- }
- }
- }
- });
- }
-
StringCallback mLineCallback;
public void setLineCallback(StringCallback callback) {
mLineCallback = callback;
@@ -40,4 +19,20 @@ public class LineEmitter {
public StringCallback getLineCallback() {
return mLineCallback;
}
+
+ @Override
+ public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
+ while (bb.remaining() > 0) {
+ byte b = bb.get();
+ if (b == '\n') {
+ Assert.assertNotNull(mLineCallback);
+ mLineCallback.onStringAvailable(data.toString());
+ data = new StringBuilder();
+ return;
+ }
+ else {
+ data.append((char)b);
+ }
+ }
+ }
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequestBody.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequestBody.java
index bc67aad..4edcdd7 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequestBody.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpRequestBody.java
@@ -1,9 +1,8 @@
package com.koushikdutta.async.http;
-import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.DataCallback;
-public interface AsyncHttpRequestBody extends DataCallback, CompletedCallback {
+public interface AsyncHttpRequestBody extends DataCallback {
public void write(AsyncHttpRequest request, AsyncHttpResponse sink);
public String getContentType();
public boolean readFullyOnRequest();
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
index a4a00e5..1997e19 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponseImpl.java
@@ -62,7 +62,8 @@ abstract class AsyncHttpResponseImpl extends FilteredDataEmitter implements Asyn
}
});
- LineEmitter liner = new LineEmitter(exchange);
+ LineEmitter liner = new LineEmitter();
+ exchange.setDataCallback(liner);
liner.setLineCallback(mHeaderCallback);
mSocket.setEndCallback(mReporter);
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/JSONRequestBody.java b/AndroidAsync/src/com/koushikdutta/async/http/JSONRequestBody.java
index 2085938..eb0a926 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/JSONRequestBody.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/JSONRequestBody.java
@@ -28,10 +28,6 @@ public class JSONRequestBody implements AsyncHttpRequestBody {
}
@Override
- public void onCompleted(Exception ex) {
- }
-
- @Override
public void write(AsyncHttpRequest request, AsyncHttpResponse sink) {
Util.writeAll(sink, mBodyBytes, new CompletedCallback() {
@Override
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/MultipartCallback.java b/AndroidAsync/src/com/koushikdutta/async/http/MultipartCallback.java
index e3eb950..4ecc34f 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/MultipartCallback.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/MultipartCallback.java
@@ -4,5 +4,5 @@ import com.koushikdutta.async.callback.DataCallback;
public interface MultipartCallback {
- public DataCallback onPart(Part part);
+ public void onPart(Part part);
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/MultipartFormDataBody.java b/AndroidAsync/src/com/koushikdutta/async/http/MultipartFormDataBody.java
index 5016447..d816736 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/MultipartFormDataBody.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/MultipartFormDataBody.java
@@ -1,48 +1,64 @@
package com.koushikdutta.async.http;
+import junit.framework.Assert;
+
+import com.koushikdutta.async.ByteBufferList;
+import com.koushikdutta.async.DataEmitter;
import com.koushikdutta.async.LineEmitter;
import com.koushikdutta.async.LineEmitter.StringCallback;
import com.koushikdutta.async.NullDataCallback;
-import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.http.libcore.RawHeaders;
-import com.koushikdutta.async.http.server.AsyncHttpRequestBodyBase;
import com.koushikdutta.async.http.server.BoundaryEmitter;
-public class MultipartFormDataBody extends AsyncHttpRequestBodyBase {
+public class MultipartFormDataBody extends BoundaryEmitter implements AsyncHttpRequestBody {
+ LineEmitter liner;
+
+ @Override
+ protected void onBoundaryStart() {
+ final RawHeaders headers = new RawHeaders();
+ liner = new LineEmitter();
+ liner.setLineCallback(new StringCallback() {
+ @Override
+ public void onStringAvailable(String s) {
+ if (!"\r".equals(s)){
+ headers.addLine(s);
+ }
+ else {
+ liner = null;
+ setDataCallback(null);
+ if (mCallback != null)
+ mCallback.onPart(new Part(headers));
+ if (getDataCallback() == null)
+ setDataCallback(new NullDataCallback());
+ }
+ }
+ });
+ setDataCallback(liner);
+ }
+
+ @Override
+ protected void report(Exception e) {
+ super.report(e);
+ }
+
+ @Override
+ public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
+ if (liner != null) {
+ liner.onDataAvailable(emitter, bb);
+ return;
+ }
+ super.onDataAvailable(emitter, bb);
+ }
+
public static final String CONTENT_TYPE = "multipart/form-data";
- BoundaryEmitter boundaryEmitter;
- String boundary;
public MultipartFormDataBody(String contentType, String[] values) {
- super(contentType);
for (String value: values) {
String[] splits = value.split("=");
if (splits.length != 2)
continue;
if (!"boundary".equals(splits[0]))
continue;
- boundary = splits[1];
- boundaryEmitter = new BoundaryEmitter(boundary) {
- @Override
- protected void onBoundaryStart() {
- final RawHeaders headers = new RawHeaders();
- new LineEmitter(boundaryEmitter).setLineCallback(new StringCallback() {
- @Override
- public void onStringAvailable(String s) {
- if (!"\r".equals(s)){
- headers.addLine(s);
- }
- else {
- boundaryEmitter.setDataCallback(onPart(new Part(headers)));
- }
- }
- });
- }
- @Override
- protected void onBoundaryEnd() {
-// System.out.println("boundary end");
- }
- };
- boundaryEmitter.setDataEmitter(this);
+ setBoundary(splits[1]);
return;
}
report(new Exception ("No boundary found for multipart/form-data"));
@@ -57,11 +73,23 @@ public class MultipartFormDataBody extends AsyncHttpRequestBodyBase {
return mCallback;
}
- private DataCallback onPart(Part part) {
-// System.out.println("here");
-// System.out.println(headers.toHeaderString());
- if (mCallback == null)
- return new NullDataCallback();
- return mCallback.onPart(part);
+ @Override
+ public void write(AsyncHttpRequest request, AsyncHttpResponse sink) {
+ Assert.fail();
+ }
+
+ @Override
+ public String getContentType() {
+ return CONTENT_TYPE;
+ }
+
+ @Override
+ public boolean readFullyOnRequest() {
+ return false;
+ }
+
+ @Override
+ public int length() {
+ return -1;
}
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/UrlEncodedFormBody.java b/AndroidAsync/src/com/koushikdutta/async/http/UrlEncodedFormBody.java
index fa9bb55..b653a88 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/UrlEncodedFormBody.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/UrlEncodedFormBody.java
@@ -61,7 +61,7 @@ public class UrlEncodedFormBody implements AsyncHttpRequestBody {
return CONTENT_TYPE;
}
- private ByteBufferList data = null;
+ private ByteBufferList data;
@Override
public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
if (data == null)
@@ -86,30 +86,28 @@ public class UrlEncodedFormBody implements AsyncHttpRequestBody {
return Collections.unmodifiableMap(map);
}
- @Override
- public void onCompleted(Exception ex) {
- ArrayList<NameValuePair> params;
- mParameters = params = new ArrayList<NameValuePair>();
- String[] pairs = data.peekString().split("&");
- for (String p : pairs) {
- String[] pair = p.split("=", 2);
- if (pair.length == 0)
- continue;
- String name = Uri.decode(pair[0]);
- String value = null;
- if (pair.length == 2)
- value = Uri.decode(pair[1]);
- params.add(new BasicNameValuePair(name, value));
- }
- }
-
public Iterable<NameValuePair> getParameters() {
+ if (mParameters == null && data != null) {
+ ArrayList<NameValuePair> params;
+ mParameters = params = new ArrayList<NameValuePair>();
+ String[] pairs = data.peekString().split("&");
+ for (String p : pairs) {
+ String[] pair = p.split("=", 2);
+ if (pair.length == 0)
+ continue;
+ String name = Uri.decode(pair[0]);
+ String value = null;
+ if (pair.length == 2)
+ value = Uri.decode(pair[1]);
+ params.add(new BasicNameValuePair(name, value));
+ }
+ }
return mParameters;
}
public Map<String, String> getParameterMap() {
HashMap<String, String> map = new HashMap<String, String>();
- for (NameValuePair pair: mParameters) {
+ for (NameValuePair pair: getParameters()) {
if (!map.containsKey(pair.getName()))
map.put(pair.getName(), pair.getValue());
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/Util.java b/AndroidAsync/src/com/koushikdutta/async/http/Util.java
index 189dd23..cafe9fc 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/Util.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/Util.java
@@ -1,20 +1,16 @@
package com.koushikdutta.async.http;
-import junit.framework.Assert;
-import android.util.Log;
-
-import com.koushikdutta.async.ByteBufferList;
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;
import com.koushikdutta.async.http.filter.GZIPInputFilter;
import com.koushikdutta.async.http.filter.InflaterInputFilter;
import com.koushikdutta.async.http.libcore.RawHeaders;
import com.koushikdutta.async.http.server.UnknownRequestBody;
public class Util {
- public static AsyncHttpRequestBody getBody(DataEmitter emitter, final CompletedCallback reporter, RawHeaders headers) {
+ public static AsyncHttpRequestBody getBody(DataEmitter emitter, CompletedCallback reporter, RawHeaders headers) {
String contentType = headers.get("Content-Type");
if (contentType != null) {
String[] values = contentType.split(";");
@@ -22,18 +18,23 @@ public class Util {
values[i] = values[i].trim();
}
for (String ct: values) {
- if (UrlEncodedFormBody.CONTENT_TYPE.equals(ct))
- return new UrlEncodedFormBody();
+ if (UrlEncodedFormBody.CONTENT_TYPE.equals(ct)) {
+ UrlEncodedFormBody ret = new UrlEncodedFormBody();
+ emitter.setDataCallback(ret);
+ return ret;
+ }
if (MultipartFormDataBody.CONTENT_TYPE.equals(ct)) {
MultipartFormDataBody ret = new MultipartFormDataBody(contentType, values);
ret.setDataEmitter(emitter);
- ret.setEndCallback(null);
- emitter.setEndCallback(reporter);
+ ret.setEndCallback(reporter);
return ret;
}
}
}
- return new UnknownRequestBody(contentType);
+
+ UnknownRequestBody ret = new UnknownRequestBody(contentType);
+ emitter.setDataCallback(ret);
+ return ret;
}
public static DataEmitter getBodyDecoder(DataEmitter emitter, RawHeaders headers, boolean server, final CompletedCallback reporter) {
@@ -64,26 +65,13 @@ public class Util {
});
return emitter;
}
- FilteredDataEmitter contentLengthWatcher = new FilteredDataEmitter() {
- int totalRead = 0;
- @Override
- public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
- Assert.assertTrue(totalRead < contentLength);
- ByteBufferList list = bb.get(Math.min(contentLength - totalRead, bb.remaining()));
- totalRead += list.remaining();
- super.onDataAvailable(emitter, list);
- if (totalRead == contentLength)
- report(null);
- }
- };
+ ContentLengthFilter contentLengthWatcher = new ContentLengthFilter(contentLength);
contentLengthWatcher.setDataEmitter(emitter);
- contentLengthWatcher.setEndCallback(reporter);
emitter = contentLengthWatcher;
}
else if ("chunked".equalsIgnoreCase(headers.get("Transfer-Encoding"))) {
ChunkedInputFilter chunker = new ChunkedInputFilter();
chunker.setDataEmitter(emitter);
- chunker.setEndCallback(reporter);
emitter = chunker;
}
else if (server) {
@@ -94,6 +82,7 @@ public class Util {
reporter.onCompleted(null);
}
});
+ return emitter;
}
if ("gzip".equals(headers.get("Content-Encoding"))) {
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedInputFilter.java b/AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedInputFilter.java
index 36d9227..411dbf0 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedInputFilter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedInputFilter.java
@@ -103,9 +103,9 @@ public class ChunkedInputFilter extends FilteredDataEmitter {
mChunkLength = 0;
break;
case COMPLETE:
- Exception fail = new Exception("Continued receiving data after chunk complete");
- report(fail);
- report(fail);
+ Assert.fail();
+// Exception fail = new Exception("Continued receiving data after chunk complete");
+// report(fail);
return;
}
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java b/AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java
index 9b8797f..544358e 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java
@@ -1,5 +1,6 @@
package com.koushikdutta.async.http.filter;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.zip.Inflater;
@@ -12,13 +13,20 @@ import com.koushikdutta.async.Util;
public class InflaterInputFilter extends FilteredDataEmitter {
private Inflater mInflater;
+
+ @Override
+ protected void report(Exception e) {
+ if (e != null && mInflater.getRemaining() > 0) {
+ e = new IOException("data still remaining in inflater");
+ }
+ super.report(e);
+ }
@Override
public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
try {
ByteBufferList transformed = new ByteBufferList();
ByteBuffer output = ByteBuffer.allocate(bb.remaining() * 2);
- int totalInflated = 0;
int totalRead = 0;
while (bb.size() > 0) {
ByteBuffer b = bb.remove();
@@ -27,7 +35,6 @@ public class InflaterInputFilter extends FilteredDataEmitter {
mInflater.setInput(b.array(), b.arrayOffset() + b.position(), b.remaining());
do {
int inflated = mInflater.inflate(output.array(), output.arrayOffset() + output.position(), output.remaining());
- totalInflated += inflated;
output.position(output.position() + inflated);
if (!output.hasRemaining()) {
output.limit(output.position());
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpRequestBodyBase.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpRequestBodyBase.java
index eaa21e4..c04c2b4 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpRequestBodyBase.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpRequestBodyBase.java
@@ -23,10 +23,10 @@ public class AsyncHttpRequestBodyBase extends FilteredDataEmitter implements Asy
return mContentType;
}
- @Override
- public void onCompleted(Exception ex) {
- report(ex);
- }
+// @Override
+// public void onCompleted(Exception ex) {
+// report(ex);
+// }
@Override
public boolean readFullyOnRequest() {
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequestImpl.java b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequestImpl.java
index 307519b..758cdd1 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequestImpl.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequestImpl.java
@@ -28,8 +28,8 @@ public abstract class AsyncHttpServerRequestImpl extends FilteredDataEmitter imp
@Override
public void onCompleted(Exception e) {
- if (mBody != null)
- mBody.onCompleted(e);
+// if (mBody != null)
+// mBody.onCompleted(e);
report(e);
}
@@ -56,8 +56,8 @@ public abstract class AsyncHttpServerRequestImpl extends FilteredDataEmitter imp
}
else {
DataEmitter emitter = Util.getBodyDecoder(mSocket, mRawHeaders, true, mReporter);
+ emitter.setEndCallback(mReporter);
mBody = Util.getBody(emitter, mReporter, mRawHeaders);
- emitter.setDataCallback(mBody);
onHeadersReceived();
}
}
@@ -74,7 +74,8 @@ public abstract class AsyncHttpServerRequestImpl extends FilteredDataEmitter imp
void setSocket(AsyncSocket socket) {
mSocket = socket;
- LineEmitter liner = new LineEmitter(mSocket);
+ LineEmitter liner = new LineEmitter();
+ mSocket.setDataCallback(liner);
liner.setLineCallback(mHeaderCallback);
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/BoundaryEmitter.java b/AndroidAsync/src/com/koushikdutta/async/http/server/BoundaryEmitter.java
index f893164..58c9923 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/BoundaryEmitter.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/BoundaryEmitter.java
@@ -10,7 +10,7 @@ import com.koushikdutta.async.FilteredDataEmitter;
public class BoundaryEmitter extends FilteredDataEmitter {
private byte[] boundary;
- public BoundaryEmitter(String boundary) {
+ public void setBoundary(String boundary) {
this.boundary = ("--" + boundary).getBytes();
}
diff --git a/AndroidAsync/src/com/koushikdutta/async/http/server/UnknownRequestBody.java b/AndroidAsync/src/com/koushikdutta/async/http/server/UnknownRequestBody.java
index e50e05c..40ed935 100644
--- a/AndroidAsync/src/com/koushikdutta/async/http/server/UnknownRequestBody.java
+++ b/AndroidAsync/src/com/koushikdutta/async/http/server/UnknownRequestBody.java
@@ -4,12 +4,12 @@ import junit.framework.Assert;
import com.koushikdutta.async.NullDataCallback;
import com.koushikdutta.async.http.AsyncHttpRequest;
+import com.koushikdutta.async.http.AsyncHttpRequestBody;
import com.koushikdutta.async.http.AsyncHttpResponse;
-public class UnknownRequestBody extends AsyncHttpRequestBodyBase {
+public class UnknownRequestBody extends NullDataCallback implements AsyncHttpRequestBody {
public UnknownRequestBody(String contentType) {
- super(contentType);
- setDataCallback(new NullDataCallback());
+ mContentType = contentType;
}
@Override
@@ -22,4 +22,14 @@ public class UnknownRequestBody extends AsyncHttpRequestBodyBase {
public String getContentType() {
return mContentType;
}
+
+ @Override
+ public boolean readFullyOnRequest() {
+ return false;
+ }
+
+ @Override
+ public int length() {
+ return -1;
+ }
}