T
tek.no.logik
I need to capture all the response data that comes back from the
servlet (Tomcat + Struts environment).
So, I have a simple filter that wraps the response object, and sends
the
wrapped object into filterChain.doFilter() method.
I've set up the web.xml so that any servlet access should trigger my
filter
(the <url-pattern> is *.jsp, *.html and *.do).
When the browser makes a .html request, everything works as expected.
After the filterChain.doFilter(), I can take a look at the wrapped
response
object and print the contents of the response.
However, when I access a .jsp page or .do action, the output stream of
my
wrapper is empty after the last call to <tiles:insert> tag.
If I don't wrap the response, then everything seems to work fine.
I've enclosed the source code & the output that demonstrates the
problem.
Is this a bug in Struts or Tomcat ? If this is a bug, is there a patch
available?
Thanks
------ Begin ResponseWrapper.java ------
public class ResponseWrapper extends HttpServletResponseWrapper {
private PrintWriter printWriter;
private ResponseOutputStream outputStream;
public ResponseWrapper(ServletResponse response) throws
java.io.IOException {
super((HttpServletResponse) response);
outputStream = new ResponseOutputStream
(response.getOutputStream());
printWriter = new PrintWriter(outputStream);
}
public ServletOutputStream getOutputStream() throws
java.io.IOException {
return outputStream;
}
public PrintWriter getWriter() throws java.io.IOException {
return printWriter;
}
}
------ End ResponseWrapper.java ------
------ Begin ResponseOutputSteam.java ------
public class ResponseOutputStream extends ServletOutputStream {
private OutputStream outputStream;
private ByteArrayOutputStream arrayStream;
private boolean closed = false;
public ResponseOutputStream(OutputStream stream) {
outputStream = stream;
arrayStream = new ByteArrayOutputStream();
}
public void write(int i) throws java.io.IOException {
arrayStream.write(i);
}
public void close() throws java.io.IOException {
if (!closed) {
processStream();
outputStream.close();
closed = true;
}
}
public void flush() throws java.io.IOException {
if (arrayStream.size() != 0) {
if (!closed) {
processStream();
arrayStream = new ByteArrayOutputStream();
}
}
}
private void processStream() throws java.io.IOException {
outputStream.write(replaceContent(arrayStream.toByteArray()));
outputStream.flush();
}
public byte[] replaceContent(byte[] bytesContent) {
byte[] returnContent = new byte[bytesContent.length];
int j = 0;
for (int i = 0; i < bytesContent.length; i++) {
if (bytesContent != '\n' && bytesContent !
= '\t') {
returnContent[j++] = bytesContent;
}
}
return returnContent;
}
}
------ End ResponseOutputSteam.java ------
------ Begin ResponseFilter.java ------
public class ResponseFilter implements Filter {
private FilterConfig filterConfig = null;
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
ResponseWrapper responseWrapper = new ResponseWrapper
(response);
chain.doFilter(request, responseWrapper);
responseWrapper.getOutputStream().close();
}
public void destroy() {
this.filterConfig =null;
}
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
}
------ End ResponseFilter.java ------
--- Begin Filter configuring into web.xml ---
<filter>
<filter-name>ResponseFilter</filter-name>
<filter-class>it.openkey.util.filters.ResponseFilter</filter-
class>
</filter>
<filter-mapping>
<filter-name>ResponseFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ResponseFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ResponseFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
--- End Filter configuring into web.xml ---
servlet (Tomcat + Struts environment).
So, I have a simple filter that wraps the response object, and sends
the
wrapped object into filterChain.doFilter() method.
I've set up the web.xml so that any servlet access should trigger my
filter
(the <url-pattern> is *.jsp, *.html and *.do).
When the browser makes a .html request, everything works as expected.
After the filterChain.doFilter(), I can take a look at the wrapped
response
object and print the contents of the response.
However, when I access a .jsp page or .do action, the output stream of
my
wrapper is empty after the last call to <tiles:insert> tag.
If I don't wrap the response, then everything seems to work fine.
I've enclosed the source code & the output that demonstrates the
problem.
Is this a bug in Struts or Tomcat ? If this is a bug, is there a patch
available?
Thanks
------ Begin ResponseWrapper.java ------
public class ResponseWrapper extends HttpServletResponseWrapper {
private PrintWriter printWriter;
private ResponseOutputStream outputStream;
public ResponseWrapper(ServletResponse response) throws
java.io.IOException {
super((HttpServletResponse) response);
outputStream = new ResponseOutputStream
(response.getOutputStream());
printWriter = new PrintWriter(outputStream);
}
public ServletOutputStream getOutputStream() throws
java.io.IOException {
return outputStream;
}
public PrintWriter getWriter() throws java.io.IOException {
return printWriter;
}
}
------ End ResponseWrapper.java ------
------ Begin ResponseOutputSteam.java ------
public class ResponseOutputStream extends ServletOutputStream {
private OutputStream outputStream;
private ByteArrayOutputStream arrayStream;
private boolean closed = false;
public ResponseOutputStream(OutputStream stream) {
outputStream = stream;
arrayStream = new ByteArrayOutputStream();
}
public void write(int i) throws java.io.IOException {
arrayStream.write(i);
}
public void close() throws java.io.IOException {
if (!closed) {
processStream();
outputStream.close();
closed = true;
}
}
public void flush() throws java.io.IOException {
if (arrayStream.size() != 0) {
if (!closed) {
processStream();
arrayStream = new ByteArrayOutputStream();
}
}
}
private void processStream() throws java.io.IOException {
outputStream.write(replaceContent(arrayStream.toByteArray()));
outputStream.flush();
}
public byte[] replaceContent(byte[] bytesContent) {
byte[] returnContent = new byte[bytesContent.length];
int j = 0;
for (int i = 0; i < bytesContent.length; i++) {
if (bytesContent != '\n' && bytesContent !
= '\t') {
returnContent[j++] = bytesContent;
}
}
return returnContent;
}
}
------ End ResponseOutputSteam.java ------
------ Begin ResponseFilter.java ------
public class ResponseFilter implements Filter {
private FilterConfig filterConfig = null;
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
ResponseWrapper responseWrapper = new ResponseWrapper
(response);
chain.doFilter(request, responseWrapper);
responseWrapper.getOutputStream().close();
}
public void destroy() {
this.filterConfig =null;
}
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
}
------ End ResponseFilter.java ------
--- Begin Filter configuring into web.xml ---
<filter>
<filter-name>ResponseFilter</filter-name>
<filter-class>it.openkey.util.filters.ResponseFilter</filter-
class>
</filter>
<filter-mapping>
<filter-name>ResponseFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ResponseFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ResponseFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
--- End Filter configuring into web.xml ---