001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * Granite Data Services is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * Granite Data Services is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 020 * USA, or see <http://www.gnu.org/licenses/>. 021 */ 022package org.granite.gravity.jetty8; 023 024import javax.servlet.ServletContext; 025import javax.servlet.http.HttpServletRequest; 026import javax.servlet.http.HttpSession; 027 028import org.eclipse.jetty.websocket.WebSocket; 029import org.eclipse.jetty.websocket.WebSocketHandler; 030import org.granite.context.GraniteContext; 031import org.granite.gravity.Gravity; 032import org.granite.gravity.GravityManager; 033import org.granite.logging.Logger; 034import org.granite.messaging.webapp.ServletGraniteContext; 035import org.granite.util.ContentType; 036 037import flex.messaging.messages.CommandMessage; 038import flex.messaging.messages.Message; 039 040public class JettyWebSocketHandler extends WebSocketHandler { 041 042 private static final Logger log = Logger.getLogger(JettyWebSocketHandler.class); 043 044 private final ServletContext servletContext; 045 046 public JettyWebSocketHandler(ServletContext servletContext) { 047 this.servletContext = servletContext; 048 } 049 050 public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { 051 if (!protocol.startsWith("org.granite.gravity")) 052 return null; 053 054 Gravity gravity = GravityManager.getGravity(servletContext); 055 JettyWebSocketChannelFactory channelFactory = new JettyWebSocketChannelFactory(gravity); 056 057 try { 058 String connectMessageId = request.getHeader("connectId") != null ? request.getHeader("connectId") : request.getParameter("connectId"); 059 String clientId = request.getHeader("GDSClientId") != null ? request.getHeader("GDSClientId") : request.getParameter("GDSClientId"); 060 String clientType = request.getHeader("GDSClientType") != null ? request.getHeader("GDSClientType") : request.getParameter("GDSClientType"); 061 String sessionId = null; 062 HttpSession session = request.getSession("true".equals(servletContext.getInitParameter("org.granite.gravity.websocket.forceCreateSession"))); 063 if (session != null) { 064 ServletGraniteContext.createThreadInstance(gravity.getGraniteConfig(), gravity.getServicesConfig(), 065 this.servletContext, session, clientType); 066 067 sessionId = session.getId(); 068 } 069 else if (request.getCookies() != null) { 070 for (int i = 0; i < request.getCookies().length; i++) { 071 if ("JSESSIONID".equals(request.getCookies()[i].getName())) { 072 sessionId = request.getCookies()[i].getValue(); 073 break; 074 } 075 } 076 ServletGraniteContext.createThreadInstance(gravity.getGraniteConfig(), gravity.getServicesConfig(), 077 this.servletContext, sessionId, clientType); 078 } 079 else { 080 ServletGraniteContext.createThreadInstance(gravity.getGraniteConfig(), gravity.getServicesConfig(), 081 this.servletContext, (String)null, clientType); 082 } 083 084 log.info("WebSocket connection started %s clientId %s sessionId %s", protocol, clientId, sessionId); 085 086 CommandMessage pingMessage = new CommandMessage(); 087 pingMessage.setMessageId(connectMessageId != null ? connectMessageId : "OPEN_CONNECTION"); 088 pingMessage.setOperation(CommandMessage.CLIENT_PING_OPERATION); 089 if (clientId != null) 090 pingMessage.setClientId(clientId); 091 092 Message ackMessage = gravity.handleMessage(channelFactory, pingMessage); 093 if (sessionId != null) 094 ackMessage.setHeader("JSESSIONID", sessionId); 095 096 JettyWebSocketChannel channel = gravity.getChannel(channelFactory, (String)ackMessage.getClientId()); 097 channel.setSession(session); 098 099 String ctype = request.getContentType(); 100 if (ctype == null && protocol.length() > "org.granite.gravity".length()) 101 ctype = "application/x-" + protocol.substring("org.granite.gravity.".length()); 102 103 ContentType contentType = ContentType.forMimeType(ctype); 104 if (contentType == null) { 105 log.warn("No (or unsupported) content type in request: %s", request.getContentType()); 106 contentType = ContentType.AMF; 107 } 108 channel.setContentType(contentType); 109 110 if (!ackMessage.getClientId().equals(clientId)) 111 channel.setConnectAckMessage(ackMessage); 112 113 return channel; 114 } 115 finally { 116 GraniteContext.release(); 117 } 118 } 119}