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