Index: stripes/src/net/sourceforge/stripes/action/StreamingResolution.java =================================================================== --- stripes/src/net/sourceforge/stripes/action/StreamingResolution.java (revision 1013) +++ stripes/src/net/sourceforge/stripes/action/StreamingResolution.java (working copy) @@ -15,6 +15,7 @@ package net.sourceforge.stripes.action; import net.sourceforge.stripes.exception.StripesRuntimeException; +import net.sourceforge.stripes.util.Log; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; @@ -53,6 +54,7 @@ * @author Tim Fennell */ public class StreamingResolution implements Resolution { + private static final Log log = Log.getInstance(StreamingResolution.class); private InputStream inputStream; private Reader reader; private String filename; @@ -131,14 +133,12 @@ } /** - * Streams data from the InputStream or Reader to the response's OutputStream or PrinterWriter, - * using a moderately sized buffer to ensure that the operation is reasonable efficient. - * Once the InputStream or Reader signaled the end of the stream, close() is called on it. + * Executes streaming data to the response. * * @param request the HttpServletRequest being processed * @param response the paired HttpServletResponse - * @throws IOException if there is a problem accessing one of the streams or reader/writer - * objects used. + * @throws Exception if any problems arise + * @see #stream(HttpServletResponse) */ final public void execute(HttpServletRequest request, HttpServletResponse response) throws Exception { response.setContentType(this.contentType); @@ -156,34 +156,57 @@ } /** - * Responsible for the actual streaming of data through the response. If subclassed, - * this method should be overridden to stream back data other than data supplied by - * an InputStream or Reader supplied to a constructor. + * Does the actual streaming of data through the response. If subclassed, this method + * should be overridden to stream back data other than data supplied by an InputStream or + * a Reader supplied to a constructor. * + *
If an InputStream or Reader was supplied to a constructor, this implementation uses + * a moderately sized buffer to stream data from it to the response to make the operation + * reasonably efficient, and closes the InputStream or the Reader. If an IOException occurs + * when closing it, that exception will be logged as a warning, and not thrown in + * order to not mask a possibly previously thrown exception.
+ * * @param response the HttpServletResponse from which either the output stream or writer * can be obtained - * @throws IOException if any problems arise when streaming data + * @throws Exception if any problems arise when streaming data */ protected void stream(HttpServletResponse response) throws Exception { int length = 0; if (this.reader != null) { char[] buffer = new char[512]; - PrintWriter out = response.getWriter(); + try { + PrintWriter out = response.getWriter(); - while ( (length = this.reader.read(buffer)) != -1 ) { - out.write(buffer, 0, length); + while ( (length = this.reader.read(buffer)) != -1 ) { + out.write(buffer, 0, length); + } } - this.reader.close(); + finally { + try { + this.reader.close(); + } + catch (IOException e) { + log.warn("Error closing reader", e); + } + } } else if (this.inputStream != null) { byte[] buffer = new byte[512]; - ServletOutputStream out = response.getOutputStream(); + try { + ServletOutputStream out = response.getOutputStream(); - while ( (length = this.inputStream.read(buffer)) != -1) { - out.write(buffer, 0, length); + while ( (length = this.inputStream.read(buffer)) != -1) { + out.write(buffer, 0, length); + } } - - this.inputStream.close(); + finally { + try { + this.inputStream.close(); + } + catch (IOException e) { + log.warn("Error closing inputStream", e); + } + } } else { throw new StripesRuntimeException("A StreamingResolution was constructed without " +