We can also add HTML to the response after the delegation. This is tricky, though. We must pass a fake response to the rest of the chain. When the fake response returns, we extract its text, modify it as we wish, then write it to the real response.
We begin by creating our fake response class, which is actually the real response encapsulated in a response wrapper (J2EE provides a wrapper class specifically for this purpose). The wrapper replaces the output stream of the real response with an array writer.
Here's the code:
import javax.servlet.http.*;
import java.io.*;
public class ResponseProxy extends
HttpServletResponseWrapper {
private CharArrayWriter output;
public String toString() {
return output.toString();
}
public ResponseProxy(HttpServletResponse
response){
super(response);
output = new CharArrayWriter();
}
public PrintWriter getWriter(){
return new PrintWriter(output);
}
}
Next we create our filter. The filter saves the response's "real" output stream, which is connected to the client. Then it creates a response wrapper with a "fake" output stream then delegates to the rest of the chain and the servlet. The servlet will unwittingly write its HTML to this stream and then close it.
After the delegation, the HTML is extracted from the fake output stream, modified, then written to the real output stream which is subsequently closed. Here's the code:
public void doFilter(
ServletRequest
request,
ServletResponse response,
FilterChain chain) throws IOException,
ServletException {
// save the real output stream:
PrintWriter out =
response.getWriter();
// create a response wrapper with
a fake output stream:
ResponseProxy wrapper = new
ResponseProxy(
(HttpServletResponse)response);
// delegate:
chain.doFilter(request, wrapper);
// now generate the web page:
String htmlText =
wrapper.toString();
int insertionPoint =
htmlText.indexOf("</body>") - 1;
String htmlPrefix = htmlText.substring(0,
insertionPoint);
htmlText = htmlPrefix +
contactInfo + "</body></html>";
out.write(htmlText);
out.close();
}
The contact information is
simply a string initialized by the init method:
private String
contactInfo;
public void init(FilterConfig
filterConfig)
throws ServletException {
_filterConfig = filterConfig;
contactInfo =
"<p>Please contact the
HR office for details</p>";
}
Here's the request:
And here's the enhanced response:
This technique does not work with JSPs because they don't use the getWriter method to extract the output stream.