Skip to content

Commit 52799c0

Browse files
committed
Revised Jetty 9.3 vs 9.4 differentiation
Issue: SPR-14940
1 parent 953bc18 commit 52799c0

File tree

3 files changed

+155
-117
lines changed

3 files changed

+155
-117
lines changed

spring-websocket/src/main/java/org/springframework/web/socket/adapter/AbstractWebSocketSession.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,13 @@ public abstract class AbstractWebSocketSession<T> implements NativeWebSocketSess
4242

4343
protected static final Log logger = LogFactory.getLog(NativeWebSocketSession.class);
4444

45+
private final Map<String, Object> attributes = new ConcurrentHashMap<>();
4546

4647
private T nativeSession;
4748

48-
private final Map<String, Object> attributes = new ConcurrentHashMap<>();
49-
5049

5150
/**
5251
* Create a new instance and associate the given attributes with it.
53-
*
5452
* @param attributes attributes from the HTTP handshake to associate with the WebSocket
5553
* session; the provided attributes are copied, the original map is not used.
5654
*/
@@ -83,7 +81,7 @@ public <R> R getNativeSession(Class<R> requiredType) {
8381
}
8482

8583
public void initializeNativeSession(T session) {
86-
Assert.notNull(session, "session must not be null");
84+
Assert.notNull(session, "WebSocket session must not be null");
8785
this.nativeSession = session;
8886
}
8987

