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