Mercurial Hosting > luan
view src/goodjava/webserver/ChunkedOutputStream.java @ 2008:bba3e529e346 default tip
chunked encoding
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 27 Aug 2025 01:14:17 -0600 |
parents | |
children |
line wrap: on
line source
package goodjava.webserver; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.IOException; public class ChunkedOutputStream extends ByteArrayOutputStream { private static final byte[] end = "0\r\n\r\n".getBytes(); private static final int OPEN = 1; private static final int CLOSING = 2; private static final int CLOSED = 3; private final Response response; private int status = OPEN; private int i = 0; public ChunkedOutputStream(Response response) { if(response==null) throw new NullPointerException(); this.response = response; response.headers.put("Transfer-Encoding","chunked"); response.body = new ChunkedInputStream(); } @Override public synchronized void close() { if( status == OPEN ) { status = CLOSING; notifyAll(); } } @Override public synchronized void write(int b) { super.write(b); notifyAll(); } @Override public synchronized void write(byte b[], int off, int len) { super.write(b,off,len); notifyAll(); } @Override public synchronized void reset() { super.reset(); i = 0; } private class ChunkedInputStream extends InputStream { @Override public int read() { throw new UnsupportedOperationException(); } @Override public int read(byte[] b,int off,int len) throws IOException { synchronized(ChunkedOutputStream.this) { if( i == count ) { if( status == CLOSED ) return -1; if( status == CLOSING ) { System.arraycopy(end,0,b,off,end.length); status = CLOSED; return end.length; } try { ChunkedOutputStream.this.wait(); } catch(InterruptedException e) { throw new RuntimeException(e); } return read(b,off,len); } int offOld = off; int left = count - i; int extra = Integer.toHexString(left).length() + 4; int n = Math.min( len - extra, left ); byte[] hex = Integer.toHexString(n).getBytes(); System.arraycopy( hex, 0, b, off, hex.length ); off += hex.length; b[off++] = '\r'; b[off++] = '\n'; System.arraycopy(buf,i,b,off,n); off += n; b[off++] = '\r'; b[off++] = '\n'; i += n; if( i == count ) ChunkedOutputStream.this.reset(); return off - offOld; } } } }