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