|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Copyright 2002-2019 the original author or authors. |
|
|
|
* Copyright 2002-2020 the original author or authors. |
|
|
|
* |
|
|
|
* |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -20,6 +20,7 @@ import java.io.IOException; |
|
|
|
import java.lang.reflect.Method; |
|
|
|
import java.lang.reflect.Method; |
|
|
|
import java.security.Principal; |
|
|
|
import java.security.Principal; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.ArrayList; |
|
|
|
|
|
|
|
import java.util.Collections; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Set; |
|
|
|
import java.util.Set; |
|
|
|
@ -72,7 +73,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv |
|
|
|
private WebSocketPolicy policy; |
|
|
|
private WebSocketPolicy policy; |
|
|
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
@Nullable |
|
|
|
private WebSocketServerFactory factory; |
|
|
|
private volatile WebSocketServerFactory factory; |
|
|
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
@Nullable |
|
|
|
private ServletContext servletContext; |
|
|
|
private ServletContext servletContext; |
|
|
|
@ -122,17 +123,20 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv |
|
|
|
if (!isRunning()) { |
|
|
|
if (!isRunning()) { |
|
|
|
this.running = true; |
|
|
|
this.running = true; |
|
|
|
try { |
|
|
|
try { |
|
|
|
if (this.factory == null) { |
|
|
|
WebSocketServerFactory factory = this.factory; |
|
|
|
this.factory = new WebSocketServerFactory(this.servletContext, this.policy); |
|
|
|
if (factory == null) { |
|
|
|
|
|
|
|
Assert.state(this.servletContext != null, "No ServletContext set"); |
|
|
|
|
|
|
|
factory = new WebSocketServerFactory(this.servletContext, this.policy); |
|
|
|
|
|
|
|
this.factory = factory; |
|
|
|
} |
|
|
|
} |
|
|
|
this.factory.setCreator((request, response) -> { |
|
|
|
factory.setCreator((request, response) -> { |
|
|
|
WebSocketHandlerContainer container = containerHolder.get(); |
|
|
|
WebSocketHandlerContainer container = containerHolder.get(); |
|
|
|
Assert.state(container != null, "Expected WebSocketHandlerContainer"); |
|
|
|
Assert.state(container != null, "Expected WebSocketHandlerContainer"); |
|
|
|
response.setAcceptedSubProtocol(container.getSelectedProtocol()); |
|
|
|
response.setAcceptedSubProtocol(container.getSelectedProtocol()); |
|
|
|
response.setExtensions(container.getExtensionConfigs()); |
|
|
|
response.setExtensions(container.getExtensionConfigs()); |
|
|
|
return container.getHandler(); |
|
|
|
return container.getHandler(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
this.factory.start(); |
|
|
|
factory.start(); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Throwable ex) { |
|
|
|
catch (Throwable ex) { |
|
|
|
throw new IllegalStateException("Unable to start Jetty WebSocketServerFactory", ex); |
|
|
|
throw new IllegalStateException("Unable to start Jetty WebSocketServerFactory", ex); |
|
|
|
@ -144,9 +148,10 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv |
|
|
|
public void stop() { |
|
|
|
public void stop() { |
|
|
|
if (isRunning()) { |
|
|
|
if (isRunning()) { |
|
|
|
this.running = false; |
|
|
|
this.running = false; |
|
|
|
if (this.factory != null) { |
|
|
|
WebSocketServerFactory factory = this.factory; |
|
|
|
|
|
|
|
if (factory != null) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
this.factory.stop(); |
|
|
|
factory.stop(); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Throwable ex) { |
|
|
|
catch (Throwable ex) { |
|
|
|
throw new IllegalStateException("Unable to stop Jetty WebSocketServerFactory", ex); |
|
|
|
throw new IllegalStateException("Unable to stop Jetty WebSocketServerFactory", ex); |
|
|
|
@ -168,10 +173,12 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public List<WebSocketExtension> getSupportedExtensions(ServerHttpRequest request) { |
|
|
|
public List<WebSocketExtension> getSupportedExtensions(ServerHttpRequest request) { |
|
|
|
if (this.supportedExtensions == null) { |
|
|
|
List<WebSocketExtension> extensions = this.supportedExtensions; |
|
|
|
this.supportedExtensions = buildWebSocketExtensions(); |
|
|
|
if (extensions == null) { |
|
|
|
|
|
|
|
extensions = buildWebSocketExtensions(); |
|
|
|
|
|
|
|
this.supportedExtensions = extensions; |
|
|
|
} |
|
|
|
} |
|
|
|
return this.supportedExtensions; |
|
|
|
return extensions; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private List<WebSocketExtension> buildWebSocketExtensions() { |
|
|
|
private List<WebSocketExtension> buildWebSocketExtensions() { |
|
|
|
@ -185,8 +192,10 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv |
|
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings({"unchecked", "deprecation"}) |
|
|
|
@SuppressWarnings({"unchecked", "deprecation"}) |
|
|
|
private Set<String> getExtensionNames() { |
|
|
|
private Set<String> getExtensionNames() { |
|
|
|
|
|
|
|
WebSocketServerFactory factory = this.factory; |
|
|
|
|
|
|
|
Assert.state(factory != null, "No WebSocketServerFactory available"); |
|
|
|
try { |
|
|
|
try { |
|
|
|
return this.factory.getAvailableExtensionNames(); |
|
|
|
return factory.getAvailableExtensionNames(); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (IncompatibleClassChangeError ex) { |
|
|
|
catch (IncompatibleClassChangeError ex) { |
|
|
|
// Fallback for versions prior to 9.4.21:
|
|
|
|
// Fallback for versions prior to 9.4.21:
|
|
|
|
@ -194,7 +203,8 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv |
|
|
|
// 9.4.21.v20190926: ExtensionFactory (interface -> abstract class) + deprecated
|
|
|
|
// 9.4.21.v20190926: ExtensionFactory (interface -> abstract class) + deprecated
|
|
|
|
Class<?> clazz = org.eclipse.jetty.websocket.api.extensions.ExtensionFactory.class; |
|
|
|
Class<?> clazz = org.eclipse.jetty.websocket.api.extensions.ExtensionFactory.class; |
|
|
|
Method method = ClassUtils.getMethod(clazz, "getExtensionNames"); |
|
|
|
Method method = ClassUtils.getMethod(clazz, "getExtensionNames"); |
|
|
|
return (Set<String>) ReflectionUtils.invokeMethod(method, this.factory.getExtensionFactory()); |
|
|
|
Set<String> result = (Set<String>) ReflectionUtils.invokeMethod(method, factory.getExtensionFactory()); |
|
|
|
|
|
|
|
return (result != null ? result : Collections.emptySet()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -209,7 +219,9 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv |
|
|
|
Assert.isInstanceOf(ServletServerHttpResponse.class, response, "ServletServerHttpResponse required"); |
|
|
|
Assert.isInstanceOf(ServletServerHttpResponse.class, response, "ServletServerHttpResponse required"); |
|
|
|
HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse(); |
|
|
|
HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse(); |
|
|
|
|
|
|
|
|
|
|
|
Assert.isTrue(this.factory.isUpgradeRequest(servletRequest, servletResponse), "Not a WebSocket handshake"); |
|
|
|
WebSocketServerFactory factory = this.factory; |
|
|
|
|
|
|
|
Assert.state(factory != null, "No WebSocketServerFactory available"); |
|
|
|
|
|
|
|
Assert.isTrue(factory.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); |
|
|
|
@ -219,7 +231,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
containerHolder.set(container); |
|
|
|
containerHolder.set(container); |
|
|
|
this.factory.acceptWebSocket(servletRequest, servletResponse); |
|
|
|
factory.acceptWebSocket(servletRequest, servletResponse); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (IOException ex) { |
|
|
|
catch (IOException ex) { |
|
|
|
throw new HandshakeFailureException( |
|
|
|
throw new HandshakeFailureException( |
|
|
|
@ -235,12 +247,13 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv |
|
|
|
|
|
|
|
|
|
|
|
private final JettyWebSocketHandlerAdapter handler; |
|
|
|
private final JettyWebSocketHandlerAdapter handler; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
private final String selectedProtocol; |
|
|
|
private final String selectedProtocol; |
|
|
|
|
|
|
|
|
|
|
|
private final List<ExtensionConfig> extensionConfigs; |
|
|
|
private final List<ExtensionConfig> extensionConfigs; |
|
|
|
|
|
|
|
|
|
|
|
public WebSocketHandlerContainer( |
|
|
|
public WebSocketHandlerContainer(JettyWebSocketHandlerAdapter handler, |
|
|
|
JettyWebSocketHandlerAdapter handler, String protocol, List<WebSocketExtension> extensions) { |
|
|
|
@Nullable String protocol, List<WebSocketExtension> extensions) { |
|
|
|
|
|
|
|
|
|
|
|
this.handler = handler; |
|
|
|
this.handler = handler; |
|
|
|
this.selectedProtocol = protocol; |
|
|
|
this.selectedProtocol = protocol; |
|
|
|
@ -259,6 +272,7 @@ public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy, Serv |
|
|
|
return this.handler; |
|
|
|
return this.handler; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
public String getSelectedProtocol() { |
|
|
|
public String getSelectedProtocol() { |
|
|
|
return this.selectedProtocol; |
|
|
|
return this.selectedProtocol; |
|
|
|
} |
|
|
|
} |
|
|
|
|