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