package org.jboss.resteasy.plugins.server.vertx; import java.io.IOException; import java.io.OutputStream; import io.vertx.core.buffer.Buffer; import org.jboss.resteasy.plugins.server.vertx.i18n.Messages; /** * Class to help application that are built to write to an * OutputStream to chunk the content * <p> * <pre> * {@code * DefaultHttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); * HttpHeaders.setTransferEncodingChunked(response); * response.headers().set(CONTENT_TYPE, "application/octet-stream"); * //other headers * ctx.write(response); * // code of the application that use the ChunkOutputStream * // Don't forget to close the ChunkOutputStream after use! * ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT).addListener(ChannelFutureListener.CLOSE); * } * </pre> * * @author tbussier */ public class ChunkOutputStream extends OutputStream { private Buffer buffer; private final VertxHttpResponse response; private final int chunkSize; ChunkOutputStream(VertxHttpResponse response, int chunksize) { this.response = response; if (chunksize < 1) { throw new IllegalArgumentException(Messages.MESSAGES.chunkSizeMustBeAtLeastOne()); } this.chunkSize = chunksize; this.buffer = Buffer.buffer(chunksize); } @Override public void write(int b) throws IOException { if (buffer.length() >= chunkSize - 1) { flush(); } buffer.appendByte((byte) b); } public void reset() { if (response.isCommitted()) throw new IllegalStateException(Messages.MESSAGES.responseIsCommitted()); buffer = Buffer.buffer(chunkSize); } @Override public void close() throws IOException { flush(); super.close(); } @Override public void write(byte[] b, int off, int len) throws IOException { int dataLengthLeftToWrite = len; int dataToWriteOffset = off; int spaceLeftInCurrentChunk; while ((spaceLeftInCurrentChunk = chunkSize - buffer.length()) < dataLengthLeftToWrite) { buffer.appendBytes(b, dataToWriteOffset, spaceLeftInCurrentChunk); dataToWriteOffset = dataToWriteOffset + spaceLeftInCurrentChunk; dataLengthLeftToWrite = dataLengthLeftToWrite - spaceLeftInCurrentChunk; flush(); } if (dataLengthLeftToWrite > 0) { buffer.appendBytes(b, dataToWriteOffset, dataLengthLeftToWrite); } } @Override public void flush() throws IOException { int readable = buffer.length(); if (readable == 0) return; if (!response.isCommitted()) response.prepareChunkStream(); response.response.write(buffer); buffer = Buffer.buffer(); super.flush(); } }