Source code: gsoft/xervlet/MultipartResponse.java
1 /*************************************************************************
2 Copyright (C) 2003 Steve Gee
3 stevesgee@cox.net
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *************************************************************************/
19
20
21 package gsoft.xervlet;
22
23 import java.io.*;
24 import javax.servlet.*;
25 import javax.servlet.http.*;
26
27 /**
28 * A utility class to generate <tt>multipart/x-mixed-replace</tt> responses,
29 * the kind of responses that implement server push. Note that Microsoft
30 * Internet Explorer does not understand this sort of response.
31 * <p>
32 * To use this class, first construct a new MultipartResponse
33 * passing to its constructor the servlet's response parameter.
34 * MultipartResponse uses the response object to fetch the
35 * servlet's output stream and to set the response's content type.
36 * <p>
37 * Then, for each page of content, begin by calling <tt>startResponse()</tt>
38 * passing in the content type for that page. Send the content for the
39 * page by writing to the output stream as usual. A call to
40 * <tt>endResponse()</tt> ends the page and flushes the content so the
41 * client can see it. At this point a <tt>sleep()</tt> or other delay
42 * can be added until the next page is ready for sending.
43 * <p>
44 * The call to <tt>endResponse()</tt> is optional. The
45 * <tt>startResponse()</tt> method knows whether the last response has
46 * been ended, and ends it itself if necessary. However, it's wise to
47 * call <tt>endResponse()</tt> if there's to be a delay between the
48 * time one response ends and the next begins. It lets the client display
49 * the latest response during the time it waits for the next one.
50 * <p>
51 * Finally, after each response page has been sent, a call to the
52 * <tt>finish()</tt> method finishes the multipart response and sends a
53 * code telling the client there will be no more responses.
54 * <p>
55 * For example:
56 * <blockquote><pre>
57 * MultipartResponse multi = new MultipartResponse(res);
58 *
59 * multi.startResponse("text/plain");
60 * out.println("On your mark");
61 * multi.endResponse();
62 *
63 * try { Thread.sleep(1000); } catch (InterruptedException e) { }
64 *
65 * multi.startResponse("text/plain");
66 * out.println("Get set");
67 * multi.endResponse();
68 *
69 * try { Thread.sleep(1000); } catch (InterruptedException e) { }
70 *
71 * multi.startResponse("image/gif");
72 * ServletUtils.returnFile(req.getRealPath("/images/go.gif"), out);
73 *
74 * multi.finish();
75 * </pre></blockquote>
76 *
77 */
78 public class MultipartResponse {
79
80 HttpServletResponse res;
81 ServletOutputStream out;
82 boolean endedLastResponse = true;
83
84 /**
85 * Constructs a new MultipartResponse to send content to the given
86 * servlet response.
87 *
88 * @param response the servlet response
89 * @exception IOException if an I/O error occurs
90 */
91 public MultipartResponse(HttpServletResponse response) throws IOException {
92 // Save the response object and output stream
93 res = response;
94 out = res.getOutputStream();
95
96 // Set things up
97 res.setContentType("multipart/x-mixed-replace;boundary=End");
98 out.println();
99 out.println("--End");
100 }
101
102 /**
103 * Begins a single response with the specified content type.
104 * This method knows whether the last response has been ended, and
105 * ends it itself if necessary.
106 *
107 * @param contentType the content type of this response part
108 * @exception IOException if an I/O error occurs
109 */
110 public void startResponse(String contentType) throws IOException {
111 // End the last response if necessary
112 if (!endedLastResponse) {
113 endResponse();
114 }
115 // Start the next one
116 out.println("Content-type: " + contentType);
117 out.println();
118 endedLastResponse = false;
119 }
120
121 /**
122 * Ends a single response. Flushes the output.
123 *
124 * @exception IOException if an I/O error occurs
125 */
126 public void endResponse() throws IOException {
127 // End the last response, and flush so the client sees the content
128 out.println();
129 out.println("--End");
130 out.flush();
131 endedLastResponse = true;
132 }
133
134 /**
135 * Finishes the multipart response. Sends a code telling the client
136 * there will be no more responses and flushes the output.
137 *
138 * @exception IOException if an I/O error occurs
139 */
140 public void finish() throws IOException {
141 out.println("--End--");
142 out.flush();
143 }
144 }