package com.koushikdutta.async.stream; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import com.koushikdutta.async.AsyncServer; import com.koushikdutta.async.ByteBufferList; import com.koushikdutta.async.DataSink; import com.koushikdutta.async.callback.CompletedCallback; import com.koushikdutta.async.callback.WritableCallback; public class OutputStreamDataSink implements DataSink { public OutputStreamDataSink(AsyncServer server) { this(server, null); } @Override public void end() { close(); } AsyncServer server; public OutputStreamDataSink(AsyncServer server, OutputStream stream) { this.server = server; setOutputStream(stream); } OutputStream mStream; public void setOutputStream(OutputStream stream) { mStream = stream; } public OutputStream getOutputStream() throws IOException { return mStream; } private boolean doPending() { try { while (pending.size() > 0) { ByteBuffer b; synchronized (pending) { b = pending.remove(); } int rem = b.remaining(); getOutputStream().write(b.array(), b.arrayOffset() + b.position(), b.remaining()); totalWritten += rem; ByteBufferList.reclaim(b); } return true; } catch (Exception e) { pending.recycle(); closeReported = true; closeException = e; return false; } } final ByteBufferList pending = new ByteBufferList(); int totalWritten; @Override public void write(final ByteBuffer bb) { try { getOutputStream().write(bb.array(), bb.arrayOffset() + bb.position(), bb.remaining()); } catch (IOException e) { reportClose(e); } bb.position(0); bb.limit(0); } @Override public void write(final ByteBufferList bb) { try { while (bb.size() > 0) { ByteBuffer b = bb.remove(); getOutputStream().write(b.array(), b.arrayOffset() + b.position(), b.remaining()); ByteBufferList.reclaim(b); } } catch (IOException e) { reportClose(e); } finally { bb.recycle(); } } WritableCallback mWritable; @Override public void setWriteableCallback(WritableCallback handler) { mWritable = handler; } @Override public WritableCallback getWriteableCallback() { return mWritable; } @Override public boolean isOpen() { return closeReported; } @Override public void close() { try { if (mStream != null) mStream.close(); reportClose(null); } catch (IOException e) { reportClose(e); } } boolean closeReported; Exception closeException; public void reportClose(Exception ex) { if (closeReported) return; closeReported = true; closeException = ex; if (mClosedCallback != null) mClosedCallback.onCompleted(closeException); } CompletedCallback mClosedCallback; @Override public void setClosedCallback(CompletedCallback handler) { mClosedCallback = handler; } @Override public CompletedCallback getClosedCallback() { return mClosedCallback; } @Override public AsyncServer getServer() { return server; } WritableCallback outputStreamCallback; public void setOutputStreamWritableCallback(WritableCallback outputStreamCallback) { this.outputStreamCallback = outputStreamCallback; } }