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.ByteArrayInputStream;
024    import java.io.ByteArrayOutputStream;
025    import java.io.IOException;
026    import java.io.InputStream;
027    import java.io.OutputStream;
028    import java.io.PrintStream;
029    
030    import javax.servlet.Filter;
031    import javax.servlet.FilterChain;
032    import javax.servlet.FilterConfig;
033    import javax.servlet.ServletException;
034    import javax.servlet.ServletInputStream;
035    import javax.servlet.ServletOutputStream;
036    import javax.servlet.ServletRequest;
037    import javax.servlet.ServletResponse;
038    import javax.servlet.http.HttpServletRequest;
039    import javax.servlet.http.HttpServletRequestWrapper;
040    import javax.servlet.http.HttpServletResponse;
041    import javax.servlet.http.HttpServletResponseWrapper;
042    
043    import org.granite.logging.Logger;
044    import org.granite.messaging.jmf.JMFDumper;
045    import org.granite.messaging.jmf.JMFServletContextListener;
046    import org.granite.messaging.jmf.SharedContext;
047    import org.granite.util.ContentType;
048    
049    /**
050     * @author Franck WOLFF
051     */
052    public class JMFDumpFilter implements Filter {
053    
054        private static final Logger log = Logger.getLogger(JMFDumpFilter.class);
055        
056        private SharedContext jmfSharedContext = null;
057    
058        public void init(FilterConfig config) throws ServletException {
059            jmfSharedContext = JMFServletContextListener.getDumpSharedContext(config.getServletContext());
060            if (jmfSharedContext == null)
061                    throw JMFServletContextListener.newSharedContextNotInitializedException();
062        }
063    
064        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
065            throws IOException, ServletException {
066    
067            if (!ContentType.JMF_AMF.mimeType().equals(request.getContentType())) {
068                    log.info("Ignoring request with content-type: " + request.getContentType());
069                    chain.doFilter(request, response);
070            }
071            else {
072                    DumpRequestWrapper requestWrapper = new DumpRequestWrapper((HttpServletRequest)request);
073                    DumpResponseWrapper responseWrapper= new DumpResponseWrapper((HttpServletResponse)response);
074            
075                    chain.doFilter(requestWrapper, responseWrapper);
076            }
077        }
078    
079        public void destroy() {
080            jmfSharedContext = null;
081        }
082    
083        private void dumpBytes(String label, byte[] bytes) throws IOException {
084            final String encoding = "UTF-8";
085            
086            ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
087            PrintStream ps = new PrintStream(baos, true, encoding);
088            
089            JMFDumper dumper = new JMFDumper(new ByteArrayInputStream(bytes), jmfSharedContext, ps);
090            dumper.dump();
091            dumper.close();
092            
093            log.info("[JMF %s (%d bytes)]\n%s", label.toUpperCase(), bytes.length, new String(baos.toByteArray(), encoding));
094        }
095    
096        class DumpRequestWrapper extends HttpServletRequestWrapper {
097    
098            private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
099    
100            public DumpRequestWrapper(HttpServletRequest request) {
101                super(request);
102            }
103    
104            @Override
105            public ServletInputStream getInputStream() throws IOException {
106    
107                final InputStream is = getRequest().getInputStream();
108    
109                return new ServletInputStream() {
110                    
111                    @Override
112                    public int read() throws IOException {
113                            int b = is.read();
114                            if (b != -1)
115                                    baos.write(b);
116                        return b;
117                    }
118    
119                                    @Override
120                                    public int available() throws IOException {
121                                            return is.available();
122                                    }
123    
124                                    @Override
125                                    public void close() throws IOException {
126                                            is.close();
127                                            
128                                            dumpBytes("request", baos.toByteArray());
129                                    }
130                };
131            }
132        }
133    
134        class DumpResponseWrapper extends HttpServletResponseWrapper {
135    
136            private final ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
137    
138            public DumpResponseWrapper(HttpServletResponse response) {
139                super(response);
140            }
141    
142            @Override
143            public ServletOutputStream getOutputStream() throws IOException {
144    
145                    final OutputStream os = getResponse().getOutputStream();
146                    
147                return new ServletOutputStream() {
148                    @Override
149                    public void write(int b) throws IOException {
150                        baos.write(b);
151                        os.write(b);
152                    }
153    
154                                    @Override
155                                    public void close() throws IOException {
156                                            os.close();
157                                            
158                                            dumpBytes("response", baos.toByteArray());
159                                    }
160                };
161            }
162        }
163    }