1717package org .springframework .web .socket .server .standard ;
1818
1919import java .lang .reflect .Constructor ;
20+ import java .lang .reflect .Method ;
2021import java .util .Arrays ;
2122import java .util .Collections ;
2223import java .util .List ;
4849import io .undertow .websockets .jsr .handshake .JsrHybi07Handshake ;
4950import io .undertow .websockets .jsr .handshake .JsrHybi08Handshake ;
5051import io .undertow .websockets .jsr .handshake .JsrHybi13Handshake ;
52+ import io .undertow .websockets .spi .WebSocketHttpExchange ;
5153import org .xnio .StreamConnection ;
5254
5355import org .springframework .http .server .ServerHttpRequest ;
5456import org .springframework .http .server .ServerHttpResponse ;
5557import org .springframework .util .ClassUtils ;
58+ import org .springframework .util .ReflectionUtils ;
5659import org .springframework .web .socket .server .HandshakeFailureException ;
5760
5861/**
5962 * A {@link org.springframework.web.socket.server.RequestUpgradeStrategy} for use
6063 * with WildFly and its underlying Undertow web server.
6164 *
62- * <p>Compatible with Undertow 1.0, 1.1, 1.2 - as included in WildFly 8.x and 9.0 .
65+ * <p>Compatible with Undertow 1.0 to 1.3 - as included in WildFly 8.x, 9 and 10 .
6366 *
6467 * @author Rossen Stoyanchev
68+ * @author Brian Clozel
69+ * @author Juergen Hoeller
6570 * @since 4.0.1
6671 */
6772public class UndertowRequestUpgradeStrategy extends AbstractStandardUpgradeStrategy {
6873
6974 private static final Constructor <ServletWebSocketHttpExchange > exchangeConstructor ;
7075
76+ private static final boolean exchangeConstructorWithPeerConnections ;
77+
7178 private static final Constructor <ConfiguredServerEndpoint > endpointConstructor ;
7279
73- private static final boolean undertow10Present ;
80+ private static final boolean endpointConstructorWithEndpointFactory ;
81+
82+ private static final Method getBufferPoolMethod ;
7483
75- private static final boolean undertow11Present ;
84+ private static final Method createChannelMethod ;
7685
7786 static {
78- Class <ServletWebSocketHttpExchange > exchangeType = ServletWebSocketHttpExchange .class ;
79- Class <?>[] exchangeParamTypes = new Class <?>[] {HttpServletRequest .class , HttpServletResponse .class , Set .class };
80- if (ClassUtils .hasConstructor (exchangeType , exchangeParamTypes )) {
81- exchangeConstructor = ClassUtils .getConstructorIfAvailable (exchangeType , exchangeParamTypes );
82- undertow10Present = false ;
83- }
84- else {
85- exchangeParamTypes = new Class <?>[] {HttpServletRequest .class , HttpServletResponse .class };
86- exchangeConstructor = ClassUtils .getConstructorIfAvailable (exchangeType , exchangeParamTypes );
87- undertow10Present = true ;
88- }
87+ try {
88+ Class <ServletWebSocketHttpExchange > exchangeType = ServletWebSocketHttpExchange .class ;
89+ Class <?>[] exchangeParamTypes =
90+ new Class <?>[] {HttpServletRequest .class , HttpServletResponse .class , Set .class };
91+ Constructor <ServletWebSocketHttpExchange > exchangeCtor =
92+ ClassUtils .getConstructorIfAvailable (exchangeType , exchangeParamTypes );
93+ if (exchangeCtor != null ) {
94+ // Undertow 1.1+
95+ exchangeConstructor = exchangeCtor ;
96+ exchangeConstructorWithPeerConnections = true ;
97+ }
98+ else {
99+ // Undertow 1.0
100+ exchangeParamTypes = new Class <?>[] {HttpServletRequest .class , HttpServletResponse .class };
101+ exchangeConstructor = exchangeType .getConstructor (exchangeParamTypes );
102+ exchangeConstructorWithPeerConnections = false ;
103+ }
89104
90- Class <ConfiguredServerEndpoint > endpointType = ConfiguredServerEndpoint .class ;
91- Class <?>[] endpointParamTypes = new Class <?>[] {ServerEndpointConfig .class , InstanceFactory .class ,
92- PathTemplate .class , EncodingFactory .class , AnnotatedEndpointFactory .class };
93- if (ClassUtils .hasConstructor (endpointType , endpointParamTypes )) {
94- endpointConstructor = ClassUtils .getConstructorIfAvailable (endpointType , endpointParamTypes );
95- undertow11Present = true ;
105+ Class <ConfiguredServerEndpoint > endpointType = ConfiguredServerEndpoint .class ;
106+ Class <?>[] endpointParamTypes = new Class <?>[] {ServerEndpointConfig .class , InstanceFactory .class ,
107+ PathTemplate .class , EncodingFactory .class , AnnotatedEndpointFactory .class };
108+ Constructor <ConfiguredServerEndpoint > endpointCtor =
109+ ClassUtils .getConstructorIfAvailable (endpointType , endpointParamTypes );
110+ if (endpointCtor != null ) {
111+ // Undertow 1.1+
112+ endpointConstructor = endpointCtor ;
113+ endpointConstructorWithEndpointFactory = true ;
114+ }
115+ else {
116+ // Undertow 1.0
117+ endpointParamTypes = new Class <?>[] {ServerEndpointConfig .class , InstanceFactory .class ,
118+ PathTemplate .class , EncodingFactory .class };
119+ endpointConstructor = endpointType .getConstructor (endpointParamTypes );
120+ endpointConstructorWithEndpointFactory = false ;
121+ }
122+
123+ // Adapting between different Pool API types in Undertow 1.0-1.2 vs 1.3
124+ getBufferPoolMethod = WebSocketHttpExchange .class .getMethod ("getBufferPool" );
125+ createChannelMethod = Handshake .class .getMethod ("createChannel" ,
126+ WebSocketHttpExchange .class , StreamConnection .class , getBufferPoolMethod .getReturnType ());
96127 }
97- else {
98- endpointParamTypes = new Class <?>[] {ServerEndpointConfig .class , InstanceFactory .class ,
99- PathTemplate .class , EncodingFactory .class };
100- endpointConstructor = ClassUtils .getConstructorIfAvailable (endpointType , endpointParamTypes );
101- undertow11Present = false ;
128+ catch (Throwable ex ) {
129+ throw new IllegalStateException ("Incompatible Undertow API version" , ex );
102130 }
103131 }
104132
@@ -113,11 +141,11 @@ public class UndertowRequestUpgradeStrategy extends AbstractStandardUpgradeStrat
113141
114142
115143 public UndertowRequestUpgradeStrategy () {
116- if (undertow10Present ) {
117- this .peerConnections = null ;
144+ if (exchangeConstructorWithPeerConnections ) {
145+ this .peerConnections = Collections . newSetFromMap ( new ConcurrentHashMap < WebSocketChannel , Boolean >()) ;
118146 }
119147 else {
120- this .peerConnections = Collections . newSetFromMap ( new ConcurrentHashMap < WebSocketChannel , Boolean >()) ;
148+ this .peerConnections = null ;
121149 }
122150 }
123151
@@ -149,7 +177,9 @@ protected void upgradeInternal(ServerHttpRequest request, ServerHttpResponse res
149177 exchange .upgradeChannel (new HttpUpgradeListener () {
150178 @ Override
151179 public void handleUpgrade (StreamConnection connection , HttpServerExchange serverExchange ) {
152- WebSocketChannel channel = handshake .createChannel (exchange , connection , exchange .getBufferPool ());
180+ Object bufferPool = ReflectionUtils .invokeMethod (getBufferPoolMethod , exchange );
181+ WebSocketChannel channel = (WebSocketChannel ) ReflectionUtils .invokeMethod (
182+ createChannelMethod , handshake , exchange , connection , bufferPool );
153183 if (peerConnections != null ) {
154184 peerConnections .add (channel );
155185 }
@@ -202,7 +232,7 @@ private ConfiguredServerEndpoint createConfiguredServerEndpoint(String selectedP
202232 Collections .<Class <?>, List <InstanceFactory <? extends Encoder >>>emptyMap (),
203233 Collections .<Class <?>, List <InstanceFactory <? extends Decoder >>>emptyMap ());
204234 try {
205- return (undertow11Present ?
235+ return (endpointConstructorWithEndpointFactory ?
206236 endpointConstructor .newInstance (endpointRegistration ,
207237 new EndpointInstanceFactory (endpoint ), null , encodingFactory , null ) :
208238 endpointConstructor .newInstance (endpointRegistration ,
0 commit comments