001: // Copyright (C) 1998-2001 by Jason Hunter <jhunter_AT_acm_DOT_org>.
002: // All rights reserved. Use of this class is limited.
003: // Please see the LICENSE for more information.
004:
005: package com.oreilly.servlet;
006:
007: import java.io.*;
008: import javax.servlet.*;
009: import javax.servlet.http.*;
010:
011: /**
012: * A utility class to generate <tt>multipart/x-mixed-replace</tt> responses,
013: * the kind of responses that implement server push. Note that Microsoft
014: * Internet Explorer does not understand this sort of response.
015: * <p>
016: * To use this class, first construct a new MultipartResponse
017: * passing to its constructor the servlet's response parameter.
018: * MultipartResponse uses the response object to fetch the
019: * servlet's output stream and to set the response's content type.
020: * <p>
021: * Then, for each page of content, begin by calling <tt>startResponse()</tt>
022: * passing in the content type for that page. Send the content for the
023: * page by writing to the output stream as usual. A call to
024: * <tt>endResponse()</tt> ends the page and flushes the content so the
025: * client can see it. At this point a <tt>sleep()</tt> or other delay
026: * can be added until the next page is ready for sending.
027: * <p>
028: * The call to <tt>endResponse()</tt> is optional. The
029: * <tt>startResponse()</tt> method knows whether the last response has
030: * been ended, and ends it itself if necessary. However, it's wise to
031: * call <tt>endResponse()</tt> if there's to be a delay between the
032: * time one response ends and the next begins. It lets the client display
033: * the latest response during the time it waits for the next one.
034: * <p>
035: * Finally, after each response page has been sent, a call to the
036: * <tt>finish()</tt> method finishes the multipart response and sends a
037: * code telling the client there will be no more responses.
038: * <p>
039: * For example:
040: * <blockquote><pre>
041: * MultipartResponse multi = new MultipartResponse(res);
042: *
043: * multi.startResponse("text/plain");
044: * out.println("On your mark");
045: * multi.endResponse();
046: *
047: * try { Thread.sleep(1000); } catch (InterruptedException e) { }
048: *
049: * multi.startResponse("text/plain");
050: * out.println("Get set");
051: * multi.endResponse();
052: *
053: * try { Thread.sleep(1000); } catch (InterruptedException e) { }
054: *
055: * multi.startResponse("image/gif");
056: * ServletUtils.returnFile(req.getRealPath("/images/go.gif"), out);
057: *
058: * multi.finish();
059: * </pre></blockquote>
060: *
061: * @see ServletUtils
062: *
063: * @author <b>Jason Hunter</b>, Copyright © 1998
064: * @version 1.0, 98/09/18
065: */
066: public class MultipartResponse {
067:
068: HttpServletResponse res;
069: ServletOutputStream out;
070: boolean endedLastResponse = true;
071:
072: /**
073: * Constructs a new MultipartResponse to send content to the given
074: * servlet response.
075: *
076: * @param response the servlet response
077: * @exception IOException if an I/O error occurs
078: */
079: public MultipartResponse(HttpServletResponse response)
080: throws IOException {
081: // Save the response object and output stream
082: res = response;
083: out = res.getOutputStream();
084:
085: // Set things up
086: res.setContentType("multipart/x-mixed-replace;boundary=End");
087: out.println();
088: out.println("--End");
089: }
090:
091: /**
092: * Begins a single response with the specified content type.
093: * This method knows whether the last response has been ended, and
094: * ends it itself if necessary.
095: *
096: * @param contentType the content type of this response part
097: * @exception IOException if an I/O error occurs
098: */
099: public void startResponse(String contentType) throws IOException {
100: // End the last response if necessary
101: if (!endedLastResponse) {
102: endResponse();
103: }
104: // Start the next one
105: out.println("Content-type: " + contentType);
106: out.println();
107: endedLastResponse = false;
108: }
109:
110: /**
111: * Ends a single response. Flushes the output.
112: *
113: * @exception IOException if an I/O error occurs
114: */
115: public void endResponse() throws IOException {
116: // End the last response, and flush so the client sees the content
117: out.println();
118: out.println("--End");
119: out.flush();
120: endedLastResponse = true;
121: }
122:
123: /**
124: * Finishes the multipart response. Sends a code telling the client
125: * there will be no more responses and flushes the output.
126: *
127: * @exception IOException if an I/O error occurs
128: */
129: public void finish() throws IOException {
130: out.println("--End--");
131: out.flush();
132: }
133: }
|