Avoid hard reference to org.xnio.StreamConnection through reflection

Issue: SPR-13529
This commit is contained in:
Juergen Hoeller 2015-10-05 20:58:36 +02:00
parent bb4e682a7e
commit 1b31d39b60
1 changed files with 26 additions and 19 deletions

View File

@ -17,7 +17,9 @@
package org.springframework.web.socket.server.standard; package org.springframework.web.socket.server.standard;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -31,7 +33,6 @@ import javax.websocket.Endpoint;
import javax.websocket.Extension; import javax.websocket.Extension;
import javax.websocket.server.ServerEndpointConfig; import javax.websocket.server.ServerEndpointConfig;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.HttpUpgradeListener; import io.undertow.server.HttpUpgradeListener;
import io.undertow.servlet.api.InstanceFactory; import io.undertow.servlet.api.InstanceFactory;
import io.undertow.servlet.api.InstanceHandle; import io.undertow.servlet.api.InstanceHandle;
@ -50,7 +51,6 @@ import io.undertow.websockets.jsr.handshake.JsrHybi07Handshake;
import io.undertow.websockets.jsr.handshake.JsrHybi08Handshake; import io.undertow.websockets.jsr.handshake.JsrHybi08Handshake;
import io.undertow.websockets.jsr.handshake.JsrHybi13Handshake; import io.undertow.websockets.jsr.handshake.JsrHybi13Handshake;
import io.undertow.websockets.spi.WebSocketHttpExchange; import io.undertow.websockets.spi.WebSocketHttpExchange;
import org.xnio.StreamConnection;
import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
@ -122,8 +122,7 @@ public class UndertowRequestUpgradeStrategy extends AbstractStandardUpgradeStrat
// Adapting between different Pool API types in Undertow 1.0-1.2 vs 1.3 // Adapting between different Pool API types in Undertow 1.0-1.2 vs 1.3
getBufferPoolMethod = WebSocketHttpExchange.class.getMethod("getBufferPool"); getBufferPoolMethod = WebSocketHttpExchange.class.getMethod("getBufferPool");
createChannelMethod = Handshake.class.getMethod("createChannel", createChannelMethod = ReflectionUtils.findMethod(Handshake.class, "createChannel", (Class<?>[]) null);
WebSocketHttpExchange.class, StreamConnection.class, getBufferPoolMethod.getReturnType());
} }
catch (Throwable ex) { catch (Throwable ex) {
throw new IllegalStateException("Incompatible Undertow API version", ex); throw new IllegalStateException("Incompatible Undertow API version", ex);
@ -162,31 +161,39 @@ public class UndertowRequestUpgradeStrategy extends AbstractStandardUpgradeStrat
HttpServletRequest servletRequest = getHttpServletRequest(request); HttpServletRequest servletRequest = getHttpServletRequest(request);
HttpServletResponse servletResponse = getHttpServletResponse(response); HttpServletResponse servletResponse = getHttpServletResponse(response);
final ServletWebSocketHttpExchange exchange = createHttpExchange(servletRequest, servletResponse); final ServletWebSocketHttpExchange exchange = createHttpExchange(servletRequest, servletResponse);
exchange.putAttachment(HandshakeUtil.PATH_PARAMS, Collections.<String, String>emptyMap()); exchange.putAttachment(HandshakeUtil.PATH_PARAMS, Collections.<String, String>emptyMap());
ServerWebSocketContainer wsContainer = (ServerWebSocketContainer) getContainer(servletRequest); ServerWebSocketContainer wsContainer = (ServerWebSocketContainer) getContainer(servletRequest);
final EndpointSessionHandler endpointSessionHandler = new EndpointSessionHandler(wsContainer); final EndpointSessionHandler endpointSessionHandler = new EndpointSessionHandler(wsContainer);
final ConfiguredServerEndpoint configuredServerEndpoint = createConfiguredServerEndpoint( final ConfiguredServerEndpoint configuredServerEndpoint = createConfiguredServerEndpoint(
selectedProtocol, selectedExtensions, endpoint, servletRequest); selectedProtocol, selectedExtensions, endpoint, servletRequest);
final Handshake handshake = getHandshakeToUse(exchange, configuredServerEndpoint); final Handshake handshake = getHandshakeToUse(exchange, configuredServerEndpoint);
exchange.upgradeChannel(new HttpUpgradeListener() { HttpUpgradeListener upgradeListener = (HttpUpgradeListener) Proxy.newProxyInstance(
@Override getClass().getClassLoader(), new Class<?>[] {HttpUpgradeListener.class},
public void handleUpgrade(StreamConnection connection, HttpServerExchange serverExchange) { new InvocationHandler() {
Object bufferPool = ReflectionUtils.invokeMethod(getBufferPoolMethod, exchange); @Override
WebSocketChannel channel = (WebSocketChannel) ReflectionUtils.invokeMethod( public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
createChannelMethod, handshake, exchange, connection, bufferPool); if ("handleUpgrade".equals(method.getName())) {
if (peerConnections != null) { Object connection = args[0]; // currently an XNIO StreamConnection
peerConnections.add(channel); Object bufferPool = ReflectionUtils.invokeMethod(getBufferPoolMethod, exchange);
} WebSocketChannel channel = (WebSocketChannel) ReflectionUtils.invokeMethod(
endpointSessionHandler.onConnect(exchange, channel); createChannelMethod, handshake, exchange, connection, bufferPool);
} if (peerConnections != null) {
}); peerConnections.add(channel);
}
endpointSessionHandler.onConnect(exchange, channel);
return null;
}
else {
// any java.lang.Object method: equals, hashCode, toString...
return ReflectionUtils.invokeMethod(method, this, args);
}
}
});
exchange.upgradeChannel(upgradeListener);
handshake.handshake(exchange); handshake.handshake(exchange);
} }