Drop support for Jetty 9.3 and OkHttp 2.x
Issue: SPR-15038
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.web.socket.adapter.jetty;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.security.Principal;
|
||||
@@ -28,15 +27,12 @@ import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
||||
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.extensions.ExtensionConfig;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.socket.BinaryMessage;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
import org.springframework.web.socket.PingMessage;
|
||||
@@ -47,7 +43,7 @@ import org.springframework.web.socket.WebSocketSession;
|
||||
import org.springframework.web.socket.adapter.AbstractWebSocketSession;
|
||||
|
||||
/**
|
||||
* A {@link WebSocketSession} for use with the Jetty 9.3/9.4 WebSocket API.
|
||||
* A {@link WebSocketSession} for use with the Jetty 9.4 WebSocket API.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Rossen Stoyanchev
|
||||
@@ -57,36 +53,6 @@ import org.springframework.web.socket.adapter.AbstractWebSocketSession;
|
||||
*/
|
||||
public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
|
||||
|
||||
// As of Jetty 9.4, UpgradeRequest and UpgradeResponse are interfaces instead of classes
|
||||
private static final boolean directInterfaceCalls;
|
||||
|
||||
private static Method getUpgradeRequest;
|
||||
private static Method getUpgradeResponse;
|
||||
private static Method getRequestURI;
|
||||
private static Method getHeaders;
|
||||
private static Method getUserPrincipal;
|
||||
private static Method getAcceptedSubProtocol;
|
||||
private static Method getExtensions;
|
||||
|
||||
static {
|
||||
directInterfaceCalls = UpgradeRequest.class.isInterface();
|
||||
if (!directInterfaceCalls) {
|
||||
try {
|
||||
getUpgradeRequest = Session.class.getMethod("getUpgradeRequest");
|
||||
getUpgradeResponse = Session.class.getMethod("getUpgradeResponse");
|
||||
getRequestURI = UpgradeRequest.class.getMethod("getRequestURI");
|
||||
getHeaders = UpgradeRequest.class.getMethod("getHeaders");
|
||||
getUserPrincipal = UpgradeRequest.class.getMethod("getUserPrincipal");
|
||||
getAcceptedSubProtocol = UpgradeResponse.class.getMethod("getAcceptedSubProtocol");
|
||||
getExtensions = UpgradeResponse.class.getMethod("getExtensions");
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new IllegalStateException("Incompatible Jetty API", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String id;
|
||||
|
||||
private URI uri;
|
||||
@@ -201,31 +167,23 @@ public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
|
||||
@Override
|
||||
public void initializeNativeSession(Session session) {
|
||||
super.initializeNativeSession(session);
|
||||
if (directInterfaceCalls) {
|
||||
initializeJettySessionDirectly(session);
|
||||
}
|
||||
else {
|
||||
initializeJettySessionReflectively(session);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeJettySessionDirectly(Session session) {
|
||||
this.id = ObjectUtils.getIdentityHexString(getNativeSession());
|
||||
this.uri = session.getUpgradeRequest().getRequestURI();
|
||||
|
||||
this.headers = new HttpHeaders();
|
||||
this.headers.putAll(session.getUpgradeRequest().getHeaders());
|
||||
this.headers = HttpHeaders.readOnlyHttpHeaders(this.headers);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.putAll(session.getUpgradeRequest().getHeaders());
|
||||
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
|
||||
|
||||
this.acceptedProtocol = session.getUpgradeResponse().getAcceptedSubProtocol();
|
||||
|
||||
List<ExtensionConfig> jettyExtensions = session.getUpgradeResponse().getExtensions();
|
||||
if (!CollectionUtils.isEmpty(jettyExtensions)) {
|
||||
this.extensions = new ArrayList<>(jettyExtensions.size());
|
||||
List<WebSocketExtension> extensions = new ArrayList<>(jettyExtensions.size());
|
||||
for (ExtensionConfig jettyExtension : jettyExtensions) {
|
||||
this.extensions.add(new WebSocketExtension(jettyExtension.getName(), jettyExtension.getParameters()));
|
||||
extensions.add(new WebSocketExtension(jettyExtension.getName(), jettyExtension.getParameters()));
|
||||
}
|
||||
this.extensions = Collections.unmodifiableList(this.extensions);
|
||||
this.extensions = Collections.unmodifiableList(extensions);
|
||||
}
|
||||
else {
|
||||
this.extensions = Collections.emptyList();
|
||||
@@ -236,37 +194,6 @@ public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void initializeJettySessionReflectively(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(this.headers);
|
||||
|
||||
this.acceptedProtocol = (String) ReflectionUtils.invokeMethod(getAcceptedSubProtocol, response);
|
||||
|
||||
List<ExtensionConfig> extensions = (List<ExtensionConfig>) ReflectionUtils.invokeMethod(getExtensions, response);
|
||||
if (!CollectionUtils.isEmpty(extensions)) {
|
||||
this.extensions = new ArrayList<>(extensions.size());
|
||||
for (ExtensionConfig extension : extensions) {
|
||||
this.extensions.add(new WebSocketExtension(extension.getName(), extension.getParameters()));
|
||||
}
|
||||
this.extensions = Collections.unmodifiableList(this.extensions);
|
||||
}
|
||||
else {
|
||||
this.extensions = Collections.emptyList();
|
||||
}
|
||||
|
||||
if (this.user == null) {
|
||||
this.user = (Principal) ReflectionUtils.invokeMethod(getUserPrincipal, request);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void sendTextMessage(TextMessage message) throws IOException {
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
import org.springframework.web.socket.WebSocketExtension;
|
||||
@@ -53,8 +52,8 @@ import org.springframework.web.socket.server.HandshakeFailureException;
|
||||
import org.springframework.web.socket.server.RequestUpgradeStrategy;
|
||||
|
||||
/**
|
||||
* A {@link RequestUpgradeStrategy} for use with Jetty 9.3 and 9.4. Based on
|
||||
* Jetty's internal {@code org.eclipse.jetty.websocket.server.WebSocketHandler} class.
|
||||
* A {@link RequestUpgradeStrategy} for use with Jetty 9.4. Based on Jetty's
|
||||
* internal {@code org.eclipse.jetty.websocket.server.WebSocketHandler} class.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Rossen Stoyanchev
|
||||
@@ -68,11 +67,9 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
|
||||
new NamedThreadLocal<>("WebSocketHandlerContainer");
|
||||
|
||||
|
||||
// Configurable factory adapter due to Jetty 9.3.15+ API differences:
|
||||
// using WebSocketServerFactory(ServletContext) as a version indicator
|
||||
private final WebSocketServerFactoryAdapter factoryAdapter =
|
||||
(ClassUtils.hasConstructor(WebSocketServerFactory.class, ServletContext.class) ?
|
||||
new ModernJettyWebSocketServerFactoryAdapter() : new LegacyJettyWebSocketServerFactoryAdapter());
|
||||
private WebSocketPolicy policy;
|
||||
|
||||
private WebSocketServerFactory factory;
|
||||
|
||||
private ServletContext servletContext;
|
||||
|
||||
@@ -86,7 +83,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
|
||||
* its default constructor thus using a default {@link WebSocketPolicy}.
|
||||
*/
|
||||
public JettyRequestUpgradeStrategy() {
|
||||
this.factoryAdapter.setPolicy(WebSocketPolicy.newServerPolicy());
|
||||
this.policy = WebSocketPolicy.newServerPolicy();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +94,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
|
||||
*/
|
||||
public JettyRequestUpgradeStrategy(WebSocketPolicy policy) {
|
||||
Assert.notNull(policy, "WebSocketPolicy must not be null");
|
||||
this.factoryAdapter.setPolicy(policy);
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +103,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
|
||||
*/
|
||||
public JettyRequestUpgradeStrategy(WebSocketServerFactory factory) {
|
||||
Assert.notNull(factory, "WebSocketServerFactory must not be null");
|
||||
this.factoryAdapter.setFactory(factory);
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +117,20 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
|
||||
if (!isRunning()) {
|
||||
this.running = true;
|
||||
try {
|
||||
this.factoryAdapter.start();
|
||||
if (this.factory == null) {
|
||||
this.factory = new WebSocketServerFactory(servletContext, this.policy);
|
||||
}
|
||||
this.factory.setCreator(new WebSocketCreator() {
|
||||
@Override
|
||||
public Object createWebSocket(ServletUpgradeRequest request, ServletUpgradeResponse response) {
|
||||
WebSocketHandlerContainer container = containerHolder.get();
|
||||
Assert.state(container != null, "Expected WebSocketHandlerContainer");
|
||||
response.setAcceptedSubProtocol(container.getSelectedProtocol());
|
||||
response.setExtensions(container.getExtensionConfigs());
|
||||
return container.getHandler();
|
||||
}
|
||||
});
|
||||
this.factory.start();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Unable to start Jetty WebSocketServerFactory", ex);
|
||||
@@ -132,11 +142,13 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
|
||||
public void stop() {
|
||||
if (isRunning()) {
|
||||
this.running = false;
|
||||
try {
|
||||
this.factoryAdapter.stop();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Unable to stop Jetty WebSocketServerFactory", ex);
|
||||
if (this.factory != null) {
|
||||
try {
|
||||
this.factory.stop();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Unable to stop Jetty WebSocketServerFactory", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,7 +173,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
|
||||
}
|
||||
|
||||
private List<WebSocketExtension> buildWebSocketExtensions() {
|
||||
Set<String> names = this.factoryAdapter.getFactory().getExtensionFactory().getExtensionNames();
|
||||
Set<String> names = this.factory.getExtensionFactory().getExtensionNames();
|
||||
List<WebSocketExtension> result = new ArrayList<>(names.size());
|
||||
for (String name : names) {
|
||||
result.add(new WebSocketExtension(name));
|
||||
@@ -180,8 +192,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
|
||||
Assert.isInstanceOf(ServletServerHttpResponse.class, response, "ServletServerHttpResponse required");
|
||||
HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse();
|
||||
|
||||
Assert.isTrue(this.factoryAdapter.getFactory().isUpgradeRequest(servletRequest, servletResponse),
|
||||
"Not a WebSocket handshake");
|
||||
Assert.isTrue(this.factory.isUpgradeRequest(servletRequest, servletResponse), "Not a WebSocket handshake");
|
||||
|
||||
JettyWebSocketSession session = new JettyWebSocketSession(attributes, user);
|
||||
JettyWebSocketHandlerAdapter handlerAdapter = new JettyWebSocketHandlerAdapter(wsHandler, session);
|
||||
@@ -191,7 +202,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
|
||||
|
||||
try {
|
||||
containerHolder.set(container);
|
||||
this.factoryAdapter.getFactory().acceptWebSocket(servletRequest, servletResponse);
|
||||
this.factory.acceptWebSocket(servletRequest, servletResponse);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new HandshakeFailureException(
|
||||
@@ -240,93 +251,4 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static abstract class WebSocketServerFactoryAdapter {
|
||||
|
||||
private WebSocketPolicy policy;
|
||||
|
||||
private WebSocketServerFactory factory;
|
||||
|
||||
public void setPolicy(WebSocketPolicy policy) {
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
public void setFactory(WebSocketServerFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public WebSocketServerFactory getFactory() {
|
||||
return this.factory;
|
||||
}
|
||||
|
||||
public void start() throws Exception {
|
||||
if (this.factory == null) {
|
||||
this.factory = createFactory(this.policy);
|
||||
}
|
||||
this.factory.setCreator(new WebSocketCreator() {
|
||||
@Override
|
||||
public Object createWebSocket(ServletUpgradeRequest request, ServletUpgradeResponse response) {
|
||||
WebSocketHandlerContainer container = containerHolder.get();
|
||||
Assert.state(container != null, "Expected WebSocketHandlerContainer");
|
||||
response.setAcceptedSubProtocol(container.getSelectedProtocol());
|
||||
response.setExtensions(container.getExtensionConfigs());
|
||||
return container.getHandler();
|
||||
}
|
||||
});
|
||||
startFactory(this.factory);
|
||||
}
|
||||
|
||||
public void stop() throws Exception {
|
||||
if (this.factory != null) {
|
||||
stopFactory(this.factory);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract WebSocketServerFactory createFactory(WebSocketPolicy policy) throws Exception;
|
||||
|
||||
protected abstract void startFactory(WebSocketServerFactory factory) throws Exception;
|
||||
|
||||
protected abstract void stopFactory(WebSocketServerFactory factory) throws Exception;
|
||||
}
|
||||
|
||||
|
||||
// Jetty 9.3.15+
|
||||
private class ModernJettyWebSocketServerFactoryAdapter extends WebSocketServerFactoryAdapter {
|
||||
|
||||
@Override
|
||||
protected WebSocketServerFactory createFactory(WebSocketPolicy policy) throws Exception {
|
||||
return new WebSocketServerFactory(servletContext, policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startFactory(WebSocketServerFactory factory) throws Exception {
|
||||
factory.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopFactory(WebSocketServerFactory factory) throws Exception {
|
||||
factory.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Jetty <9.3.15
|
||||
private class LegacyJettyWebSocketServerFactoryAdapter extends WebSocketServerFactoryAdapter {
|
||||
|
||||
@Override
|
||||
protected WebSocketServerFactory createFactory(WebSocketPolicy policy) throws Exception {
|
||||
return WebSocketServerFactory.class.getConstructor(WebSocketPolicy.class).newInstance(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startFactory(WebSocketServerFactory factory) throws Exception {
|
||||
WebSocketServerFactory.class.getMethod("init", ServletContext.class).invoke(factory, servletContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopFactory(WebSocketServerFactory factory) throws Exception {
|
||||
WebSocketServerFactory.class.getMethod("cleanup").invoke(factory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user