001 // This file is part of the Attempto Java Packages.
002 // Copyright 2008, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch).
003 //
004 // The Attempto Java Packages is free software: you can redistribute it and/or modify it under the
005 // terms of the GNU Lesser General Public License as published by the Free Software Foundation,
006 // either version 3 of the License, or (at your option) any later version.
007 //
008 // The Attempto Java Packages is distributed in the hope that it will be useful, but WITHOUT ANY
009 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
010 // PURPOSE. See the GNU Lesser General Public License for more details.
011 //
012 // You should have received a copy of the GNU Lesser General Public License along with the Attempto
013 // Java Packages. If not, see http://www.gnu.org/licenses/.
014
015 package ch.uzh.ifi.attempto.echocomp;
016
017 import java.io.ByteArrayInputStream;
018 import java.io.ByteArrayOutputStream;
019 import java.io.IOException;
020 import java.io.UnsupportedEncodingException;
021
022 import javax.servlet.Filter;
023 import javax.servlet.FilterChain;
024 import javax.servlet.FilterConfig;
025 import javax.servlet.ServletException;
026 import javax.servlet.ServletInputStream;
027 import javax.servlet.ServletRequest;
028 import javax.servlet.ServletResponse;
029 import javax.servlet.http.HttpServletRequest;
030 import javax.servlet.http.HttpServletRequestWrapper;
031
032 /**
033 * This filter is a workaround for the problem that Firefox 3.0.0 to 3.0.4 somehow sends wrong
034 * XML headers to the server.
035 * See the discussion in <a href="http://echo.nextapp.com/site/node/5230" target="_blank">this thread</a>
036 * of the Echo forum.
037 * This code is inspired by the workaround proposed by the user "Nadir".
038 *<p>
039 * In order to apply this filter, the following lines have to be added to web.xml:
040 *
041 * <pre>
042 * <filter>
043 * <filter-name>headercontrol</filter-name>
044 * <filter-class>ch.uzh.ifi.attempto.echocomp.HeaderControlFilter</filter-class>
045 * <init-param>
046 * <param-name>request.reencoding</param-name>
047 * <param-value>UTF-8</param-value>
048 * </init-param>
049 * </filter>
050 *
051 * <filter-mapping>
052 * <filter-name>headercontrol</filter-name>
053 * <url-pattern>*</url-pattern>
054 * </filter-mapping>
055 * </pre>
056 */
057 public class HeaderControlFilter implements Filter {
058
059 protected String reencParam = null;
060
061 public void init(FilterConfig filterConfig) throws ServletException {
062 this.reencParam = filterConfig.getInitParameter("request.reencoding");
063 }
064
065 public void destroy() {
066 }
067
068 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
069 HttpServletRequest httpRequest = (HttpServletRequest) req;
070 // Firefox 3.0.4 requires a less strict check. Before it was:
071 // if (reencParam != null && req.getCharacterEncoding() != null && !reencParam.equals(req.getCharacterEncoding())) {
072 if (reencParam != null && req.getCharacterEncoding() != null) {
073 req = new HeaderControlRequest(httpRequest, reencParam);
074 }
075 chain.doFilter(req, resp);
076 }
077
078 }
079
080
081 class HeaderControlRequest extends HttpServletRequestWrapper {
082
083 String encoding;
084 ServletInputStream inputStream;
085
086 public HeaderControlRequest(HttpServletRequest req, String encoding) {
087 super(req);
088 this.encoding = encoding;
089 }
090
091 public ServletInputStream getInputStream() throws IOException {
092 if (inputStream == null) {
093 inputStream = new InputStreamReencoder(super.getInputStream(), super.getCharacterEncoding(), encoding);
094 }
095 return inputStream;
096 }
097
098 }
099
100
101 class InputStreamReencoder extends ServletInputStream {
102
103 ByteArrayInputStream byteInputStream;
104
105 public InputStreamReencoder(ServletInputStream inputStream, String encIn, String encOut) {
106 ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
107 byte[] buffer = new byte[4096];
108
109 int bytesRead = 0;
110 try {
111 do {
112 bytesRead = inputStream.read(buffer);
113 if (bytesRead > 0) {
114 byteOutputStream.write(buffer, 0, bytesRead);
115 }
116 } while (bytesRead > 0);
117 } catch (IOException e) {
118 e.printStackTrace();
119 } finally {
120 if (inputStream != null) {
121 try {
122 inputStream.close();
123 } catch (IOException ex) {}
124 }
125 }
126
127 byte[] data = byteOutputStream.toByteArray();
128 try {
129 data = new String(data, encIn).trim().getBytes(encOut);
130 byteInputStream = new ByteArrayInputStream(data);
131 } catch (UnsupportedEncodingException ex) {}
132 }
133
134 public int read() throws IOException {
135 return byteInputStream.read();
136 }
137
138 }