1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server;
15
16 import java.io.IOException;
17 import java.io.PrintWriter;
18 import java.util.Collections;
19 import java.util.Enumeration;
20 import java.util.Locale;
21
22 import javax.servlet.ServletOutputStream;
23 import javax.servlet.http.Cookie;
24 import javax.servlet.http.HttpServletResponse;
25 import javax.servlet.http.HttpSession;
26
27 import org.eclipse.jetty.http.HttpCookie;
28 import org.eclipse.jetty.http.HttpFields;
29 import org.eclipse.jetty.http.HttpGenerator;
30 import org.eclipse.jetty.http.HttpHeaderValues;
31 import org.eclipse.jetty.http.HttpHeaders;
32 import org.eclipse.jetty.http.HttpSchemes;
33 import org.eclipse.jetty.http.HttpStatus;
34 import org.eclipse.jetty.http.HttpURI;
35 import org.eclipse.jetty.http.HttpVersions;
36 import org.eclipse.jetty.http.MimeTypes;
37 import org.eclipse.jetty.io.BufferCache.CachedBuffer;
38 import org.eclipse.jetty.server.handler.ContextHandler;
39 import org.eclipse.jetty.server.handler.ErrorHandler;
40 import org.eclipse.jetty.util.ByteArrayISO8859Writer;
41 import org.eclipse.jetty.util.QuotedStringTokenizer;
42 import org.eclipse.jetty.util.StringUtil;
43 import org.eclipse.jetty.util.URIUtil;
44 import org.eclipse.jetty.util.log.Log;
45 import org.eclipse.jetty.util.log.Logger;
46
47
48
49
50
51
52 public class Response implements HttpServletResponse
53 {
54 private static final Logger LOG = Log.getLogger(Response.class);
55
56 public static final int
57 NONE=0,
58 STREAM=1,
59 WRITER=2;
60
61
62
63
64
65
66 public final static String SET_INCLUDE_HEADER_PREFIX = "org.eclipse.jetty.server.include.";
67
68 private final HttpConnection _connection;
69 private int _status=SC_OK;
70 private String _reason;
71 private Locale _locale;
72 private String _mimeType;
73 private CachedBuffer _cachedMimeType;
74 private String _characterEncoding;
75 private boolean _explicitEncoding;
76 private String _contentType;
77 private int _outputState;
78 private PrintWriter _writer;
79
80
81
82
83
84 public Response(HttpConnection connection)
85 {
86 _connection=connection;
87 }
88
89
90
91
92
93
94 protected void recycle()
95 {
96 _status=SC_OK;
97 _reason=null;
98 _locale=null;
99 _mimeType=null;
100 _cachedMimeType=null;
101 _characterEncoding=null;
102 _explicitEncoding=false;
103 _contentType=null;
104 _outputState=NONE;
105 _writer=null;
106 }
107
108
109
110
111
112 public void addCookie(HttpCookie cookie)
113 {
114 _connection.getResponseFields().addSetCookie(cookie);
115 }
116
117
118
119
120
121 public void addCookie(Cookie cookie)
122 {
123 _connection.getResponseFields().addSetCookie(cookie.getName(),
124 cookie.getValue(),
125 cookie.getDomain(),
126 cookie.getPath(),
127 cookie.getMaxAge(),
128 cookie.getComment(),
129 cookie.getSecure(),
130 false,
131 cookie.getVersion());
132 }
133
134
135
136
137
138 public boolean containsHeader(String name)
139 {
140 return _connection.getResponseFields().containsKey(name);
141 }
142
143
144
145
146
147 public String encodeURL(String url)
148 {
149 final Request request=_connection.getRequest();
150 SessionManager sessionManager = request.getSessionManager();
151 if (sessionManager==null)
152 return url;
153
154 HttpURI uri = null;
155 if (sessionManager.isCheckingRemoteSessionIdEncoding() && URIUtil.hasScheme(url))
156 {
157 uri = new HttpURI(url);
158 String path = uri.getPath();
159 path = (path == null?"":path);
160 int port=uri.getPort();
161 if (port<0)
162 port = HttpSchemes.HTTPS.equalsIgnoreCase(uri.getScheme())?443:80;
163 if (!request.getServerName().equalsIgnoreCase(uri.getHost()) ||
164 request.getServerPort()!=port ||
165 !path.startsWith(request.getContextPath()))
166 return url;
167 }
168
169 String sessionURLPrefix = sessionManager.getSessionIdPathParameterNamePrefix();
170 if (sessionURLPrefix==null)
171 return url;
172
173 if (url==null)
174 return null;
175
176
177 if (request.isRequestedSessionIdFromCookie())
178 {
179 int prefix=url.indexOf(sessionURLPrefix);
180 if (prefix!=-1)
181 {
182 int suffix=url.indexOf("?",prefix);
183 if (suffix<0)
184 suffix=url.indexOf("#",prefix);
185
186 if (suffix<=prefix)
187 return url.substring(0,prefix);
188 return url.substring(0,prefix)+url.substring(suffix);
189 }
190 return url;
191 }
192
193
194 HttpSession session=request.getSession(false);
195
196
197 if (session == null)
198 return url;
199
200
201 if (!sessionManager.isValid(session))
202 return url;
203
204 String id=sessionManager.getNodeId(session);
205
206 if (uri == null)
207 uri = new HttpURI(url);
208
209
210
211 int prefix=url.indexOf(sessionURLPrefix);
212 if (prefix!=-1)
213 {
214 int suffix=url.indexOf("?",prefix);
215 if (suffix<0)
216 suffix=url.indexOf("#",prefix);
217
218 if (suffix<=prefix)
219 return url.substring(0,prefix+sessionURLPrefix.length())+id;
220 return url.substring(0,prefix+sessionURLPrefix.length())+id+
221 url.substring(suffix);
222 }
223
224
225 int suffix=url.indexOf('?');
226 if (suffix<0)
227 suffix=url.indexOf('#');
228 if (suffix<0)
229 {
230 return url+
231 ((HttpSchemes.HTTPS.equalsIgnoreCase(uri.getScheme()) || HttpSchemes.HTTP.equalsIgnoreCase(uri.getScheme())) && uri.getPath()==null?"/":"") +
232 sessionURLPrefix+id;
233 }
234
235
236 return url.substring(0,suffix)+
237 ((HttpSchemes.HTTPS.equalsIgnoreCase(uri.getScheme()) || HttpSchemes.HTTP.equalsIgnoreCase(uri.getScheme())) && uri.getPath()==null?"/":"")+
238 sessionURLPrefix+id+url.substring(suffix);
239 }
240
241
242
243
244
245 public String encodeRedirectURL(String url)
246 {
247 return encodeURL(url);
248 }
249
250
251 @Deprecated
252 public String encodeUrl(String url)
253 {
254 return encodeURL(url);
255 }
256
257
258 @Deprecated
259 public String encodeRedirectUrl(String url)
260 {
261 return encodeRedirectURL(url);
262 }
263
264
265
266
267
268 public void sendError(int code, String message) throws IOException
269 {
270 if (_connection.isIncluding())
271 return;
272
273 if (isCommitted())
274 LOG.warn("Committed before "+code+" "+message);
275
276 resetBuffer();
277 _characterEncoding=null;
278 setHeader(HttpHeaders.EXPIRES,null);
279 setHeader(HttpHeaders.LAST_MODIFIED,null);
280 setHeader(HttpHeaders.CACHE_CONTROL,null);
281 setHeader(HttpHeaders.CONTENT_TYPE,null);
282 setHeader(HttpHeaders.CONTENT_LENGTH,null);
283
284 _outputState=NONE;
285 setStatus(code,message);
286
287 if (message==null)
288 message=HttpStatus.getMessage(code);
289
290
291 if (code!=SC_NO_CONTENT &&
292 code!=SC_NOT_MODIFIED &&
293 code!=SC_PARTIAL_CONTENT &&
294 code>=SC_OK)
295 {
296 Request request = _connection.getRequest();
297
298 ErrorHandler error_handler = null;
299 ContextHandler.Context context = request.getContext();
300 if (context!=null)
301 error_handler=context.getContextHandler().getErrorHandler();
302 if (error_handler==null)
303 error_handler = _connection.getConnector().getServer().getBean(ErrorHandler.class);
304 if (error_handler!=null)
305 {
306 request.setAttribute(Dispatcher.ERROR_STATUS_CODE,new Integer(code));
307 request.setAttribute(Dispatcher.ERROR_MESSAGE, message);
308 request.setAttribute(Dispatcher.ERROR_REQUEST_URI, request.getRequestURI());
309 request.setAttribute(Dispatcher.ERROR_SERVLET_NAME,request.getServletName());
310 error_handler.handle(null,_connection.getRequest(),_connection.getRequest(),this );
311 }
312 else
313 {
314 setHeader(HttpHeaders.CACHE_CONTROL, "must-revalidate,no-cache,no-store");
315 setContentType(MimeTypes.TEXT_HTML_8859_1);
316 ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(2048);
317 if (message != null)
318 {
319 message= StringUtil.replace(message, "&", "&");
320 message= StringUtil.replace(message, "<", "<");
321 message= StringUtil.replace(message, ">", ">");
322 }
323 String uri= request.getRequestURI();
324 if (uri!=null)
325 {
326 uri= StringUtil.replace(uri, "&", "&");
327 uri= StringUtil.replace(uri, "<", "<");
328 uri= StringUtil.replace(uri, ">", ">");
329 }
330
331 writer.write("<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\"/>\n");
332 writer.write("<title>Error ");
333 writer.write(Integer.toString(code));
334 writer.write(' ');
335 if (message==null)
336 message=HttpStatus.getMessage(code);
337 writer.write(message);
338 writer.write("</title>\n</head>\n<body>\n<h2>HTTP ERROR: ");
339 writer.write(Integer.toString(code));
340 writer.write("</h2>\n<p>Problem accessing ");
341 writer.write(uri);
342 writer.write(". Reason:\n<pre> ");
343 writer.write(message);
344 writer.write("</pre>");
345 writer.write("</p>\n<hr /><i><small>Powered by Jetty://</small></i>");
346
347 for (int i= 0; i < 20; i++)
348 writer.write("\n ");
349 writer.write("\n</body>\n</html>\n");
350
351 writer.flush();
352 setContentLength(writer.size());
353 writer.writeTo(getOutputStream());
354 writer.destroy();
355 }
356 }
357 else if (code!=SC_PARTIAL_CONTENT)
358 {
359 _connection.getRequestFields().remove(HttpHeaders.CONTENT_TYPE_BUFFER);
360 _connection.getRequestFields().remove(HttpHeaders.CONTENT_LENGTH_BUFFER);
361 _characterEncoding=null;
362 _mimeType=null;
363 _cachedMimeType=null;
364 }
365
366 complete();
367 }
368
369
370
371
372
373 public void sendError(int sc) throws IOException
374 {
375 if (sc==102)
376 sendProcessing();
377 else
378 sendError(sc,null);
379 }
380
381
382
383
384
385
386
387
388
389 public void sendProcessing() throws IOException
390 {
391 if (_connection.isExpecting102Processing() && !isCommitted())
392 ((HttpGenerator)_connection.getGenerator()).send1xx(HttpStatus.PROCESSING_102);
393 }
394
395
396
397
398
399 public void sendRedirect(String location) throws IOException
400 {
401 if (_connection.isIncluding())
402 return;
403
404 if (location==null)
405 throw new IllegalArgumentException();
406
407 if (!URIUtil.hasScheme(location))
408 {
409 StringBuilder buf = _connection.getRequest().getRootURL();
410 if (location.startsWith("/"))
411 buf.append(location);
412 else
413 {
414 String path=_connection.getRequest().getRequestURI();
415 String parent=(path.endsWith("/"))?path:URIUtil.parentPath(path);
416 location=URIUtil.addPaths(parent,location);
417 if(location==null)
418 throw new IllegalStateException("path cannot be above root");
419 if (!location.startsWith("/"))
420 buf.append('/');
421 buf.append(location);
422 }
423
424 location=buf.toString();
425 HttpURI uri = new HttpURI(location);
426 String path=uri.getDecodedPath();
427 String canonical=URIUtil.canonicalPath(path);
428 if (canonical==null)
429 throw new IllegalArgumentException();
430 if (!canonical.equals(path))
431 {
432 buf = _connection.getRequest().getRootURL();
433 buf.append(URIUtil.encodePath(canonical));
434 if (uri.getQuery()!=null)
435 {
436 buf.append('?');
437 buf.append(uri.getQuery());
438 }
439 if (uri.getFragment()!=null)
440 {
441 buf.append('#');
442 buf.append(uri.getFragment());
443 }
444 location=buf.toString();
445 }
446 }
447
448 location=encodeRedirectURL(location);
449 resetBuffer();
450 setHeader(HttpHeaders.LOCATION,location);
451 setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
452 complete();
453
454 }
455
456
457
458
459
460 public void setDateHeader(String name, long date)
461 {
462 if (!_connection.isIncluding())
463 _connection.getResponseFields().putDateField(name, date);
464 }
465
466
467
468
469
470 public void addDateHeader(String name, long date)
471 {
472 if (!_connection.isIncluding())
473 _connection.getResponseFields().addDateField(name, date);
474 }
475
476
477
478
479
480 public void setHeader(String name, String value)
481 {
482 if (HttpHeaders.CONTENT_TYPE.equalsIgnoreCase(name))
483 setContentType(value);
484 else
485 {
486 if (_connection.isIncluding())
487 {
488 if (name.startsWith(SET_INCLUDE_HEADER_PREFIX))
489 name=name.substring(SET_INCLUDE_HEADER_PREFIX.length());
490 else
491 return;
492 }
493 _connection.getResponseFields().put(name, value);
494 if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name))
495 {
496 if (value==null)
497 _connection._generator.setContentLength(-1);
498 else
499 _connection._generator.setContentLength(Long.parseLong(value));
500 }
501 }
502 }
503
504
505
506
507 public String getHeader(String name)
508 {
509 return _connection.getResponseFields().getStringField(name);
510 }
511
512
513
514
515 public Enumeration getHeaders(String name)
516 {
517 Enumeration e = _connection.getResponseFields().getValues(name);
518 if (e==null)
519 return Collections.enumeration(Collections.EMPTY_LIST);
520 return e;
521 }
522
523
524
525
526
527 public void addHeader(String name, String value)
528 {
529 if (_connection.isIncluding())
530 {
531 if (name.startsWith(SET_INCLUDE_HEADER_PREFIX))
532 name=name.substring(SET_INCLUDE_HEADER_PREFIX.length());
533 else
534 return;
535 }
536
537 _connection.getResponseFields().add(name, value);
538 if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name))
539 _connection._generator.setContentLength(Long.parseLong(value));
540 }
541
542
543
544
545
546 public void setIntHeader(String name, int value)
547 {
548 if (!_connection.isIncluding())
549 {
550 _connection.getResponseFields().putLongField(name, value);
551 if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name))
552 _connection._generator.setContentLength(value);
553 }
554 }
555
556
557
558
559
560 public void addIntHeader(String name, int value)
561 {
562 if (!_connection.isIncluding())
563 {
564 _connection.getResponseFields().addLongField(name, value);
565 if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name))
566 _connection._generator.setContentLength(value);
567 }
568 }
569
570
571
572
573
574 public void setStatus(int sc)
575 {
576 setStatus(sc,null);
577 }
578
579
580
581
582
583 public void setStatus(int sc, String sm)
584 {
585 if (sc<=0)
586 throw new IllegalArgumentException();
587 if (!_connection.isIncluding())
588 {
589 _status=sc;
590 _reason=sm;
591 }
592 }
593
594
595
596
597
598 public String getCharacterEncoding()
599 {
600 if (_characterEncoding==null)
601 _characterEncoding=StringUtil.__ISO_8859_1;
602 return _characterEncoding;
603 }
604
605
606 String getSetCharacterEncoding()
607 {
608 return _characterEncoding;
609 }
610
611
612
613
614
615 public String getContentType()
616 {
617 return _contentType;
618 }
619
620
621
622
623
624 public ServletOutputStream getOutputStream() throws IOException
625 {
626 if (_outputState!=NONE && _outputState!=STREAM)
627 throw new IllegalStateException("WRITER");
628
629 _outputState=STREAM;
630 return _connection.getOutputStream();
631 }
632
633
634 public boolean isWriting()
635 {
636 return _outputState==WRITER;
637 }
638
639
640 public boolean isOutputing()
641 {
642 return _outputState!=NONE;
643 }
644
645
646
647
648
649 public PrintWriter getWriter() throws IOException
650 {
651 if (_outputState!=NONE && _outputState!=WRITER)
652 throw new IllegalStateException("STREAM");
653
654
655 if (_writer==null)
656 {
657
658 String encoding = _characterEncoding;
659
660 if (encoding==null)
661 {
662
663 if(_cachedMimeType != null)
664 encoding = MimeTypes.getCharsetFromContentType(_cachedMimeType);
665
666 if (encoding==null)
667 encoding = StringUtil.__ISO_8859_1;
668
669 setCharacterEncoding(encoding);
670 }
671
672
673 _writer = _connection.getPrintWriter(encoding);
674 }
675 _outputState=WRITER;
676 return _writer;
677 }
678
679
680
681
682
683 public void setCharacterEncoding(String encoding)
684 {
685 if (_connection.isIncluding())
686 return;
687
688 if (this._outputState==0 && !isCommitted())
689 {
690 _explicitEncoding=true;
691
692 if (encoding==null)
693 {
694
695 if (_characterEncoding!=null)
696 {
697 _characterEncoding=null;
698 if (_cachedMimeType!=null)
699 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_cachedMimeType);
700 else
701 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_mimeType);
702 }
703 }
704 else
705 {
706
707 _characterEncoding=encoding;
708 if (_contentType!=null)
709 {
710 int i0=_contentType.indexOf(';');
711 if (i0<0)
712 {
713 _contentType=null;
714 if(_cachedMimeType!=null)
715 {
716 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
717 if (content_type!=null)
718 {
719 _contentType=content_type.toString();
720 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
721 }
722 }
723
724 if (_contentType==null)
725 {
726 _contentType = _mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
727 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
728 }
729 }
730 else
731 {
732 int i1=_contentType.indexOf("charset=",i0);
733 if (i1<0)
734 {
735 _contentType = _contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
736 }
737 else
738 {
739 int i8=i1+8;
740 int i2=_contentType.indexOf(" ",i8);
741 if (i2<0)
742 _contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
743 else
744 _contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ")+_contentType.substring(i2);
745 }
746 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
747 }
748 }
749 }
750 }
751 }
752
753
754
755
756
757 public void setContentLength(int len)
758 {
759
760
761
762 if (isCommitted() || _connection.isIncluding())
763 return;
764 _connection._generator.setContentLength(len);
765 if (len>=0)
766 {
767 _connection.getResponseFields().putLongField(HttpHeaders.CONTENT_LENGTH, len);
768 if (_connection._generator.isAllContentWritten())
769 {
770 if (_outputState==WRITER)
771 _writer.close();
772 else if (_outputState==STREAM)
773 {
774 try
775 {
776 getOutputStream().close();
777 }
778 catch(IOException e)
779 {
780 throw new RuntimeException(e);
781 }
782 }
783 }
784 }
785 }
786
787
788
789
790
791 public void setLongContentLength(long len)
792 {
793
794
795
796 if (isCommitted() || _connection.isIncluding())
797 return;
798 _connection._generator.setContentLength(len);
799 _connection.getResponseFields().putLongField(HttpHeaders.CONTENT_LENGTH, len);
800 }
801
802
803
804
805
806 public void setContentType(String contentType)
807 {
808 if (isCommitted() || _connection.isIncluding())
809 return;
810
811
812
813
814
815 if (contentType==null)
816 {
817 if (_locale==null)
818 _characterEncoding=null;
819 _mimeType=null;
820 _cachedMimeType=null;
821 _contentType=null;
822 _connection.getResponseFields().remove(HttpHeaders.CONTENT_TYPE_BUFFER);
823 }
824 else
825 {
826
827 int i0=contentType.indexOf(';');
828
829 if (i0>0)
830 {
831
832
833
834 _mimeType=contentType.substring(0,i0).trim();
835 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
836
837
838 int i1=contentType.indexOf("charset=",i0+1);
839 if (i1>=0)
840 {
841 _explicitEncoding=true;
842 int i8=i1+8;
843 int i2 = contentType.indexOf(' ',i8);
844
845 if (_outputState==WRITER)
846 {
847
848 if ((i1==i0+1 && i2<0) || (i1==i0+2 && i2<0 && contentType.charAt(i0+1)==' '))
849 {
850 if (_cachedMimeType!=null)
851 {
852 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
853 if (content_type!=null)
854 {
855 _contentType=content_type.toString();
856 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
857 }
858 else
859 {
860 _contentType=_mimeType+";charset="+_characterEncoding;
861 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
862 }
863 }
864 else
865 {
866 _contentType=_mimeType+";charset="+_characterEncoding;
867 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
868 }
869 }
870 else if (i2<0)
871 {
872 _contentType=contentType.substring(0,i1)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
873 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
874 }
875 else
876 {
877 _contentType=contentType.substring(0,i1)+contentType.substring(i2)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
878 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
879 }
880 }
881 else if ((i1==i0+1 && i2<0) || (i1==i0+2 && i2<0 && contentType.charAt(i0+1)==' '))
882 {
883
884 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
885 _characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8));
886
887 if (_cachedMimeType!=null)
888 {
889 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
890 if (content_type!=null)
891 {
892 _contentType=content_type.toString();
893 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
894 }
895 else
896 {
897 _contentType=contentType;
898 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
899 }
900 }
901 else
902 {
903 _contentType=contentType;
904 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
905 }
906 }
907 else if (i2>0)
908 {
909 _characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8,i2));
910 _contentType=contentType;
911 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
912 }
913 else
914 {
915 _characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8));
916 _contentType=contentType;
917 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
918 }
919 }
920 else
921 {
922 _cachedMimeType=null;
923 _contentType=_characterEncoding==null?contentType:contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
924 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
925 }
926 }
927 else
928 {
929 _mimeType=contentType;
930 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
931
932 if (_characterEncoding!=null)
933 {
934 if (_cachedMimeType!=null)
935 {
936 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
937 if (content_type!=null)
938 {
939 _contentType=content_type.toString();
940 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
941 }
942 else
943 {
944 _contentType=_mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
945 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
946 }
947 }
948 else
949 {
950 _contentType=contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
951 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
952 }
953 }
954 else if (_cachedMimeType!=null)
955 {
956 _contentType=_cachedMimeType.toString();
957 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_cachedMimeType);
958 }
959 else
960 {
961 _contentType=contentType;
962 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
963 }
964 }
965 }
966 }
967
968
969
970
971
972 public void setBufferSize(int size)
973 {
974 if (isCommitted() || getContentCount()>0)
975 throw new IllegalStateException("Committed or content written");
976 _connection.getGenerator().increaseContentBufferSize(size);
977 }
978
979
980
981
982
983 public int getBufferSize()
984 {
985 return _connection.getGenerator().getContentBufferSize();
986 }
987
988
989
990
991
992 public void flushBuffer() throws IOException
993 {
994 _connection.flushResponse();
995 }
996
997
998
999
1000
1001 public void reset()
1002 {
1003 resetBuffer();
1004 fwdReset();
1005 _status=200;
1006 _reason=null;
1007
1008 HttpFields response_fields=_connection.getResponseFields();
1009
1010 response_fields.clear();
1011 String connection=_connection.getRequestFields().getStringField(HttpHeaders.CONNECTION_BUFFER);
1012 if (connection!=null)
1013 {
1014 String[] values = connection.split(",");
1015 for (int i=0;values!=null && i<values.length;i++)
1016 {
1017 CachedBuffer cb = HttpHeaderValues.CACHE.get(values[0].trim());
1018
1019 if (cb!=null)
1020 {
1021 switch(cb.getOrdinal())
1022 {
1023 case HttpHeaderValues.CLOSE_ORDINAL:
1024 response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
1025 break;
1026
1027 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
1028 if (HttpVersions.HTTP_1_0.equalsIgnoreCase(_connection.getRequest().getProtocol()))
1029 response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE);
1030 break;
1031 case HttpHeaderValues.TE_ORDINAL:
1032 response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.TE);
1033 break;
1034 }
1035 }
1036 }
1037 }
1038 }
1039
1040
1041
1042
1043
1044 public void fwdReset()
1045 {
1046 resetBuffer();
1047
1048 _outputState=NONE;
1049 _writer=null;
1050 }
1051
1052
1053
1054
1055
1056 public void resetBuffer()
1057 {
1058 if (isCommitted())
1059 throw new IllegalStateException("Committed");
1060 _connection.getGenerator().resetBuffer();
1061 }
1062
1063
1064
1065
1066
1067 public boolean isCommitted()
1068 {
1069 return _connection.isResponseCommitted();
1070 }
1071
1072
1073
1074
1075
1076
1077 public void setLocale(Locale locale)
1078 {
1079 if (locale == null || isCommitted() ||_connection.isIncluding())
1080 return;
1081
1082 _locale = locale;
1083 _connection.getResponseFields().put(HttpHeaders.CONTENT_LANGUAGE_BUFFER,locale.toString().replace('_','-'));
1084
1085 if (_explicitEncoding || _outputState!=0 )
1086 return;
1087
1088 if (_connection.getRequest().getContext()==null)
1089 return;
1090
1091 String charset = _connection.getRequest().getContext().getContextHandler().getLocaleEncoding(locale);
1092
1093 if (charset!=null && charset.length()>0)
1094 {
1095 _characterEncoding=charset;
1096
1097
1098 String type=getContentType();
1099 if (type!=null)
1100 {
1101 _characterEncoding=charset;
1102 int semi=type.indexOf(';');
1103 if (semi<0)
1104 {
1105 _mimeType=type;
1106 _contentType= type += ";charset="+charset;
1107 }
1108 else
1109 {
1110 _mimeType=type.substring(0,semi);
1111 _contentType= _mimeType += ";charset="+charset;
1112 }
1113
1114 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
1115 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
1116 }
1117 }
1118 }
1119
1120
1121
1122
1123
1124 public Locale getLocale()
1125 {
1126 if (_locale==null)
1127 return Locale.getDefault();
1128 return _locale;
1129 }
1130
1131
1132
1133
1134
1135
1136 public int getStatus()
1137 {
1138 return _status;
1139 }
1140
1141
1142
1143
1144
1145
1146 public String getReason()
1147 {
1148 return _reason;
1149 }
1150
1151
1152
1153
1154 public void complete()
1155 throws IOException
1156 {
1157 _connection.completeResponse();
1158 }
1159
1160
1161
1162
1163
1164 public long getContentCount()
1165 {
1166 if (_connection==null || _connection.getGenerator()==null)
1167 return -1;
1168 return _connection.getGenerator().getContentWritten();
1169 }
1170
1171
1172 public HttpFields getHttpFields()
1173 {
1174 return _connection.getResponseFields();
1175 }
1176
1177
1178 @Override
1179 public String toString()
1180 {
1181 return "HTTP/1.1 "+_status+" "+ (_reason==null?"":_reason) +System.getProperty("line.separator")+
1182 _connection.getResponseFields().toString();
1183 }
1184
1185
1186
1187
1188 private static class NullOutput extends ServletOutputStream
1189 {
1190 @Override
1191 public void write(int b) throws IOException
1192 {
1193 }
1194
1195 @Override
1196 public void print(String s) throws IOException
1197 {
1198 }
1199
1200 @Override
1201 public void println(String s) throws IOException
1202 {
1203 }
1204
1205 @Override
1206 public void write(byte[] b, int off, int len) throws IOException
1207 {
1208 }
1209
1210 }
1211
1212 }