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 location=encodeRedirectURL(location);
470 resetBuffer();
471 setHeader(HttpHeaders.LOCATION,location);
472 setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
473 complete();
474
475 }
476
477
478
479
480
481 public void setDateHeader(String name, long date)
482 {
483 if (!_connection.isIncluding())
484 _connection.getResponseFields().putDateField(name, date);
485 }
486
487
488
489
490
491 public void addDateHeader(String name, long date)
492 {
493 if (!_connection.isIncluding())
494 _connection.getResponseFields().addDateField(name, date);
495 }
496
497
498
499
500
501 public void setHeader(String name, String value)
502 {
503 if (HttpHeaders.CONTENT_TYPE.equalsIgnoreCase(name))
504 setContentType(value);
505 else
506 {
507 if (_connection.isIncluding())
508 {
509 if (name.startsWith(SET_INCLUDE_HEADER_PREFIX))
510 name=name.substring(SET_INCLUDE_HEADER_PREFIX.length());
511 else
512 return;
513 }
514 _connection.getResponseFields().put(name, value);
515 if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name))
516 {
517 if (value==null)
518 _connection._generator.setContentLength(-1);
519 else
520 _connection._generator.setContentLength(Long.parseLong(value));
521 }
522 }
523 }
524
525
526
527
528 public String getHeader(String name)
529 {
530 return _connection.getResponseFields().getStringField(name);
531 }
532
533
534
535
536 public Enumeration getHeaders(String name)
537 {
538 Enumeration e = _connection.getResponseFields().getValues(name);
539 if (e==null)
540 return Collections.enumeration(Collections.EMPTY_LIST);
541 return e;
542 }
543
544
545
546
547
548 public void addHeader(String name, String value)
549 {
550 if (_connection.isIncluding())
551 {
552 if (name.startsWith(SET_INCLUDE_HEADER_PREFIX))
553 name=name.substring(SET_INCLUDE_HEADER_PREFIX.length());
554 else
555 return;
556 }
557
558 _connection.getResponseFields().add(name, value);
559 if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name))
560 _connection._generator.setContentLength(Long.parseLong(value));
561 }
562
563
564
565
566
567 public void setIntHeader(String name, int value)
568 {
569 if (!_connection.isIncluding())
570 {
571 _connection.getResponseFields().putLongField(name, value);
572 if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name))
573 _connection._generator.setContentLength(value);
574 }
575 }
576
577
578
579
580
581 public void addIntHeader(String name, int value)
582 {
583 if (!_connection.isIncluding())
584 {
585 _connection.getResponseFields().addLongField(name, value);
586 if (HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name))
587 _connection._generator.setContentLength(value);
588 }
589 }
590
591
592
593
594
595 public void setStatus(int sc)
596 {
597 setStatus(sc,null);
598 }
599
600
601
602
603
604 public void setStatus(int sc, String sm)
605 {
606 if (sc<=0)
607 throw new IllegalArgumentException();
608 if (!_connection.isIncluding())
609 {
610 _status=sc;
611 _reason=sm;
612 }
613 }
614
615
616
617
618
619 public String getCharacterEncoding()
620 {
621 if (_characterEncoding==null)
622 _characterEncoding=StringUtil.__ISO_8859_1;
623 return _characterEncoding;
624 }
625
626
627 String getSetCharacterEncoding()
628 {
629 return _characterEncoding;
630 }
631
632
633
634
635
636 public String getContentType()
637 {
638 return _contentType;
639 }
640
641
642
643
644
645 public ServletOutputStream getOutputStream() throws IOException
646 {
647 if (_outputState!=NONE && _outputState!=STREAM)
648 throw new IllegalStateException("WRITER");
649
650 _outputState=STREAM;
651 return _connection.getOutputStream();
652 }
653
654
655 public boolean isWriting()
656 {
657 return _outputState==WRITER;
658 }
659
660
661 public boolean isOutputing()
662 {
663 return _outputState!=NONE;
664 }
665
666
667
668
669
670 public PrintWriter getWriter() throws IOException
671 {
672 if (_outputState!=NONE && _outputState!=WRITER)
673 throw new IllegalStateException("STREAM");
674
675
676 if (_writer==null)
677 {
678
679 String encoding = _characterEncoding;
680
681 if (encoding==null)
682 {
683
684 if(_cachedMimeType != null)
685 encoding = MimeTypes.getCharsetFromContentType(_cachedMimeType);
686
687 if (encoding==null)
688 encoding = StringUtil.__ISO_8859_1;
689
690 setCharacterEncoding(encoding);
691 }
692
693
694 _writer = _connection.getPrintWriter(encoding);
695 }
696 _outputState=WRITER;
697 return _writer;
698 }
699
700
701
702
703
704 public void setCharacterEncoding(String encoding)
705 {
706 if (_connection.isIncluding())
707 return;
708
709 if (this._outputState==0 && !isCommitted())
710 {
711 _explicitEncoding=true;
712
713 if (encoding==null)
714 {
715
716 if (_characterEncoding!=null)
717 {
718 _characterEncoding=null;
719 if (_cachedMimeType!=null)
720 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_cachedMimeType);
721 else
722 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_mimeType);
723 }
724 }
725 else
726 {
727
728 _characterEncoding=encoding;
729 if (_contentType!=null)
730 {
731 int i0=_contentType.indexOf(';');
732 if (i0<0)
733 {
734 _contentType=null;
735 if(_cachedMimeType!=null)
736 {
737 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
738 if (content_type!=null)
739 {
740 _contentType=content_type.toString();
741 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
742 }
743 }
744
745 if (_contentType==null)
746 {
747 _contentType = _mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
748 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
749 }
750 }
751 else
752 {
753 int i1=_contentType.indexOf("charset=",i0);
754 if (i1<0)
755 {
756 _contentType = _contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
757 }
758 else
759 {
760 int i8=i1+8;
761 int i2=_contentType.indexOf(" ",i8);
762 if (i2<0)
763 _contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
764 else
765 _contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ")+_contentType.substring(i2);
766 }
767 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
768 }
769 }
770 }
771 }
772 }
773
774
775
776
777
778 public void setContentLength(int len)
779 {
780
781
782
783 if (isCommitted() || _connection.isIncluding())
784 return;
785 _connection._generator.setContentLength(len);
786 if (len>=0)
787 {
788 _connection.getResponseFields().putLongField(HttpHeaders.CONTENT_LENGTH, len);
789 if (_connection._generator.isAllContentWritten())
790 {
791 if (_outputState==WRITER)
792 _writer.close();
793 else if (_outputState==STREAM)
794 {
795 try
796 {
797 getOutputStream().close();
798 }
799 catch(IOException e)
800 {
801 throw new RuntimeException(e);
802 }
803 }
804 }
805 }
806 }
807
808
809
810
811
812 public void setLongContentLength(long len)
813 {
814
815
816
817 if (isCommitted() || _connection.isIncluding())
818 return;
819 _connection._generator.setContentLength(len);
820 _connection.getResponseFields().putLongField(HttpHeaders.CONTENT_LENGTH, len);
821 }
822
823
824
825
826
827 public void setContentType(String contentType)
828 {
829 if (isCommitted() || _connection.isIncluding())
830 return;
831
832
833
834
835
836 if (contentType==null)
837 {
838 if (_locale==null)
839 _characterEncoding=null;
840 _mimeType=null;
841 _cachedMimeType=null;
842 _contentType=null;
843 _connection.getResponseFields().remove(HttpHeaders.CONTENT_TYPE_BUFFER);
844 }
845 else
846 {
847
848 int i0=contentType.indexOf(';');
849
850 if (i0>0)
851 {
852
853
854
855 _mimeType=contentType.substring(0,i0).trim();
856 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
857
858
859 int i1=contentType.indexOf("charset=",i0+1);
860 if (i1>=0)
861 {
862 _explicitEncoding=true;
863 int i8=i1+8;
864 int i2 = contentType.indexOf(' ',i8);
865
866 if (_outputState==WRITER)
867 {
868
869 if ((i1==i0+1 && i2<0) || (i1==i0+2 && i2<0 && contentType.charAt(i0+1)==' '))
870 {
871 if (_cachedMimeType!=null)
872 {
873 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
874 if (content_type!=null)
875 {
876 _contentType=content_type.toString();
877 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
878 }
879 else
880 {
881 _contentType=_mimeType+";charset="+_characterEncoding;
882 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
883 }
884 }
885 else
886 {
887 _contentType=_mimeType+";charset="+_characterEncoding;
888 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
889 }
890 }
891 else if (i2<0)
892 {
893 _contentType=contentType.substring(0,i1)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
894 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
895 }
896 else
897 {
898 _contentType=contentType.substring(0,i1)+contentType.substring(i2)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
899 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
900 }
901 }
902 else if ((i1==i0+1 && i2<0) || (i1==i0+2 && i2<0 && contentType.charAt(i0+1)==' '))
903 {
904
905 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
906 _characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8));
907
908 if (_cachedMimeType!=null)
909 {
910 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
911 if (content_type!=null)
912 {
913 _contentType=content_type.toString();
914 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
915 }
916 else
917 {
918 _contentType=contentType;
919 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
920 }
921 }
922 else
923 {
924 _contentType=contentType;
925 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
926 }
927 }
928 else if (i2>0)
929 {
930 _characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8,i2));
931 _contentType=contentType;
932 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
933 }
934 else
935 {
936 _characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8));
937 _contentType=contentType;
938 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
939 }
940 }
941 else
942 {
943 _cachedMimeType=null;
944 _contentType=_characterEncoding==null?contentType:contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
945 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
946 }
947 }
948 else
949 {
950 _mimeType=contentType;
951 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
952
953 if (_characterEncoding!=null)
954 {
955 if (_cachedMimeType!=null)
956 {
957 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
958 if (content_type!=null)
959 {
960 _contentType=content_type.toString();
961 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
962 }
963 else
964 {
965 _contentType=_mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
966 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
967 }
968 }
969 else
970 {
971 _contentType=contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
972 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
973 }
974 }
975 else if (_cachedMimeType!=null)
976 {
977 _contentType=_cachedMimeType.toString();
978 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_cachedMimeType);
979 }
980 else
981 {
982 _contentType=contentType;
983 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
984 }
985 }
986 }
987 }
988
989
990
991
992
993 public void setBufferSize(int size)
994 {
995 if (isCommitted() || getContentCount()>0)
996 throw new IllegalStateException("Committed or content written");
997 _connection.getGenerator().increaseContentBufferSize(size);
998 }
999
1000
1001
1002
1003
1004 public int getBufferSize()
1005 {
1006 return _connection.getGenerator().getContentBufferSize();
1007 }
1008
1009
1010
1011
1012
1013 public void flushBuffer() throws IOException
1014 {
1015 _connection.flushResponse();
1016 }
1017
1018
1019
1020
1021
1022 public void reset()
1023 {
1024 resetBuffer();
1025 fwdReset();
1026 _status=200;
1027 _reason=null;
1028
1029 HttpFields response_fields=_connection.getResponseFields();
1030
1031 response_fields.clear();
1032 String connection=_connection.getRequestFields().getStringField(HttpHeaders.CONNECTION_BUFFER);
1033 if (connection!=null)
1034 {
1035 String[] values = connection.split(",");
1036 for (int i=0;values!=null && i<values.length;i++)
1037 {
1038 CachedBuffer cb = HttpHeaderValues.CACHE.get(values[0].trim());
1039
1040 if (cb!=null)
1041 {
1042 switch(cb.getOrdinal())
1043 {
1044 case HttpHeaderValues.CLOSE_ORDINAL:
1045 response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
1046 break;
1047
1048 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
1049 if (HttpVersions.HTTP_1_0.equalsIgnoreCase(_connection.getRequest().getProtocol()))
1050 response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE);
1051 break;
1052 case HttpHeaderValues.TE_ORDINAL:
1053 response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.TE);
1054 break;
1055 }
1056 }
1057 }
1058 }
1059 }
1060
1061
1062
1063
1064
1065 public void fwdReset()
1066 {
1067 resetBuffer();
1068
1069 _outputState=NONE;
1070 _writer=null;
1071 }
1072
1073
1074
1075
1076
1077 public void resetBuffer()
1078 {
1079 if (isCommitted())
1080 throw new IllegalStateException("Committed");
1081 _connection.getGenerator().resetBuffer();
1082 }
1083
1084
1085
1086
1087
1088 public boolean isCommitted()
1089 {
1090 return _connection.isResponseCommitted();
1091 }
1092
1093
1094
1095
1096
1097
1098 public void setLocale(Locale locale)
1099 {
1100 if (locale == null || isCommitted() ||_connection.isIncluding())
1101 return;
1102
1103 _locale = locale;
1104 _connection.getResponseFields().put(HttpHeaders.CONTENT_LANGUAGE_BUFFER,locale.toString().replace('_','-'));
1105
1106 if (_explicitEncoding || _outputState!=0 )
1107 return;
1108
1109 if (_connection.getRequest().getContext()==null)
1110 return;
1111
1112 String charset = _connection.getRequest().getContext().getContextHandler().getLocaleEncoding(locale);
1113
1114 if (charset!=null && charset.length()>0)
1115 {
1116 _characterEncoding=charset;
1117
1118
1119 String type=getContentType();
1120 if (type!=null)
1121 {
1122 _characterEncoding=charset;
1123 int semi=type.indexOf(';');
1124 if (semi<0)
1125 {
1126 _mimeType=type;
1127 _contentType= type += ";charset="+charset;
1128 }
1129 else
1130 {
1131 _mimeType=type.substring(0,semi);
1132 _contentType= _mimeType += ";charset="+charset;
1133 }
1134
1135 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
1136 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
1137 }
1138 }
1139 }
1140
1141
1142
1143
1144
1145 public Locale getLocale()
1146 {
1147 if (_locale==null)
1148 return Locale.getDefault();
1149 return _locale;
1150 }
1151
1152
1153
1154
1155
1156
1157 public int getStatus()
1158 {
1159 return _status;
1160 }
1161
1162
1163
1164
1165
1166
1167 public String getReason()
1168 {
1169 return _reason;
1170 }
1171
1172
1173
1174
1175 public void complete()
1176 throws IOException
1177 {
1178 _connection.completeResponse();
1179 }
1180
1181
1182
1183
1184
1185 public long getContentCount()
1186 {
1187 if (_connection==null || _connection.getGenerator()==null)
1188 return -1;
1189 return _connection.getGenerator().getContentWritten();
1190 }
1191
1192
1193 public HttpFields getHttpFields()
1194 {
1195 return _connection.getResponseFields();
1196 }
1197
1198
1199 @Override
1200 public String toString()
1201 {
1202 return "HTTP/1.1 "+_status+" "+ (_reason==null?"":_reason) +System.getProperty("line.separator")+
1203 _connection.getResponseFields().toString();
1204 }
1205
1206
1207
1208
1209 private static class NullOutput extends ServletOutputStream
1210 {
1211 @Override
1212 public void write(int b) throws IOException
1213 {
1214 }
1215
1216 @Override
1217 public void print(String s) throws IOException
1218 {
1219 }
1220
1221 @Override
1222 public void println(String s) throws IOException
1223 {
1224 }
1225
1226 @Override
1227 public void write(byte[] b, int off, int len) throws IOException
1228 {
1229 }
1230
1231 }
1232
1233 }