Merge remote-tracking branch 'eclipse/jetty-9.4.x' into jetty-9.4.x-stackTraceRemoval
This commit is contained in:
commit
52ffe24389
|
@ -46,4 +46,4 @@ bin/
|
|||
|
||||
# test generated content
|
||||
*/src/test/*/WEB-INF/lib/test*.jar
|
||||
|
||||
.flattened-pom.xml
|
||||
|
|
|
@ -206,18 +206,6 @@ xmlns:date="http://exslt.org/dates-and-times"
|
|||
</span>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-1149868-7']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.nio.channels.WritePendingException;
|
|||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.FutureCallback;
|
||||
import org.eclipse.jetty.util.IteratingCallback;
|
||||
import org.eclipse.jetty.util.thread.Invocable;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -200,7 +201,8 @@ public interface EndPoint extends Closeable
|
|||
/**
|
||||
* <p>Requests callback methods to be invoked when a call to {@link #fill(ByteBuffer)} would return data or EOF.</p>
|
||||
*
|
||||
* @param callback the callback to call when an error occurs or we are readable.
|
||||
* @param callback the callback to call when an error occurs or we are readable. The callback may implement the {@link Invocable} interface to
|
||||
* self declare its blocking status. Non-blocking callbacks may be called more efficiently without dispatch delays.
|
||||
* @throws ReadPendingException if another read operation is concurrent.
|
||||
*/
|
||||
void fillInterested(Callback callback) throws ReadPendingException;
|
||||
|
@ -208,7 +210,8 @@ public interface EndPoint extends Closeable
|
|||
/**
|
||||
* <p>Requests callback methods to be invoked when a call to {@link #fill(ByteBuffer)} would return data or EOF.</p>
|
||||
*
|
||||
* @param callback the callback to call when an error occurs or we are readable.
|
||||
* @param callback the callback to call when an error occurs or we are readable. The callback may implement the {@link Invocable} interface to
|
||||
* self declare its blocking status. Non-blocking callbacks may be called more efficiently without dispatch delays.
|
||||
* @return true if set
|
||||
*/
|
||||
boolean tryFillInterested(Callback callback);
|
||||
|
@ -223,7 +226,8 @@ public interface EndPoint extends Closeable
|
|||
* <p>Writes the given buffers via {@link #flush(ByteBuffer...)} and invokes callback methods when either
|
||||
* all the data has been flushed or an error occurs.</p>
|
||||
*
|
||||
* @param callback the callback to call when an error occurs or the write completed.
|
||||
* @param callback the callback to call when an error occurs or the write completed. The callback may implement the {@link Invocable} interface to
|
||||
* self declare its blocking status. Non-blocking callbacks may be called more efficiently without dispatch delays.
|
||||
* @param buffers one or more {@link ByteBuffer}s that will be flushed.
|
||||
* @throws WritePendingException if another write operation is concurrent.
|
||||
*/
|
||||
|
|
|
@ -69,15 +69,6 @@ import org.eclipse.jetty.util.thread.Scheduler;
|
|||
* </p>
|
||||
* <h2>Selectors</h2>
|
||||
* <p>
|
||||
* The connector will use the {@link Executor} service to execute a number of Selector Tasks,
|
||||
* which are implemented to each use a NIO {@link Selector} instance to asynchronously
|
||||
* schedule a set of accepted connections. It is the selector thread that will call the
|
||||
* {@link Callback} instances passed in the {@link EndPoint#fillInterested(Callback)} or
|
||||
* {@link EndPoint#write(Callback, java.nio.ByteBuffer...)} methods. It is expected
|
||||
* that these callbacks may do some non-blocking IO work, but will always dispatch to the
|
||||
* {@link Executor} service any blocking, long running or application tasks.
|
||||
* </p>
|
||||
* <p>
|
||||
* The default number of selectors is equal to half of the number of processors available to the JVM,
|
||||
* which should allow optimal performance even if all the connections used are performing
|
||||
* significant non-blocking work in the callback tasks.
|
||||
|
|
|
@ -43,6 +43,8 @@ import org.eclipse.jetty.server.handler.AbstractHandler;
|
|||
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
|
||||
import org.eclipse.jetty.toolchain.test.TestTracker;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.log.StacklessLogging;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
|
@ -55,6 +57,8 @@ import org.junit.runner.RunWith;
|
|||
@RunWith(AdvancedRunner.class)
|
||||
public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
||||
{
|
||||
protected static final Logger LOG = Log.getLogger(ConnectorTimeoutTest.class);
|
||||
|
||||
@Rule
|
||||
public TestTracker tracker = new TestTracker();
|
||||
|
||||
|
@ -610,11 +614,17 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
}
|
||||
catch(SSLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
if(LOG.isDebugEnabled())
|
||||
LOG.debug(e);
|
||||
else
|
||||
LOG.info(e.getMessage());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
if(LOG.isDebugEnabled())
|
||||
LOG.debug(e);
|
||||
else
|
||||
LOG.info(e.getMessage());
|
||||
}
|
||||
Assert.assertTrue(TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) - start < maximumTestRuntime);
|
||||
|
||||
|
@ -639,11 +649,17 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
}
|
||||
catch(SSLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
if(LOG.isDebugEnabled())
|
||||
LOG.debug(e);
|
||||
else
|
||||
LOG.info(e.getMessage());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
if(LOG.isDebugEnabled())
|
||||
LOG.debug(e);
|
||||
else
|
||||
LOG.info(e.getMessage());
|
||||
}
|
||||
Assert.assertTrue(TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) - start < maximumTestRuntime);
|
||||
|
||||
|
|
|
@ -19,11 +19,9 @@
|
|||
package org.eclipse.jetty.server;
|
||||
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
@ -39,6 +37,10 @@ import org.junit.Ignore;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
@RunWith(AdvancedRunner.class)
|
||||
public class LowResourcesMonitorTest
|
||||
{
|
||||
|
@ -216,32 +218,67 @@ public class LowResourcesMonitorTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testMaxLowResourceTime() throws Exception
|
||||
public void testMaxLowResourcesTime() throws Exception
|
||||
{
|
||||
_lowResourcesMonitor.setMaxLowResourcesTime(5000);
|
||||
int monitorPeriod = _lowResourcesMonitor.getPeriod();
|
||||
int lowResourcesIdleTimeout = _lowResourcesMonitor.getLowResourcesIdleTimeout();
|
||||
Assert.assertThat(lowResourcesIdleTimeout, Matchers.lessThan(monitorPeriod));
|
||||
|
||||
int maxLowResourcesTime = 5 * monitorPeriod;
|
||||
_lowResourcesMonitor.setMaxLowResourcesTime(maxLowResourcesTime);
|
||||
Assert.assertFalse(_lowResourcesMonitor.isLowOnResources());
|
||||
|
||||
try(Socket socket0 = new Socket("localhost",_connector.getLocalPort()))
|
||||
{
|
||||
// Put the lowResourceMonitor in low mode.
|
||||
_lowResourcesMonitor.setMaxMemory(1);
|
||||
|
||||
Thread.sleep(2400);
|
||||
// Wait a couple of monitor periods so that
|
||||
// lowResourceMonitor detects it is in low mode.
|
||||
Thread.sleep(2 * monitorPeriod);
|
||||
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
||||
|
||||
// We already waited enough for lowResourceMonitor to close socket0.
|
||||
Assert.assertEquals(-1, socket0.getInputStream().read());
|
||||
|
||||
// New connections are not affected by the
|
||||
// low mode until maxLowResourcesTime elapses.
|
||||
try(Socket socket1 = new Socket("localhost",_connector.getLocalPort()))
|
||||
{
|
||||
Thread.sleep(2400);
|
||||
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
||||
Assert.assertEquals(-1,socket0.getInputStream().read());
|
||||
socket1.getOutputStream().write("G".getBytes(StandardCharsets.UTF_8));
|
||||
// Set a very short read timeout so we can test if the server closed.
|
||||
socket1.setSoTimeout(1);
|
||||
InputStream input1 = socket1.getInputStream();
|
||||
|
||||
Thread.sleep(2400);
|
||||
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
||||
socket1.getOutputStream().write("E".getBytes(StandardCharsets.UTF_8));
|
||||
try
|
||||
{
|
||||
input1.read();
|
||||
Assert.fail();
|
||||
}
|
||||
catch (SocketTimeoutException expected)
|
||||
{
|
||||
}
|
||||
|
||||
Thread.sleep(2400);
|
||||
// Wait a couple of lowResources idleTimeouts.
|
||||
Thread.sleep(2 * lowResourcesIdleTimeout);
|
||||
|
||||
// Verify the new socket is still open.
|
||||
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
||||
Assert.assertEquals(-1,socket1.getInputStream().read());
|
||||
try
|
||||
{
|
||||
input1.read();
|
||||
Assert.fail();
|
||||
}
|
||||
catch (SocketTimeoutException expected)
|
||||
{
|
||||
}
|
||||
|
||||
// Let the maxLowResourcesTime elapse.
|
||||
Thread.sleep(maxLowResourcesTime);
|
||||
|
||||
Assert.assertTrue(_lowResourcesMonitor.isLowOnResources());
|
||||
// Now also the new socket should be closed.
|
||||
Assert.assertEquals(-1, input1.read());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.eclipse.jetty.server.session.SessionHandler;
|
|||
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.log.StacklessLogging;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
@ -134,7 +135,7 @@ public class ServerConnectorTimeoutTest extends ConnectorTimeoutTest
|
|||
@Test
|
||||
public void testHttpWriteIdleTimeout() throws Exception
|
||||
{
|
||||
_httpConfiguration.setBlockingTimeout(500);
|
||||
_httpConfiguration.setIdleTimeout(500);
|
||||
configureServer(new AbstractHandler.ErrorDispatchHandler()
|
||||
{
|
||||
@Override
|
||||
|
|
|
@ -53,12 +53,13 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
|
|||
|
||||
public AnnotatedServerEndpointConfig(WebSocketContainerScope containerScope, Class<?> endpointClass, ServerEndpoint anno, ServerEndpointConfig baseConfig) throws DeploymentException
|
||||
{
|
||||
ServerEndpointConfig.Configurator configr = null;
|
||||
// A manually declared Configurator (not the one from the annotation)
|
||||
ServerEndpointConfig.Configurator manualConfigurator = null;
|
||||
|
||||
// Copy from base config
|
||||
if (baseConfig != null)
|
||||
{
|
||||
configr = baseConfig.getConfigurator();
|
||||
manualConfigurator = baseConfig.getConfigurator();
|
||||
}
|
||||
|
||||
// Decoders (favor provided config over annotation)
|
||||
|
@ -112,24 +113,24 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
|
|||
userProperties.putAll(baseConfig.getUserProperties());
|
||||
}
|
||||
|
||||
ServerEndpointConfig.Configurator cfgr;
|
||||
ServerEndpointConfig.Configurator resolvedConfigurator;
|
||||
|
||||
if (anno.configurator() == ServerEndpointConfig.Configurator.class)
|
||||
// Use ServerEndpointConfig provided configurator if declared
|
||||
if ( (manualConfigurator != null) && !(manualConfigurator instanceof ContainerDefaultConfigurator) )
|
||||
{
|
||||
if (configr != null)
|
||||
{
|
||||
cfgr = configr;
|
||||
}
|
||||
else
|
||||
{
|
||||
cfgr = new ContainerDefaultConfigurator();
|
||||
}
|
||||
resolvedConfigurator = manualConfigurator;
|
||||
}
|
||||
// Use Container Default if annotation based configurator is undeclared
|
||||
else if (anno.configurator() == ServerEndpointConfig.Configurator.class)
|
||||
{
|
||||
resolvedConfigurator = new ContainerDefaultConfigurator();
|
||||
}
|
||||
// Use annotation declared configurator
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
cfgr = anno.configurator().getDeclaredConstructor( ).newInstance();
|
||||
resolvedConfigurator = anno.configurator().getDeclaredConstructor( ).newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -143,7 +144,7 @@ public class AnnotatedServerEndpointConfig implements ServerEndpointConfig
|
|||
}
|
||||
|
||||
// Make sure all Configurators obtained are decorated
|
||||
this.configurator = containerScope.getObjectFactory().decorate(cfgr);
|
||||
this.configurator = containerScope.getObjectFactory().decorate(resolvedConfigurator);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -362,6 +362,35 @@ public class ConfiguratorTest
|
|||
}
|
||||
}
|
||||
|
||||
public static class ConfigNormalConfigurator extends ServerEndpointConfig.Configurator
|
||||
{
|
||||
@Override
|
||||
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response)
|
||||
{
|
||||
sec.getUserProperties().put("self.configurator", this.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConfigOverrideConfigurator extends ServerEndpointConfig.Configurator
|
||||
{
|
||||
@Override
|
||||
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response)
|
||||
{
|
||||
sec.getUserProperties().put("self.configurator", this.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@ServerEndpoint(value = "/config-normal",
|
||||
configurator = ConfigNormalConfigurator.class)
|
||||
public static class ConfigNormalSocket
|
||||
{
|
||||
@OnMessage
|
||||
public String onMessage(Session session, String msg)
|
||||
{
|
||||
return String.format("UserProperties[self.configurator] = %s", session.getUserProperties().get("self.configurator"));
|
||||
}
|
||||
}
|
||||
|
||||
private static BlockheadClient client;
|
||||
private static Server server;
|
||||
private static URI baseServerUri;
|
||||
|
@ -387,6 +416,13 @@ public class ConfiguratorTest
|
|||
container.addEndpoint(AddressSocket.class);
|
||||
container.addEndpoint(TimeDecoderSocket.class);
|
||||
|
||||
container.addEndpoint(ConfigNormalSocket.class);
|
||||
ServerEndpointConfig overrideEndpointConfig = ServerEndpointConfig.Builder
|
||||
.create(ConfigNormalSocket.class, "/config-override")
|
||||
.configurator(new ConfigOverrideConfigurator())
|
||||
.build();
|
||||
container.addEndpoint(overrideEndpointConfig);
|
||||
|
||||
server.start();
|
||||
String host = connector.getHost();
|
||||
if (host == null)
|
||||
|
@ -667,4 +703,44 @@ public class ConfiguratorTest
|
|||
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("cal=2016.06.20 AD at 14:27:44 +0000"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a Configurator declared in the annotation is used
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testAnnotationConfigurator() throws Exception
|
||||
{
|
||||
URI uri = baseServerUri.resolve("/config-normal");
|
||||
BlockheadClientRequest request = client.newWsRequest(uri);
|
||||
Future<BlockheadConnection> connFut = request.sendAsync();
|
||||
|
||||
try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT))
|
||||
{
|
||||
clientConn.write(new TextFrame().setPayload("tellme"));
|
||||
LinkedBlockingQueue<WebSocketFrame> frames = clientConn.getFrameQueue();
|
||||
WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT);
|
||||
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("UserProperties[self.configurator] = " + ConfigNormalConfigurator.class.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a provided ServerEndpointConfig can override the annotation Configurator
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testOverrideConfigurator() throws Exception
|
||||
{
|
||||
URI uri = baseServerUri.resolve("/config-override");
|
||||
BlockheadClientRequest request = client.newWsRequest(uri);
|
||||
Future<BlockheadConnection> connFut = request.sendAsync();
|
||||
|
||||
try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT))
|
||||
{
|
||||
clientConn.write(new TextFrame().setPayload("tellme"));
|
||||
LinkedBlockingQueue<WebSocketFrame> frames = clientConn.getFrameQueue();
|
||||
WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT);
|
||||
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("UserProperties[self.configurator] = " + ConfigOverrideConfigurator.class.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,11 +52,12 @@ public class PongContextListener implements ServletContextListener
|
|||
try
|
||||
{
|
||||
Configurator config = new Config();
|
||||
|
||||
|
||||
// Use manually declared Configurator
|
||||
container.addEndpoint(ServerEndpointConfig.Builder.create(PongMessageEndpoint.class,"/ping").configurator(config).build());
|
||||
container.addEndpoint(ServerEndpointConfig.Builder.create(PongMessageEndpoint.class,"/pong").configurator(config).build());
|
||||
// Use annotation declared Configurator
|
||||
container.addEndpoint(ServerEndpointConfig.Builder.create(PongSocket.class,"/ping-socket").build());
|
||||
container.addEndpoint(ServerEndpointConfig.Builder.create(PongSocket.class,"/pong-socket").build());
|
||||
}
|
||||
catch (DeploymentException e)
|
||||
{
|
||||
|
|
18
pom.xml
18
pom.xml
|
@ -31,7 +31,7 @@
|
|||
<jmhjar.name>benchmarks</jmhjar.name>
|
||||
<surefireVersion>2.21.0</surefireVersion>
|
||||
|
||||
<mavenPluginToolsVersion>3.5</mavenPluginToolsVersion>
|
||||
<mavenPluginToolsVersion>3.5.2</mavenPluginToolsVersion>
|
||||
<mavenVersion>3.5.0</mavenVersion>
|
||||
</properties>
|
||||
|
||||
|
@ -477,7 +477,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.0.1</version>
|
||||
<configuration>
|
||||
<charset>UTF-8</charset>
|
||||
<docencoding>UTF-8</docencoding>
|
||||
|
@ -1293,20 +1293,6 @@
|
|||
<configuration>
|
||||
<!-- needed for Java 8+ -->
|
||||
<additionalparam>--allow-script-in-comments</additionalparam>
|
||||
<header>
|
||||
<![CDATA[
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-1149868-7']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
]]>
|
||||
</header>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
|
Loading…
Reference in New Issue