001/*
002 * Copyright 2002-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.socket.server.standard;
018
019import java.lang.reflect.Method;
020import java.util.Collections;
021import java.util.List;
022import java.util.Map;
023
024import javax.servlet.http.HttpServletRequest;
025import javax.servlet.http.HttpServletResponse;
026import javax.websocket.Endpoint;
027import javax.websocket.Extension;
028import javax.websocket.server.ServerContainer;
029import javax.websocket.server.ServerEndpointConfig;
030
031import org.springframework.http.server.ServerHttpRequest;
032import org.springframework.http.server.ServerHttpResponse;
033import org.springframework.lang.Nullable;
034import org.springframework.web.socket.server.HandshakeFailureException;
035
036/**
037 * WebSphere support for upgrading an {@link HttpServletRequest} during a
038 * WebSocket handshake. To modify properties of the underlying
039 * {@link javax.websocket.server.ServerContainer} you can use
040 * {@link ServletServerContainerFactoryBean} in XML configuration or, when using
041 * Java configuration, access the container instance through the
042 * "javax.websocket.server.ServerContainer" ServletContext attribute.
043 *
044 * <p>Tested with WAS Liberty beta (August 2015) for the upcoming 8.5.5.7 release.
045 *
046 * @author Rossen Stoyanchev
047 * @since 4.2.1
048 */
049public class WebSphereRequestUpgradeStrategy extends AbstractStandardUpgradeStrategy {
050
051        private static final Method upgradeMethod;
052
053        static {
054                ClassLoader loader = WebSphereRequestUpgradeStrategy.class.getClassLoader();
055                try {
056                        Class<?> type = loader.loadClass("com.ibm.websphere.wsoc.WsWsocServerContainer");
057                        upgradeMethod = type.getMethod("doUpgrade", HttpServletRequest.class,
058                                        HttpServletResponse.class, ServerEndpointConfig.class, Map.class);
059                }
060                catch (Exception ex) {
061                        throw new IllegalStateException("No compatible WebSphere version found", ex);
062                }
063        }
064
065
066        @Override
067        public String[] getSupportedVersions() {
068                return new String[] {"13"};
069        }
070
071        @Override
072        public void upgradeInternal(ServerHttpRequest httpRequest, ServerHttpResponse httpResponse,
073                        @Nullable String selectedProtocol, List<Extension> selectedExtensions, Endpoint endpoint)
074                        throws HandshakeFailureException {
075
076                HttpServletRequest request = getHttpServletRequest(httpRequest);
077                HttpServletResponse response = getHttpServletResponse(httpResponse);
078
079                StringBuffer requestUrl = request.getRequestURL();
080                String path = request.getRequestURI();  // shouldn't matter
081                Map<String, String> pathParams = Collections.<String, String> emptyMap();
082
083                ServerEndpointRegistration endpointConfig = new ServerEndpointRegistration(path, endpoint);
084                endpointConfig.setSubprotocols(Collections.singletonList(selectedProtocol));
085                endpointConfig.setExtensions(selectedExtensions);
086
087                try {
088                        ServerContainer container = getContainer(request);
089                        upgradeMethod.invoke(container, request, response, endpointConfig, pathParams);
090                }
091                catch (Exception ex) {
092                        throw new HandshakeFailureException(
093                                        "Servlet request failed to upgrade to WebSocket for " + requestUrl, ex);
094                }
095        }
096
097}