Merge remote-tracking branch 'origin/jetty-9.4.x'

This commit is contained in:
Greg Wilkins 2017-05-11 10:08:36 +02:00
commit cbe857de01
27 changed files with 702 additions and 89 deletions

View File

@ -13,6 +13,6 @@ GCloudDatastore is an open source project hosted on Github and released under th
https://github.com/GoogleCloudPlatform/gcloud-java
http://www.apache.org/licenses/LICENSE-2.0.html
[ini-template]
[ini]
## Hide the gcloud libraries from deployed webapps
jetty.webapp.addServerClasses+=,${jetty.base.uri}/lib/gcloud/

View File

@ -41,5 +41,5 @@ http://www.apache.org/licenses/LICENSE-2.0
[ini-template]
## Jminix Configuration
jminix.port=8088
# jminix.port=8088

View File

@ -117,7 +117,7 @@ public class ResourceHttpContent implements HttpContent
{
return _contentType==null?null:MimeTypes.CACHE.get(MimeTypes.getContentTypeWithoutCharset(_contentType));
}
/* ------------------------------------------------------------ */
@Override
public HttpField getLastModified()
@ -227,7 +227,7 @@ public class ResourceHttpContent implements HttpContent
@Override
public String toString()
{
return String.format("%s@%x{r=%s,c=%b}",this.getClass().getSimpleName(),hashCode(),_resource,_precompressedContents!=null);
return String.format("%s@%x{r=%s,ct=%s,c=%b}",this.getClass().getSimpleName(),hashCode(),_resource,_contentType,_precompressedContents!=null);
}
/* ------------------------------------------------------------ */

View File

@ -409,7 +409,7 @@ public class MongoSessionDataStore extends NoSqlSessionDataStore
BasicDBList list = new BasicDBList();
list.add(gt);
list.add(lt);
query.append("and", list);
query.append("$and", list);
DBCursor oldExpiredSessions = null;
try

View File

@ -11,5 +11,5 @@ server
[xml]
etc/jetty-stats.xml
[ini-template]
[ini]
jetty.webapp.addServerClasses+=,-org.eclipse.jetty.servlet.StatisticsServlet

View File

@ -1454,9 +1454,10 @@ public class Response implements HttpServletResponse
{
if (_characterEncoding!=null &&
content.getCharacterEncoding()==null &&
content.getContentTypeValue()!=null &&
__explicitCharset.contains(_encodingFrom))
{
setContentType(content.getMimeType().getBaseType().asString());
setContentType(MimeTypes.getContentTypeWithoutCharset(content.getContentTypeValue()));
}
else
{

View File

@ -681,8 +681,7 @@ public class AsyncServletIOTest
}
LOG.debug("last: "+last);
// last non empty line should contain some X's
assertThat(last,Matchers.anyOf(containsString("X"),is("")));
// last non empty line should not contain end chunk
assertThat(last,not(containsString("0")));
}

View File

@ -791,6 +791,8 @@ public class DefaultServletTest
FS.ensureDirExists(resBase);
File file0 = new File(resBase, "data0.txt");
createFile(file0, "Hello Text 0");
File image = new File(resBase, "image.jpg");
createFile(image, "not an image");
String resBasePath = resBase.getAbsolutePath();
@ -817,6 +819,11 @@ public class DefaultServletTest
assertResponseNotContains("Content-Length: 12", response);
assertResponseContains("Content-Type: text/plain;charset=utf-8", response);
response = connector.getResponse("GET /context/image.jpg HTTP/1.0\r\n\r\n");
assertResponseContains("Content-Length: 2", response); // 20 something long
assertResponseContains("Extra Info", response);
assertResponseContains("Content-Type: image/jpeg;charset=utf-8", response);
server.stop();
context.getServletHandler().setFilterMappings(new FilterMapping[]{});
context.getServletHandler().setFilters(new FilterHolder[]{});
@ -827,6 +834,7 @@ public class DefaultServletTest
assertResponseContains("Content-Length: 2", response); // 20 something long
assertResponseContains("Extra Info", response);
assertResponseNotContains("Content-Length: 12", response);
}

