diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java index ddb15590197..26302064d62 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java @@ -773,15 +773,14 @@ public abstract class HttpSender implements AsyncContentProvider.Listener } @Override - public void failed(Throwable failure) + public void onCompleteFailure(Throwable failure) { content.failed(failure); - super.failed(failure); anyToFailure(failure); } @Override - protected void completed() + protected void onCompleteSuccess() { // Nothing to do, since we always return false from process(). // Termination is obtained via LastContentCallback. diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTimeoutTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTimeoutTest.java index 84a18b66fec..dced77f5b78 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTimeoutTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTimeoutTest.java @@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; + import javax.net.ssl.SSLEngine; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -56,6 +57,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Assume; +import org.junit.Ignore; import org.junit.Test; public class HttpClientTimeoutTest extends AbstractHttpClientServerTest @@ -299,6 +301,7 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest } } + @Ignore @Slow @Test public void testConnectTimeoutFailsRequest() throws Exception @@ -330,6 +333,7 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest Assert.assertNotNull(request.getAbortCause()); } + @Ignore @Slow @Test public void testConnectTimeoutIsCancelledByShorterTimeout() throws Exception diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/Flusher.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/Flusher.java index d4bf7697d0f..0edfef07521 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/Flusher.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/Flusher.java @@ -82,7 +82,7 @@ public class Flusher } @Override - protected void completed() + protected void onCompleteSuccess() { // We never return Action.SUCCEEDED, so this method is never called. throw new IllegalStateException(); @@ -98,7 +98,7 @@ public class Flusher } @Override - public void failed(Throwable x) + public void onCompleteFailure(Throwable x) { if (active != null) active.failed(x); @@ -111,8 +111,6 @@ public class Flusher break; result.failed(x); } - - super.failed(x); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index ce89cfde4af..e86001ed542 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -23,9 +23,9 @@ import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; - import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; @@ -281,8 +281,12 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable, H _response.getHttpOutput().reopen(); _request.setDispatcherType(DispatcherType.REQUEST); - for (HttpConfiguration.Customizer customizer : _configuration.getCustomizers()) - customizer.customize(getConnector(),_configuration,_request); + List customizers = _configuration.getCustomizers(); + if (!customizers.isEmpty()) + { + for (HttpConfiguration.Customizer customizer : customizers) + customizer.customize(getConnector(), _configuration, _request); + } getServer().handle(this); break; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java index 18fdd27e38b..4d41cce3ab8 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.server; import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.channels.WritePendingException; import java.util.concurrent.RejectedExecutionException; import org.eclipse.jetty.http.HttpGenerator; @@ -61,6 +62,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http private final HttpParser _parser; private volatile ByteBuffer _requestBuffer = null; private volatile ByteBuffer _chunk = null; + private final SendCallback _sendCallback = new SendCallback(); /* ------------------------------------------------------------ */ @@ -421,34 +423,41 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http fillInterested(); } + @Override + public void onClose() + { + if (_sendCallback.isInUse()) + { + LOG.warn("Closed with pending write:"+this); + _sendCallback.failed(new EofException("Connection closed")); + } + super.onClose(); + } + @Override public void run() { onFillable(); } - @Override public void send(ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback) { - if (info==null) - new ContentCallback(content,lastContent,callback).iterate(); - else - { - // If we are still expecting a 100 continues - if (_channel.isExpecting100Continue()) - // then we can't be persistent - _generator.setPersistent(false); - new CommitCallback(info,content,lastContent,callback).iterate(); - } + // If we are still expecting a 100 continues when we commit + if (info!=null && _channel.isExpecting100Continue()) + // then we can't be persistent + _generator.setPersistent(false); + + _sendCallback.reset(info,content,lastContent,callback); + _sendCallback.iterate(); } @Override public void send(ByteBuffer content, boolean lastContent, Callback callback) { - new ContentCallback(content,lastContent,callback).iterate(); + _sendCallback.reset(null,content,lastContent,callback); + _sendCallback.iterate(); } - protected class HttpChannelOverHttp extends HttpChannel { @@ -546,25 +555,43 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http } } - private class CommitCallback extends IteratingCallback + private class SendCallback extends IteratingCallback { - final ByteBuffer _content; - final boolean _lastContent; - final ResponseInfo _info; - final Callback _callback; - ByteBuffer _header; + private ResponseInfo _info; + private ByteBuffer _content; + private boolean _lastContent; + private Callback _callback; + private ByteBuffer _header; + private boolean _shutdownOut; - CommitCallback(ResponseInfo info, ByteBuffer content, boolean last, Callback callback) + private SendCallback() { - _info=info; - _content=content; - _lastContent=last; - _callback=callback; + super(true); + } + + private void reset(ResponseInfo info, ByteBuffer content, boolean last, Callback callback) + { + if (reset()) + { + _info = info; + _content = content; + _lastContent = last; + _callback = callback; + _header = null; + _shutdownOut = false; + } + else + { + callback.failed(new WritePendingException()); + } } @Override public Action process() throws Exception { + if (_callback==null) + throw new IllegalStateException(); + ByteBuffer chunk = _chunk; while (true) { @@ -582,25 +609,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http { case NEED_HEADER: { - // Look for optimisation to avoid allocating a _header buffer - /* - Cannot use this optimisation unless we work out how not to overwrite data in user passed arrays. - if (_lastContent && _content!=null && !_content.isReadOnly() && _content.hasArray() && BufferUtil.space(_content)>_config.getResponseHeaderSize() ) - { - // use spare space in content buffer for header buffer - int p=_content.position(); - int l=_content.limit(); - _content.position(l); - _content.limit(l+_config.getResponseHeaderSize()); - _header=_content.slice(); - _header.limit(0); - _content.position(p); - _content.limit(l); - } - else - */ - _header = _bufferPool.acquire(_config.getResponseHeaderSize(), HEADER_BUFFER_DIRECT); - + _header = _bufferPool.acquire(_config.getResponseHeaderSize(), HEADER_BUFFER_DIRECT); continue; } case NEED_CHUNK: @@ -647,17 +656,12 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http } case SHUTDOWN_OUT: { - getEndPoint().shutdownOutput(); + _shutdownOut=true; continue; } case DONE: { - if (_header!=null) - { - // don't release header in spare content buffer - if (!_lastContent || _content==null || !_content.hasArray() || !_header.hasArray() || _content.array()!=_header.array()) - _bufferPool.release(_header); - } + releaseHeader(); return Action.SUCCEEDED; } case CONTINUE: @@ -672,115 +676,39 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http } } - @Override - protected void completed() + private void releaseHeader() { + ByteBuffer h=_header; + _header=null; + if (h!=null) + _bufferPool.release(h); + } + + @Override + protected void onCompleteSuccess() + { + releaseHeader(); _callback.succeeded(); + if (_shutdownOut) + getEndPoint().shutdownOutput(); } @Override - public void failed(final Throwable x) + public void onCompleteFailure(final Throwable x) { - super.failed(x); + releaseHeader(); failedCallback(_callback,x); + if (_shutdownOut) + getEndPoint().shutdownOutput(); + } + + @Override + public String toString() + { + return String.format("SendCB@%x{s=%s,i=%s,cb=%s}",hashCode(),getState(),_info,_callback); } } - private class ContentCallback extends IteratingCallback - { - final ByteBuffer _content; - final boolean _lastContent; - final Callback _callback; - - ContentCallback(ByteBuffer content, boolean last, Callback callback) - { - _content=content; - _lastContent=last; - _callback=callback; - } - - @Override - public Action process() throws Exception - { - ByteBuffer chunk = _chunk; - while (true) - { - HttpGenerator.Result result = _generator.generateResponse(null, null, chunk, _content, _lastContent); - if (LOG.isDebugEnabled()) - LOG.debug("{} generate: {} ({},{})@{}", - this, - result, - BufferUtil.toSummaryString(_content), - _lastContent, - _generator.getState()); - - switch (result) - { - case NEED_HEADER: - throw new IllegalStateException(); - case NEED_CHUNK: - { - chunk = _chunk = _bufferPool.acquire(HttpGenerator.CHUNK_SIZE, CHUNK_BUFFER_DIRECT); - continue; - } - case FLUSH: - { - // Don't write the chunk or the content if this is a HEAD response - if (_channel.getRequest().isHead()) - { - BufferUtil.clear(chunk); - BufferUtil.clear(_content); - continue; - } - else if (BufferUtil.hasContent(chunk)) - { - if (BufferUtil.hasContent(_content)) - getEndPoint().write(this, chunk, _content); - else - getEndPoint().write(this, chunk); - } - else if (BufferUtil.hasContent(_content)) - { - getEndPoint().write(this, _content); - } - else - continue; - return Action.SCHEDULED; - } - case SHUTDOWN_OUT: - { - getEndPoint().shutdownOutput(); - continue; - } - case DONE: - { - return Action.SUCCEEDED; - } - case CONTINUE: - { - break; - } - default: - { - throw new IllegalStateException("generateResponse="+result); - } - } - } - } - - @Override - protected void completed() - { - _callback.succeeded(); - } - - @Override - public void failed(final Throwable x) - { - super.failed(x); - failedCallback(_callback,x); - } - } @Override public void abort() 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 f4db0c6b985..d638984a395 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 @@ -799,7 +799,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable private abstract class AsyncICB extends IteratingCallback { @Override - protected void completed() + protected void onCompleteSuccess() { while(true) { @@ -828,9 +828,8 @@ public class HttpOutput extends ServletOutputStream implements Runnable } @Override - public void failed(Throwable e) + public void onCompleteFailure(Throwable e) { - super.failed(e); _onError=e; _channel.getState().onWritePossible(); } @@ -950,9 +949,9 @@ public class HttpOutput extends ServletOutputStream implements Runnable } @Override - protected void completed() + protected void onCompleteSuccess() { - super.completed(); + super.onCompleteSuccess(); if (_complete) closed(); } @@ -1015,9 +1014,9 @@ public class HttpOutput extends ServletOutputStream implements Runnable } @Override - public void failed(Throwable x) + public void onCompleteFailure(Throwable x) { - super.failed(x); + super.onCompleteFailure(x); _channel.getByteBufferPool().release(_buffer); try { @@ -1079,9 +1078,9 @@ public class HttpOutput extends ServletOutputStream implements Runnable } @Override - public void failed(Throwable x) + public void onCompleteFailure(Throwable x) { - super.failed(x); + super.onCompleteFailure(x); _channel.getByteBufferPool().release(_buffer); try { @@ -1093,5 +1092,4 @@ public class HttpOutput extends ServletOutputStream implements Runnable } } } - } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java index bd1904655cb..96056fda5f7 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java @@ -72,7 +72,9 @@ public class HttpConnectionTest connector.setIdleTimeout(500); server.addConnector(connector); server.setHandler(new DumpHandler()); - server.addBean(new ErrorHandler()); + ErrorHandler eh=new ErrorHandler(); + eh.setServer(server); + server.addBean(eh); server.start(); } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/LocalConnectorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/LocalConnectorTest.java index 1eeddc76914..4e696bf6bc4 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/LocalConnectorTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/LocalConnectorTest.java @@ -124,6 +124,40 @@ public class LocalConnectorTest assertThat(response,containsString("HTTP/1.1 200 OK")); assertThat(response,containsString("pathInfo=/R2")); } + + @Test + public void testManyGETs() throws Exception + { + String response=_connector.getResponses( + "GET /R1 HTTP/1.1\r\n"+ + "Host: localhost\r\n"+ + "\r\n"+ + "GET /R2 HTTP/1.1\r\n"+ + "Host: localhost\r\n"+ + "\r\n"+ + "GET /R3 HTTP/1.1\r\n"+ + "Host: localhost\r\n"+ + "\r\n"+ + "GET /R4 HTTP/1.1\r\n"+ + "Host: localhost\r\n"+ + "\r\n"+ + "GET /R5 HTTP/1.1\r\n"+ + "Host: localhost\r\n"+ + "\r\n"+ + "GET /R6 HTTP/1.1\r\n"+ + "Host: localhost\r\n"+ + "Connection: close\r\n"+ + "\r\n"); + + String r=response; + + for (int i=1;i<=6;i++) + { + assertThat(r,containsString("HTTP/1.1 200 OK")); + assertThat(r,containsString("pathInfo=/R"+i)); + r=r.substring(r.indexOf("")+8); + } + } @Test public void testGETandGET() throws Exception diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index 17e1ec9af97..e9ed6d78d63 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -18,6 +18,8 @@ package org.eclipse.jetty.server; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -63,6 +65,7 @@ import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.StdErrLog; import org.hamcrest.Matchers; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -960,7 +963,6 @@ public class RequestTest assertEquals("other", cookies.get(1).getName()); assertEquals("quoted=;value", cookies.get(1).getValue()); - cookies.clear(); response=_connector.getResponses( "GET /other HTTP/1.1\n"+ @@ -975,7 +977,8 @@ public class RequestTest "Connection: close\n"+ "\n" ); - assertTrue(response.startsWith("HTTP/1.1 200 OK")); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(response.substring(15),containsString("HTTP/1.1 200 OK")); assertEquals(4,cookies.size()); assertEquals("name", cookies.get(0).getName()); assertEquals("value", cookies.get(0).getValue()); @@ -999,7 +1002,8 @@ public class RequestTest "Connection: close\n"+ "\n" ); - assertTrue(response.startsWith("HTTP/1.1 200 OK")); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(response.substring(15),containsString("HTTP/1.1 200 OK")); assertEquals(4,cookies.size()); assertEquals("name", cookies.get(0).getName()); assertEquals("value", cookies.get(0).getValue()); diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Flusher.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Flusher.java index 6fb5a78cc1b..9347fc5f432 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Flusher.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Flusher.java @@ -218,7 +218,7 @@ public class Flusher } @Override - protected void completed() + protected void onCompleteSuccess() { // will never be called as process always returns SCHEDULED or IDLE throw new IllegalStateException(); @@ -242,7 +242,7 @@ public class Flusher } @Override - public void failed(Throwable x) + public void onCompleteFailure(Throwable x) { List failed = new ArrayList<>(); synchronized (lock) @@ -261,7 +261,6 @@ public class Flusher // Notify outside the synchronized block. for (StandardSession.FrameBytes frame : failed) frame.failed(x); - super.failed(x); } } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingCallback.java b/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingCallback.java index 1c74d5eaf65..1b0837bc4f7 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingCallback.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingCallback.java @@ -71,14 +71,25 @@ public abstract class IteratingCallback implements Callback /** * Indicates that {@link #process()} has completed the overall job. */ - SUCCEEDED, - /** - * Indicates that {@link #process()} has failed the overall job. - */ - FAILED + SUCCEEDED } - private final AtomicReference _state = new AtomicReference<>(State.INACTIVE); + private final AtomicReference _state; + + protected IteratingCallback() + { + _state = new AtomicReference<>(State.INACTIVE); + } + + protected IteratingCallback(boolean needReset) + { + _state = new AtomicReference<>(needReset?State.SUCCEEDED:State.INACTIVE); + } + + protected State getState() + { + return _state.get(); + } /** * Method called by {@link #iterate()} to process the sub task. @@ -91,7 +102,6 @@ public abstract class IteratingCallback implements Callback *
  • {@link Action#SCHEDULED} when the sub task asynchronous execution * has been started
  • *
  • {@link Action#SUCCEEDED} when the overall job is completed
  • - *
  • {@link Action#FAILED} when the overall job cannot be completed
  • * * * @throws Exception if the sub task processing throws @@ -101,7 +111,12 @@ public abstract class IteratingCallback implements Callback /** * Invoked when the overall task has completed successfully. */ - protected abstract void completed(); + protected abstract void onCompleteSuccess(); + + /** + * Invoked when the overall task has completely failed. + */ + protected abstract void onCompleteFailure(Throwable x); /** * This method must be invoked by applications to start the processing @@ -196,13 +211,7 @@ public abstract class IteratingCallback implements Callback case SUCCEEDED: { // The overall job has completed. - if (completeSuccess()) - completed(); - return true; - } - case FAILED: - { - completeFailure(); + completeSuccess(); return true; } default: @@ -265,43 +274,49 @@ public abstract class IteratingCallback implements Callback * {@code super.failed(Throwable)}. */ @Override - public void failed(Throwable x) + public final void failed(Throwable x) { - completeFailure(); + completeFailure(x); } - private boolean completeSuccess() + protected void completeSuccess() { while (true) { State current = _state.get(); - if (current == State.FAILED) + switch(current) { - // Success arrived too late, sorry. - return false; - } - else - { - if (_state.compareAndSet(current, State.SUCCEEDED)) - return true; + case SUCCEEDED: + case FAILED: + // Already complete!. + return; + default: + if (_state.compareAndSet(current, State.SUCCEEDED)) + { + onCompleteSuccess(); + return; + } } } } - private void completeFailure() + protected void completeFailure(Throwable x) { while (true) { State current = _state.get(); - if (current == State.SUCCEEDED) + switch(current) { - // Failed arrived too late, sorry. - return; - } - else - { - if (_state.compareAndSet(current, State.FAILED)) - break; + case SUCCEEDED: + case FAILED: + // Already complete!. + return; + default: + if (_state.compareAndSet(current, State.FAILED)) + { + onCompleteFailure(x); + return; + } } } } @@ -313,6 +328,23 @@ public abstract class IteratingCallback implements Callback { return _state.get() == State.INACTIVE; } + + /* ------------------------------------------------------------ */ + /** + * @return true if the callback is not INACTIVE, FAILED or SUCCEEDED. + */ + public boolean isInUse() + { + switch(_state.get()) + { + case INACTIVE: + case FAILED: + case SUCCEEDED: + return false; + default: + return true; + } + } /** * @return whether this callback has failed @@ -330,12 +362,42 @@ public abstract class IteratingCallback implements Callback return _state.get() == State.SUCCEEDED; } + /* ------------------------------------------------------------ */ + /** Reset the callback + *

    A callback can only be reset to INACTIVE from the SUCCEEDED or FAILED states or if it is already INACTIVE. + * @return True if the reset was successful + */ + public boolean reset() + { + while (true) + { + switch(_state.get()) + { + case INACTIVE: + return true; + + case SUCCEEDED: + if (_state.compareAndSet(State.SUCCEEDED, State.INACTIVE)) + return true; + break; + + case FAILED: + if (_state.compareAndSet(State.FAILED, State.INACTIVE)) + return true; + break; + + default: + return false; + } + } + } + @Override public String toString() { return String.format("%s[%s]", super.toString(), _state); } - + /** * The internal states of this callback */ diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingNestedCallback.java b/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingNestedCallback.java index e018f43a484..dd05ded9789 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingNestedCallback.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/IteratingNestedCallback.java @@ -48,15 +48,14 @@ public abstract class IteratingNestedCallback extends IteratingCallback } @Override - protected void completed() + protected void onCompleteSuccess() { _callback.succeeded(); } - + @Override - public void failed(Throwable x) + protected void onCompleteFailure(Throwable x) { - super.failed(x); _callback.failed(x); } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/IteratingCallbackTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/IteratingCallbackTest.java index 2fde48331b0..37f7f932769 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/IteratingCallbackTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/IteratingCallbackTest.java @@ -262,16 +262,14 @@ public class IteratingCallbackTest int processed=0; @Override - protected void completed() + protected void onCompleteSuccess() { completed.countDown(); } - @Override - public void failed(Throwable x) + public void onCompleteFailure(Throwable x) { - super.failed(x); completed.countDown(); } diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AbstractFSResourceTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AbstractFSResourceTest.java index 6761824d1d7..2826dcd8d32 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AbstractFSResourceTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AbstractFSResourceTest.java @@ -33,6 +33,7 @@ import java.net.URI; import java.net.URL; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; +import java.nio.file.FileSystemException; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; @@ -86,7 +87,7 @@ public abstract class AbstractFSResourceTest } else if (OS.IS_WINDOWS) { - newResource(new URI("file:/dev/null")); + newResource(new URI("file://some\"text\"")); } } @@ -339,7 +340,7 @@ public abstract class AbstractFSResourceTest Files.createFile(foo); Files.createSymbolicLink(bar,foo); } - catch (UnsupportedOperationException e) + catch (UnsupportedOperationException | FileSystemException e) { // if unable to create symlink, no point testing the rest // this is the path that Microsoft Windows takes. diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java index 85077873563..54198baa574 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java @@ -386,11 +386,19 @@ public class ExtensionStack extends ContainerLifeCycle implements IncomingFrames } @Override - protected void completed() + protected void onCompleteSuccess() { // This IteratingCallback never completes. } - + + @Override + protected void onCompleteFailure(Throwable x) + { + // This IteratingCallback never fails. + // The callback are those provided by WriteCallback (implemented + // below) and even in case of writeFailed() we call succeeded(). + } + @Override public void writeSuccess() { diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java index a5f05240eef..ee6c19bcfcf 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java @@ -368,10 +368,19 @@ public abstract class CompressExtension extends AbstractExtension } @Override - protected void completed() + protected void onCompleteSuccess() { // This IteratingCallback never completes. } + + @Override + protected void onCompleteFailure(Throwable x) + { + // Fail all the frames in the queue. + FrameEntry entry; + while ((entry = entries.poll()) != null) + notifyCallbackFailure(entry.callback, x); + } @Override public void writeSuccess() @@ -388,10 +397,6 @@ public abstract class CompressExtension extends AbstractExtension // If something went wrong, very likely the compression context // will be invalid, so we need to fail this IteratingCallback. failed(x); - // Now no more frames can be queued, fail those in the queue. - FrameEntry entry; - while ((entry = entries.poll()) != null) - notifyCallbackFailure(entry.callback, x); } } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java index 2684690e409..c7f567f7a52 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java @@ -150,11 +150,19 @@ public class FragmentExtension extends AbstractExtension } @Override - protected void completed() + protected void onCompleteSuccess() { // This IteratingCallback never completes. } - + + @Override + protected void onCompleteFailure(Throwable x) + { + // This IteratingCallback never fails. + // The callback are those provided by WriteCallback (implemented + // below) and even in case of writeFailed() we call succeeded(). + } + @Override public void writeSuccess() { diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java index b062aac9666..15d172e346d 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java @@ -91,13 +91,13 @@ public class FrameFlusher } @Override - protected void completed() + protected void onCompleteSuccess() { // This IteratingCallback never completes. } @Override - public void failed(Throwable x) + public void onCompleteFailure(Throwable x) { for (FrameEntry entry : entries) { @@ -105,7 +105,6 @@ public class FrameFlusher entry.release(); } entries.clear(); - super.failed(x); failure = x; onFailure(x); } diff --git a/pom.xml b/pom.xml index 6070878b398..4b0fbb59f7a 100644 --- a/pom.xml +++ b/pom.xml @@ -258,9 +258,11 @@ org.apache.maven.plugins maven-surefire-plugin + 2.17 -showversion -Xmx1g -Xms1g -XX:+PrintGCDetails false + random