001package org.granite.gravity.jetty8;
002
003import javax.servlet.ServletContext;
004import javax.servlet.http.HttpServletRequest;
005import javax.servlet.http.HttpSession;
006
007import org.eclipse.jetty.websocket.WebSocket;
008import org.eclipse.jetty.websocket.WebSocketHandler;
009import org.granite.context.GraniteContext;
010import org.granite.gravity.Gravity;
011import org.granite.gravity.GravityManager;
012import org.granite.logging.Logger;
013import org.granite.messaging.webapp.ServletGraniteContext;
014
015import flex.messaging.messages.CommandMessage;
016import flex.messaging.messages.Message;
017
018public class JettyWebSocketHandler extends WebSocketHandler {
019        
020        private static final Logger log = Logger.getLogger(JettyWebSocketHandler.class);
021        
022        private final ServletContext servletContext;
023        
024        public JettyWebSocketHandler(ServletContext servletContext) {
025                this.servletContext = servletContext;
026        }
027        
028    public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
029        if (!"org.granite.gravity".equals(protocol))
030                return null;
031        
032                Gravity gravity = GravityManager.getGravity(servletContext);
033                JettyWebSocketChannelFactory channelFactory = new JettyWebSocketChannelFactory(gravity, servletContext);
034                
035                try {
036                        String connectMessageId = request.getHeader("connectId") != null ? request.getHeader("connectId") : request.getParameter("connectId");
037                        String clientId = request.getHeader("GDSClientId") != null ? request.getHeader("GDSClientId") : request.getParameter("GDSClientId");
038                        String clientType = request.getHeader("GDSClientType") != null ? request.getHeader("GDSClientType") : request.getParameter("GDSClientType");
039                        String sessionId = null;
040                        HttpSession session = request.getSession(false);
041                        if (session != null) {
042                        ServletGraniteContext.createThreadInstance(gravity.getGraniteConfig(), gravity.getServicesConfig(), 
043                                        this.servletContext, session, clientType);
044                        
045                                sessionId = session.getId();
046                        }
047                        else {
048                                for (int i = 0; i < request.getCookies().length; i++) {
049                                        if ("JSESSIONID".equals(request.getCookies()[i].getName())) {
050                                                sessionId = request.getCookies()[i].getValue();
051                                                break;
052                                        }
053                                }                               
054                        ServletGraniteContext.createThreadInstance(gravity.getGraniteConfig(), gravity.getServicesConfig(), 
055                                        this.servletContext, sessionId, clientType);
056                        }
057                        
058                        log.info("WebSocket connection started %s clientId %s sessionId %s", protocol, clientId, sessionId);
059                        
060                        CommandMessage pingMessage = new CommandMessage();
061                        pingMessage.setMessageId(connectMessageId != null ? connectMessageId : "OPEN_CONNECTION");
062                        pingMessage.setOperation(CommandMessage.CLIENT_PING_OPERATION);
063                        if (clientId != null)
064                                pingMessage.setClientId(clientId);
065                        
066                        Message ackMessage = gravity.handleMessage(channelFactory, pingMessage);
067                        
068                        JettyWebSocketChannel channel = gravity.getChannel(channelFactory, (String)ackMessage.getClientId());
069                        
070                        if (!ackMessage.getClientId().equals(clientId))
071                                channel.setConnectAckMessage(ackMessage);
072                        
073                        return channel;
074                }
075                finally {
076                        GraniteContext.release();
077                }
078    }
079}