17
17
package org .springframework .web .socket .server .standard ;
18
18
19
19
import java .lang .reflect .Constructor ;
20
+ import java .lang .reflect .Method ;
20
21
import java .util .Arrays ;
21
22
import java .util .Collections ;
22
23
import java .util .List ;
48
49
import io .undertow .websockets .jsr .handshake .JsrHybi07Handshake ;
49
50
import io .undertow .websockets .jsr .handshake .JsrHybi08Handshake ;
50
51
import io .undertow .websockets .jsr .handshake .JsrHybi13Handshake ;
52
+ import io .undertow .websockets .spi .WebSocketHttpExchange ;
51
53
import org .xnio .StreamConnection ;
52
54
53
55
import org .springframework .http .server .ServerHttpRequest ;
54
56
import org .springframework .http .server .ServerHttpResponse ;
55
57
import org .springframework .util .ClassUtils ;
58
+ import org .springframework .util .ReflectionUtils ;
56
59
import org .springframework .web .socket .server .HandshakeFailureException ;
57
60
58
61
/**
59
62
* A {@link org.springframework.web.socket.server.RequestUpgradeStrategy} for use
60
63
* with WildFly and its underlying Undertow web server.
61
64
*
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 .
63
66
*
64
67
* @author Rossen Stoyanchev
68
+ * @author Brian Clozel
69
+ * @author Juergen Hoeller
65
70
* @since 4.0.1
66
71
*/
67
72
public class UndertowRequestUpgradeStrategy extends AbstractStandardUpgradeStrategy {
68
73
69
74
private static final Constructor <ServletWebSocketHttpExchange > exchangeConstructor ;
70
75
76
+ private static final boolean exchangeConstructorWithPeerConnections ;
77
+
71
78
private static final Constructor <ConfiguredServerEndpoint > endpointConstructor ;
72
79
73
- private static final boolean undertow10Present ;
80
+ private static final boolean endpointConstructorWithEndpointFactory ;
81
+
82
+ private static final Method getBufferPoolMethod ;
74
83
75
- private static final boolean undertow11Present ;
84
+ private static final Method createChannelMethod ;
76
85
77
86
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
+ }
89
104
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 ());
96
127
}
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 );
102
130
}
103
131
}
104
132
@@ -113,11 +141,11 @@ public class UndertowRequestUpgradeStrategy extends AbstractStandardUpgradeStrat
113
141
114
142
115
143
public UndertowRequestUpgradeStrategy () {
116
- if (undertow10Present ) {
117
- this .peerConnections = null ;
144
+ if (exchangeConstructorWithPeerConnections ) {
145
+ this .peerConnections = Collections . newSetFromMap ( new ConcurrentHashMap < WebSocketChannel , Boolean >()) ;
118
146
}
119
147
else {
120
- this .peerConnections = Collections . newSetFromMap ( new ConcurrentHashMap < WebSocketChannel , Boolean >()) ;
148
+ this .peerConnections = null ;
121
149
}
122
150
}
123
151
@@ -149,7 +177,9 @@ protected void upgradeInternal(ServerHttpRequest request, ServerHttpResponse res
149
177
exchange .upgradeChannel (new HttpUpgradeListener () {
150
178
@ Override
151
179
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 );
153
183
if (peerConnections != null ) {
154
184
peerConnections .add (channel );
155
185
}
@@ -202,7 +232,7 @@ private ConfiguredServerEndpoint createConfiguredServerEndpoint(String selectedP
202
232
Collections .<Class <?>, List <InstanceFactory <? extends Encoder >>>emptyMap (),
203
233
Collections .<Class <?>, List <InstanceFactory <? extends Decoder >>>emptyMap ());
204
234
try {
205
- return (undertow11Present ?
235
+ return (endpointConstructorWithEndpointFactory ?
206
236
endpointConstructor .newInstance (endpointRegistration ,
207
237
new EndpointInstanceFactory (endpoint ), null , encodingFactory , null ) :
208
238
endpointConstructor .newInstance (endpointRegistration ,
0 commit comments