The other day I made a custom JSP tag which renders other views in the middle of a JSP, which involves getting the view output as a string. Below is the code I used for doing this, which is based on assorted fragments of code I found on the 'net. I should work for any View, not just JSPs (mine are XSLT views).
Code:
/**
* An output stream which stores it's content in an accessible string buffer.
*/
public class DummyOutputStream extends ServletOutputStream {
private StringBuffer buffer = new StringBuffer();
/** @{inheritDoc} */
public String toString() {
return buffer.toString();
}
/** @{inheritDoc} */
public StringBuffer getBuffer() {
return buffer;
}
/** @{inheritDoc} */
public void write(final int b) throws IOException {
buffer.append(b);
}
/** @{inheritDoc} */
public void print(final boolean arg0) throws IOException {
buffer.append(arg0);
}
/** @{inheritDoc} */
public void print(final char arg0) throws IOException {
buffer.append(arg0);
}
/** @{inheritDoc} */
public void print(final double arg0) throws IOException {
buffer.append(arg0);
}
/** @{inheritDoc} */
public void print(final float arg0) throws IOException {
buffer.append(arg0);
}
/** @{inheritDoc} */
public void print(final int arg0) throws IOException {
buffer.append(arg0);
}
/** @{inheritDoc} */
public void print(final long arg0) throws IOException {
buffer.append(arg0);
}
/** @{inheritDoc} */
public void print(final String arg0) throws IOException {
buffer.append(arg0);
}
/** @{inheritDoc} */
public void println() throws IOException {
buffer.append("\n");
}
/** @{inheritDoc} */
public void println(final boolean arg0) throws IOException {
buffer.append(arg0);
buffer.append("\n");
}
/** @{inheritDoc} */
public void println(final char arg0) throws IOException {
buffer.append(arg0);
buffer.append("\n");
}
/** @{inheritDoc} */
public void println(final double arg0) throws IOException {
buffer.append(arg0);
buffer.append("\n");
}
/** @{inheritDoc} */
public void println(final float arg0) throws IOException {
buffer.append(arg0);
buffer.append("\n");
}
/** @{inheritDoc} */
public void println(final int arg0) throws IOException {
buffer.append(arg0);
buffer.append("\n");
}
/** @{inheritDoc} */
public void println(final long arg0) throws IOException {
buffer.append(arg0);
buffer.append("\n");
}
/** @{inheritDoc} */
public void println(final String arg0) throws IOException {
buffer.append(arg0);
buffer.append("\n");
}
/** @{inheritDoc} */
public void write(final byte[] b) throws IOException {
print(new String(b));
}
/** @{inheritDoc} */
public void write(final byte[] b, final int off, final int len) throws IOException {
write(ArrayUtils.subarray(b, off, off + len));
}
}
/**
* Wraps a HttpServletResponse to redirect the output to a StringBuffer.
*/
public class ContentAdapterResponseWrapper extends HttpServletResponseWrapper {
private DummyOutputStream outstream;
/**
* Constructor.
*
* @param response the response to wrap
*/
public ContentAdapterResponseWrapper(final HttpServletResponse response) {
super(response);
outstream = new DummyOutputStream();
}
/**
* @return the string buffer containing the wrapped responses output
*/
public StringBuffer getBuffer() {
return outstream.getBuffer();
}
/** @{inheritDoc} */
public ServletOutputStream getOutputStream() throws IOException {
return outstream;
}
/** @{inheritDoc} */
public PrintWriter getWriter() throws IOException {
return new PrintWriter(outstream);
}
/** @{inheritDoc} */
public String toString() {
return outstream.toString();
}
/**
* Override to always have the original content type.
*/
public void setContentType(final String arg0) {
}
}
You'd use the classes something like the following:
Code:
Map renderModel;
HttpServletRequest request;
HttpServletResponse response;
View someview;
ContentAdapterResponseWrapper proxyResponse = new ContentAdapterResponseWrapper(response);
proxyResponse.setContentType("application/xhtml+xml");
view.render(renderModel, request, proxyResponse);
String output = proxyResponse.getBuffer().toString();