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