@@ -125,6 +123,7 @@ else if (message instanceof PongMessage) {
125123

126124
protected abstract void sendPongMessage(PongMessage message) throws IOException;
127125

126+
128127
@Override
129128
public final void close() throws IOException {
130129
close(CloseStatus.NORMAL);

spring-websocket/src/main/java/org/springframework/web/socket/adapter/jetty/JettyWebSocketSession.java

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -45,59 +45,61 @@
4545
import org.springframework.web.socket.adapter.AbstractWebSocketSession;
4646

4747
/**
48-
* A {@link WebSocketSession} for use with the Jetty 9 WebSocket API.
48+
* A {@link WebSocketSession} for use with the Jetty 9.3/9.4 WebSocket API.
4949
*
5050
* @author Phillip Webb
5151
* @author Rossen Stoyanchev
5252
* @author Brian Clozel
53+
* @author Juergen Hoeller
5354
* @since 4.0
5455
*/
5556
public class JettyWebSocketSession extends AbstractWebSocketSession<Session> {
5657

5758
// As of Jetty 9.4, UpgradeRequest and UpgradeResponse are interfaces instead of classes
58-
private static final boolean isJetty94;
59+
private static final boolean directInterfaceCalls;
5960

6061
private static Method getUpgradeRequest;
6162
private static Method getUpgradeResponse;
6263
private static Method getRequestURI;
6364
private static Method getHeaders;
65+
private static Method getUserPrincipal;
6466
private static Method getAcceptedSubProtocol;
6567
private static Method getExtensions;
66-
private static Method getUserPrincipal;
67-
68-
private String id;
69-
70-
private URI uri;
71-
72-
private HttpHeaders headers;
73-
74-
private String acceptedProtocol;
75-
76-
private List<WebSocketExtension> extensions;
77-
78-
private Principal user;
7968

8069
static {
81-
isJetty94 = UpgradeRequest.class.isInterface();
82-
if (!isJetty94) {
70+
directInterfaceCalls = UpgradeRequest.class.isInterface();
71+
if (!directInterfaceCalls) {
8372
try {
8473
getUpgradeRequest = Session.class.getMethod("getUpgradeRequest");
8574
getUpgradeResponse = Session.class.getMethod("getUpgradeResponse");
8675
getRequestURI = UpgradeRequest.class.getMethod("getRequestURI");
8776
getHeaders = UpgradeRequest.class.getMethod("getHeaders");
77+
getUserPrincipal = UpgradeRequest.class.getMethod("getUserPrincipal");
8878
getAcceptedSubProtocol = UpgradeResponse.class.getMethod("getAcceptedSubProtocol");
8979
getExtensions = UpgradeResponse.class.getMethod("getExtensions");
90-
getUserPrincipal = UpgradeRequest.class.getMethod("getUserPrincipal");
9180
}
9281
catch (NoSuchMethodException ex) {
9382
throw new IllegalStateException("Incompatible Jetty API", ex);
9483
}
9584
}
9685
}
9786

87+
88+
private String id;
89+
90+
private URI uri;
91+
92+
private HttpHeaders headers;
93+
94+
private String acceptedProtocol;
95+
96+
private List<WebSocketExtension> extensions;
97+
98+
private Principal user;
99+
100+
98101
/**
99102
* Create a new {@link JettyWebSocketSession} instance.
100-
*
101103
* @param attributes attributes from the HTTP handshake to associate with the WebSocket session
102104
*/
103105
public JettyWebSocketSession(Map<String, Object> attributes) {
@@ -106,11 +108,10 @@ public JettyWebSocketSession(Map<String, Object> attributes) {
106108

107109
/**
108110
* Create a new {@link JettyWebSocketSession} instance associated with the given user.
109-
*
110111
* @param attributes attributes from the HTTP handshake to associate with the WebSocket
111112
* session; the provided attributes are copied, the original map is not used.
112-
* @param user the user associated with the session; if {@code null} we'll fallback on the user
113-
* available via {@link org.eclipse.jetty.websocket.api.Session#getUpgradeRequest()}
113+
* @param user the user associated with the session; if {@code null} we'll fallback on the
114+
* user available via {@link org.eclipse.jetty.websocket.api.Session#getUpgradeRequest()}
114115
*/
115116
public JettyWebSocketSession(Map<String, Object> attributes, Principal user) {
116117
super(attributes);
@@ -191,36 +192,32 @@ public int getBinaryMessageSizeLimit() {
191192

192193
@Override
193194
public boolean isOpen() {
194-
return ((getNativeSession() != null) && getNativeSession().isOpen());
195+
return (getNativeSession() != null && getNativeSession().isOpen());
195196
}
196197

198+
197199
@Override
198200
public void initializeNativeSession(Session session) {
199201
super.initializeNativeSession(session);
200-
if (isJetty94) {
201-
initializeJetty94Session(session);
202+
if (directInterfaceCalls) {
203+
initializeJettySessionDirectly(session);
202204
}
203205
else {
204-
initializeJettySession(session);
206+
initializeJettySessionReflectively(session);
205207
}
206208
}
207209

208-
@SuppressWarnings("unchecked")
209-
private void initializeJettySession(Session session) {
210-
211-
Object request = ReflectionUtils.invokeMethod(getUpgradeRequest, session);
212-
Object response = ReflectionUtils.invokeMethod(getUpgradeResponse, session);
213-
210+
private void initializeJettySessionDirectly(Session session) {
214211
this.id = ObjectUtils.getIdentityHexString(getNativeSession());
215-
this.uri = (URI) ReflectionUtils.invokeMethod(getRequestURI, request);
212+
this.uri = session.getUpgradeRequest().getRequestURI();
216213

217214
this.headers = new HttpHeaders();
218-
this.headers.putAll((Map<String, List<String>>) ReflectionUtils.invokeMethod(getHeaders, request));
215+
this.headers.putAll(session.getUpgradeRequest().getHeaders());
219216
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
220217

221-
this.acceptedProtocol = (String) ReflectionUtils.invokeMethod(getAcceptedSubProtocol, response);
218+
this.acceptedProtocol = session.getUpgradeResponse().getAcceptedSubProtocol();
222219

223-
List<ExtensionConfig> source = (List<ExtensionConfig>) ReflectionUtils.invokeMethod(getExtensions, response);
220+
List<ExtensionConfig> source = session.getUpgradeResponse().getExtensions();
224221
if (source != null) {
225222
this.extensions = new ArrayList<>(source.size());
226223
for (ExtensionConfig ec : source) {
@@ -232,21 +229,25 @@ private void initializeJettySession(Session session) {
232229
}
233230

234231
if (this.user == null) {
235-
this.user = (Principal) ReflectionUtils.invokeMethod(getUserPrincipal, request);
232+
this.user = session.getUpgradeRequest().getUserPrincipal();
236233
}
237234
}
238235

239-
private void initializeJetty94Session(Session session) {
236+
@SuppressWarnings("unchecked")
237+
private void initializeJettySessionReflectively(Session session) {
238+
Object request = ReflectionUtils.invokeMethod(getUpgradeRequest, session);
239+
Object response = ReflectionUtils.invokeMethod(getUpgradeResponse, session);
240+
240241
this.id = ObjectUtils.getIdentityHexString(getNativeSession());
241-
this.uri = session.getUpgradeRequest().getRequestURI();
242+
this.uri = (URI) ReflectionUtils.invokeMethod(getRequestURI, request);
242243

243244
this.headers = new HttpHeaders();
244-
this.headers.putAll(session.getUpgradeRequest().getHeaders());
245+
this.headers.putAll((Map<String, List<String>>) ReflectionUtils.invokeMethod(getHeaders, request));
245246
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
246247

247-
this.acceptedProtocol = session.getUpgradeResponse().getAcceptedSubProtocol();
248+
this.acceptedProtocol = (String) ReflectionUtils.invokeMethod(getAcceptedSubProtocol, response);
248249

249-
List<ExtensionConfig> source = session.getUpgradeResponse().getExtensions();
250+
List<ExtensionConfig> source = (List<ExtensionConfig>) ReflectionUtils.invokeMethod(getExtensions, response);
250251
if (source != null) {
251252
this.extensions = new ArrayList<>(source.size());
252253
for (ExtensionConfig ec : source) {
@@ -258,10 +259,11 @@ private void initializeJetty94Session(Session session) {
258259
}
259260

260261
if (this.user == null) {
261-
this.user = session.getUpgradeRequest().getUserPrincipal();
262+
this.user = (Principal) ReflectionUtils.invokeMethod(getUserPrincipal, request);
262263
}
263264
}
264265

266+
265267
@Override
266268
protected void sendTextMessage(TextMessage message) throws IOException {
267269
getRemoteEndpoint().sendString(message.getPayload());
@@ -287,7 +289,7 @@ private RemoteEndpoint getRemoteEndpoint() throws IOException {
287289
return getNativeSession().getRemote();
288290
}
289291
catch (WebSocketException ex) {
290-
throw new IOException("Unable to obtain RemoteEndpoint in session=" + getId(), ex);
292+
throw new IOException("Unable to obtain RemoteEndpoint in session " + getId(), ex);
291293
}
292294
}
293295

0 commit comments

Comments
 (0)