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