View File

@ -29,6 +29,7 @@ import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -123,7 +124,7 @@ class JarFileResource extends JarResource
int sep = _urlString.lastIndexOf("!/");
_jarUrl=_urlString.substring(0,sep+2);
_path=_urlString.substring(sep+2);
_path=URIUtil.decodePath(_urlString.substring(sep+2));
if (_path.length()==0)
_path=null;
_jarFile=_jarConnection.getJarFile();

View File

@ -201,5 +201,13 @@ public class JarResourceTest
assertFalse(dest.exists());
}
@Test
public void testEncodedFileName()
throws Exception
{
String s = "jar:"+testResURI+"TestData/test.zip!/file%20name.txt";
Resource r = Resource.newResource(s);
assertTrue(r.exists());
}
}

View File

@ -46,12 +46,14 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ShutdownThread;
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.client.io.UpgradeListener;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.scopes.DelegatedContainerScope;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
@ -81,6 +83,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
private final EncoderFactory encoderFactory;
/** The jetty websocket client in use for this container */
private final WebSocketClient client;
private final boolean internalClient;
/** Tracking for all declared Client endpoints */
private final Map<Class<?>, EndpointMetadata> endpointClientMetadataCache;
@ -99,26 +102,74 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
*
* @param scope the scope of the ServerContainer
*/
public ClientContainer(WebSocketContainerScope scope)
public ClientContainer(final WebSocketContainerScope scope)
{
boolean trustAll = Boolean.getBoolean("org.eclipse.jetty.websocket.jsr356.ssl-trust-all");
this.scopeDelegate = scope;
client = new WebSocketClient(scope,
new JsrEventDriverFactory(scope),
String jsr356TrustAll = System.getProperty("org.eclipse.jetty.websocket.jsr356.ssl-trust-all");
WebSocketContainerScope clientScope;
if (scope.getPolicy().getBehavior() == WebSocketBehavior.CLIENT)
{
clientScope = scope;
}
else
{
// We need to wrap the scope for the CLIENT Policy behaviors
clientScope = new DelegatedContainerScope(WebSocketPolicy.newClientPolicy(), scope);
}
this.scopeDelegate = clientScope;
this.client = new WebSocketClient(scopeDelegate,
new JsrEventDriverFactory(scopeDelegate),
new JsrSessionFactory(this));
client.getSslContextFactory().setTrustAll(trustAll);
addBean(client);
this.internalClient = true;
if(jsr356TrustAll != null)
{
boolean trustAll = Boolean.parseBoolean(jsr356TrustAll);
client.getSslContextFactory().setTrustAll(trustAll);
}
this.endpointClientMetadataCache = new ConcurrentHashMap<>();
this.decoderFactory = new DecoderFactory(this,PrimitiveDecoderMetadataSet.INSTANCE);
this.encoderFactory = new EncoderFactory(this,PrimitiveEncoderMetadataSet.INSTANCE);
ShutdownThread.register(this);
}
/**
* Build a ClientContainer with a specific WebSocketClient in mind.
*
* @param client the WebSocketClient to use.
*/
public ClientContainer(WebSocketClient client)
{
this.scopeDelegate = client;
this.client = client;
this.internalClient = false;
this.endpointClientMetadataCache = new ConcurrentHashMap<>();
this.decoderFactory = new DecoderFactory(this,PrimitiveDecoderMetadataSet.INSTANCE);
this.encoderFactory = new EncoderFactory(this,PrimitiveEncoderMetadataSet.INSTANCE);
}
private Session connect(EndpointInstance instance, URI path) throws IOException
{
synchronized (this.client)
{
if (this.internalClient && !this.client.isStarted())
{
try
{
this.client.start();
addManaged(this.client);
}
catch (Exception e)
{
throw new RuntimeException("Unable to start Client", e);
}
}
}
Objects.requireNonNull(instance,"EndpointInstance cannot be null");
Objects.requireNonNull(path,"Path cannot be null");

View File

@ -29,6 +29,34 @@ import javax.websocket.WebSocketContainer;
*/
public class JettyClientContainerProvider extends ContainerProvider
{
private static Object lock = new Object();
private static ClientContainer INSTANCE;
public static ClientContainer getInstance()
{
return INSTANCE;
}
public static void stop() throws Exception
{
synchronized (lock)
{
if (INSTANCE == null)
{
return;
}
try
{
INSTANCE.stop();
}
finally
{
INSTANCE = null;
}
}
}
/**
* Used by {@link ContainerProvider#getWebSocketContainer()} to get a new instance
* of the Client {@link WebSocketContainer}.
@ -36,16 +64,26 @@ public class JettyClientContainerProvider extends ContainerProvider
@Override
protected WebSocketContainer getContainer()
{
ClientContainer container = new ClientContainer();
try
synchronized (lock)
{
// We need to start this container properly.
container.start();
return container;
}
catch (Exception e)
{
throw new RuntimeException("Unable to start Client Container",e);
if (INSTANCE == null)
{
INSTANCE = new ClientContainer();
}
if (!INSTANCE.isStarted())
{
try
{
INSTANCE.start();
}
catch (Exception e)
{
throw new RuntimeException("Unable to start Client Container", e);
}
}
return INSTANCE;
}
}
}

View File

@ -44,6 +44,7 @@ import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class CookiesTest
@ -70,6 +71,12 @@ public class CookiesTest
{
server.stop();
}
@Before
public void resetClientContainer() throws Exception
{
JettyClientContainerProvider.stop();
}
@Test
public void testCookiesAreSentToServer() throws Exception

View File

@ -0,0 +1,69 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.ContainerProvider;
import javax.websocket.WebSocketContainer;
import org.junit.Before;
import org.junit.Test;
public class DelayedStartClientTest
{
@Before
public void stopClientContainer() throws Exception
{
JettyClientContainerProvider.stop();
}
@Test
public void testNoExtraHttpClientThreads()
{
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
assertThat("Container", container, notNullValue());
List<String> threadNames = getThreadNames();
assertThat("Threads", threadNames, not(hasItem(containsString("SimpleContainerScope.Executor@"))));
assertThat("Threads", threadNames, not(hasItem(containsString("HttpClient@"))));
}
private List<String> getThreadNames()
{
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
ThreadInfo[] threads = threadMXBean.dumpAllThreads(false, false);
List<String> ret = new ArrayList<>();
for (ThreadInfo info : threads)
{
ret.add(info.getThreadName());
}
return ret;
}
}

View File

@ -67,7 +67,6 @@ public class BinaryStreamTest
server.start();
wsClient = ContainerProvider.getWebSocketContainer();
server.addBean(wsClient, true);
}
@After

View File

@ -0,0 +1,347 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.net.HttpURLConnection;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.ContainerProvider;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
import org.eclipse.jetty.websocket.jsr356.JettyClientContainerProvider;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.junit.Before;
import org.junit.Test;
public class DelayedStartClientOnServerTest
{
@ServerEndpoint("/echo")
public static class EchoSocket
{
@OnMessage
public String echo(String msg)
{
return msg;
}
}
@Before
public void stopClientContainer() throws Exception
{
JettyClientContainerProvider.stop();
}
/**
* Using the Client specific techniques of JSR356, connect to the echo socket
* and perform an echo request.
*/
public static class ClientConnectServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
// Client specific technique
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
try
{
URI wsURI = WSURI.toWebsocket(req.getRequestURL()).resolve("/echo");
Session session = container.connectToServer(new Endpoint()
{
@Override
public void onOpen(Session session, EndpointConfig config)
{
/* do nothing */
}
}, wsURI);
// don't care about the data sent, just the connect itself.
session.getBasicRemote().sendText("Hello");
session.close();
resp.setContentType("text/plain");
resp.getWriter().println("Connected to " + wsURI);
}
catch (Throwable t)
{
throw new ServletException(t);
}
}
}
/**
* Using the Server specific techniques of JSR356, connect to the echo socket
* and perform an echo request.
*/
public static class ServerConnectServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
// Server specific technique
javax.websocket.server.ServerContainer container =
(javax.websocket.server.ServerContainer)
req.getServletContext().getAttribute("javax.websocket.server.ServerContainer");
try
{
URI wsURI = WSURI.toWebsocket(req.getRequestURL()).resolve("/echo");
Session session = container.connectToServer(new Endpoint()
{
@Override
public void onOpen(Session session, EndpointConfig config)
{
/* do nothing */
}
}, wsURI);
// don't care about the data sent, just the connect itself.
session.getBasicRemote().sendText("Hello");
session.close();
resp.setContentType("text/plain");
resp.getWriter().println("Connected to " + wsURI);
}
catch (Throwable t)
{
throw new ServletException(t);
}
}
}
/**
* Using the Client specific techniques of JSR356, configure the WebSocketContainer.
*/
public static class ClientConfigureServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
// Client specific technique
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
try
{
container.setAsyncSendTimeout(5000);
container.setDefaultMaxTextMessageBufferSize(1000);
resp.setContentType("text/plain");
resp.getWriter().printf("Configured %s - %s%n", container.getClass().getName(), container);
}
catch (Throwable t)
{
throw new ServletException(t);
}
}
}
/**
* Using the Server specific techniques of JSR356, configure the WebSocketContainer.
*/
public static class ServerConfigureServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
// Server specific technique
javax.websocket.server.ServerContainer container =
(javax.websocket.server.ServerContainer)
req.getServletContext().getAttribute("javax.websocket.server.ServerContainer");
try
{
container.setAsyncSendTimeout(5000);
container.setDefaultMaxTextMessageBufferSize(1000);
resp.setContentType("text/plain");
resp.getWriter().printf("Configured %s - %s%n", container.getClass().getName(), container);
}
catch (Throwable t)
{
throw new ServletException(t);
}
}
}
@Test
public void testNoExtraHttpClientThreads() throws Exception
{
Server server = new Server(0);
ServletContextHandler contextHandler = new ServletContextHandler();
server.setHandler(contextHandler);
WebSocketServerContainerInitializer.configureContext(contextHandler);
try
{
server.start();
List<String> threadNames = getThreadNames();
assertThat("Threads", threadNames, not(hasItem(containsString("SimpleContainerScope.Executor@"))));
assertThat("Threads", threadNames, not(hasItem(containsString("HttpClient@"))));
}
finally
{
server.stop();
}
}
@Test
public void testHttpClientThreads_AfterClientConnectTo() throws Exception
{
Server server = new Server(0);
ServletContextHandler contextHandler = new ServletContextHandler();
server.setHandler(contextHandler);
// Using JSR356 Client Techniques to connectToServer()
contextHandler.addServlet(ClientConnectServlet.class, "/connect");
javax.websocket.server.ServerContainer container = WebSocketServerContainerInitializer.configureContext(contextHandler);
container.addEndpoint(EchoSocket.class);
try
{
server.start();
String response = GET(server.getURI().resolve("/connect"));
assertThat("Response", response, startsWith("Connected to ws://"));
List<String> threadNames = getThreadNames();
assertThat("Threads", threadNames, hasItem(containsString("SimpleContainerScope.Executor@")));
assertThat("Threads", threadNames, hasItem(containsString("HttpClient@")));
}
finally
{
server.stop();
}
}
@Test
public void testHttpClientThreads_AfterServerConnectTo() throws Exception
{
Server server = new Server(0);
ServletContextHandler contextHandler = new ServletContextHandler();
server.setHandler(contextHandler);
// Using JSR356 Server Techniques to connectToServer()
contextHandler.addServlet(ServerConnectServlet.class, "/connect");
javax.websocket.server.ServerContainer container = WebSocketServerContainerInitializer.configureContext(contextHandler);
container.addEndpoint(EchoSocket.class);
try
{
server.start();
String response = GET(server.getURI().resolve("/connect"));
assertThat("Response", response, startsWith("Connected to ws://"));
List<String> threadNames = getThreadNames();
assertThat("Threads", threadNames, hasItem(containsString("HttpClient@")));
}
finally
{
server.stop();
}
}
@Test
public void testHttpClientThreads_AfterClientConfigure() throws Exception
{
Server server = new Server(0);
ServletContextHandler contextHandler = new ServletContextHandler();
server.setHandler(contextHandler);
// Using JSR356 Client Techniques to configure WebSocketContainer
contextHandler.addServlet(ClientConfigureServlet.class, "/configure");
javax.websocket.server.ServerContainer container = WebSocketServerContainerInitializer.configureContext(contextHandler);
container.addEndpoint(EchoSocket.class);
try
{
server.start();
String response = GET(server.getURI().resolve("/configure"));
assertThat("Response", response, startsWith("Configured " + ClientContainer.class.getName()));
List<String> threadNames = getThreadNames();
assertThat("Threads", threadNames, not(hasItem(containsString("SimpleContainerScope.Executor@"))));
assertThat("Threads", threadNames, not(hasItem(containsString("HttpClient@"))));
}
finally
{
server.stop();
}
}
@Test
public void testHttpClientThreads_AfterServerConfigure() throws Exception
{
Server server = new Server(0);
ServletContextHandler contextHandler = new ServletContextHandler();
server.setHandler(contextHandler);
// Using JSR356 Server Techniques to configure WebSocketContainer
contextHandler.addServlet(ServerConfigureServlet.class, "/configure");
javax.websocket.server.ServerContainer container = WebSocketServerContainerInitializer.configureContext(contextHandler);
container.addEndpoint(EchoSocket.class);
try
{
server.start();
String response = GET(server.getURI().resolve("/configure"));
assertThat("Response", response, startsWith("Configured " + ServerContainer.class.getName()));
List<String> threadNames = getThreadNames();
assertThat("Threads", threadNames, not(hasItem(containsString("SimpleContainerScope.Executor@"))));
assertThat("Threads", threadNames, not(hasItem(containsString("HttpClient@"))));
}
finally
{
server.stop();
}
}
private String GET(URI destURI) throws IOException
{
HttpURLConnection http = (HttpURLConnection) destURI.toURL().openConnection();
assertThat("HTTP GET (" + destURI + ") Response Code", http.getResponseCode(), is(200));
try (InputStream in = http.getInputStream();
InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
StringWriter writer = new StringWriter())
{
IO.copy(reader, writer);
return writer.toString();
}
}
private List<String> getThreadNames()
{
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
ThreadInfo[] threads = threadMXBean.dumpAllThreads(false, false);
List<String> ret = new ArrayList<>();
for (ThreadInfo info : threads)
{
ret.add(info.getThreadName());
}
return ret;
}
}

