diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/WebSphereRequestUpgradeStrategy.java b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/WebSphereRequestUpgradeStrategy.java new file mode 100644 index 0000000000..c338033fa5 --- /dev/null +++ b/spring-websocket/src/main/java/org/springframework/web/socket/server/standard/WebSphereRequestUpgradeStrategy.java @@ -0,0 +1,95 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.socket.server.standard; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.websocket.Endpoint; +import javax.websocket.Extension; +import javax.websocket.server.ServerContainer; +import javax.websocket.server.ServerEndpointConfig; + +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.socket.server.HandshakeFailureException; + +/** + * WebSphere support for upgrading an {@link HttpServletRequest} during a + * WebSocket handshake. To modify properties of the underlying + * {@link javax.websocket.server.ServerContainer} you can use + * {@link ServletServerContainerFactoryBean} in XML configuration or, when using + * Java configuration, access the container instance through the + * "javax.websocket.server.ServerContainer" ServletContext attribute. + * + *

Tested with WAS Liberty beta (August 2015) for the upcoming 8.5.5.7 release. + * + * @author Rossen Stoyanchev + * @since 4.2.1 + */ +public class WebSphereRequestUpgradeStrategy extends AbstractStandardUpgradeStrategy { + + private final static Method upgradeMethod; + + static { + ClassLoader loader = WebSphereRequestUpgradeStrategy.class.getClassLoader(); + try { + Class type = loader.loadClass("com.ibm.websphere.wsoc.WsWsocServerContainer"); + upgradeMethod = type.getMethod("doUpgrade", HttpServletRequest.class, + HttpServletResponse.class, ServerEndpointConfig.class, Map.class); + } + catch (Exception ex) { + throw new IllegalStateException("No compatible WebSphere version found", ex); + } + } + + + @Override + public String[] getSupportedVersions() { + return new String[] {"13"}; + } + + @Override + public void upgradeInternal(ServerHttpRequest httpRequest, ServerHttpResponse httpResponse, + String selectedProtocol, List selectedExtensions, Endpoint endpoint) + throws HandshakeFailureException { + + HttpServletRequest request = getHttpServletRequest(httpRequest); + HttpServletResponse response = getHttpServletResponse(httpResponse); + + StringBuffer requestUrl = request.getRequestURL(); + String path = request.getRequestURI(); // shouldn't matter + Map pathParams = Collections. emptyMap(); + + ServerEndpointRegistration endpointConfig = new ServerEndpointRegistration(path, endpoint); + endpointConfig.setSubprotocols(Collections.singletonList(selectedProtocol)); + endpointConfig.setExtensions(selectedExtensions); + + try { + ServerContainer container = getContainer(request); + upgradeMethod.invoke(container, request, response, endpointConfig, pathParams); + } + catch (Exception ex) { + throw new HandshakeFailureException( + "Servlet request failed to upgrade to WebSocket, uri=" + requestUrl, ex); + } + } + +} diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/server/support/AbstractHandshakeHandler.java b/spring-websocket/src/main/java/org/springframework/web/socket/server/support/AbstractHandshakeHandler.java index 85096911ff..e431b0dc11 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/server/support/AbstractHandshakeHandler.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/server/support/AbstractHandshakeHandler.java @@ -65,20 +65,25 @@ public abstract class AbstractHandshakeHandler implements HandshakeHandler, Life private static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); + private static final ClassLoader classLoader = AbstractHandshakeHandler.class.getClassLoader(); + private static final boolean jettyWsPresent = ClassUtils.isPresent( - "org.eclipse.jetty.websocket.server.WebSocketServerFactory", AbstractHandshakeHandler.class.getClassLoader()); + "org.eclipse.jetty.websocket.server.WebSocketServerFactory", classLoader); private static final boolean tomcatWsPresent = ClassUtils.isPresent( - "org.apache.tomcat.websocket.server.WsHttpUpgradeHandler", AbstractHandshakeHandler.class.getClassLoader()); + "org.apache.tomcat.websocket.server.WsHttpUpgradeHandler", classLoader); private static final boolean undertowWsPresent = ClassUtils.isPresent( - "io.undertow.websockets.jsr.ServerWebSocketContainer", AbstractHandshakeHandler.class.getClassLoader()); + "io.undertow.websockets.jsr.ServerWebSocketContainer", classLoader); private static final boolean glassFishWsPresent = ClassUtils.isPresent( - "org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler", AbstractHandshakeHandler.class.getClassLoader()); + "org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler", classLoader); private static final boolean webLogicWsPresent = ClassUtils.isPresent( - "weblogic.websocket.tyrus.TyrusServletWriter", AbstractHandshakeHandler.class.getClassLoader()); + "weblogic.websocket.tyrus.TyrusServletWriter", classLoader); + + private static final boolean webSphereWsPresent = ClassUtils.isPresent( + "com.ibm.websphere.wsoc.WsWsocServerContainer", classLoader); protected final Log logger = LogFactory.getLog(getClass()); @@ -126,15 +131,19 @@ public abstract class AbstractHandshakeHandler implements HandshakeHandler, Life else if (webLogicWsPresent) { className = "org.springframework.web.socket.server.standard.WebLogicRequestUpgradeStrategy"; } + else if (webSphereWsPresent) { + className = "org.springframework.web.socket.server.standard.WebSphereRequestUpgradeStrategy"; + } else { throw new IllegalStateException("No suitable default RequestUpgradeStrategy found"); } try { - Class clazz = ClassUtils.forName(className, AbstractHandshakeHandler.class.getClassLoader()); + Class clazz = ClassUtils.forName(className, classLoader); return (RequestUpgradeStrategy) clazz.newInstance(); } catch (Throwable ex) { - throw new IllegalStateException("Failed to instantiate RequestUpgradeStrategy: " + className, ex); + throw new IllegalStateException( + "Failed to instantiate RequestUpgradeStrategy: " + className, ex); } }