Update websocket support for Jetty 9.3+
Due to a few changes in `WebSocketServerFactory` and `Session` API, our `JettyRequestUpgradeStrategy` and `JettyWebSocketSession` needed to adapt. As of 9.3.15+ and 9.4.0+, some reflection is required to support previous versions. Spring 4.3 websocket officially supports Jetty 9.1 to 9.3. Issue: SPR-14940
This commit is contained in:
parent
75034c3710
commit
35b0c8b577
|
@ -56,6 +56,7 @@ configure(allprojects) { project ->
|
||||||
ext.jasperreportsVersion = "6.2.1" // our tests fail with JR-internal NPEs against 6.2.2 and higher
|
ext.jasperreportsVersion = "6.2.1" // our tests fail with JR-internal NPEs against 6.2.2 and higher
|
||||||
ext.javamailVersion = "1.5.6"
|
ext.javamailVersion = "1.5.6"
|
||||||
ext.jettyVersion = "9.3.13.v20161014"
|
ext.jettyVersion = "9.3.13.v20161014"
|
||||||
|
ext.jetty94Version = "9.4.0.v20161208" // for spring-websocket support
|
||||||
ext.jodaVersion = "2.9.6"
|
ext.jodaVersion = "2.9.6"
|
||||||
ext.jrubyVersion = "1.7.26" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
|
ext.jrubyVersion = "1.7.26" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
|
||||||
ext.jtaVersion = "1.2"
|
ext.jtaVersion = "1.2"
|
||||||
|
@ -949,11 +950,11 @@ project("spring-websocket") {
|
||||||
optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
|
optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
|
||||||
exclude group: "javax.servlet", module: "javax.servlet"
|
exclude group: "javax.servlet", module: "javax.servlet"
|
||||||
}
|
}
|
||||||
optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") {
|
optional("org.eclipse.jetty.websocket:websocket-server:${jetty94Version}") {
|
||||||
exclude group: "javax.servlet", module: "javax.servlet"
|
exclude group: "javax.servlet", module: "javax.servlet"
|
||||||
}
|
}
|
||||||
optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
|
optional("org.eclipse.jetty.websocket:websocket-client:${jetty94Version}")
|
||||||
optional("org.eclipse.jetty:jetty-client:${jettyVersion}")
|
optional("org.eclipse.jetty:jetty-client:${jetty94Version}")
|
||||||
optional("io.undertow:undertow-core:${undertowVersion}")
|
optional("io.undertow:undertow-core:${undertowVersion}")
|
||||||
optional("io.undertow:undertow-servlet:${undertowVersion}") {
|
optional("io.undertow:undertow-servlet:${undertowVersion}") {
|
||||||
exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec"
|
exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec"
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.web.socket.adapter.jetty;
|
package org.springframework.web.socket.adapter.jetty;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
@ -26,11 +27,14 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
||||||
import org.eclipse.jetty.websocket.api.Session;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
|
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||||
|
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
import org.springframework.web.socket.BinaryMessage;
|
import org.springframework.web.socket.BinaryMessage;
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.PingMessage;
|
import org.springframework.web.socket.PingMessage;
|
||||||
|
@ -45,10 +49,22 @@ import org.springframework.web.socket.adapter.AbstractWebSocketSession;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Brian Clozel
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
|
public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
|
||||||
|
|
||||||
|
// As of Jetty 9.4, UpgradeRequest and UpgradeResponse are interfaces instead of classes
|
||||||
|
private static final boolean isJetty94;
|
||||||
|
|
||||||
|
private static Method getUpgradeRequest;
|
||||||
|
private static Method getUpgradeResponse;
|
||||||
|
private static Method getRequestURI;
|
||||||
|
private static Method getHeaders;
|
||||||
|
private static Method getAcceptedSubProtocol;
|
||||||
|
private static Method getExtensions;
|
||||||
|
private static Method getUserPrincipal;
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
private URI uri;
|
private URI uri;
|
||||||
|
@ -61,6 +77,23 @@ public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
|
||||||
|
|
||||||
private Principal user;
|
private Principal user;
|
||||||
|
|
||||||
|
static {
|
||||||
|
isJetty94 = UpgradeRequest.class.isInterface();
|
||||||
|
if (!isJetty94) {
|
||||||
|
try {
|
||||||
|
getUpgradeRequest = Session.class.getMethod("getUpgradeRequest");
|
||||||
|
getUpgradeResponse = Session.class.getMethod("getUpgradeResponse");
|
||||||
|
getRequestURI = UpgradeRequest.class.getMethod("getRequestURI");
|
||||||
|
getHeaders = UpgradeRequest.class.getMethod("getHeaders");
|
||||||
|
getAcceptedSubProtocol = UpgradeResponse.class.getMethod("getAcceptedSubProtocol");
|
||||||
|
getExtensions = UpgradeResponse.class.getMethod("getExtensions");
|
||||||
|
getUserPrincipal = UpgradeRequest.class.getMethod("getUserPrincipal");
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException ex) {
|
||||||
|
throw new IllegalStateException("Incompatible Jetty API", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link JettyWebSocketSession} instance.
|
* Create a new {@link JettyWebSocketSession} instance.
|
||||||
|
@ -164,20 +197,64 @@ public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
|
||||||
@Override
|
@Override
|
||||||
public void initializeNativeSession(Session session) {
|
public void initializeNativeSession(Session session) {
|
||||||
super.initializeNativeSession(session);
|
super.initializeNativeSession(session);
|
||||||
|
if (isJetty94) {
|
||||||
|
initializeJetty94Session(session);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
initializeJettySession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void initializeJettySession(Session session) {
|
||||||
|
|
||||||
|
Object request = ReflectionUtils.invokeMethod(getUpgradeRequest, session);
|
||||||
|
Object response = ReflectionUtils.invokeMethod(getUpgradeResponse, session);
|
||||||
|
|
||||||
|
this.id = ObjectUtils.getIdentityHexString(getNativeSession());
|
||||||
|
this.uri = (URI) ReflectionUtils.invokeMethod(getRequestURI, request);
|
||||||
|
|
||||||
|
this.headers = new HttpHeaders();
|
||||||
|
this.headers.putAll((Map<String, List<String>>) ReflectionUtils.invokeMethod(getHeaders, request));
|
||||||
|
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
|
||||||
|
|
||||||
|
this.acceptedProtocol = (String) ReflectionUtils.invokeMethod(getAcceptedSubProtocol, response);
|
||||||
|
|
||||||
|
List<ExtensionConfig> source = (List<ExtensionConfig>) ReflectionUtils.invokeMethod(getExtensions, response);
|
||||||
|
if (source != null) {
|
||||||
|
this.extensions = new ArrayList<WebSocketExtension>(source.size());
|
||||||
|
for (ExtensionConfig ec : source) {
|
||||||
|
this.extensions.add(new WebSocketExtension(ec.getName(), ec.getParameters()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.extensions = new ArrayList<WebSocketExtension>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.user == null) {
|
||||||
|
this.user = (Principal) ReflectionUtils.invokeMethod(getUserPrincipal, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeJetty94Session(Session session) {
|
||||||
this.id = ObjectUtils.getIdentityHexString(getNativeSession());
|
this.id = ObjectUtils.getIdentityHexString(getNativeSession());
|
||||||
this.uri = session.getUpgradeRequest().getRequestURI();
|
this.uri = session.getUpgradeRequest().getRequestURI();
|
||||||
|
|
||||||
this.headers = new HttpHeaders();
|
this.headers = new HttpHeaders();
|
||||||
this.headers.putAll(getNativeSession().getUpgradeRequest().getHeaders());
|
this.headers.putAll(session.getUpgradeRequest().getHeaders());
|
||||||
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
|
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
|
||||||
|
|
||||||
this.acceptedProtocol = session.getUpgradeResponse().getAcceptedSubProtocol();
|
this.acceptedProtocol = session.getUpgradeResponse().getAcceptedSubProtocol();
|
||||||
|
|
||||||
List<ExtensionConfig> source = getNativeSession().getUpgradeResponse().getExtensions();
|
List<ExtensionConfig> source = getNativeSession().getUpgradeResponse().getExtensions();
|
||||||
this.extensions = new ArrayList<WebSocketExtension>(source.size());
|
if (source != null) {
|
||||||
for (ExtensionConfig ec : source) {
|
this.extensions = new ArrayList<WebSocketExtension>(source.size());
|
||||||
this.extensions.add(new WebSocketExtension(ec.getName(), ec.getParameters()));
|
for (ExtensionConfig ec : source) {
|
||||||
|
this.extensions.add(new WebSocketExtension(ec.getName(), ec.getParameters()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.extensions = new ArrayList<WebSocketExtension>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.user == null) {
|
if (this.user == null) {
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package org.springframework.web.socket.server.jetty;
|
package org.springframework.web.socket.server.jetty;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -27,8 +26,7 @@ import javax.servlet.ServletContext;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||||
import org.eclipse.jetty.websocket.server.HandshakeRFC6455;
|
import org.eclipse.jetty.websocket.server.HandshakeRFC6455;
|
||||||
|
@ -56,69 +54,54 @@ import org.springframework.web.socket.server.HandshakeFailureException;
|
||||||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link RequestUpgradeStrategy} for use with Jetty 9.0-9.3. Based on Jetty's
|
* A {@link RequestUpgradeStrategy} for use with Jetty 9.1-9.3. Based on Jetty's
|
||||||
* internal {@code org.eclipse.jetty.websocket.server.WebSocketHandler} class.
|
* internal {@code org.eclipse.jetty.websocket.server.WebSocketHandler} class.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Brian Clozel
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Lifecycle, ServletContextAware {
|
public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Lifecycle, ServletContextAware {
|
||||||
|
|
||||||
// Pre-Jetty 9.3 init method without ServletContext
|
|
||||||
private static final Method webSocketFactoryInitMethod =
|
|
||||||
ClassUtils.getMethodIfAvailable(WebSocketServerFactory.class, "init");
|
|
||||||
|
|
||||||
private static final ThreadLocal<WebSocketHandlerContainer> wsContainerHolder =
|
private static final ThreadLocal<WebSocketHandlerContainer> wsContainerHolder =
|
||||||
new NamedThreadLocal<WebSocketHandlerContainer>("WebSocket Handler Container");
|
new NamedThreadLocal<WebSocketHandlerContainer>("WebSocket Handler Container");
|
||||||
|
|
||||||
|
// Actually 9.3.15+
|
||||||
|
private static boolean isJetty94 = ClassUtils.hasConstructor(WebSocketServerFactory.class, ServletContext.class);
|
||||||
|
|
||||||
private final WebSocketServerFactory factory;
|
private static boolean isJetty91 = ClassUtils.hasMethod(WebSocketServerFactory.class, "init");
|
||||||
|
|
||||||
|
private WebSocketServerFactoryAdapter factoryAdapter;
|
||||||
|
|
||||||
private volatile List<WebSocketExtension> supportedExtensions;
|
private volatile List<WebSocketExtension> supportedExtensions;
|
||||||
|
|
||||||
private ServletContext servletContext;
|
protected ServletContext servletContext;
|
||||||
|
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor that creates {@link WebSocketServerFactory} through
|
* Default constructor that creates {@link WebSocketServerFactory} through
|
||||||
* its default constructor thus using a default {@link WebSocketPolicy}.
|
* its default constructor thus using a default {@link WebSocketPolicy}.
|
||||||
*/
|
*/
|
||||||
public JettyRequestUpgradeStrategy() {
|
public JettyRequestUpgradeStrategy() {
|
||||||
this(new WebSocketServerFactory());
|
this(WebSocketPolicy.newServerPolicy());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A constructor accepting a {@link WebSocketServerFactory}.
|
* A constructor accepting a {@link WebSocketPolicy}
|
||||||
* This may be useful for modifying the factory's {@link WebSocketPolicy}
|
* to be used when creating the {@link WebSocketServerFactory} instance.
|
||||||
* via {@link WebSocketServerFactory#getPolicy()}.
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
public JettyRequestUpgradeStrategy(WebSocketServerFactory factory) {
|
public JettyRequestUpgradeStrategy(WebSocketPolicy webSocketPolicy) {
|
||||||
Assert.notNull(factory, "WebSocketServerFactory must not be null");
|
this.factoryAdapter = isJetty94 ? new Jetty94WebSocketServerFactoryAdapter()
|
||||||
this.factory = factory;
|
: new JettyWebSocketServerFactoryAdapter();
|
||||||
this.factory.setCreator(new WebSocketCreator() {
|
this.factoryAdapter.setWebSocketPolicy(webSocketPolicy);
|
||||||
@Override
|
|
||||||
public Object createWebSocket(ServletUpgradeRequest request, ServletUpgradeResponse response) {
|
|
||||||
// Cast to avoid infinite recursion
|
|
||||||
return createWebSocket((UpgradeRequest) request, (UpgradeResponse) response);
|
|
||||||
}
|
|
||||||
// For Jetty 9.0.x
|
|
||||||
public Object createWebSocket(UpgradeRequest request, UpgradeResponse response) {
|
|
||||||
WebSocketHandlerContainer container = wsContainerHolder.get();
|
|
||||||
Assert.state(container != null, "Expected WebSocketHandlerContainer");
|
|
||||||
response.setAcceptedSubProtocol(container.getSelectedProtocol());
|
|
||||||
response.setExtensions(container.getExtensionConfigs());
|
|
||||||
return container.getHandler();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getSupportedVersions() {
|
public String[] getSupportedVersions() {
|
||||||
return new String[] { String.valueOf(HandshakeRFC6455.VERSION) };
|
return new String[] {String.valueOf(HandshakeRFC6455.VERSION)};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -131,7 +114,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Life
|
||||||
|
|
||||||
private List<WebSocketExtension> getWebSocketExtensions() {
|
private List<WebSocketExtension> getWebSocketExtensions() {
|
||||||
List<WebSocketExtension> result = new ArrayList<WebSocketExtension>();
|
List<WebSocketExtension> result = new ArrayList<WebSocketExtension>();
|
||||||
for (String name : this.factory.getExtensionFactory().getExtensionNames()) {
|
for (String name : this.factoryAdapter.getFactory().getExtensionFactory().getExtensionNames()) {
|
||||||
result.add(new WebSocketExtension(name));
|
result.add(new WebSocketExtension(name));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -153,15 +136,10 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Life
|
||||||
if (!isRunning()) {
|
if (!isRunning()) {
|
||||||
this.running = true;
|
this.running = true;
|
||||||
try {
|
try {
|
||||||
if (webSocketFactoryInitMethod != null) {
|
this.factoryAdapter.start();
|
||||||
webSocketFactoryInitMethod.invoke(this.factory);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.factory.init(this.servletContext);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new IllegalStateException("Unable to initialize Jetty WebSocketServerFactory", ex);
|
throw new IllegalStateException("Unable to start Jetty WebSocketServerFactory", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,8 +147,13 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Life
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if (isRunning()) {
|
if (isRunning()) {
|
||||||
this.running = false;
|
try {
|
||||||
this.factory.cleanup();
|
this.running = false;
|
||||||
|
factoryAdapter.stop();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new IllegalStateException("Unable to stop Jetty WebSocketServerFactory", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +168,8 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Life
|
||||||
Assert.isInstanceOf(ServletServerHttpResponse.class, response);
|
Assert.isInstanceOf(ServletServerHttpResponse.class, response);
|
||||||
HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse();
|
HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse();
|
||||||
|
|
||||||
Assert.isTrue(this.factory.isUpgradeRequest(servletRequest, servletResponse), "Not a WebSocket handshake");
|
Assert.isTrue(this.factoryAdapter.getFactory()
|
||||||
|
.isUpgradeRequest(servletRequest, servletResponse), "Not a WebSocket handshake");
|
||||||
|
|
||||||
JettyWebSocketSession session = new JettyWebSocketSession(attributes, user);
|
JettyWebSocketSession session = new JettyWebSocketSession(attributes, user);
|
||||||
JettyWebSocketHandlerAdapter handlerAdapter = new JettyWebSocketHandlerAdapter(wsHandler, session);
|
JettyWebSocketHandlerAdapter handlerAdapter = new JettyWebSocketHandlerAdapter(wsHandler, session);
|
||||||
|
@ -195,7 +179,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Life
|
||||||
|
|
||||||
try {
|
try {
|
||||||
wsContainerHolder.set(container);
|
wsContainerHolder.set(container);
|
||||||
this.factory.acceptWebSocket(servletRequest, servletResponse);
|
this.factoryAdapter.getFactory().acceptWebSocket(servletRequest, servletResponse);
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
throw new HandshakeFailureException(
|
throw new HandshakeFailureException(
|
||||||
|
@ -219,7 +203,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Life
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
this.selectedProtocol = protocol;
|
this.selectedProtocol = protocol;
|
||||||
if (CollectionUtils.isEmpty(extensions)) {
|
if (CollectionUtils.isEmpty(extensions)) {
|
||||||
this.extensionConfigs = null;
|
this.extensionConfigs = new ArrayList<ExtensionConfig>();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.extensionConfigs = new ArrayList<ExtensionConfig>();
|
this.extensionConfigs = new ArrayList<ExtensionConfig>();
|
||||||
|
@ -242,4 +226,74 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Life
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static abstract class WebSocketServerFactoryAdapter {
|
||||||
|
|
||||||
|
protected WebSocketServerFactory factory;
|
||||||
|
|
||||||
|
protected WebSocketPolicy webSocketPolicy;
|
||||||
|
|
||||||
|
public WebSocketServerFactory getFactory() {
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebSocketPolicy(WebSocketPolicy webSocketPolicy) {
|
||||||
|
this.webSocketPolicy = webSocketPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void configureFactory() {
|
||||||
|
this.factory.setCreator(new WebSocketCreator() {
|
||||||
|
@Override
|
||||||
|
public Object createWebSocket(ServletUpgradeRequest request, ServletUpgradeResponse response) {
|
||||||
|
WebSocketHandlerContainer container = wsContainerHolder.get();
|
||||||
|
Assert.state(container != null, "Expected WebSocketHandlerContainer");
|
||||||
|
response.setAcceptedSubProtocol(container.getSelectedProtocol());
|
||||||
|
response.setExtensions(container.getExtensionConfigs());
|
||||||
|
return container.getHandler();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract void start() throws Exception;
|
||||||
|
|
||||||
|
abstract void stop() throws Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JettyWebSocketServerFactoryAdapter extends WebSocketServerFactoryAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void start() throws Exception {
|
||||||
|
this.factory = WebSocketServerFactory.class.getConstructor(WebSocketPolicy.class)
|
||||||
|
.newInstance(this.webSocketPolicy);
|
||||||
|
configureFactory();
|
||||||
|
if(isJetty91) {
|
||||||
|
WebSocketServerFactory.class.getMethod("init").invoke(this.factory);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WebSocketServerFactory.class.getMethod("init", ServletContext.class)
|
||||||
|
.invoke(this.factory, servletContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void stop() throws Exception {
|
||||||
|
WebSocketServerFactory.class.getMethod("cleanup").invoke(this.factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Jetty94WebSocketServerFactoryAdapter extends WebSocketServerFactoryAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void start() throws Exception {
|
||||||
|
servletContext.setAttribute(DecoratedObjectFactory.ATTR, new DecoratedObjectFactory());
|
||||||
|
this.factory = new WebSocketServerFactory(servletContext, this.webSocketPolicy);
|
||||||
|
configureFactory();
|
||||||
|
this.factory.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void stop() throws Exception {
|
||||||
|
this.factory.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue