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.io.IOException; 020import java.lang.reflect.Constructor; 021import java.util.List; 022import java.util.Map; 023import javax.servlet.ServletException; 024import javax.servlet.http.HttpServletRequest; 025import javax.servlet.http.HttpServletResponse; 026 027import org.glassfish.tyrus.core.TyrusUpgradeResponse; 028import org.glassfish.tyrus.core.Utils; 029import org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler; 030import org.glassfish.tyrus.spi.WebSocketEngine.UpgradeInfo; 031import org.glassfish.tyrus.spi.Writer; 032 033import org.springframework.util.ReflectionUtils; 034import org.springframework.web.socket.server.HandshakeFailureException; 035 036/** 037 * A WebSocket {@code RequestUpgradeStrategy} for Oracle's GlassFish 4.1 and higher. 038 * 039 * @author Rossen Stoyanchev 040 * @author Juergen Hoeller 041 * @author Michael Irwin 042 * @since 4.0 043 */ 044public class GlassFishRequestUpgradeStrategy extends AbstractTyrusRequestUpgradeStrategy { 045 046 private static final TyrusEndpointHelper endpointHelper = new Tyrus17EndpointHelper(); 047 048 private static final GlassFishServletWriterHelper servletWriterHelper = new GlassFishServletWriterHelper(); 049 050 051 @Override 052 protected TyrusEndpointHelper getEndpointHelper() { 053 return endpointHelper; 054 } 055 056 @Override 057 protected void handleSuccess(HttpServletRequest request, HttpServletResponse response, 058 UpgradeInfo upgradeInfo, TyrusUpgradeResponse upgradeResponse) throws IOException, ServletException { 059 060 TyrusHttpUpgradeHandler handler = request.upgrade(TyrusHttpUpgradeHandler.class); 061 Writer servletWriter = servletWriterHelper.newInstance(handler); 062 handler.preInit(upgradeInfo, servletWriter, request.getUserPrincipal() != null); 063 064 response.setStatus(upgradeResponse.getStatus()); 065 for (Map.Entry<String, List<String>> entry : upgradeResponse.getHeaders().entrySet()) { 066 response.addHeader(entry.getKey(), Utils.getHeaderFromList(entry.getValue())); 067 } 068 response.flushBuffer(); 069 } 070 071 072 /** 073 * Helps to create and invoke {@code org.glassfish.tyrus.servlet.TyrusServletWriter}. 074 */ 075 private static class GlassFishServletWriterHelper { 076 077 private static final Constructor<?> constructor; 078 079 static { 080 try { 081 ClassLoader classLoader = GlassFishRequestUpgradeStrategy.class.getClassLoader(); 082 Class<?> type = classLoader.loadClass("org.glassfish.tyrus.servlet.TyrusServletWriter"); 083 constructor = type.getDeclaredConstructor(TyrusHttpUpgradeHandler.class); 084 ReflectionUtils.makeAccessible(constructor); 085 } 086 catch (Exception ex) { 087 throw new IllegalStateException("No compatible Tyrus version found", ex); 088 } 089 } 090 091 private Writer newInstance(TyrusHttpUpgradeHandler handler) { 092 try { 093 return (Writer) constructor.newInstance(handler); 094 } 095 catch (Exception ex) { 096 throw new HandshakeFailureException("Failed to instantiate TyrusServletWriter", ex); 097 } 098 } 099 } 100 101}