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 }