View File

@ -75,7 +75,6 @@ public class ExtensionStackProcessingTest
container.addEndpoint(config);
client = ContainerProvider.getWebSocketContainer();
server.addBean(client, true);
server.start();
}

View File

@ -22,42 +22,31 @@ import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.net.URI;
import java.util.Queue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StacklessLogging;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
import org.eclipse.jetty.websocket.jsr356.annotations.JsrEvents;
import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.IdleTimeoutContextListener;
import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.OnOpenIdleTimeoutEndpoint;
import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.OnOpenIdleTimeoutSocket;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
public class IdleTimeoutTest
{
private static final Logger LOG = Log.getLogger(IdleTimeoutTest.class);
@Rule
public TestingDir testdir = new TestingDir();
@Rule
public LeakTrackingBufferPoolRule bufferPool = new LeakTrackingBufferPoolRule("Test");
private static WSServer server;
@BeforeClass
@ -85,15 +74,15 @@ public class IdleTimeoutTest
server.stop();
}
private void assertConnectionTimeout(URI uri) throws Exception, IOException, InterruptedException, ExecutionException, TimeoutException
private void assertConnectionTimeout(URI uri) throws Exception
{
WebSocketClient client = new WebSocketClient(bufferPool);
WebSocketClient client = new WebSocketClient();
try
{
client.start();
JettyEchoSocket clientEcho = new JettyEchoSocket();
if (LOG.isDebugEnabled())
LOG.debug("Client Attempting to connnect");
LOG.debug("Client Attempting to connect");
Future<Session> future = client.connect(clientEcho,uri);
// wait for connect
future.get(1,TimeUnit.SECONDS);
@ -129,7 +118,7 @@ public class IdleTimeoutTest
@Test
public void testAnnotated() throws Exception
{
try(StacklessLogging stackless = new StacklessLogging(JsrEvents.class))
try(StacklessLogging ignored = new StacklessLogging(JsrEvents.class))
{
URI uri = server.getServerBaseURI();
assertConnectionTimeout(uri.resolve("idle-onopen-socket"));

View File

@ -64,7 +64,6 @@ public class JsrBatchModeTest
server.start();
client = ContainerProvider.getWebSocketContainer();
server.addBean(client, true);
}
@After

View File

@ -66,7 +66,6 @@ public class MemoryUsageTest
server.start();
client = ContainerProvider.getWebSocketContainer();
server.addBean(client, true);
}
@After

View File

@ -89,7 +89,6 @@ public class OnPartialTest
@SuppressWarnings("resource")
JsrSession session = new JsrSession(container,id,requestURI,driver,connection);
session.setPolicy(policy);
session.start();
session.open();
return driver;

View File

@ -67,7 +67,6 @@ public class TextStreamTest
server.start();
wsClient = ContainerProvider.getWebSocketContainer();
server.addBean(wsClient, true);
}
@After

View File

@ -42,6 +42,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.Scheduler;
import org.eclipse.jetty.util.thread.ShutdownThread;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
@ -54,6 +55,7 @@ import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.WebSocketSessionFactory;
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
import org.eclipse.jetty.websocket.common.scopes.DelegatedContainerScope;
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
@ -72,7 +74,6 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
private final WebSocketExtensionFactory extensionRegistry;
private final EventDriverFactory eventDriverFactory;
private final SessionFactory sessionFactory;
private Masker masker;
private final int id = ThreadLocalRandom.current().nextInt();
@ -110,7 +111,6 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
this.containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy(),new MappedByteBufferPool(),objectFactory);
this.httpClient = httpClient;
this.extensionRegistry = new WebSocketExtensionFactory(containerScope);
this.masker = new RandomMasker();
this.eventDriverFactory = new EventDriverFactory(containerScope);
this.sessionFactory = new WebSocketSessionFactory(containerScope);
}
@ -133,9 +133,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
*
* @param bufferPool
* byte buffer pool to use
* @deprecated use {@link #WebSocketClient(HttpClient)} instead
*/
@Deprecated
public WebSocketClient(ByteBufferPool bufferPool)
{
this(null,null,bufferPool);
@ -234,7 +232,6 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
this.extensionRegistry = new WebSocketExtensionFactory(containerScope);
this.masker = new RandomMasker();
this.eventDriverFactory = new EventDriverFactory(containerScope);
this.sessionFactory = new WebSocketSessionFactory(containerScope);
}
@ -250,9 +247,20 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
* @param sessionFactory
* the SessionFactory to use
*/
public WebSocketClient(WebSocketContainerScope scope, EventDriverFactory eventDriverFactory, SessionFactory sessionFactory)
public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory eventDriverFactory, SessionFactory sessionFactory)
{
this.containerScope = scope;
WebSocketContainerScope clientScope;
if (scope.getPolicy().getBehavior() == WebSocketBehavior.CLIENT)
{
clientScope = scope;
}
else
{
// We need to wrap the scope
clientScope = new DelegatedContainerScope(WebSocketPolicy.newClientPolicy(), scope);
}
this.containerScope = clientScope;
SslContextFactory sslContextFactory = scope.getSslContextFactory();
if(sslContextFactory == null)
{
@ -264,7 +272,6 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
this.extensionRegistry = new WebSocketExtensionFactory(containerScope);
this.masker = new RandomMasker();
this.eventDriverFactory = eventDriverFactory;
this.sessionFactory = sessionFactory;
}
@ -435,10 +442,14 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
{
return extensionRegistry;
}
/**
* @deprecated not used, no replacement
*/
@Deprecated
public Masker getMasker()
{
return masker;
return new RandomMasker();
}
/**
@ -603,7 +614,11 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
{
this.httpClient.setCookieStore(cookieStore);
}
/**
* @deprecated not used, configure threading in HttpClient instead
*/
@Deprecated
public void setDaemon(boolean daemon)
{
// do nothing
@ -619,10 +634,14 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
{
this.httpClient.setExecutor(executor);
}
/**
* @deprecated not used, no replacement
*/
@Deprecated
public void setMasker(Masker masker)
{
this.masker = masker;
/* do nothing */
}
public void setMaxBinaryMessageBufferSize(int max)

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.websocket.client;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
@ -36,7 +37,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeException;
@ -44,6 +44,7 @@ import org.eclipse.jetty.websocket.common.AcceptHash;
import org.eclipse.jetty.websocket.common.test.BlockheadServer;
import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection;
import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@ -67,21 +68,18 @@ public class ClientConnectTest
private WebSocketClient client;
@SuppressWarnings("unchecked")
private <E extends Throwable> E assertExpectedError(ExecutionException e, JettyTrackingSocket wsocket, Class<E> errorClass) throws IOException
private <E extends Throwable> E assertExpectedError(ExecutionException e, JettyTrackingSocket wsocket, Matcher<Throwable> errorMatcher) throws IOException
{
// Validate thrown cause
Throwable cause = e.getCause();
if(!errorClass.isInstance(cause))
{
cause.printStackTrace(System.err);
Assert.assertThat("ExecutionException.cause",cause,instanceOf(errorClass));
}
Assert.assertThat("ExecutionException.cause",cause,errorMatcher);
// Validate websocket captured cause
Assert.assertThat("Error Queue Length",wsocket.errorQueue.size(),greaterThanOrEqualTo(1));
Throwable capcause = wsocket.errorQueue.poll();
Assert.assertThat("Error Queue[0]",capcause,notNullValue());
Assert.assertThat("Error Queue[0]",capcause,instanceOf(errorClass));
Assert.assertThat("Error Queue[0]",capcause,errorMatcher);
// Validate that websocket didn't see an open event
wsocket.assertNotOpened();
@ -214,7 +212,7 @@ public class ClientConnectTest
catch (ExecutionException e)
{
// Expected Path
UpgradeException ue = assertExpectedError(e,wsocket,UpgradeException.class);
UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class));
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue());
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString()));
Assert.assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(404));
@ -245,7 +243,7 @@ public class ClientConnectTest
catch (ExecutionException e)
{
// Expected Path
UpgradeException ue = assertExpectedError(e,wsocket,UpgradeException.class);
UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class));
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue());
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString()));
Assert.assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(200));
@ -282,7 +280,7 @@ public class ClientConnectTest
catch (ExecutionException e)
{
// Expected Path
UpgradeException ue = assertExpectedError(e,wsocket,UpgradeException.class);
UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class));
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue());
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString()));
Assert.assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(200));
@ -318,7 +316,7 @@ public class ClientConnectTest
catch (ExecutionException e)
{
// Expected Path
UpgradeException ue = assertExpectedError(e,wsocket,UpgradeException.class);
UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class));
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue());
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString()));
Assert.assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(101));
@ -354,7 +352,7 @@ public class ClientConnectTest
catch (ExecutionException e)
{
// Expected Path
UpgradeException ue = assertExpectedError(e,wsocket,UpgradeException.class);
UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class));
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue());
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString()));
Assert.assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(101));
@ -383,7 +381,7 @@ public class ClientConnectTest
catch (ExecutionException e)
{
// Expected Path
UpgradeException ue = assertExpectedError(e,wsocket,UpgradeException.class);
UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class));
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue());
Assert.assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString()));
Assert.assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(101));
@ -408,7 +406,7 @@ public class ClientConnectTest
}
catch (ExecutionException e)
{
assertExpectedError(e,wsocket,UpgradeException.class);
assertExpectedError(e,wsocket,instanceOf(UpgradeException.class));
// Possible Passing Path (active session wait timeout)
wsocket.assertNotOpened();
}
@ -443,15 +441,11 @@ public class ClientConnectTest
}
catch (ExecutionException e)
{
if(OS.IS_WINDOWS)
{
// On windows, this is a SocketTimeoutException
assertExpectedError(e, wsocket, SocketTimeoutException.class);
} else
{
// Expected path - java.net.ConnectException
assertExpectedError(e,wsocket,ConnectException.class);
}
assertExpectedError(e, wsocket,
anyOf(
instanceOf(UpgradeException.class),
instanceOf(SocketTimeoutException.class),
instanceOf(ConnectException.class)));
}
}
@ -477,7 +471,7 @@ public class ClientConnectTest
catch (ExecutionException e)
{
// Expected path - java.net.ConnectException ?
assertExpectedError(e,wsocket,ConnectException.class);
assertExpectedError(e,wsocket,instanceOf(ConnectException.class));
}
}
}

