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.messaging.webapp;
023    
024    import java.io.BufferedInputStream;
025    import java.io.IOException;
026    import java.io.InputStream;
027    import java.io.OutputStream;
028    
029    import javax.servlet.ServletContext;
030    import javax.servlet.ServletException;
031    import javax.servlet.http.HttpServletRequest;
032    import javax.servlet.http.HttpServletResponse;
033    
034    import org.granite.config.GraniteConfig;
035    import org.granite.config.GraniteConfigListener;
036    import org.granite.config.flex.ServicesConfig;
037    import org.granite.context.GraniteContext;
038    import org.granite.logging.Logger;
039    import org.granite.messaging.amf.AMF0Message;
040    import org.granite.messaging.amf.io.AMF0Deserializer;
041    import org.granite.messaging.amf.io.AMF0Serializer;
042    import org.granite.messaging.amf.process.AMF0MessageProcessor;
043    import org.granite.messaging.jmf.JMFDeserializer;
044    import org.granite.messaging.jmf.JMFSerializer;
045    import org.granite.messaging.jmf.SharedContext;
046    import org.granite.util.ContentType;
047    
048    /**
049     * @author Franck WOLFF
050     */
051    public class AMFEndpoint {
052    
053        private static final Logger log = Logger.getLogger(AMFEndpoint.class);
054        
055        public void init(ServletContext context) {
056        }
057        
058        public void destroy() {
059        }
060        
061        public void service(GraniteConfig graniteConfig, ServicesConfig servicesConfig, ServletContext context,
062                    HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
063            
064            if (ContentType.JMF_AMF.mimeType().equals(request.getContentType()))
065                    serviceJMFAMF(graniteConfig, servicesConfig, context, request, response);
066            else
067                    serviceAMF(graniteConfig, servicesConfig, context, request, response);
068        }
069        
070        protected void serviceAMF(GraniteConfig graniteConfig, ServicesConfig servicesConfig, ServletContext context,
071                    HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {            
072                log.debug(">> Incoming AMF0 request from: %s", request.getRequestURL());
073    
074                InputStream is = null;
075                OutputStream os = null;
076                
077                try {
078                    is = new BufferedInputStream(request.getInputStream());
079                    
080                    HttpGraniteContext.createThreadIntance(
081                        graniteConfig, servicesConfig, context,
082                        request, response
083                    );
084            
085                    log.debug(">> Deserializing AMF0 request...");
086            
087                    AMF0Deserializer deserializer = new AMF0Deserializer(is);
088                    AMF0Message amf0Request = deserializer.getAMFMessage();
089    
090                log.debug(">> Processing AMF0 request: %s", amf0Request);
091    
092                AMF0Message amf0Response = AMF0MessageProcessor.process(amf0Request);
093            
094                    log.debug("<< Serializing AMF0 response: %s", amf0Response);
095            
096                    response.setStatus(HttpServletResponse.SC_OK);
097                    response.setContentType(ContentType.AMF.mimeType());
098                    response.setDateHeader("Expire", 0L);
099                    response.setHeader("Cache-Control", "no-store");
100                    
101                    os = response.getOutputStream();
102                    AMF0Serializer serializer = new AMF0Serializer(os);
103                    
104                    serializer.serializeMessage(amf0Response);
105                    
106                    response.flushBuffer();
107                }
108                catch (IOException e) {
109                    if ("org.apache.catalina.connector.ClientAbortException".equals(e.getClass().getName()))
110                            log.debug(e, "Connection closed by client");
111                    else
112                            log.error(e, "AMF message error");
113                    throw e;
114                }
115                catch (Exception e) {
116                    log.error(e, "AMF message error");
117                    throw new ServletException(e);
118                }
119                finally {
120                    GraniteContext.release();
121                }
122            }
123        
124        protected void serviceJMFAMF(GraniteConfig graniteConfig, ServicesConfig servicesConfig, ServletContext context,
125                    HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {            
126                
127            log.debug(">> Incoming JMF+AMF request from: %s", request.getRequestURL());
128            
129            SharedContext jmfSharedContext = GraniteConfigListener.getSharedContext(context);
130            if (jmfSharedContext == null)
131                    throw GraniteConfigListener.newSharedContextNotInitializedException();
132    
133                InputStream is = null;
134                OutputStream os = null;
135                
136                try {
137                    is = request.getInputStream();
138                    
139                    HttpGraniteContext.createThreadIntance(
140                        graniteConfig, servicesConfig, context,
141                        request, response
142                    );
143            
144                    log.debug(">> Deserializing JMF+AMF request...");
145            
146                    @SuppressWarnings("all") // JDK7 warning (Resource leak: 'deserializer' is never closed)...
147                            JMFDeserializer deserializer = new JMFDeserializer(is, jmfSharedContext);
148                    AMF0Message amf0Request = (AMF0Message)deserializer.readObject();
149    
150                log.debug(">> Processing AMF0 request: %s", amf0Request);
151    
152                AMF0Message amf0Response = AMF0MessageProcessor.process(amf0Request);
153            
154                    log.debug("<< Serializing JMF+AMF response: %s", amf0Response);
155            
156                    response.setStatus(HttpServletResponse.SC_OK);
157                    response.setContentType(ContentType.JMF_AMF.mimeType());
158                    response.setDateHeader("Expire", 0L);
159                    response.setHeader("Cache-Control", "no-store");
160                    
161                    os = response.getOutputStream();
162                    
163                    @SuppressWarnings("all") // JDK7 warning (Resource leak: 'serializer' is never closed)...
164                            JMFSerializer serializer = new JMFSerializer(os, jmfSharedContext);
165                    serializer.writeObject(amf0Response);
166                    
167                    response.flushBuffer();
168                }
169                catch (IOException e) {
170                    if ("org.apache.catalina.connector.ClientAbortException".equals(e.getClass().getName()))
171                            log.debug(e, "Connection closed by client");
172                    else
173                            log.error(e, "JMF+AMF message error");
174                    throw e;
175                }
176                catch (Exception e) {
177                    log.error(e, "JMF+AMF message error");
178                    throw new ServletException(e);
179                }
180                finally {
181                    GraniteContext.release();
182                }
183            }
184    }