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