diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java index d841628725b..c77fbb0cc78 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java @@ -146,6 +146,12 @@ public class HttpOutput extends ServletOutputStream implements Runnable _state.set(OutputState.OPEN); } + private boolean isLastContentToWrite(int len) + { + _written+=len; + return _channel.getResponse().isAllContentWritten(_written); + } + public boolean isAllContentWritten() { return _channel.getResponse().isAllContentWritten(_written); @@ -370,9 +376,6 @@ public class HttpOutput extends ServletOutputStream implements Runnable @Override public void write(byte[] b, int off, int len) throws IOException { - _written+=len; - boolean complete=_channel.getResponse().isAllContentWritten(_written); - // Async or Blocking ? while(true) { @@ -390,7 +393,8 @@ public class HttpOutput extends ServletOutputStream implements Runnable continue; // Should we aggregate? - if (!complete && len<=_commitSize) + boolean last = isLastContentToWrite(len); + if (!last && len<=_commitSize) { if (_aggregate == null) _aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), _interceptor.isOptimizedForDirectBuffers()); @@ -412,7 +416,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable } // Do the asynchronous writing from the callback - new AsyncWrite(b,off,len,complete).iterate(); + new AsyncWrite(b,off,len,last).iterate(); return; case PENDING: @@ -435,7 +439,8 @@ public class HttpOutput extends ServletOutputStream implements Runnable // Should we aggregate? int capacity = getBufferSize(); - if (!complete && len<=_commitSize) + boolean last = isLastContentToWrite(len); + if (!last && len<=_commitSize) { if (_aggregate == null) _aggregate = _channel.getByteBufferPool().acquire(capacity, _interceptor.isOptimizedForDirectBuffers()); @@ -455,10 +460,10 @@ public class HttpOutput extends ServletOutputStream implements Runnable // flush any content from the aggregate if (BufferUtil.hasContent(_aggregate)) { - write(_aggregate, complete && len==0); + write(_aggregate, last && len==0); // should we fill aggregate again from the buffer? - if (len>0 && !complete && len<=_commitSize && len<=BufferUtil.space(_aggregate)) + if (len>0 && !last && len<=_commitSize && len<=BufferUtil.space(_aggregate)) { BufferUtil.append(_aggregate, b, off, len); return; @@ -481,22 +486,19 @@ public class HttpOutput extends ServletOutputStream implements Runnable view.limit(l+Math.min(len,getBufferSize())); view.position(l); } - write(view,complete); + write(view,last); } - else if (complete) + else if (last) { write(BufferUtil.EMPTY_BUFFER,true); } - if (complete) + if (last) closed(); } public void write(ByteBuffer buffer) throws IOException { - _written+=buffer.remaining(); - boolean complete=_channel.getResponse().isAllContentWritten(_written); - // Async or Blocking ? while(true) { @@ -514,7 +516,8 @@ public class HttpOutput extends ServletOutputStream implements Runnable continue; // Do the asynchronous writing from the callback - new AsyncWrite(buffer,complete).iterate(); + boolean last = isLastContentToWrite(buffer.remaining()); + new AsyncWrite(buffer,last).iterate(); return; case PENDING: @@ -536,18 +539,19 @@ public class HttpOutput extends ServletOutputStream implements Runnable // handle blocking write int len=BufferUtil.length(buffer); + boolean last = isLastContentToWrite(len); // flush any content from the aggregate if (BufferUtil.hasContent(_aggregate)) - write(_aggregate, complete && len==0); + write(_aggregate, last && len==0); // write any remaining content in the buffer directly if (len>0) - write(buffer, complete); - else if (complete) + write(buffer, last); + else if (last) write(BufferUtil.EMPTY_BUFFER, true); - if (complete) + if (last) closed(); } @@ -1009,6 +1013,13 @@ public class HttpOutput extends ServletOutputStream implements Runnable private abstract class AsyncICB extends IteratingCallback { + final boolean _last; + + AsyncICB(boolean last) + { + _last=last; + } + @Override protected void onCompleteSuccess() { @@ -1025,6 +1036,8 @@ public class HttpOutput extends ServletOutputStream implements Runnable case UNREADY: if (!_state.compareAndSet(OutputState.UNREADY, OutputState.READY)) continue; + if (_last) + closed(); if (_channel.getState().onWritePossible()) _channel.execute(_channel); break; @@ -1054,6 +1067,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable public AsyncFlush() { + super(false); } @Override @@ -1081,21 +1095,21 @@ public class HttpOutput extends ServletOutputStream implements Runnable { private final ByteBuffer _buffer; private final ByteBuffer _slice; - private final boolean _complete; private final int _len; protected volatile boolean _completed; - public AsyncWrite(byte[] b, int off, int len, boolean complete) + public AsyncWrite(byte[] b, int off, int len, boolean last) { + super(last); _buffer=ByteBuffer.wrap(b, off, len); _len=len; // always use a view for large byte arrays to avoid JVM pooling large direct buffers _slice=_len - *

- * UTF-8 encoding is used by default for % encoded characters. This - * may be overridden with the org.eclipse.jetty.util.URI.charset system property. - *

* * @see UrlEncoded */