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 volatile 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 _writer=null;
112 _outputState=NONE;
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.replace(HTTP_ONLY_COMMENT,"").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 ServletOutputStream out = _connection.getOutputStream();
650 _outputState=STREAM;
651 return out;
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 _contentType=_cachedMimeType.toString();
721 else if (_mimeType!=null)
722 _contentType=_mimeType;
723 else
724 _contentType=null;
725
726 if (_contentType==null)
727 _connection.getResponseFields().remove(HttpHeaders.CONTENT_TYPE_BUFFER);
728 else
729 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
730 }
731 }
732 else
733 {
734
735 _characterEncoding=encoding;
736 if (_contentType!=null)
737 {
738 int i0=_contentType.indexOf(';');
739 if (i0<0)
740 {
741 _contentType=null;
742 if(_cachedMimeType!=null)
743 {
744 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
745 if (content_type!=null)
746 {
747 _contentType=content_type.toString();
748 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
749 }
750 }
751
752 if (_contentType==null)
753 {
754 _contentType = _mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
755 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
756 }
757 }
758 else
759 {
760 int i1=_contentType.indexOf("charset=",i0);
761 if (i1<0)
762 {
763 _contentType = _contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
764 }
765 else
766 {
767 int i8=i1+8;
768 int i2=_contentType.indexOf(" ",i8);
769 if (i2<0)
770 _contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
771 else
772 _contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ")+_contentType.substring(i2);
773 }
774 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
775 }
776 }
777 }
778 }
779 }
780
781
782
783
784
785 public void setContentLength(int len)
786 {
787
788
789
790 if (isCommitted() || _connection.isIncluding())
791 return;
792 _connection._generator.setContentLength(len);
793 if (len>0)
794 {
795 _connection.getResponseFields().putLongField(HttpHeaders.CONTENT_LENGTH, len);
796 if (_connection._generator.isAllContentWritten())
797 {
798 if (_outputState==WRITER)
799 _writer.close();
800 else if (_outputState==STREAM)
801 {
802 try
803 {
804 getOutputStream().close();
805 }
806 catch(IOException e)
807 {
808 throw new RuntimeException(e);
809 }
810 }
811 }
812 }
813 }
814
815
816
817
818
819 public void setLongContentLength(long len)
820 {
821
822
823
824 if (isCommitted() || _connection.isIncluding())
825 return;
826 _connection._generator.setContentLength(len);
827 _connection.getResponseFields().putLongField(HttpHeaders.CONTENT_LENGTH, len);
828 }
829
830
831
832
833
834 public void setContentType(String contentType)
835 {
836 if (isCommitted() || _connection.isIncluding())
837 return;
838
839
840
841
842
843 if (contentType==null)
844 {
845 if (_locale==null)
846 _characterEncoding=null;
847 _mimeType=null;
848 _cachedMimeType=null;
849 _contentType=null;
850 _connection.getResponseFields().remove(HttpHeaders.CONTENT_TYPE_BUFFER);
851 }
852 else
853 {
854
855 int i0=contentType.indexOf(';');
856
857 if (i0>0)
858 {
859
860
861
862 _mimeType=contentType.substring(0,i0).trim();
863 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
864
865
866 int i1=contentType.indexOf("charset=",i0+1);
867 if (i1>=0)
868 {
869 _explicitEncoding=true;
870 int i8=i1+8;
871 int i2 = contentType.indexOf(' ',i8);
872
873 if (_outputState==WRITER)
874 {
875
876 if ((i1==i0+1 && i2<0) || (i1==i0+2 && i2<0 && contentType.charAt(i0+1)==' '))
877 {
878 if (_cachedMimeType!=null)
879 {
880 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
881 if (content_type!=null)
882 {
883 _contentType=content_type.toString();
884 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
885 }
886 else
887 {
888 _contentType=_mimeType+";charset="+_characterEncoding;
889 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
890 }
891 }
892 else
893 {
894 _contentType=_mimeType+";charset="+_characterEncoding;
895 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
896 }
897 }
898 else if (i2<0)
899 {
900 _contentType=contentType.substring(0,i1)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
901 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
902 }
903 else
904 {
905 _contentType=contentType.substring(0,i1)+contentType.substring(i2)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
906 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
907 }
908 }
909 else if ((i1==i0+1 && i2<0) || (i1==i0+2 && i2<0 && contentType.charAt(i0+1)==' '))
910 {
911
912 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
913 _characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8));
914
915 if (_cachedMimeType!=null)
916 {
917 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
918 if (content_type!=null)
919 {
920 _contentType=content_type.toString();
921 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
922 }
923 else
924 {
925 _contentType=contentType;
926 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
927 }
928 }
929 else
930 {
931 _contentType=contentType;
932 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
933 }
934 }
935 else if (i2>0)
936 {
937 _characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8,i2));
938 _contentType=contentType;
939 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
940 }
941 else
942 {
943 _characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8));
944 _contentType=contentType;
945 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
946 }
947 }
948 else
949 {
950 _cachedMimeType=null;
951 _contentType=_characterEncoding==null?contentType:contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
952 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
953 }
954 }
955 else
956 {
957 _mimeType=contentType;
958 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
959
960 if (_characterEncoding!=null)
961 {
962 if (_cachedMimeType!=null)
963 {
964 CachedBuffer content_type = _cachedMimeType.getAssociate(_characterEncoding);
965 if (content_type!=null)
966 {
967 _contentType=content_type.toString();
968 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
969 }
970 else
971 {
972 _contentType=_mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
973 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
974 }
975 }
976 else
977 {
978 _contentType=contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
979 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
980 }
981 }
982 else if (_cachedMimeType!=null)
983 {
984 _contentType=_cachedMimeType.toString();
985 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_cachedMimeType);
986 }
987 else
988 {
989 _contentType=contentType;
990 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
991 }
992 }
993 }
994 }
995
996
997
998
999
1000 public void setBufferSize(int size)
1001 {
1002 if (isCommitted() || getContentCount()>0)
1003 throw new IllegalStateException("Committed or content written");
1004 _connection.getGenerator().increaseContentBufferSize(size);
1005 }
1006
1007
1008
1009
1010
1011 public int getBufferSize()
1012 {
1013 return _connection.getGenerator().getContentBufferSize();
1014 }
1015
1016
1017
1018
1019
1020 public void flushBuffer() throws IOException
1021 {
1022 _connection.flushResponse();
1023 }
1024
1025
1026
1027
1028
1029 public void reset()
1030 {
1031 resetBuffer();
1032 fwdReset();
1033 _status=200;
1034 _reason=null;
1035
1036 HttpFields response_fields=_connection.getResponseFields();
1037
1038 response_fields.clear();
1039 String connection=_connection.getRequestFields().getStringField(HttpHeaders.CONNECTION_BUFFER);
1040 if (connection!=null)
1041 {
1042 String[] values = connection.split(",");
1043 for (int i=0;values!=null && i<values.length;i++)
1044 {
1045 CachedBuffer cb = HttpHeaderValues.CACHE.get(values[0].trim());
1046
1047 if (cb!=null)
1048 {
1049 switch(cb.getOrdinal())
1050 {
1051 case HttpHeaderValues.CLOSE_ORDINAL:
1052 response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE_BUFFER);
1053 break;
1054
1055 case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
1056 if (HttpVersions.HTTP_1_0.equalsIgnoreCase(_connection.getRequest().getProtocol()))
1057 response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE);
1058 break;
1059 case HttpHeaderValues.TE_ORDINAL:
1060 response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.TE);
1061 break;
1062 }
1063 }
1064 }
1065 }
1066 }
1067
1068
1069
1070
1071
1072 public void fwdReset()
1073 {
1074 resetBuffer();
1075
1076 _writer=null;
1077 _outputState=NONE;
1078 }
1079
1080
1081
1082
1083
1084 public void resetBuffer()
1085 {
1086 if (isCommitted())
1087 throw new IllegalStateException("Committed");
1088 _connection.getGenerator().resetBuffer();
1089 }
1090
1091
1092
1093
1094
1095 public boolean isCommitted()
1096 {
1097 return _connection.isResponseCommitted();
1098 }
1099
1100
1101
1102
1103
1104
1105 public void setLocale(Locale locale)
1106 {
1107 if (locale == null || isCommitted() ||_connection.isIncluding())
1108 return;
1109
1110 _locale = locale;
1111 _connection.getResponseFields().put(HttpHeaders.CONTENT_LANGUAGE_BUFFER,locale.toString().replace('_','-'));
1112
1113 if (_explicitEncoding || _outputState!=0 )
1114 return;
1115
1116 if (_connection.getRequest().getContext()==null)
1117 return;
1118
1119 String charset = _connection.getRequest().getContext().getContextHandler().getLocaleEncoding(locale);
1120
1121 if (charset!=null && charset.length()>0)
1122 {
1123 _characterEncoding=charset;
1124
1125
1126 String type=getContentType();
1127 if (type!=null)
1128 {
1129 _characterEncoding=charset;
1130 int semi=type.indexOf(';');
1131 if (semi<0)
1132 {
1133 _mimeType=type;
1134 _contentType= type += ";charset="+charset;
1135 }
1136 else
1137 {
1138 _mimeType=type.substring(0,semi);
1139 _contentType= _mimeType += ";charset="+charset;
1140 }
1141
1142 _cachedMimeType=MimeTypes.CACHE.get(_mimeType);
1143 _connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
1144 }
1145 }
1146 }
1147
1148
1149
1150
1151
1152 public Locale getLocale()
1153 {
1154 if (_locale==null)
1155 return Locale.getDefault();
1156 return _locale;
1157 }
1158
1159
1160
1161
1162
1163
1164 public int getStatus()
1165 {
1166 return _status;
1167 }
1168
1169
1170
1171
1172
1173
1174 public String getReason()
1175 {
1176 return _reason;
1177 }
1178
1179
1180
1181
1182 public void complete()
1183 throws IOException
1184 {
1185 _connection.completeResponse();
1186 }
1187
1188
1189
1190
1191
1192 public long getContentCount()
1193 {
1194 if (_connection==null || _connection.getGenerator()==null)
1195 return -1;
1196 return _connection.getGenerator().getContentWritten();
1197 }
1198
1199
1200 public HttpFields getHttpFields()
1201 {
1202 return _connection.getResponseFields();
1203 }
1204
1205
1206 @Override
1207 public String toString()
1208 {
1209 return "HTTP/1.1 "+_status+" "+ (_reason==null?"":_reason) +System.getProperty("line.separator")+
1210 _connection.getResponseFields().toString();
1211 }
1212
1213
1214
1215
1216 private static class NullOutput extends ServletOutputStream
1217 {
1218 @Override
1219 public void write(int b) throws IOException
1220 {
1221 }
1222
1223 @Override
1224 public void print(String s) throws IOException
1225 {
1226 }
1227
1228 @Override
1229 public void println(String s) throws IOException
1230 {
1231 }
1232
1233 @Override
1234 public void write(byte[] b, int off, int len) throws IOException
1235 {
1236 }
1237
1238 }
1239
1240 }