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