package org.stagemonitor.web.monitor.filter; import java.io.ByteArrayOutputStream; import java.io.CharArrayWriter; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class HttpServletResponseBufferWrapper extends HttpServletResponseWrapper { private BufferingServletOutputStream servletOutputStream; private boolean usingOutputStream = false; private BufferingPrintWriter printWriter; private boolean usingWriter = false; private boolean committed = false; public HttpServletResponseBufferWrapper(HttpServletResponse response) { super(response); } @Override public BufferingPrintWriter getWriter() { if (usingOutputStream) { throw new IllegalStateException("getOutputStream has already been called"); } usingWriter = true; if (printWriter == null) { printWriter = new BufferingPrintWriter(); } return printWriter; } @Override public BufferingServletOutputStream getOutputStream() throws IOException { if (usingWriter) { throw new IllegalStateException("getWriter has already been called"); } usingOutputStream = true; if (servletOutputStream == null) { servletOutputStream = new BufferingServletOutputStream(); } return servletOutputStream; } @Override public void setContentLength(int len) { // ignore } @Override public void flushBuffer() throws IOException { // the purpose of this wrapper is to buffer all the content committed = true; } @Override public void setBufferSize(int size) { // ignore } @Override public void resetBuffer() { assertNotCommitted(); servletOutputStream = null; usingOutputStream = false; printWriter = null; usingWriter = false; } @Override public void reset() { resetBuffer(); super.reset(); } @Override public void sendError(int sc, String msg) throws IOException { assertNotCommitted(); super.sendError(sc, msg); committed = true; } @Override public void sendError(int sc) throws IOException { assertNotCommitted(); super.sendError(sc); committed = true; } @Override public void sendRedirect(String location) throws IOException { assertNotCommitted(); super.sendRedirect(location); committed = true; } @Override public void setStatus(int sc, String sm) { if (!isCommitted()) { super.setStatus(sc, sm); } } @Override public void setStatus(int sc) { if (!isCommitted()) { super.setStatus(sc); } } @Override public boolean isCommitted() { return committed || super.isCommitted(); } public boolean isUsingWriter() { return usingWriter; } public static class BufferingServletOutputStream extends ServletOutputStream { private ByteArrayOutputStream output = new ByteArrayOutputStream(); @Override public void write(int b) throws IOException { output.write(b); } public ByteArrayOutputStream getOutput() { return output; } } public static class BufferingPrintWriter extends PrintWriter { private CharArrayWriter output; private BufferingPrintWriter() { this(new CharArrayWriter()); } private BufferingPrintWriter(CharArrayWriter out) { super(out); this.output = out; } public CharArrayWriter getOutput() { return output; } } private void assertNotCommitted() { if (isCommitted()) { throw new IllegalStateException("The response has already been committed"); } } }