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.messaging.webapp; 023 024import java.io.ByteArrayInputStream; 025import java.io.ByteArrayOutputStream; 026import java.io.File; 027import java.io.FileOutputStream; 028import java.io.IOException; 029import java.io.InputStream; 030import java.io.OutputStream; 031 032import javax.servlet.Filter; 033import javax.servlet.FilterChain; 034import javax.servlet.FilterConfig; 035import javax.servlet.ServletException; 036import javax.servlet.ServletInputStream; 037import javax.servlet.ServletOutputStream; 038import javax.servlet.ServletRequest; 039import javax.servlet.ServletResponse; 040import javax.servlet.http.HttpServletRequest; 041import javax.servlet.http.HttpServletRequestWrapper; 042import javax.servlet.http.HttpServletResponse; 043import javax.servlet.http.HttpServletResponseWrapper; 044 045import org.granite.logging.Logger; 046import org.granite.util.ServletParams; 047 048/** 049 * @author Franck WOLFF 050 */ 051public class DumpFilter implements Filter { 052 053 private static final Logger log = Logger.getLogger(DumpFilter.class); 054 private static final String HEXS = "0123456789ABCDEF"; 055 private static final String DUMP_DIR = "dumpDir"; 056 057 File dumpDir = null; 058 059 public void init(FilterConfig config) throws ServletException { 060 String dumpDirString = ServletParams.get(config, DUMP_DIR, String.class, null); 061 if (dumpDirString != null) { 062 File dumpDir = new File(dumpDirString); 063 if (!dumpDir.exists() || !dumpDir.isDirectory() || !dumpDir.canWrite()) 064 log.warn("Ignoring dump directory (is it a writable directory?): %s", dumpDir); 065 else 066 this.dumpDir = dumpDir; 067 } 068 } 069 070 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 071 throws IOException, ServletException { 072 073 DumpRequestWrapper requestWrapper = new DumpRequestWrapper((HttpServletRequest)request); 074 DumpResponseWrapper responseWrapper= new DumpResponseWrapper((HttpServletResponse)response); 075 076 dumpBytes("request", requestWrapper.getBytes()); 077 chain.doFilter(requestWrapper, responseWrapper); 078 dumpBytes("response", responseWrapper.getBytes()); 079 } 080 081 public void destroy() { 082 dumpDir = null; 083 } 084 085 private void dumpBytes(String label, byte[] bytes) { 086 StringBuilder hexSb = new StringBuilder(); 087 StringBuilder charSb = new StringBuilder(); 088 089 for (int i = 0; i < bytes.length; i++) { 090 int b = bytes[i] & 0xFF; 091 if (hexSb.length() > 0) { 092 hexSb.append(' '); 093 charSb.append(' '); 094 } 095 hexSb.append(HEXS.charAt(b >> 4)).append(HEXS.charAt(b & 0x0F)); 096 if (b >= 0x20 && b <= 0x7e) 097 charSb.append(' ').append((char)b); 098 else 099 charSb.append("##"); 100 } 101 102 log.info("[RAW %s] {\n%s\n%s\n}", label.toUpperCase(), hexSb.toString(), charSb.toString()); 103 104 if (dumpDir != null) { 105 File file = new File(dumpDir.getPath() + File.separator + label + "_" + System.currentTimeMillis() + ".amf"); 106 for (int i = 1; i < 100 && file.exists(); i++) 107 file = new File(file.getAbsolutePath() + "." + i); 108 109 OutputStream os = null; 110 try { 111 os = new FileOutputStream(file); 112 os.write(bytes); 113 } catch (Exception e) { 114 log.error(e, "Could not write dump file: %s", file); 115 } finally { 116 if (os != null) try { 117 os.close(); 118 } catch (Exception e) { 119 } 120 } 121 } 122 } 123 124 class DumpRequestWrapper extends HttpServletRequestWrapper { 125 126 private byte[] bytes = null; 127 128 public DumpRequestWrapper(HttpServletRequest request) throws IOException { 129 super(request); 130 131 setCharacterEncoding("UTF-8"); 132 133 InputStream is = null; 134 try { 135 is = request.getInputStream(); 136 137 ByteArrayOutputStream out = new ByteArrayOutputStream(128); 138 for (int b = is.read(); b != -1; b = is.read()) 139 out.write(b); 140 141 this.bytes = out.toByteArray(); 142 } catch (Exception e) { 143 throw new RuntimeException(e); 144 } 145 } 146 147 @Override 148 public ServletInputStream getInputStream() throws IOException { 149 150 final ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 151 152 return new ServletInputStream() { 153 @Override 154 public int read() throws IOException { 155 return bais.read(); 156 } 157 }; 158 } 159 160 public byte[] getBytes() { 161 return bytes; 162 } 163 } 164 165 class DumpResponseWrapper extends HttpServletResponseWrapper { 166 167 private ByteArrayOutputStream baos = new ByteArrayOutputStream(256); 168 private ServletOutputStream out = null; 169 170 public DumpResponseWrapper(HttpServletResponse response) throws IOException { 171 super(response); 172 this.out = response.getOutputStream(); 173 } 174 175 @Override 176 public ServletOutputStream getOutputStream() throws IOException { 177 178 return new ServletOutputStream() { 179 @Override 180 public void write(int b) throws IOException { 181 baos.write(b); 182 out.write(b); 183 } 184 }; 185 } 186 187 public byte[] getBytes() { 188 return baos.toByteArray(); 189 } 190 } 191}