Annotation of java/classes/org/w3c/jigsaw/servlet/JigsawHttpServletResponse.java, revision 1.33
1.1 abaird 1: // JigsawHttpServletReponse.java
1.33 ! bmahe 2: // $Id: JigsawHttpServletResponse.java,v 1.31.4.6 2000/02/11 13:07:12 bmahe Exp $
1.1 abaird 3: // (c) COPYRIGHT MIT and INRIA, 1996.
4: // Please first read the full copyright statement in file COPYRIGHT.html
5:
1.10 bmahe 6: package org.w3c.jigsaw.servlet;
1.1 abaird 7:
8: import java.io.*;
1.6 bmahe 9: import javax.servlet.*;
10: import javax.servlet.http.*;
1.4 abaird 11: import java.net.*;
1.33 ! bmahe 12: import java.util.Locale;
1.1 abaird 13:
1.10 bmahe 14: import org.w3c.www.mime.*;
15: import org.w3c.www.http.*;
16: import org.w3c.jigsaw.http.*;
1.33 ! bmahe 17: import org.w3c.www.http.HeaderValue;
1.2 abaird 18:
19: /**
1.30 bmahe 20: * @author Alexandre Rafalovitch <alex@access.com.au>
21: * @author Anselm Baird-Smith <abaird@w3.org>
22: * @author Benoît Mahé (bmahe@w3.org)
23: * @author Roland Mainz (Roland.Mainz@informatik.med.uni-giessen.de)
1.2 abaird 24: */
1.1 abaird 25:
1.29 bmahe 26: public class JigsawHttpServletResponse implements HttpServletResponse {
27:
1.33 ! bmahe 28: public final static String CHARSET_PARAMETER = "charset";
! 29:
! 30: public final static int DEFAULT_BUFFER_SIZE = 8 * 1024; // 8KB buffer
! 31: public final static int MIN_BUFFER_SIZE = 4 * 1024; // 4KB buffer
! 32:
1.31 ylafon 33: private final static int STATE_INITIAL = 0;
34: private final static int STATE_HEADERS_DONE = 1;
35: private final static int STATE_ALL_DONE = 2;
1.11 bmahe 36: private final static int STREAM_STATE_INITIAL = 0;
1.31 ylafon 37: private final static int STREAM_WRITER_USED = 1;
38: private final static int OUTPUT_STREAM_USED = 2;
1.11 bmahe 39:
40: private int stream_state = STREAM_STATE_INITIAL;
1.20 bmahe 41:
42: private JigsawServletOutputStream output = null;
43: private PrintWriter writer = null;
1.7 bmahe 44:
1.30 bmahe 45: private MimeTypeFormatException setContentTypeException = null;
46:
47: // servlet has set a fixed content length or not,
48: // and cut (see flushStream) any data which are too much here...
49: private final static int CALC_CONTENT_LENGTH = -1;
50: private int fixedContentLength = CALC_CONTENT_LENGTH;
51:
1.33 ! bmahe 52: // Our Locale
! 53: protected Locale locale;
! 54:
1.29 bmahe 55: /**
56: * Our temp stream.
57: */
58: protected ByteArrayOutputStream out = null;
59:
1.14 bmahe 60: protected JigsawHttpServletRequest jrequest = null;
61:
1.33 ! bmahe 62: protected int buffer_size;
! 63:
1.14 bmahe 64: protected void setServletRequest(JigsawHttpServletRequest jrequest) {
65: this.jrequest = jrequest;
66: }
67:
1.7 bmahe 68: public static final
1.29 bmahe 69: String INCLUDED = "org.w3c.jigsaw.servlet.included";
1.28 bmahe 70:
1.1 abaird 71: int state = STATE_INITIAL;
72: Reply reply = null;
73: Request request = null;
74:
1.18 bmahe 75: /**
76: * Sets the content length for this response.
77: * @param len - the content length
78: */
1.5 abaird 79: public void setContentLength(int i) {
1.30 bmahe 80: fixedContentLength = i;
1.1 abaird 81: reply.setContentLength(i);
82: }
1.18 bmahe 83:
84: /**
85: * Sets the content type for this response. This type may later be
86: * implicitly modified by addition of properties such as the MIME
87: * charset=<value> if the service finds it necessary, and the appropriate
88: * media type property has not been set.
89: * <p>This response property may only be assigned one time. If a writer
90: * is to be used to write a text response, this method must be
91: * called before the method getWriter. If an output stream will be used
92: * to write a response, this method must be called before the
93: * output stream is used to write response data.
94: * @param spec - the content's MIME type
1.27 ylafon 95: * @see JigsawHttpServletResponse#getOutputStream
96: * @see JigsawHttpServletResponse#getWriter
1.18 bmahe 97: */
1.5 abaird 98: public void setContentType(String spec) {
1.1 abaird 99: try {
100: MimeType type= new MimeType(spec);
101: reply.setContentType(type);
1.30 bmahe 102: setContentTypeException = null;
1.1 abaird 103: } catch(MimeTypeFormatException ex) {
1.30 bmahe 104: //store exception
105: setContentTypeException = ex;
1.1 abaird 106: }
107: }
1.5 abaird 108:
1.28 bmahe 109: protected boolean isStreamObtained() {
110: return (stream_state != STREAM_STATE_INITIAL);
111: }
112:
1.29 bmahe 113: protected Reply getReply() {
114: return reply;
115: }
116:
1.18 bmahe 117: /**
118: * Returns an output stream for writing binary response data.
1.24 bmahe 119: * @return A ServletOutputStream
1.18 bmahe 120: * @exception IOException if an I/O exception has occurred
121: * @exception IllegalStateException if getWriter has been called on this
122: * same request.
1.27 ylafon 123: * @see JigsawHttpServletResponse#getWriter
1.18 bmahe 124: */
1.5 abaird 125: public synchronized ServletOutputStream getOutputStream()
126: throws IOException
127: {
1.12 bmahe 128: if (stream_state == STREAM_WRITER_USED)
129: throw new IllegalStateException("Writer used");
130: stream_state = OUTPUT_STREAM_USED;
131: return getJigsawOutputStream();
1.11 bmahe 132: }
133:
134: protected ServletOutputStream getJigsawOutputStream()
135: throws IOException
136: {
1.12 bmahe 137: if ( output != null )
138: return output;
1.30 bmahe 139:
140: // any exception during setContentType ?
141: if( setContentTypeException != null ) {
142: // "wrap" the exception from setContentType in an IOException
1.33 ! bmahe 143: throw new IOException("Illegal Content Type: "+
1.30 bmahe 144: setContentTypeException.toString());
145: }
146:
147: if( request.hasState(INCLUDED) ) {
148: out = new ByteArrayOutputStream();
149: output = new JigsawServletOutputStream(this,
1.33 ! bmahe 150: new DataOutputStream(out),
! 151: buffer_size);
1.30 bmahe 152: } else {
1.33 ! bmahe 153: output = new JigsawServletOutputStream(this, reply, buffer_size);
1.30 bmahe 154: }
1.5 abaird 155: return output;
1.1 abaird 156: }
1.29 bmahe 157:
1.18 bmahe 158: /**
159: * Sets the status code and message for this response. If the field had
160: * already been set, the new value overwrites the previous one. The message
161: * is sent as the body of an HTML page, which is returned to the user to
162: * describe the problem. The page is sent with a default HTML header; the
163: * message is enclosed in simple body tags (<body></body>).
164: * @param i - the status code
165: * @param reason - the status message
1.28 bmahe 166: * @deprecated since jsdk2.1
1.18 bmahe 167: */
1.5 abaird 168: public void setStatus(int i, String reason) {
1.1 abaird 169: reply.setStatus(i);
170: reply.setReason(reason);
171: }
172:
1.18 bmahe 173: /**
174: * Sets the status code for this response. This method is used to set the
175: * return status code when there is no error (for example, for the status
176: * codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error, the
177: * sendError method should be used instead.
178: * @param i - the status code
1.27 ylafon 179: * @see JigsawHttpServletResponse#sendError
1.18 bmahe 180: */
1.5 abaird 181: public void setStatus(int i) {
1.1 abaird 182: setStatus(i, reply.getStandardReason(i));
183: }
184:
1.18 bmahe 185: /**
186: * Adds a field to the response header with the given name and value. If
187: * the field had already been set, the new value overwrites the previous
188: * one. The containsHeader method can be used to test for the presence of a
189: * header before setting its value.
190: * @param name - the name of the header field
191: * @param value - the header field's value
1.27 ylafon 192: * @see JigsawHttpServletResponse#containsHeader
1.18 bmahe 193: */
1.5 abaird 194: public void setHeader(String name, String value) {
1.1 abaird 195: reply.setValue(name, value);
196: }
197:
1.18 bmahe 198: /**
199: * Adds a field to the response header with the given name and integer
200: * value. If the field had already been set, the new value overwrites the
201: * previous one. The containsHeader method can be used to test for the
202: * presence of a header before setting its value.
203: * @param name - the name of the header field
204: * @param value - the header field's integer value
1.27 ylafon 205: * @see JigsawHttpServletResponse#containsHeader
1.18 bmahe 206: */
1.5 abaird 207: public void setIntHeader(String name, int value) {
1.1 abaird 208: setHeader(name, String.valueOf(value));
209: }
210:
1.18 bmahe 211: /**
212: * Adds a field to the response header with the given name and date-valued
213: * field. The date is specified in terms of milliseconds since the epoch.
214: * If the date field had already been set, the new value overwrites the
215: * previous one. The containsHeader method can be used to test for the
216: * presence of a header before setting its value.
217: * @param name - the name of the header field
218: * @param value - the header field's date value
1.27 ylafon 219: * @see JigsawHttpServletResponse#containsHeader
1.18 bmahe 220: */
1.5 abaird 221: public void setDateHeader(String name, long date) {
1.32 bmahe 222: setHeader(name, HttpFactory.makeDate(date).toExternalForm());
1.1 abaird 223: }
224:
1.5 abaird 225: public void unsetHeader(String name) {
1.1 abaird 226: setHeader(name, null);
227: }
228:
1.18 bmahe 229: /**
230: * Sends an error response to the client using the specified status code
231: * and descriptive message. If setStatus has previously been called, it is
232: * reset to the error status code. The message is sent as the body of an
233: * HTML page, which is returned to the user to describe the problem. The
234: * page is sent with a default HTML header; the message is enclosed in
235: * simple body tags (<body></body>).
236: * @param sc - the status code
237: * @param msg - the detail message
238: * @exception IOException If an I/O error has occurred.
239: */
1.5 abaird 240: public void sendError(int i, String msg)
241: throws IOException
1.1 abaird 242: {
243: setStatus(i);
244: reply.setContent(msg);
245: state = STATE_ALL_DONE;
246: }
1.18 bmahe 247:
248: /**
249: * Sends an error response to the client using the specified status
250: * code and a default message.
251: * @param sc - the status code
252: * @exception IOException If an I/O error has occurred.
253: */
1.1 abaird 254: public void sendError(int i)
255: throws IOException
256: {
257: setStatus(i);
258: reply.setContent(reply.getStandardReason(i));
259: state = STATE_ALL_DONE;
260: }
261:
1.18 bmahe 262: /**
263: * Sends a temporary redirect response to the client using the specified
264: * redirect location URL. The URL must be absolute (for example,
265: * https://hostname/path/file.html). Relative URLs are not permitted here.
266: * @param url - the redirect location URL
267: * @exception IOException If an I/O error has occurred.
268: */
1.1 abaird 269: public void sendRedirect(String url)
270: throws IOException
271: {
1.4 abaird 272: URL loc = null;
273: try {
274: loc = new URL(request.getURL(), url);
275: setStatus(SC_MOVED_TEMPORARILY);
276: reply.setLocation(loc);
277: state = STATE_ALL_DONE;
278: } catch (Exception ex) {
279: ex.printStackTrace();
280: }
1.1 abaird 281: }
1.6 bmahe 282:
1.18 bmahe 283: /**
284: * Checks whether the response message header has a field with the
285: * specified name.
286: * @param name - the header field name
287: * @return true if the response message header has a field with the
288: * specified name; false otherwise
289: */
1.12 bmahe 290: public boolean containsHeader(String header) {
291: return reply.hasHeader(header);
292: }
293:
1.18 bmahe 294: /**
295: * Adds the specified cookie to the response. It can be called multiple
296: * times to set more than one cookie.
297: * @param cookie - the Cookie to return to the client
298: */
1.12 bmahe 299: public void addCookie(Cookie cookie) {
1.13 bmahe 300: HttpSetCookieList clist = reply.getSetCookie();
301: if (clist == null) {
302: HttpSetCookie cookies [] = new HttpSetCookie[1];
303: cookies[0] = convertCookie(cookie);
304: clist = new HttpSetCookieList(cookies);
305: } else {
306: clist.addSetCookie(convertCookie(cookie));
307: }
308: reply.setSetCookie(clist);
309: }
1.12 bmahe 310:
1.31 ylafon 311: private HttpSetCookie convertCookie(Cookie cookie) {
1.13 bmahe 312: HttpSetCookie scookie = new HttpSetCookie(true,
313: cookie.getName(),
314: cookie.getValue());
315: scookie.setComment(cookie.getComment());
316: scookie.setDomain(cookie.getDomain());
317: scookie.setMaxAge(cookie.getMaxAge());
318: scookie.setPath(cookie.getPath());
319: scookie.setSecurity(cookie.getSecure());
320: scookie.setVersion(cookie.getVersion());
321: return scookie;
1.12 bmahe 322: }
323:
1.18 bmahe 324: /**
325: * Encodes the specified URL for use in the sendRedirect method or, if
326: * encoding is not needed, returns the URL unchanged. The implementation
327: * of this method should include the logic to determine whether the
328: * session ID needs to be encoded in the URL.
329: * Because the rules for making this determination differ from those used
330: * to decide whether to encode a normal link, this method is seperate from
331: * the encodeUrl method.
332: * <p>All URLs sent to the HttpServletResponse.sendRedirect method should
333: * be run through this method. Otherwise, URL rewriting canont be used
334: * with browsers which do not support cookies.
335: * @param url - the url to be encoded.
336: * @return the encoded URL if encoding is needed; the unchanged URL
337: * otherwise.
1.28 bmahe 338: * @deprecated since jsdk2.1
1.27 ylafon 339: * @see JigsawHttpServletResponse#sendRedirect
340: * @see JigsawHttpServletResponse#encodeUrl
1.18 bmahe 341: */
1.12 bmahe 342: public String encodeRedirectUrl(String url) {
1.19 bmahe 343: try {
344: URL redirect = new URL(url);
345: URL requested = new URL(jrequest.getRequestURI());
346: if ( redirect.getHost().equals(requested.getHost()) &&
347: redirect.getPort() == requested.getPort())
348: return encodeUrl(url);
349: } catch (MalformedURLException ex) {
350: //error so return url.
351: return url;
352: }
353: return url;
1.12 bmahe 354: }
355:
1.28 bmahe 356: /**
357: * Encodes the specified URL for use in the sendRedirect method or, if
358: * encoding is not needed, returns the URL unchanged. The implementation
359: * of this method should include the logic to determine whether the
360: * session ID needs to be encoded in the URL.
361: * Because the rules for making this determination differ from those used
362: * to decide whether to encode a normal link, this method is seperate from
363: * the encodeUrl method.
364: * <p>All URLs sent to the HttpServletResponse.sendRedirect method should
365: * be run through this method. Otherwise, URL rewriting canont be used
366: * with browsers which do not support cookies.
367: * @param url - the url to be encoded.
368: * @return the encoded URL if encoding is needed; the unchanged URL
369: * otherwise.
370: * @see JigsawHttpServletResponse#sendRedirect
371: * @see JigsawHttpServletResponse#encodeUrl
372: */
373: public String encodeRedirectURL(String url) {
374: return encodeRedirectUrl(url);
375: }
376:
1.18 bmahe 377: /**
378: * Encodes the specified URL by including the session ID in it, or, if
379: * encoding is not needed, returns the URL unchanged. The implementation of
380: * this method should include the logic to determine whether the session ID
381: * needs to be encoded in the URL. For example, if the browser supports
382: * cookies, or session tracking is turned off, URL encoding is unnecessary.
383: * <p>All URLs emitted by a Servlet should be run through this method.
384: * Otherwise, URL rewriting cannot be used with browsers which do not
385: * support cookies.
386: * @param url - the url to be encoded.
387: * @return the encoded URL if encoding is needed; the unchanged URL
388: * otherwise.
1.28 bmahe 389: * @deprecated since jsdk2.1
1.18 bmahe 390: */
1.12 bmahe 391: public String encodeUrl(String url) {
1.15 bmahe 392: if (! jrequest.isRequestedSessionIdFromCookie()) {
1.25 bmahe 393: url = url + ((url.indexOf("?") != -1) ? "&" : "?")+
394: jrequest.getCookieName()+"="+
1.15 bmahe 395: jrequest.getSession(true).getId();
396: }
1.12 bmahe 397: return url;
1.28 bmahe 398: }
399:
400: /**
401: * Encodes the specified URL by including the session ID in it, or, if
402: * encoding is not needed, returns the URL unchanged. The implementation of
403: * this method should include the logic to determine whether the session ID
404: * needs to be encoded in the URL. For example, if the browser supports
405: * cookies, or session tracking is turned off, URL encoding is unnecessary.
406: * <p>All URLs emitted by a Servlet should be run through this method.
407: * Otherwise, URL rewriting cannot be used with browsers which do not
408: * support cookies.
409: * @param url - the url to be encoded.
410: * @return the encoded URL if encoding is needed; the unchanged URL
411: * otherwise.
412: */
413: public String encodeURL(String url) {
414: return encodeUrl(url);
1.12 bmahe 415: }
416:
417: /**
418: * Return the Charset parameter of content type
419: * @return A String instance
420: */
421: public String getCharacterEncoding() {
422: org.w3c.www.mime.MimeType type = reply.getContentType();
1.33 ! bmahe 423: if ((type != null) && (type.hasParameter(CHARSET_PARAMETER))) {
! 424: return type.getParameterValue(CHARSET_PARAMETER);
1.12 bmahe 425: }
1.30 bmahe 426: return System.getProperty("file.encoding");
1.12 bmahe 427: }
428:
1.18 bmahe 429: /**
430: * Returns a print writer for writing formatted text responses.
431: * The MIME type of the response will be modified, if necessary, to
432: * reflect the character encoding used, through the charset=... property.
433: * This means that the content type must be set before calling this
434: * method.
435: * @exception UnsupportedEncodingException if no such encoding can be
436: * provided
437: * @exception IllegalStateException if getOutputStream has been called
438: * on this same request.
439: * @exception IOException on other errors.
1.27 ylafon 440: * @see JigsawHttpServletResponse#getOutputStream
441: * @see JigsawHttpServletResponse#setContentType
1.18 bmahe 442: */
1.12 bmahe 443: public synchronized PrintWriter getWriter()
444: throws IOException, UnsupportedEncodingException
445: {
446: if (stream_state == OUTPUT_STREAM_USED)
447: throw new IllegalStateException("Output stream used");
448: stream_state = STREAM_WRITER_USED;
1.11 bmahe 449:
1.12 bmahe 450: if (writer == null) {
451: writer = new PrintWriter(
1.29 bmahe 452: new OutputStreamWriter(getJigsawOutputStream(),
453: getCharacterEncoding()));
1.12 bmahe 454: }
455: return writer;
1.20 bmahe 456: }
457:
1.31 ylafon 458: /**
459: * Flush the output stream.
460: * @param close Close the stream if true.
461: * @exception IOException if an IO error occurs.
462: */
1.30 bmahe 463: protected synchronized void flushStream(boolean close)
464: throws IOException
465: {
466: int writeLength;
1.29 bmahe 467:
1.30 bmahe 468: if (stream_state == OUTPUT_STREAM_USED) {
469: output.flush();
470: } else if (stream_state == STREAM_WRITER_USED) {
471: writer.flush();
472: }
1.29 bmahe 473:
1.30 bmahe 474: if (request.hasState(INCLUDED)) {
475: if (out == null)
476: return;
477:
478: if( fixedContentLength != CALC_CONTENT_LENGTH ) {
479: writeLength = (out.size() < fixedContentLength)
480: ? (out.size())
481: : (fixedContentLength);
1.29 bmahe 482: } else {
1.30 bmahe 483: writeLength = out.size();
1.29 bmahe 484: }
1.30 bmahe 485: reply.setContentLength(writeLength);
486:
487: OutputStream rout = reply.getOutputStream(false);
488: byte content[] = out.toByteArray();
489: if (close)
490: out.close();
491: else
492: out.reset();
493: rout.write(content);
494: rout.flush();
1.29 bmahe 495: }
1.13 bmahe 496: }
497:
1.33 ! bmahe 498: // 2.2
! 499:
! 500: /**
! 501: * Sets the preferred buffer size for the body of the response.
! 502: * The servlet container will use a buffer at least as large as
! 503: * the size requested. The actual buffer size used can be found
! 504: * using <code>getBufferSize</code>.
! 505: *
! 506: * <p>A larger buffer allows more content to be written before anything is
! 507: * actually sent, thus providing the servlet with more time to set
! 508: * appropriate status codes and headers. A smaller buffer decreases
! 509: * server memory load and allows the client to start receiving data more
! 510: * quickly.
! 511: *
! 512: * <p>This method must be called before any response body content is
! 513: * written; if content has been written, this method throws an
! 514: * <code>IllegalStateException</code>.
! 515: * @param size the preferred buffer size
! 516: * @exception IllegalStateException if this method is called after
! 517: * content has been written
! 518: * @see #getBufferSize
! 519: * @see #flushBuffer
! 520: * @see #isCommitted
! 521: * @see #reset
! 522: */
! 523: public void setBufferSize(int size) {
! 524: if (stream_state != STREAM_STATE_INITIAL) {
! 525: throw new IllegalStateException("Stream already initialized");
! 526: }
! 527: if (size < MIN_BUFFER_SIZE) {
! 528: buffer_size = MIN_BUFFER_SIZE;
! 529: } else {
! 530: buffer_size = size;
! 531: }
! 532: }
! 533:
! 534: /**
! 535: * Returns the actual buffer size used for the response. If no buffering
! 536: * is used, this method returns 0.
! 537: * @return the actual buffer size used
! 538: * @see #setBufferSize
! 539: * @see #flushBuffer
! 540: * @see #isCommitted
! 541: * @see #reset
! 542: */
! 543: public int getBufferSize() {
! 544: return buffer_size;
! 545: }
! 546:
! 547: /**
! 548: * Forces any content in the buffer to be written to the client. A call
! 549: * to this method automatically commits the response, meaning the status
! 550: * code and headers will be written.
! 551: * @see #setBufferSize
! 552: * @see #getBufferSize
! 553: * @see #isCommitted
! 554: * @see #reset
! 555: */
! 556: public void flushBuffer()
! 557: throws IOException
! 558: {
! 559: if (output != null) {
! 560: output.flush();
! 561: }
! 562: }
! 563:
! 564: /**
! 565: * Returns a boolean indicating if the response has been
! 566: * committed. A commited response has already had its status
! 567: * code and headers written.
! 568: * @return a boolean indicating if the response has been
! 569: * committed
! 570: * @see #setBufferSize
! 571: * @see #getBufferSize
! 572: * @see #flushBuffer
! 573: * @see #reset
! 574: */
! 575: public boolean isCommitted() {
! 576: if (output != null) {
! 577: return output.isCommitted();
! 578: } else {
! 579: return false;
! 580: }
! 581: }
! 582:
! 583: /**
! 584: * Clears any data that exists in the buffer as well as the status code and
! 585: * headers. If the response has been committed, this method throws an
! 586: * <code>IllegalStateException</code>.
! 587: * @exception IllegalStateException if the response has already been
! 588: * committed
! 589: * @see #setBufferSize
! 590: * @see #getBufferSize
! 591: * @see #flushBuffer
! 592: * @see #isCommitted
! 593: */
! 594: public void reset() {
! 595: if (output != null) {
! 596: output.reset();
! 597: }
! 598: }
! 599:
! 600: /**
! 601: * Sets the locale of the response, setting the headers (including the
! 602: * Content-Type's charset) as appropriate. This method should be called
! 603: * before a call to {@link #getWriter}. By default, the response locale
! 604: * is the default locale for the server.
! 605: * @param loc the locale of the response
! 606: * @see #getLocale
! 607: */
! 608: public void setLocale(Locale locale) {
! 609: if (locale == null) {
! 610: return;
! 611: }
! 612: this.locale = locale;
! 613:
! 614: // content language
! 615: String lang = locale.getLanguage();
! 616: if (lang.length() > 0) {
! 617: String array[] = new String[1];
! 618: array[0] = lang;
! 619: reply.setContentLanguage(array);
! 620: }
! 621:
! 622: // content type (charset)
! 623: String charset = org.w3c.www.mime.Utils.getCharset(locale);
! 624: if (charset != null) {
! 625: MimeType contentType = reply.getContentType();
! 626: // override charset
! 627: contentType.setParameter(CHARSET_PARAMETER, charset);
! 628: }
! 629: }
! 630:
! 631: /**
! 632: * Returns the locale assigned to the response.
! 633: * @see #setLocale
! 634: */
! 635: public Locale getLocale() {
! 636: return locale;
! 637: }
! 638:
! 639: public void addHeader(String name, String value) {
! 640: String lname = name.toLowerCase();
! 641: HeaderValue hvalue = reply.getHeaderValue(lname);
! 642: //
! 643: // Horrible, Shame on us, I hate that
! 644: //
! 645: if (hvalue == null) {
! 646: setHeader(name, value);
! 647: } else if (hvalue instanceof HttpAcceptCharsetList) {
! 648: HttpAcceptCharsetList acl = (HttpAcceptCharsetList) hvalue;
! 649: acl.addCharset(HttpFactory.parseAcceptCharset(value));
! 650: } else if (hvalue instanceof HttpAcceptEncodingList) {
! 651: HttpAcceptEncodingList ael = (HttpAcceptEncodingList) hvalue;
! 652: ael.addEncoding(HttpFactory.parseAcceptEncoding(value));
! 653: } else if (hvalue instanceof HttpAcceptLanguageList) {
! 654: HttpAcceptLanguageList all = (HttpAcceptLanguageList) hvalue;
! 655: all.addLanguage(HttpFactory.parseAcceptLanguage(value));
! 656: } else if (hvalue instanceof HttpAcceptList) {
! 657: HttpAcceptList al = (HttpAcceptList) hvalue;
! 658: al.addAccept(HttpFactory.parseAccept(value));
! 659: } else if (hvalue instanceof HttpEntityTagList) {
! 660: HttpEntityTagList etl = (HttpEntityTagList) hvalue;
! 661: etl.addTag(HttpFactory.parseETag(value));
! 662: } else if (hvalue instanceof HttpExtList) {
! 663: HttpExtList el = (HttpExtList) hvalue;
! 664: el.addHttpExt(new HttpExt(value, false));
! 665: } else if (hvalue instanceof HttpCookieList) {
! 666: // shouldn't be used, but who knows?
! 667: HttpCookieList cl = (HttpCookieList) hvalue;
! 668: HttpCookieList ncl = HttpFactory.parseCookieList(value);
! 669: HttpCookie scookies[] = ncl.getCookies();
! 670: for (int i = 0 ; i < scookies.length ; i++) {
! 671: HttpCookie cookie = scookies[i];
! 672: cl.addCookie(cookie.getName(), cookie.getValue());
! 673: }
! 674: } else if (hvalue instanceof HttpParamList) {
! 675: int idx = value.indexOf('=');
! 676: if (idx != -1) {
! 677: String pname = value.substring(0, idx);
! 678: String pvalue = value.substring(idx+1);
! 679: HttpParamList pl = (HttpParamList) hvalue;
! 680: pl.setParameter(pname, pvalue);
! 681: }
! 682: } else if (hvalue instanceof HttpRangeList) {
! 683: HttpRangeList rl = (HttpRangeList) hvalue;
! 684: rl.addRange(HttpFactory.parseRange(value));
! 685: } else if (hvalue instanceof HttpSetCookieList) {
! 686: HttpSetCookieList scl = (HttpSetCookieList) hvalue;
! 687: HttpSetCookieList nscl = HttpFactory.parseSetCookieList(value);
! 688: HttpSetCookie scookies[] = nscl.getSetCookies();
! 689: for (int i = 0 ; i < scookies.length ; i++) {
! 690: scl.addSetCookie(scookies[i]);
! 691: }
! 692: } else if (hvalue instanceof HttpTokenList) {
! 693: ((HttpTokenList) hvalue).addToken(value, true);
! 694: } else if (hvalue instanceof HttpWarningList) {
! 695: HttpWarningList wl = (HttpWarningList) hvalue;
! 696: wl.addWarning(HttpFactory.parseWarning(value));
! 697: } else if (hvalue instanceof HttpString) {
! 698: // this is the default type for unkown header
! 699: // we don't know what it is, so just append
! 700: HttpString s = (HttpString) hvalue;
! 701: String string = (String) s.getValue();
! 702: s.setValue(string+", "+value);
! 703: } else {
! 704: // not compliant with HTTP/1.1, override
! 705: setHeader(name, value);
! 706: }
! 707: }
! 708:
! 709: public void addDateHeader(String name, long date) {
! 710: addHeader(name, HttpFactory.makeDate(date).toExternalForm());
! 711: }
! 712:
! 713: public void addIntHeader(String name, int value) {
! 714: addHeader(name, String.valueOf(value));
! 715: }
! 716:
1.13 bmahe 717: JigsawHttpServletResponse(Request request, Reply reply) {
1.33 ! bmahe 718: this.request = request;
! 719: this.reply = reply;
! 720: this.buffer_size = DEFAULT_BUFFER_SIZE;
1.11 bmahe 721: }
1.6 bmahe 722:
1.1 abaird 723: }
Webmaster