Here's a somewhat crazy idea, but i would probably solve it like this.
If you really can't touch the broken Filter (really?), write another filter that you place before the broken Filter.
This looks more complex than it is, but that's only because of Java's verbosity, so please bear with me.
Basically what it does is that it uses HttpServletResponseWrapper
to wrap/"override" response.getWriter()
in filters and the servlet following it in the chain.
So when your broken Filter calls response.getWriter()
, it will instead get a proxy PrintWriter that only calls the real response.getWriter()
the first time it is actually written to.
Then it no longer matters if the broken Filter calls response.getWriter()
without writing to it.
I haven't actually tested this code, but i believe it should work.
Note that this assumes that the broken Filter calls response.getWriter()
without actually writing something. The output would be corrupt anyway if the broken filter wrote something and then you tried to write a PDF to it as well.
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
public class BrokenWriterGetterFixingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, final ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(servletRequest, new BrokenWriterGetterFixingResponseWrapper((HttpServletResponse) servletResponse));
}
@Override
public void destroy() {
}
private static class BrokenWriterGetterFixingResponseWrapper extends HttpServletResponseWrapper {
public BrokenWriterGetterFixingResponseWrapper(HttpServletResponse response) {
super(response);
}
@Override
public PrintWriter getWriter() throws IOException {
return new PrintWriter(new BrokenWriterGetterFixingWriter(getResponse()));
}
}
private static class BrokenWriterGetterFixingWriter extends Writer {
private PrintWriter responseWriter;
private final ServletResponse response;
public BrokenWriterGetterFixingWriter(ServletResponse response) {
this.response = response;
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
getResponseWriter().write(cbuf, off, len);
}
@Override
public void flush() throws IOException {
getResponseWriter().flush();
}
@Override
public void close() throws IOException {
getResponseWriter().close();
}
private PrintWriter getResponseWriter() throws IOException {
if (null == responseWriter) {
responseWriter = response.getWriter();
}
return responseWriter;
}
}
}