View File

@ -0,0 +1,87 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.common.scopes;
import java.util.concurrent.Executor;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.DecoratedObjectFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.WebSocketSession;
public class DelegatedContainerScope implements WebSocketContainerScope
{
private final WebSocketPolicy policy;
private final WebSocketContainerScope delegate;
public DelegatedContainerScope(WebSocketPolicy policy, WebSocketContainerScope parentScope)
{
this.policy = policy;
this.delegate = parentScope;
}
@Override
public ByteBufferPool getBufferPool()
{
return this.delegate.getBufferPool();
}
@Override
public Executor getExecutor()
{
return this.delegate.getExecutor();
}
@Override
public DecoratedObjectFactory getObjectFactory()
{
return this.delegate.getObjectFactory();
}
@Override
public WebSocketPolicy getPolicy()
{
return this.policy;
}
@Override
public SslContextFactory getSslContextFactory()
{
return this.delegate.getSslContextFactory();
}
@Override
public boolean isRunning()
{
return this.delegate.isRunning();
}
@Override
public void onSessionOpened(WebSocketSession session)
{
this.delegate.onSessionOpened(session);
}
@Override
public void onSessionClosed(WebSocketSession session)
{
this.delegate.onSessionClosed(session);
}
}

View File

@ -443,8 +443,9 @@
<docencoding>UTF-8</docencoding>
<encoding>UTF-8</encoding>
<docfilessubdirs>true</docfilessubdirs>
<detectLinks>true</detectLinks>
<detectJavaApiLink>true</detectJavaApiLink>
<detectLinks>false</detectLinks>
<detectJavaApiLink>false</detectJavaApiLink>
<detectOfflineLinks>false</detectOfflineLinks>
<show>protected</show>
<excludePackageNames>com.acme.*;org.slf4j.*;org.mortbay.*</excludePackageNames>
<links>