| Index: src/org/adblockplus/ChunkedOutputStream.java |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/src/org/adblockplus/ChunkedOutputStream.java |
| @@ -0,0 +1,77 @@ |
| +package org.adblockplus; |
| + |
| +import java.io.FilterOutputStream; |
| +import java.io.IOException; |
| +import java.io.OutputStream; |
| + |
| +/** |
| + * ChunkedOutputStream implements chunked HTTP transfer encoding wrapper for |
| + * OutputStream. |
| + */ |
| +public class ChunkedOutputStream extends FilterOutputStream |
| +{ |
| + private static final byte[] CRLF = {'\r', '\n'}; |
| + private static final byte[] FINAL_CHUNK = new byte[] {'0', '\r', '\n', '\r', '\n'}; |
| + private boolean wroteFinalChunk = false; |
| + |
| + public ChunkedOutputStream(OutputStream out) |
| + { |
| + super(out); |
| + } |
| + |
| + @Override |
| + public void close() throws IOException |
| + { |
| + if (!wroteFinalChunk) |
| + writeFinalChunk(); |
| + super.close(); |
| + } |
| + |
| + @Override |
| + public void write(byte[] buffer, int offset, int length) throws IOException |
| + { |
| + writeChunk(buffer, offset, length); |
| + } |
| + |
| + @Override |
| + public void write(byte[] buffer) throws IOException |
| + { |
| + writeChunk(buffer, 0, buffer.length); |
| + } |
| + |
| + @Override |
| + public void write(int oneByte) throws IOException |
| + { |
| + throw new UnsupportedOperationException("Not implemented"); |
| + } |
| + |
| + public void writeFinalChunk() throws IOException |
| + { |
| + out.write(FINAL_CHUNK); |
| + out.flush(); |
| + wroteFinalChunk = true; |
| + } |
| + |
| + private void writeChunk(byte buffer[], int offset, int length) throws IOException |
| + { |
| + // Zero sized buffers are ok on slow connections but not in our case - zero |
| + // chunk is used to indicate the end of transfer. |
| + if (length > 0) |
| + { |
| + // Write the chunk length as a hex number |
| + writeHex(length); |
| + // Write the data |
| + out.write(buffer, offset, length); |
| + // Write a CRLF |
| + out.write(CRLF); |
| + // Flush the underlying stream |
| + out.flush(); |
| + } |
| + } |
| + |
| + private void writeHex(int i) throws IOException |
| + { |
| + out.write(Integer.toHexString(i).getBytes()); |
| + out.write(CRLF); |
| + } |
| +} |