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