001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.messaging.webapp;
022    
023    import java.io.BufferedInputStream;
024    import java.io.IOException;
025    import java.io.InputStream;
026    import java.io.OutputStream;
027    
028    import javax.servlet.ServletContext;
029    import javax.servlet.ServletException;
030    import javax.servlet.http.HttpServletRequest;
031    import javax.servlet.http.HttpServletResponse;
032    
033    import org.granite.config.GraniteConfig;
034    import org.granite.config.flex.ServicesConfig;
035    import org.granite.context.GraniteContext;
036    import org.granite.logging.Logger;
037    import org.granite.messaging.amf.AMF0Message;
038    import org.granite.messaging.amf.io.AMF0Deserializer;
039    import org.granite.messaging.amf.io.AMF0Serializer;
040    import org.granite.messaging.amf.process.AMF0MessageProcessor;
041    import org.granite.messaging.jmf.JMFDeserializer;
042    import org.granite.messaging.jmf.JMFSerializer;
043    import org.granite.messaging.jmf.JMFServletContextListener;
044    import org.granite.messaging.jmf.SharedContext;
045    import org.granite.util.ContentType;
046    
047    /**
048     * @author Franck WOLFF
049     */
050    public class AMFEndpoint {
051    
052        private static final Logger log = Logger.getLogger(AMFEndpoint.class);
053        
054        private SharedContext jmfSharedContext = null;
055    
056        public void init(ServletContext context) {
057            jmfSharedContext = JMFServletContextListener.getSharedContext(context);
058            
059        }
060        
061        public void destroy() {
062            jmfSharedContext = null;
063        }
064        
065        public void service(GraniteConfig graniteConfig, ServicesConfig servicesConfig, ServletContext context,
066                    HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
067            
068            if (ContentType.JMF_AMF.mimeType().equals(request.getContentType()))
069                    serviceJMFAMF(graniteConfig, servicesConfig, context, request, response);
070            else
071                    serviceAMF(graniteConfig, servicesConfig, context, request, response);
072        }
073        
074        protected void serviceAMF(GraniteConfig graniteConfig, ServicesConfig servicesConfig, ServletContext context,
075                    HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {            
076                log.debug(">> Incoming AMF0 request from: %s", request.getRequestURL());
077    
078                InputStream is = null;
079                OutputStream os = null;
080                
081                try {
082                    is = new BufferedInputStream(request.getInputStream());
083                    
084                    HttpGraniteContext.createThreadIntance(
085                        graniteConfig, servicesConfig, context,
086                        request, response
087                    );
088            
089                    log.debug(">> Deserializing AMF0 request...");
090            
091                    AMF0Deserializer deserializer = new AMF0Deserializer(is);
092                    AMF0Message amf0Request = deserializer.getAMFMessage();
093    
094                log.debug(">> Processing AMF0 request: %s", amf0Request);
095    
096                AMF0Message amf0Response = AMF0MessageProcessor.process(amf0Request);
097            
098                    log.debug("<< Serializing AMF0 response: %s", amf0Response);
099            
100                    response.setStatus(HttpServletResponse.SC_OK);
101                    response.setContentType(ContentType.AMF.mimeType());
102                    response.setDateHeader("Expire", 0L);
103                    response.setHeader("Cache-Control", "no-store");
104                    
105                    os = response.getOutputStream();
106                    AMF0Serializer serializer = new AMF0Serializer(os);
107                    
108                    serializer.serializeMessage(amf0Response);
109                    
110                    response.flushBuffer();
111                }
112                catch (IOException e) {
113                    if ("org.apache.catalina.connector.ClientAbortException".equals(e.getClass().getName()))
114                            log.debug(e, "Connection closed by client");
115                    else
116                            log.error(e, "AMF message error");
117                    throw e;
118                }
119                catch (Exception e) {
120                    log.error(e, "AMF message error");
121                    throw new ServletException(e);
122                }
123                finally {
124                    GraniteContext.release();
125                }
126            }
127        
128        protected void serviceJMFAMF(GraniteConfig graniteConfig, ServicesConfig servicesConfig, ServletContext context,
129                    HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {            
130                
131            log.debug(">> Incoming JMF+AMF request from: %s", request.getRequestURL());
132            
133            if (jmfSharedContext == null)
134                    throw JMFServletContextListener.newSharedContextNotInitializedException();
135    
136                InputStream is = null;
137                OutputStream os = null;
138                
139                try {
140                    is = request.getInputStream();
141                    
142                    HttpGraniteContext.createThreadIntance(
143                        graniteConfig, servicesConfig, context,
144                        request, response
145                    );
146            
147                    log.debug(">> Deserializing JMF+AMF request...");
148            
149                    @SuppressWarnings("all") // JDK7 warning (Resource leak: 'deserializer' is never closed)...
150                            JMFDeserializer deserializer = new JMFDeserializer(is, jmfSharedContext);
151                    AMF0Message amf0Request = (AMF0Message)deserializer.readObject();
152    
153                log.debug(">> Processing AMF0 request: %s", amf0Request);
154    
155                AMF0Message amf0Response = AMF0MessageProcessor.process(amf0Request);
156            
157                    log.debug("<< Serializing JMF+AMF response: %s", amf0Response);
158            
159                    response.setStatus(HttpServletResponse.SC_OK);
160                    response.setContentType(ContentType.JMF_AMF.mimeType());
161                    response.setDateHeader("Expire", 0L);
162                    response.setHeader("Cache-Control", "no-store");
163                    
164                    os = response.getOutputStream();
165                    
166                    @SuppressWarnings("all") // JDK7 warning (Resource leak: 'serializer' is never closed)...
167                            JMFSerializer serializer = new JMFSerializer(os, jmfSharedContext);
168                    serializer.writeObject(amf0Response);
169                    
170                    response.flushBuffer();
171                }
172                catch (IOException e) {
173                    if ("org.apache.catalina.connector.ClientAbortException".equals(e.getClass().getName()))
174                            log.debug(e, "Connection closed by client");
175                    else
176                            log.error(e, "JMF+AMF message error");
177                    throw e;
178                }
179                catch (Exception e) {
180                    log.error(e, "JMF+AMF message error");
181                    throw new ServletException(e);
182                }
183                finally {
184                    GraniteContext.release();
185                }
186            }
187    }