001/*
002 * Copyright 2002-2015 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;
023import javax.servlet.http.HttpServletRequest;
024import javax.servlet.http.HttpServletResponse;
025import javax.websocket.Endpoint;
026import javax.websocket.Extension;
027import javax.websocket.server.ServerContainer;
028import javax.websocket.server.ServerEndpointConfig;
029
030import org.springframework.http.server.ServerHttpRequest;
031import org.springframework.http.server.ServerHttpResponse;
032import org.springframework.web.socket.server.HandshakeFailureException;
033
034/**
035 * WebSphere support for upgrading an {@link HttpServletRequest} during a
036 * WebSocket handshake. To modify properties of the underlying
037 * {@link javax.websocket.server.ServerContainer} you can use
038 * {@link ServletServerContainerFactoryBean} in XML configuration or, when using
039 * Java configuration, access the container instance through the
040 * "javax.websocket.server.ServerContainer" ServletContext attribute.
041 *
042 * <p>Tested with WAS Liberty beta (August 2015) for the upcoming 8.5.5.7 release.
043 *
044 * @author Rossen Stoyanchev
045 * @since 4.2.1
046 */
047public class WebSphereRequestUpgradeStrategy extends AbstractStandardUpgradeStrategy {
048
049        private final static Method upgradeMethod;
050
051        static {
052                ClassLoader loader = WebSphereRequestUpgradeStrategy.class.getClassLoader();
053                try {
054                        Class<?> type = loader.loadClass("com.ibm.websphere.wsoc.WsWsocServerContainer");
055                        upgradeMethod = type.getMethod("doUpgrade", HttpServletRequest.class,
056                                        HttpServletResponse.class, ServerEndpointConfig.class, Map.class);
057                }
058                catch (Exception ex) {
059                        throw new IllegalStateException("No compatible WebSphere version found", ex);
060                }
061        }
062
063
064        @Override
065        public String[] getSupportedVersions() {
066                return new String[] {"13"};
067        }
068
069        @Override
070        public void upgradeInternal(ServerHttpRequest httpRequest, ServerHttpResponse httpResponse,
071                        String selectedProtocol, List<Extension> selectedExtensions, Endpoint endpoint)
072                        throws HandshakeFailureException {
073
074                HttpServletRequest request = getHttpServletRequest(httpRequest);
075                HttpServletResponse response = getHttpServletResponse(httpResponse);
076
077                StringBuffer requestUrl = request.getRequestURL();
078                String path = request.getRequestURI();  // shouldn't matter
079                Map<String, String> pathParams = Collections.<String, String> emptyMap();
080
081                ServerEndpointRegistration endpointConfig = new ServerEndpointRegistration(path, endpoint);
082                endpointConfig.setSubprotocols(Collections.singletonList(selectedProtocol));
083                endpointConfig.setExtensions(selectedExtensions);
084
085                try {
086                        ServerContainer container = getContainer(request);
087                        upgradeMethod.invoke(container, request, response, endpointConfig, pathParams);
088                }
089                catch (Exception ex) {
090                        throw new HandshakeFailureException(
091                                        "Servlet request failed to upgrade to WebSocket for " + requestUrl, ex);
092                }
093        }
094
095}