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