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