Source Code Cross Referenced for JigsawHttpServletResponse.java in  » Web-Server » Jigsaw » org » w3c » jigsaw » servlet » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Jigsaw » org.w3c.jigsaw.servlet 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // JigsawHttpServletReponse.java
002:        // $Id: JigsawHttpServletResponse.java,v 1.53 2003/02/04 16:21:43 ylafon Exp $
003:        // (c) COPYRIGHT MIT and INRIA, 1996.
004:        // Please first read the full copyright statement in file COPYRIGHT.html
005:
006:        package org.w3c.jigsaw.servlet;
007:
008:        import java.io.ByteArrayOutputStream;
009:        import java.io.DataOutputStream;
010:        import java.io.IOException;
011:        import java.io.OutputStream;
012:        import java.io.OutputStreamWriter;
013:        import java.io.PipedOutputStream;
014:        import java.io.PrintWriter;
015:        import java.io.UnsupportedEncodingException;
016:
017:        import javax.servlet.ServletOutputStream;
018:
019:        import javax.servlet.http.Cookie;
020:        import javax.servlet.http.HttpServletResponse;
021:        import javax.servlet.http.HttpSession;
022:
023:        import java.net.MalformedURLException;
024:        import java.net.URL;
025:
026:        import java.util.Locale;
027:
028:        import org.w3c.www.mime.MimeType;
029:        import org.w3c.www.mime.MimeTypeFormatException;
030:        import org.w3c.www.mime.Utils;
031:
032:        import org.w3c.www.http.BasicValue;
033:        import org.w3c.www.http.HttpAcceptCharsetList;
034:        import org.w3c.www.http.HttpAcceptEncodingList;
035:        import org.w3c.www.http.HttpAcceptLanguageList;
036:        import org.w3c.www.http.HttpAcceptList;
037:        import org.w3c.www.http.HttpCookie;
038:        import org.w3c.www.http.HttpCookieList;
039:        import org.w3c.www.http.HttpEntityMessage;
040:        import org.w3c.www.http.HttpEntityTagList;
041:        import org.w3c.www.http.HttpExt;
042:        import org.w3c.www.http.HttpExtList;
043:        import org.w3c.www.http.HttpFactory;
044:        import org.w3c.www.http.HttpMessage;
045:        import org.w3c.www.http.HttpParamList;
046:        import org.w3c.www.http.HttpRangeList;
047:        import org.w3c.www.http.HttpReplyMessage;
048:        import org.w3c.www.http.HttpRequestMessage;
049:        import org.w3c.www.http.HttpSetCookie;
050:        import org.w3c.www.http.HttpSetCookieList;
051:        import org.w3c.www.http.HttpString;
052:        import org.w3c.www.http.HttpTokenList;
053:        import org.w3c.www.http.HttpWarningList;
054:
055:        import org.w3c.jigsaw.html.HtmlGenerator;
056:
057:        import org.w3c.jigsaw.http.Reply;
058:        import org.w3c.jigsaw.http.Request;
059:
060:        import org.w3c.www.http.HeaderValue;
061:
062:        /**
063:         * @author Alexandre Rafalovitch <alex@access.com.au>
064:         * @author Anselm Baird-Smith <abaird@w3.org>
065:         * @author Benoît Mahé (bmahe@w3.org)
066:         * @author Roland Mainz (Roland.Mainz@informatik.med.uni-giessen.de)
067:         */
068:
069:        public class JigsawHttpServletResponse implements  HttpServletResponse {
070:
071:            public final static String CHARSET_PARAMETER = "charset";
072:
073:            public final static int DEFAULT_BUFFER_SIZE = 8 * 1024; // 8KB buffer
074:            public final static int MIN_BUFFER_SIZE = 4 * 1024; // 4KB buffer
075:
076:            private final static int STATE_INITIAL = 0;
077:            private final static int STATE_HEADERS_DONE = 1;
078:            private final static int STATE_ALL_DONE = 2;
079:
080:            private final static int STREAM_STATE_INITIAL = 0;
081:            private final static int STREAM_WRITER_USED = 1;
082:            private final static int OUTPUT_STREAM_USED = 2;
083:
084:            private int stream_state = STREAM_STATE_INITIAL;
085:
086:            private JigsawServletOutputStream output = null;
087:            private PrintWriter writer = null;
088:
089:            private MimeTypeFormatException setContentTypeException = null;
090:
091:            // servlet has set a fixed content length or not, 
092:            // and cut (see flushStream) any data which are too much here...
093:            private final static int CALC_CONTENT_LENGTH = -1;
094:            private int fixedContentLength = CALC_CONTENT_LENGTH;
095:
096:            // Our Locale
097:            protected Locale locale;
098:
099:            /**
100:             * Our temp stream.
101:             */
102:            protected ByteArrayOutputStream out = null;
103:            protected PipedOutputStream pout = null;
104:
105:            protected JigsawHttpServletRequest jrequest = null;
106:
107:            protected int buffer_size;
108:
109:            protected void setServletRequest(JigsawHttpServletRequest jrequest) {
110:                this .jrequest = jrequest;
111:            }
112:
113:            public static final String INCLUDED = "org.w3c.jigsaw.servlet.included";
114:            public static final String STREAM = "org.w3c.jigsaw.servlet.stream";
115:            public static final String MONITOR = "org.w3c.jigsaw.servlet.monitor";
116:
117:            int state = STATE_INITIAL;
118:            Reply reply = null;
119:            Request request = null;
120:
121:            /**
122:             * Sets the content length for this response. 
123:             * @param len - the content length 
124:             */
125:            public void setContentLength(int i) {
126:                fixedContentLength = i;
127:                reply.setContentLength(i);
128:            }
129:
130:            /**
131:             * Sets the content type for this response. This type may later be 
132:             * implicitly modified by addition of properties such as the MIME
133:             * charset=<value> if the service finds it necessary, and the appropriate
134:             * media type property has not been set.
135:             * <p>This response property may only be assigned one time. If a writer 
136:             * is to be used to write a text response, this method must be
137:             * called before the method getWriter. If an output stream will be used 
138:             * to write a response, this method must be called before the
139:             * output stream is used to write response data. 
140:             * @param spec - the content's MIME type 
141:             * @see JigsawHttpServletResponse#getOutputStream
142:             * @see JigsawHttpServletResponse#getWriter
143:             */
144:            public void setContentType(String spec) {
145:                try {
146:                    MimeType type = new MimeType(spec);
147:                    reply.setContentType(type);
148:                    setContentTypeException = null;
149:                } catch (MimeTypeFormatException ex) {
150:                    //store exception
151:                    setContentTypeException = ex;
152:                }
153:            }
154:
155:            protected boolean isStreamObtained() {
156:                return (stream_state != STREAM_STATE_INITIAL);
157:            }
158:
159:            protected Reply getReply() {
160:                return reply;
161:            }
162:
163:            /**
164:             * Returns an output stream for writing binary response data.
165:             * @return A ServletOutputStream
166:             * @exception IOException if an I/O exception has occurred 
167:             * @exception IllegalStateException if getWriter has been called on this 
168:             * same request. 
169:             * @see JigsawHttpServletResponse#getWriter
170:             */
171:            public synchronized ServletOutputStream getOutputStream()
172:                    throws IOException {
173:                if (stream_state == STREAM_WRITER_USED) {
174:                    // obviously output is not null, but it doesn't cost...
175:                    if ((output != null) && output.isCommitted()) {
176:                        throw new IllegalStateException("Writer used");
177:                    }
178:                    output.reset();
179:                }
180:                stream_state = OUTPUT_STREAM_USED;
181:                return getJigsawOutputStream(false);
182:            }
183:
184:            /** 
185:             * returns the raw output stream regardless of what happened before
186:             * used for internal operation (e.g. writing an exception trailer).
187:             * @return an underlying output stream if available (even when a writer is
188:             * used)
189:             */
190:
191:            protected synchronized OutputStream getRawOutputStream() {
192:                return output;
193:            }
194:
195:            synchronized ServletOutputStream getJigsawOutputStream(
196:                    boolean writerUsed) throws IOException {
197:                if (output != null)
198:                    return output;
199:
200:                if (state == STATE_ALL_DONE) {
201:                    throw new IOException("Processing finished");
202:                }
203:                // any exception during setContentType ?    
204:                if (setContentTypeException != null) {
205:                    // "wrap" the exception from setContentType in an IOException
206:                    throw new IOException("Illegal Content Type: "
207:                            + setContentTypeException.toString());
208:                }
209:
210:                if (request.hasState(INCLUDED)) {
211:                    out = new ByteArrayOutputStream();
212:                    output = new JigsawServletOutputStream(this ,
213:                            new DataOutputStream(out), buffer_size, writerUsed);
214:                    reply.setState(STREAM, new Object());
215:                } else {
216:                    if (reply.hasState(STREAM)) {
217:                        try {
218:                            pout = (PipedOutputStream) reply.getState(STREAM);
219:                            DataOutputStream dos = new DataOutputStream(pout);
220:                            output = new JigsawServletOutputStream(this , dos,
221:                                    buffer_size, writerUsed);
222:                            reply.setState(STREAM, null);
223:                        } catch (ClassCastException ex) {
224:                            // it is null, no OutputStream -> redirect done
225:                            // we will eat this anyway
226:                            output = new JigsawServletOutputStream(this , reply,
227:                                    buffer_size, writerUsed);
228:                            reply.setState(STREAM, new Object());
229:                        }
230:                    } else {
231:                        output = new JigsawServletOutputStream(this , reply,
232:                                buffer_size, writerUsed);
233:                        reply.setState(STREAM, new Object());
234:                    }
235:                }
236:                return output;
237:            }
238:
239:            synchronized void notifyClient() {
240:                Object o = reply.getState(MONITOR);
241:                if (o != null) {
242:                    synchronized (o) {
243:                        o.notifyAll();
244:                    }
245:                }
246:            }
247:
248:            /**
249:             * Sets the status code and message for this response. If the field had
250:             * already been set, the new value overwrites the previous one. The message
251:             * is sent as the body of an HTML page, which is returned to the user to
252:             * describe the problem. The page is sent with a default HTML header; the
253:             * message is enclosed in simple body tags (<body></body>).
254:             * @param i - the status code 
255:             * @param reason - the status message
256:             * @deprecated since jsdk2.1
257:             */
258:            public void setStatus(int i, String reason) {
259:                reply.setStatus(i);
260:                reply.setReason(reason);
261:            }
262:
263:            /**
264:             * Sets the status code for this response. This method is used to set the
265:             * return status code when there is no error (for example, for the status
266:             * codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error, the 
267:             * sendError method should be used instead.
268:             * @param i - the status code 
269:             * @see JigsawHttpServletResponse#sendError
270:             */
271:            public void setStatus(int i) {
272:                setStatus(i, reply.getStandardReason(i));
273:            }
274:
275:            /**
276:             * Adds a field to the response header with the given name and value. If
277:             * the field had already been set, the new value overwrites the previous
278:             * one. The containsHeader method can be used to test for the presence of a
279:             * header before setting its value.
280:             * @param name - the name of the header field 
281:             * @param value - the header field's value 
282:             * @see JigsawHttpServletResponse#containsHeader
283:             */
284:            public void setHeader(String name, String value) {
285:                reply.setValue(name, value);
286:            }
287:
288:            /**
289:             * Adds a field to the response header with the given name and integer
290:             * value. If the field had already been set, the new value overwrites the
291:             * previous one. The containsHeader method can be used to test for the
292:             * presence of a header before setting its value.
293:             * @param name - the name of the header field 
294:             * @param value - the header field's integer value 
295:             * @see JigsawHttpServletResponse#containsHeader
296:             */
297:            public void setIntHeader(String name, int value) {
298:                setHeader(name, String.valueOf(value));
299:            }
300:
301:            /**
302:             * Adds a field to the response header with the given name and date-valued
303:             * field. The date is specified in terms of milliseconds since the epoch. 
304:             * If the date field had already been set, the new value overwrites the
305:             * previous one. The containsHeader method can be used to test for the
306:             * presence of a header before setting its value.
307:             * @param name - the name of the header field 
308:             * @param value - the header field's date value 
309:             * @see JigsawHttpServletResponse#containsHeader 
310:             */
311:            public void setDateHeader(String name, long date) {
312:                setHeader(name, HttpFactory.makeDate(date).toExternalForm());
313:            }
314:
315:            public void unsetHeader(String name) {
316:                setHeader(name, null);
317:            }
318:
319:            /**
320:             * Sends an error response to the client using the specified status code
321:             * and descriptive message. If setStatus has previously been called, it is
322:             * reset to the error status code. The message is sent as the body of an
323:             * HTML page, which is returned to the user to describe the problem. The
324:             * page is sent with a default HTML header; the message is enclosed in
325:             * simple body tags (<body></body>).
326:             * @param sc - the status code 
327:             * @param msg - the detail message 
328:             * @exception IOException If an I/O error has occurred.
329:             */
330:            public synchronized void sendError(int i, String msg)
331:                    throws IOException {
332:                if (isStreamObtained() && (output != null)
333:                        && output.isCommitted()) {
334:                    throw new IOException("Reply already started in servlet");
335:                }
336:                if (output != null) {
337:                    output.reset();
338:                }
339:                setStatus(i);
340:                reply.setContent(msg);
341:                state = STATE_ALL_DONE;
342:                reply.setState(STREAM, new Object());
343:                notifyClient();
344:            }
345:
346:            /**
347:             * Sends an error response to the client using the specified status 
348:             * code and a default message. 
349:             * @param sc - the status code 
350:             * @exception IOException If an I/O error has occurred.
351:             */
352:            public synchronized void sendError(int i) throws IOException {
353:                sendError(i, reply.getStandardReason(i));
354:            }
355:
356:            /**
357:             * Sends a temporary redirect response to the client using the specified
358:             *  redirect location URL. The URL must be absolute (for example, 
359:             * https://hostname/path/file.html). Relative URLs are not permitted here. 
360:             * @param url - the redirect location URL 
361:             * @exception IOException If an I/O error has occurred. 
362:             */
363:            public synchronized void sendRedirect(String url)
364:                    throws IOException {
365:                URL loc = null;
366:                if (isStreamObtained() && (output != null)
367:                        && output.isCommitted()) {
368:                    throw new IOException("Reply already started in servlet");
369:                }
370:                if (output != null) {
371:                    output.reset();
372:                }
373:                try {
374:                    String requri = jrequest.getRequestURI();
375:                    URL requrl = request.getURL();
376:                    loc = new URL(requrl.getProtocol(), requrl.getHost(),
377:                            requrl.getPort(), requri);
378:                    loc = new URL(loc, url);
379:                    //  Removed (netscape doesn't know SEE OTHER! sig)
380:                    // 	    if (jrequest.getMethod().equalsIgnoreCase("POST") &&
381:                    // 		jrequest.getProtocol().equals("HTTP/1.1")) {
382:                    // 		setStatus(SC_SEE_OTHER);
383:                    // 	    } else {
384:                    setStatus(SC_MOVED_TEMPORARILY);
385:                    //	    }
386:                    reply.setLocation(loc);
387:                    HtmlGenerator g = new HtmlGenerator("Moved");
388:                    g
389:                            .append("<P>This resource has moved, click on the link if your"
390:                                    + " browser doesn't support automatic redirection<BR>"
391:                                    + "<A HREF=\""
392:                                    + loc.toExternalForm()
393:                                    + "\">" + loc.toExternalForm() + "</A>");
394:                    reply.setStream(g);
395:                } catch (Exception ex) {
396:                    ex.printStackTrace();
397:                } finally {
398:                    state = STATE_ALL_DONE;
399:                    reply.setState(STREAM, new Object());
400:                    notifyClient();
401:                }
402:            }
403:
404:            /**
405:             * Checks whether the response message header has a field with the
406:             * specified name. 
407:             * @param name - the header field name 
408:             * @return true if the response message header has a field with the 
409:             * specified name; false otherwise
410:             */
411:            public boolean containsHeader(String header) {
412:                return reply.hasHeader(header);
413:            }
414:
415:            /**
416:             * Adds the specified cookie to the response. It can be called multiple 
417:             * times to set more than one cookie. 
418:             * @param cookie - the Cookie to return to the client 
419:             */
420:            public void addCookie(Cookie cookie) {
421:                HttpSetCookieList clist = reply.getSetCookie();
422:                if (clist == null) {
423:                    HttpSetCookie cookies[] = new HttpSetCookie[1];
424:                    cookies[0] = convertCookie(cookie);
425:                    clist = new HttpSetCookieList(cookies);
426:                } else {
427:                    clist.addSetCookie(convertCookie(cookie));
428:                }
429:                reply.setSetCookie(clist);
430:            }
431:
432:            private HttpSetCookie convertCookie(Cookie cookie) {
433:                HttpSetCookie scookie = new HttpSetCookie(true, cookie
434:                        .getName(), cookie.getValue());
435:                scookie.setComment(cookie.getComment());
436:                scookie.setDomain(cookie.getDomain());
437:                scookie.setMaxAge(cookie.getMaxAge());
438:                scookie.setPath(cookie.getPath());
439:                scookie.setSecurity(cookie.getSecure());
440:                scookie.setVersion(cookie.getVersion());
441:                return scookie;
442:            }
443:
444:            /**
445:             * Encodes the specified URL for use in the sendRedirect method or, if 
446:             * encoding is not needed, returns the URL unchanged. The implementation 
447:             * of this method should include the logic to determine whether the 
448:             * session ID needs to be encoded in the URL.
449:             * Because the rules for making this determination differ from those used
450:             * to decide whether to encode a normal link, this method is seperate from
451:             * the encodeUrl method.
452:             * <p>All URLs sent to the HttpServletResponse.sendRedirect method should
453:             * be run through this method. Otherwise, URL rewriting canont be used 
454:             * with browsers which do not support cookies. 
455:             * @param url - the url to be encoded. 
456:             * @return the encoded URL if encoding is needed; the unchanged URL 
457:             * otherwise. 
458:             * @deprecated since jsdk2.1
459:             * @see JigsawHttpServletResponse#sendRedirect
460:             * @see JigsawHttpServletResponse#encodeUrl
461:             */
462:            public String encodeRedirectUrl(String url) {
463:                try {
464:                    URL redirect = new URL(url);
465:                    URL requested = new URL(jrequest.getRequestURI());
466:                    if (redirect.getHost().equals(requested.getHost())
467:                            && redirect.getPort() == requested.getPort())
468:                        return encodeUrl(url);
469:                } catch (MalformedURLException ex) {
470:                    //error so return url.
471:                    return url;
472:                }
473:                return url;
474:            }
475:
476:            /**
477:             * Encodes the specified URL for use in the sendRedirect method or, if 
478:             * encoding is not needed, returns the URL unchanged. The implementation 
479:             * of this method should include the logic to determine whether the 
480:             * session ID needs to be encoded in the URL.
481:             * Because the rules for making this determination differ from those used
482:             * to decide whether to encode a normal link, this method is seperate from
483:             * the encodeUrl method.
484:             * <p>All URLs sent to the HttpServletResponse.sendRedirect method should
485:             * be run through this method. Otherwise, URL rewriting canont be used 
486:             * with browsers which do not support cookies. 
487:             * @param url - the url to be encoded. 
488:             * @return the encoded URL if encoding is needed; the unchanged URL 
489:             * otherwise. 
490:             * @see JigsawHttpServletResponse#sendRedirect
491:             * @see JigsawHttpServletResponse#encodeUrl
492:             */
493:            public String encodeRedirectURL(String url) {
494:                return encodeRedirectUrl(url);
495:            }
496:
497:            /**
498:             * Encodes the specified URL by including the session ID in it, or, if 
499:             * encoding is not needed, returns the URL unchanged. The implementation of
500:             * this method should include the logic to determine whether the session ID
501:             * needs to be encoded in the URL. For example, if the browser supports
502:             * cookies, or session tracking is turned off, URL encoding is unnecessary.
503:             * <p>All URLs emitted by a Servlet should be run through this method. 
504:             * Otherwise, URL rewriting cannot be used with browsers which do not 
505:             * support cookies.
506:             * @param url - the url to be encoded. 
507:             * @return the encoded URL if encoding is needed; the unchanged URL 
508:             * otherwise. 
509:             * @deprecated since jsdk2.1
510:             */
511:            public String encodeUrl(String url) {
512:                if (!jrequest.isRequestedSessionIdFromCookie()) {
513:                    url = url + ((url.indexOf("?") != -1) ? "&" : "?")
514:                            + jrequest.getCookieName() + "="
515:                            + jrequest.getSession(true).getId();
516:                }
517:                return url;
518:            }
519:
520:            /**
521:             * Encodes the specified URL by including the session ID in it, or, if 
522:             * encoding is not needed, returns the URL unchanged. The implementation of
523:             * this method should include the logic to determine whether the session ID
524:             * needs to be encoded in the URL. For example, if the browser supports
525:             * cookies, or session tracking is turned off, URL encoding is unnecessary.
526:             * <p>All URLs emitted by a Servlet should be run through this method. 
527:             * Otherwise, URL rewriting cannot be used with browsers which do not 
528:             * support cookies.
529:             * @param url - the url to be encoded. 
530:             * @return the encoded URL if encoding is needed; the unchanged URL 
531:             * otherwise. 
532:             */
533:            public String encodeURL(String url) {
534:                return encodeUrl(url);
535:            }
536:
537:            /**
538:             * Return the Charset parameter of content type
539:             * @return A String instance
540:             */
541:            public String getCharacterEncoding() {
542:                org.w3c.www.mime.MimeType type = reply.getContentType();
543:                if ((type != null) && (type.hasParameter(CHARSET_PARAMETER))) {
544:                    return type.getParameterValue(CHARSET_PARAMETER);
545:                }
546:                // as specified in the javadoc, default to iso-8859-1
547:                return "ISO-8859-1".intern();
548:            }
549:
550:            /**
551:             * Returns a print writer for writing formatted text responses. 
552:             * The MIME type of the response will be modified, if necessary, to
553:             * reflect the character encoding used, through the charset=... property. 
554:             * This means that the content type must be set before calling this 
555:             * method. 
556:             * @exception UnsupportedEncodingException if no such encoding can be 
557:             * provided 
558:             * @exception IllegalStateException if getOutputStream has been called 
559:             * on this same request.
560:             * @exception IOException on other errors. 
561:             * @see JigsawHttpServletResponse#getOutputStream
562:             * @see JigsawHttpServletResponse#setContentType 
563:             */
564:            public synchronized PrintWriter getWriter() throws IOException,
565:                    UnsupportedEncodingException {
566:                if (stream_state == OUTPUT_STREAM_USED) {
567:                    // obviously output is not null, but it doesn't cost...
568:                    if ((output != null) && output.isCommitted()) {
569:                        throw new IllegalStateException("Output stream used");
570:                    }
571:                    output.reset();
572:                }
573:
574:                stream_state = STREAM_WRITER_USED;
575:
576:                if (writer == null) {
577:                    writer = new PrintWriter(
578:                            new OutputStreamWriter(getJigsawOutputStream(true),
579:                                    getCharacterEncoding()));
580:                }
581:                return writer;
582:            }
583:
584:            /**
585:             * Flush the output stream.
586:             * @param close Close the stream if true.
587:             * @exception IOException if an IO error occurs.
588:             */
589:            protected synchronized void flushStream(boolean close)
590:                    throws IOException {
591:                if (state == STATE_ALL_DONE) {
592:                    return;
593:                }
594:                int writeLength;
595:
596:                if (stream_state == OUTPUT_STREAM_USED) {
597:                    output.flush();
598:                } else if (stream_state == STREAM_WRITER_USED) {
599:                    writer.flush();
600:                    if (close) {
601:                        output.realFlush();
602:                    } else {
603:                        output.flush();
604:                    }
605:                } else {
606:                    // force flush even if no stream are openned
607:                    getWriter();
608:                    writer.flush();
609:                    output.realFlush();
610:                }
611:
612:                if (request.hasState(INCLUDED)) {
613:                    if (out == null)
614:                        return;
615:
616:                    if (fixedContentLength != CALC_CONTENT_LENGTH) {
617:                        writeLength = (out.size() < fixedContentLength) ? (out
618:                                .size()) : (fixedContentLength);
619:                    } else {
620:                        writeLength = out.size();
621:                    }
622:                    reply.setContentLength(writeLength);
623:
624:                    OutputStream rout = reply.getOutputStream(false);
625:                    byte content[] = out.toByteArray();
626:                    if (close)
627:                        out.close();
628:                    else
629:                        out.reset();
630:                    rout.write(content);
631:                    rout.flush();
632:                } else {
633:                    if ((pout != null) && close) {
634:                        pout.flush();
635:                        pout.close();
636:                    }
637:                }
638:            }
639:
640:            // 2.2
641:
642:            /**
643:             * Sets the preferred buffer size for the body of the response.  
644:             * The servlet container will use a buffer at least as large as 
645:             * the size requested.  The actual buffer size used can be found
646:             * using <code>getBufferSize</code>.
647:             *
648:             * <p>A larger buffer allows more content to be written before anything is
649:             * actually sent, thus providing the servlet with more time to set
650:             * appropriate status codes and headers.  A smaller buffer decreases 
651:             * server memory load and allows the client to start receiving data more
652:             * quickly.
653:             *
654:             * <p>This method must be called before any response body content is
655:             * written; if content has been written, this method throws an 
656:             * <code>IllegalStateException</code>.
657:             * @param size the preferred buffer size
658:             * @exception IllegalStateException	if this method is called after
659:             * content has been written
660:             * @see #getBufferSize
661:             * @see #flushBuffer
662:             * @see #isCommitted
663:             * @see #reset
664:             */
665:            public void setBufferSize(int size) {
666:                if (stream_state != STREAM_STATE_INITIAL) {
667:                    throw new IllegalStateException(
668:                            "Stream already initialized");
669:                }
670:                buffer_size = size < MIN_BUFFER_SIZE ? MIN_BUFFER_SIZE : size;
671:            }
672:
673:            /**
674:             * Returns the actual buffer size used for the response.  If no buffering
675:             * is used, this method returns 0.
676:             * @return the actual buffer size used
677:             * @see #setBufferSize
678:             * @see #flushBuffer
679:             * @see #isCommitted
680:             * @see #reset
681:             */
682:            public int getBufferSize() {
683:                return buffer_size;
684:            }
685:
686:            /**
687:             * Forces any content in the buffer to be written to the client.  A call
688:             * to this method automatically commits the response, meaning the status 
689:             * code and headers will be written.
690:             * @see #setBufferSize
691:             * @see #getBufferSize
692:             * @see #isCommitted
693:             * @see #reset
694:             */
695:            public void flushBuffer() throws IOException {
696:                if (output != null) {
697:                    if (stream_state == STREAM_WRITER_USED) {
698:                        writer.flush();
699:                    }
700:                    output.flush();
701:                }
702:            }
703:
704:            /**
705:             * Returns a boolean indicating if the response has been
706:             * committed.  A commited response has already had its status 
707:             * code and headers written.
708:             * @return a boolean indicating if the response has been
709:             * committed
710:             * @see #setBufferSize
711:             * @see #getBufferSize
712:             * @see #flushBuffer
713:             * @see #reset
714:             */
715:            public boolean isCommitted() {
716:                if (output != null) {
717:                    return output.isCommitted();
718:                } else {
719:                    return false;
720:                }
721:            }
722:
723:            /**
724:             * Clears any data that exists in the buffer as well as the status code and
725:             * headers.  If the response has been committed, this method throws an 
726:             * <code>IllegalStateException</code>.
727:             * @exception IllegalStateException  if the response has already been
728:             *                                   committed
729:             * @see #setBufferSize
730:             * @see #getBufferSize
731:             * @see #flushBuffer
732:             * @see #isCommitted
733:             */
734:            public void reset() {
735:                // FIXME needs to clear headers and status
736:                if (output != null) {
737:                    if (stream_state == STREAM_WRITER_USED) {
738:                        writer.flush();
739:                    }
740:                    output.reset();
741:                }
742:            }
743:
744:            /**
745:             * Clears any data that exists in the buffer but not status code and 
746:             * headers.  If the response has been committed, this method throws an 
747:             * <code>IllegalStateException</code>.
748:             * @exception IllegalStateException  if the response has already been
749:             *                                   committed
750:             * @see #setBufferSize
751:             * @see #getBufferSize
752:             * @see #flushBuffer
753:             * @see #isCommitted
754:             */
755:            public void resetBuffer() {
756:                if (output != null) {
757:                    if (stream_state == STREAM_WRITER_USED) {
758:                        writer.flush();
759:                    }
760:                    output.reset();
761:                }
762:            }
763:
764:            /**
765:             * Sets the locale of the response, setting the headers (including the
766:             * Content-Type's charset) as appropriate.  This method should be called
767:             * before a call to {@link #getWriter}.  By default, the response locale
768:             * is the default locale for the server.
769:             * @param loc  the locale of the response
770:             * @see #getLocale
771:             */
772:            public void setLocale(Locale locale) {
773:                if (locale == null) {
774:                    return;
775:                }
776:                this .locale = locale;
777:
778:                // content language
779:                String lang = locale.getLanguage();
780:                if (lang.length() > 0) {
781:                    String array[] = new String[1];
782:                    array[0] = lang;
783:                    reply.setContentLanguage(array);
784:                }
785:
786:                // content type (charset)
787:                String charset = org.w3c.www.mime.Utils.getCharset(locale);
788:                if (charset != null) {
789:                    MimeType contentType = reply.getContentType();
790:                    // override charset
791:                    contentType.setParameter(CHARSET_PARAMETER, charset);
792:                }
793:            }
794:
795:            /**
796:             * Returns the locale assigned to the response.
797:             * @see #setLocale
798:             */
799:            public Locale getLocale() {
800:                return locale;
801:            }
802:
803:            public void addHeader(String name, String value) {
804:                String lname = name.toLowerCase();
805:                HeaderValue hvalue = reply.getHeaderValue(lname);
806:                //
807:                // Horrible, Shame on us, I hate that
808:                //
809:                if (hvalue == null) {
810:                    setHeader(name, value);
811:                } else if (hvalue instanceof  HttpAcceptCharsetList) {
812:                    HttpAcceptCharsetList acl = (HttpAcceptCharsetList) hvalue;
813:                    acl.addCharset(HttpFactory.parseAcceptCharset(value));
814:                } else if (hvalue instanceof  HttpAcceptEncodingList) {
815:                    HttpAcceptEncodingList ael = (HttpAcceptEncodingList) hvalue;
816:                    ael.addEncoding(HttpFactory.parseAcceptEncoding(value));
817:                } else if (hvalue instanceof  HttpAcceptLanguageList) {
818:                    HttpAcceptLanguageList all = (HttpAcceptLanguageList) hvalue;
819:                    all.addLanguage(HttpFactory.parseAcceptLanguage(value));
820:                } else if (hvalue instanceof  HttpAcceptList) {
821:                    HttpAcceptList al = (HttpAcceptList) hvalue;
822:                    al.addAccept(HttpFactory.parseAccept(value));
823:                } else if (hvalue instanceof  HttpEntityTagList) {
824:                    HttpEntityTagList etl = (HttpEntityTagList) hvalue;
825:                    etl.addTag(HttpFactory.parseETag(value));
826:                } else if (hvalue instanceof  HttpExtList) {
827:                    HttpExtList el = (HttpExtList) hvalue;
828:                    el.addHttpExt(new HttpExt(value, false));
829:                } else if (hvalue instanceof  HttpCookieList) {
830:                    // shouldn't be used, but who knows?
831:                    HttpCookieList cl = (HttpCookieList) hvalue;
832:                    HttpCookieList ncl = HttpFactory.parseCookieList(value);
833:                    HttpCookie scookies[] = ncl.getCookies();
834:                    for (int i = 0; i < scookies.length; i++) {
835:                        HttpCookie cookie = scookies[i];
836:                        cl.addCookie(cookie.getName(), cookie.getValue());
837:                    }
838:                } else if (hvalue instanceof  HttpParamList) {
839:                    int idx = value.indexOf('=');
840:                    if (idx != -1) {
841:                        String pname = value.substring(0, idx);
842:                        String pvalue = value.substring(idx + 1);
843:                        HttpParamList pl = (HttpParamList) hvalue;
844:                        pl.setParameter(pname, pvalue);
845:                    }
846:                } else if (hvalue instanceof  HttpRangeList) {
847:                    HttpRangeList rl = (HttpRangeList) hvalue;
848:                    rl.addRange(HttpFactory.parseRange(value));
849:                } else if (hvalue instanceof  HttpSetCookieList) {
850:                    HttpSetCookieList scl = (HttpSetCookieList) hvalue;
851:                    HttpSetCookieList nscl = HttpFactory
852:                            .parseSetCookieList(value);
853:                    HttpSetCookie scookies[] = nscl.getSetCookies();
854:                    for (int i = 0; i < scookies.length; i++) {
855:                        scl.addSetCookie(scookies[i]);
856:                    }
857:                } else if (hvalue instanceof  HttpTokenList) {
858:                    ((HttpTokenList) hvalue).addToken(value, true);
859:                } else if (hvalue instanceof  HttpWarningList) {
860:                    HttpWarningList wl = (HttpWarningList) hvalue;
861:                    wl.addWarning(HttpFactory.parseWarning(value));
862:                } else if (hvalue instanceof  HttpString) {
863:                    // this is the default type for unkown header
864:                    // we don't know what it is, so just append
865:                    HttpString s = (HttpString) hvalue;
866:                    String string = (String) s.getValue();
867:                    s.setValue(string + ", " + value);
868:                } else {
869:                    // not compliant with HTTP/1.1, override
870:                    setHeader(name, value);
871:                }
872:            }
873:
874:            public void addDateHeader(String name, long date) {
875:                addHeader(name, HttpFactory.makeDate(date).toExternalForm());
876:            }
877:
878:            public void addIntHeader(String name, int value) {
879:                addHeader(name, String.valueOf(value));
880:            }
881:
882:            JigsawHttpServletResponse(Request request, Reply reply) {
883:                this.request = request;
884:                this.reply = reply;
885:                this.buffer_size = DEFAULT_BUFFER_SIZE;
886:            }
887:
888:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.