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;
023
024import java.io.IOException;
025import java.io.InputStream;
026import java.io.ObjectInput;
027import java.io.ObjectOutput;
028import java.io.OutputStream;
029
030import javax.servlet.ServletConfig;
031import javax.servlet.ServletContext;
032import javax.servlet.ServletException;
033import javax.servlet.http.HttpServletRequest;
034import javax.servlet.http.HttpServletResponse;
035
036import org.granite.context.GraniteContext;
037import org.granite.messaging.webapp.HttpGraniteContext;
038import org.granite.util.ContentType;
039import org.granite.util.UUIDUtil;
040
041import flex.messaging.messages.CommandMessage;
042import flex.messaging.messages.Message;
043
044
045public class GravityServletUtil {
046
047    public static final String CONNECT_MESSAGE_KEY = AbstractGravityServlet.class.getName() + ".CONNECT_MESSAGE";
048
049    public static void init(ServletConfig config) throws ServletException {
050        GravityManager.start(config);
051    }
052
053    public static void rejectJMFContentType(HttpServletRequest request) throws ServletException {
054        if (ContentType.JMF_AMF.mimeType().equals(request.getContentType()))
055            throw new ServletException("JMF not supported, use Servlet 3 AsyncServlet");
056    }
057
058    ///////////////////////////////////////////////////////////////////////////
059        // Connect messages management (request attribute).
060        
061        public static void setConnectMessage(HttpServletRequest request, Message connect) {
062                if (!(connect instanceof CommandMessage) && ((CommandMessage)connect).getOperation() != CommandMessage.CONNECT_OPERATION)
063                        throw new IllegalArgumentException("Not a connect message: " + connect);
064                request.setAttribute(CONNECT_MESSAGE_KEY, connect);
065        }
066        
067        public static CommandMessage getConnectMessage(HttpServletRequest request) {
068                return (CommandMessage)request.getAttribute(CONNECT_MESSAGE_KEY);
069        }
070        
071        public static void removeConnectMessage(HttpServletRequest request) {
072                request.removeAttribute(CONNECT_MESSAGE_KEY);
073        }
074
075        ///////////////////////////////////////////////////////////////////////////
076        // Long polling timeout.
077        
078        public static long getLongPollingTimeout(ServletContext context) {
079                return GravityManager.getGravity(context).getGravityConfig().getLongPollingTimeoutMillis();
080        }
081
082        ///////////////////////////////////////////////////////////////////////////
083        // AMF (de)serialization methods.
084        
085        public static Gravity initializeRequest(ServletConfig config, Gravity gravity, HttpServletRequest request, HttpServletResponse response) {
086        HttpGraniteContext.createThreadIntance(
087            gravity.getGraniteConfig(), gravity.getServicesConfig(),
088            config.getServletContext(), request, response
089        );
090        return gravity;
091        }
092
093        public static Message[] deserialize(Gravity gravity, HttpServletRequest request) throws ClassNotFoundException, IOException {
094                InputStream is = request.getInputStream();
095                try {
096                        return deserialize(gravity, request, is);
097                }
098                finally {
099                        is.close();
100                }
101        }
102        
103        public static Message[] deserialize(Gravity gravity, HttpServletRequest request, InputStream is) throws ClassNotFoundException, IOException {
104                ObjectInput amf3Deserializer = gravity.getGraniteConfig().newAMF3Deserializer(is);
105        Object[] objects = (Object[])amf3Deserializer.readObject();
106        Message[] messages = new Message[objects.length];
107        System.arraycopy(objects, 0, messages, 0, objects.length);
108        
109        return messages;
110        }
111        
112        public static void serialize(Gravity gravity, HttpServletResponse response, Message[] messages) throws IOException {
113                OutputStream os = null;
114                try {
115            // For SDK 2.0.1_Hotfix2+ (LCDS 2.5+).
116                        String dsId = null;
117            for (Message message : messages) {
118                    if ("nil".equals(message.getHeader(Message.DS_ID_HEADER))) {
119                        if (dsId == null)
120                                dsId = UUIDUtil.randomUUID();
121                        message.getHeaders().put(Message.DS_ID_HEADER, dsId);
122                    }
123            }
124                        
125                response.setStatus(HttpServletResponse.SC_OK);
126                response.setContentType(ContentType.AMF.mimeType());
127                response.setDateHeader("Expire", 0L);
128                response.setHeader("Cache-Control", "no-store");
129                
130                os = response.getOutputStream();
131                ObjectOutput amf3Serializer = gravity.getGraniteConfig().newAMF3Serializer(os);
132                amf3Serializer.writeObject(messages);
133                
134                os.flush();
135                response.flushBuffer();
136                }
137                finally {
138                        if (os != null)
139                                os.close();
140                }
141        }
142        
143        public static void cleanupRequest(HttpServletRequest request) {
144                GraniteContext.release();
145        }
146}