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 */
022 package org.granite.gravity.jetty8;
023
024 import javax.servlet.ServletContext;
025 import javax.servlet.http.HttpServletRequest;
026 import javax.servlet.http.HttpSession;
027
028 import org.eclipse.jetty.websocket.WebSocket;
029 import org.eclipse.jetty.websocket.WebSocketHandler;
030 import org.granite.context.GraniteContext;
031 import org.granite.gravity.Gravity;
032 import org.granite.gravity.GravityManager;
033 import org.granite.logging.Logger;
034 import org.granite.messaging.webapp.ServletGraniteContext;
035 import org.granite.util.ContentType;
036
037 import flex.messaging.messages.CommandMessage;
038 import flex.messaging.messages.Message;
039
040 public 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 }