001 /* 002 * Copyright 2004 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package javax.servlet.http; 017 018 import java.io.IOException; 019 import java.io.PrintWriter; 020 import java.io.OutputStreamWriter; 021 import java.io.UnsupportedEncodingException; 022 import java.lang.reflect.Method; 023 import java.text.MessageFormat; 024 import java.util.Enumeration; 025 import java.util.Locale; 026 import java.util.ResourceBundle; 027 028 import javax.servlet.GenericServlet; 029 import javax.servlet.ServletException; 030 import javax.servlet.ServletOutputStream; 031 import javax.servlet.ServletRequest; 032 import javax.servlet.ServletResponse; 033 034 035 /** 036 * 037 * Provides an abstract class to be subclassed to create 038 * an HTTP servlet suitable for a Web site. A subclass of 039 * <code>HttpServlet</code> must override at least 040 * one method, usually one of these: 041 * 042 * <ul> 043 * <li> <code>doGet</code>, if the servlet supports HTTP GET requests 044 * <li> <code>doPost</code>, for HTTP POST requests 045 * <li> <code>doPut</code>, for HTTP PUT requests 046 * <li> <code>doDelete</code>, for HTTP DELETE requests 047 * <li> <code>init</code> and <code>destroy</code>, 048 * to manage resources that are held for the life of the servlet 049 * <li> <code>getServletInfo</code>, which the servlet uses to 050 * provide information about itself 051 * </ul> 052 * 053 * <p>There's almost no reason to override the <code>service</code> 054 * method. <code>service</code> handles standard HTTP 055 * requests by dispatching them to the handler methods 056 * for each HTTP request type (the <code>do</code><i>XXX</i> 057 * methods listed above). 058 * 059 * <p>Likewise, there's almost no reason to override the 060 * <code>doOptions</code> and <code>doTrace</code> methods. 061 * 062 * <p>Servlets typically run on multithreaded servers, 063 * so be aware that a servlet must handle concurrent 064 * requests and be careful to synchronize access to shared resources. 065 * Shared resources include in-memory data such as 066 * instance or class variables and external objects 067 * such as files, database connections, and network 068 * connections. 069 * See the 070 * <a href="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html"> 071 * Java Tutorial on Multithreaded Programming</a> for more 072 * information on handling multiple threads in a Java program. 073 * 074 * @author Various 075 * @version $Version$ 076 * 077 */ 078 079 080 081 public abstract class HttpServlet extends GenericServlet 082 implements java.io.Serializable 083 { 084 private static final String METHOD_DELETE = "DELETE"; 085 private static final String METHOD_HEAD = "HEAD"; 086 private static final String METHOD_GET = "GET"; 087 private static final String METHOD_OPTIONS = "OPTIONS"; 088 private static final String METHOD_POST = "POST"; 089 private static final String METHOD_PUT = "PUT"; 090 private static final String METHOD_TRACE = "TRACE"; 091 092 private static final String HEADER_IFMODSINCE = "If-Modified-Since"; 093 private static final String HEADER_LASTMOD = "Last-Modified"; 094 095 private static final String LSTRING_FILE = 096 "javax.servlet.http.LocalStrings"; 097 private static ResourceBundle lStrings = 098 ResourceBundle.getBundle(LSTRING_FILE); 099 100 101 102 103 /** 104 * Does nothing, because this is an abstract class. 105 * 106 */ 107 108 public HttpServlet() { } 109 110 111 112 /** 113 * 114 * Called by the server (via the <code>service</code> method) to 115 * allow a servlet to handle a GET request. 116 * 117 * <p>Overriding this method to support a GET request also 118 * automatically supports an HTTP HEAD request. A HEAD 119 * request is a GET request that returns no body in the 120 * response, only the request header fields. 121 * 122 * <p>When overriding this method, read the request data, 123 * write the response headers, get the response's writer or 124 * output stream object, and finally, write the response data. 125 * It's best to include content type and encoding. When using 126 * a <code>PrintWriter</code> object to return the response, 127 * set the content type before accessing the 128 * <code>PrintWriter</code> object. 129 * 130 * <p>The servlet container must write the headers before 131 * committing the response, because in HTTP the headers must be sent 132 * before the response body. 133 * 134 * <p>Where possible, set the Content-Length header (with the 135 * {@link javax.servlet.ServletResponse#setContentLength} method), 136 * to allow the servlet container to use a persistent connection 137 * to return its response to the client, improving performance. 138 * The content length is automatically set if the entire response fits 139 * inside the response buffer. 140 * 141 * <p>When using HTTP 1.1 chunked encoding (which means that the response 142 * has a Transfer-Encoding header), do not set the Content-Length header. 143 * 144 * <p>The GET method should be safe, that is, without 145 * any side effects for which users are held responsible. 146 * For example, most form queries have no side effects. 147 * If a client request is intended to change stored data, 148 * the request should use some other HTTP method. 149 * 150 * <p>The GET method should also be idempotent, meaning 151 * that it can be safely repeated. Sometimes making a 152 * method safe also makes it idempotent. For example, 153 * repeating queries is both safe and idempotent, but 154 * buying a product online or modifying data is neither 155 * safe nor idempotent. 156 * 157 * <p>If the request is incorrectly formatted, <code>doGet</code> 158 * returns an HTTP "Bad Request" message. 159 * 160 * 161 * @param req an {@link HttpServletRequest} object that 162 * contains the request the client has made 163 * of the servlet 164 * 165 * @param resp an {@link HttpServletResponse} object that 166 * contains the response the servlet sends 167 * to the client 168 * 169 * @exception IOException if an input or output error is 170 * detected when the servlet handles 171 * the GET request 172 * 173 * @exception ServletException if the request for the GET 174 * could not be handled 175 * 176 * 177 * @see javax.servlet.ServletResponse#setContentType 178 * 179 */ 180 181 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 182 throws ServletException, IOException 183 { 184 String protocol = req.getProtocol(); 185 String msg = lStrings.getString("http.method_get_not_supported"); 186 if (protocol.endsWith("1.1")) { 187 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); 188 } else { 189 resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); 190 } 191 } 192 193 194 195 196 197 /** 198 * 199 * Returns the time the <code>HttpServletRequest</code> 200 * object was last modified, 201 * in milliseconds since midnight January 1, 1970 GMT. 202 * If the time is unknown, this method returns a negative 203 * number (the default). 204 * 205 * <p>Servlets that support HTTP GET requests and can quickly determine 206 * their last modification time should override this method. 207 * This makes browser and proxy caches work more effectively, 208 * reducing the load on server and network resources. 209 * 210 * 211 * @param req the <code>HttpServletRequest</code> 212 * object that is sent to the servlet 213 * 214 * @return a <code>long</code> integer specifying 215 * the time the <code>HttpServletRequest</code> 216 * object was last modified, in milliseconds 217 * since midnight, January 1, 1970 GMT, or 218 * -1 if the time is not known 219 * 220 */ 221 222 protected long getLastModified(HttpServletRequest req) { 223 return -1; 224 } 225 226 227 228 229 /** 230 * 231 * 232 * <p>Receives an HTTP HEAD request from the protected 233 * <code>service</code> method and handles the 234 * request. 235 * The client sends a HEAD request when it wants 236 * to see only the headers of a response, such as 237 * Content-Type or Content-Length. The HTTP HEAD 238 * method counts the output bytes in the response 239 * to set the Content-Length header accurately. 240 * 241 * <p>If you override this method, you can avoid computing 242 * the response body and just set the response headers 243 * directly to improve performance. Make sure that the 244 * <code>doHead</code> method you write is both safe 245 * and idempotent (that is, protects itself from being 246 * called multiple times for one HTTP HEAD request). 247 * 248 * <p>If the HTTP HEAD request is incorrectly formatted, 249 * <code>doHead</code> returns an HTTP "Bad Request" 250 * message. 251 * 252 * 253 * @param req the request object that is passed 254 * to the servlet 255 * 256 * @param resp the response object that the servlet 257 * uses to return the headers to the clien 258 * 259 * @exception IOException if an input or output error occurs 260 * 261 * @exception ServletException if the request for the HEAD 262 * could not be handled 263 */ 264 265 protected void doHead(HttpServletRequest req, HttpServletResponse resp) 266 throws ServletException, IOException 267 { 268 NoBodyResponse response = new NoBodyResponse(resp); 269 270 doGet(req, response); 271 response.setContentLength(); 272 } 273 274 275 276 277 278 /** 279 * 280 * Called by the server (via the <code>service</code> method) 281 * to allow a servlet to handle a POST request. 282 * 283 * The HTTP POST method allows the client to send 284 * data of unlimited length to the Web server a single time 285 * and is useful when posting information such as 286 * credit card numbers. 287 * 288 * <p>When overriding this method, read the request data, 289 * write the response headers, get the response's writer or output 290 * stream object, and finally, write the response data. It's best 291 * to include content type and encoding. When using a 292 * <code>PrintWriter</code> object to return the response, set the 293 * content type before accessing the <code>PrintWriter</code> object. 294 * 295 * <p>The servlet container must write the headers before committing the 296 * response, because in HTTP the headers must be sent before the 297 * response body. 298 * 299 * <p>Where possible, set the Content-Length header (with the 300 * {@link javax.servlet.ServletResponse#setContentLength} method), 301 * to allow the servlet container to use a persistent connection 302 * to return its response to the client, improving performance. 303 * The content length is automatically set if the entire response fits 304 * inside the response buffer. 305 * 306 * <p>When using HTTP 1.1 chunked encoding (which means that the response 307 * has a Transfer-Encoding header), do not set the Content-Length header. 308 * 309 * <p>This method does not need to be either safe or idempotent. 310 * Operations requested through POST can have side effects for 311 * which the user can be held accountable, for example, 312 * updating stored data or buying items online. 313 * 314 * <p>If the HTTP POST request is incorrectly formatted, 315 * <code>doPost</code> returns an HTTP "Bad Request" message. 316 * 317 * 318 * @param req an {@link HttpServletRequest} object that 319 * contains the request the client has made 320 * of the servlet 321 * 322 * @param resp an {@link HttpServletResponse} object that 323 * contains the response the servlet sends 324 * to the client 325 * 326 * @exception IOException if an input or output error is 327 * detected when the servlet handles 328 * the request 329 * 330 * @exception ServletException if the request for the POST 331 * could not be handled 332 * 333 * 334 * @see javax.servlet.ServletOutputStream 335 * @see javax.servlet.ServletResponse#setContentType 336 * 337 * 338 */ 339 340 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 341 throws ServletException, IOException 342 { 343 String protocol = req.getProtocol(); 344 String msg = lStrings.getString("http.method_post_not_supported"); 345 if (protocol.endsWith("1.1")) { 346 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); 347 } else { 348 resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); 349 } 350 } 351 352 353 354 355 /** 356 * Called by the server (via the <code>service</code> method) 357 * to allow a servlet to handle a PUT request. 358 * 359 * The PUT operation allows a client to 360 * place a file on the server and is similar to 361 * sending a file by FTP. 362 * 363 * <p>When overriding this method, leave intact 364 * any content headers sent with the request (including 365 * Content-Length, Content-Type, Content-Transfer-Encoding, 366 * Content-Encoding, Content-Base, Content-Language, Content-Location, 367 * Content-MD5, and Content-Range). If your method cannot 368 * handle a content header, it must issue an error message 369 * (HTTP 501 - Not Implemented) and discard the request. 370 * For more information on HTTP 1.1, see RFC 2616 371 * <a href="http://www.ietf.org/rfc/rfc2616.txt"></a>. 372 * 373 * <p>This method does not need to be either safe or idempotent. 374 * Operations that <code>doPut</code> performs can have side 375 * effects for which the user can be held accountable. When using 376 * this method, it may be useful to save a copy of the 377 * affected URL in temporary storage. 378 * 379 * <p>If the HTTP PUT request is incorrectly formatted, 380 * <code>doPut</code> returns an HTTP "Bad Request" message. 381 * 382 * 383 * @param req the {@link HttpServletRequest} object that 384 * contains the request the client made of 385 * the servlet 386 * 387 * @param resp the {@link HttpServletResponse} object that 388 * contains the response the servlet returns 389 * to the client 390 * 391 * @exception IOException if an input or output error occurs 392 * while the servlet is handling the 393 * PUT request 394 * 395 * @exception ServletException if the request for the PUT 396 * cannot be handled 397 * 398 */ 399 400 protected void doPut(HttpServletRequest req, HttpServletResponse resp) 401 throws ServletException, IOException 402 { 403 String protocol = req.getProtocol(); 404 String msg = lStrings.getString("http.method_put_not_supported"); 405 if (protocol.endsWith("1.1")) { 406 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); 407 } else { 408 resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); 409 } 410 } 411 412 413 414 415 /** 416 * 417 * Called by the server (via the <code>service</code> method) 418 * to allow a servlet to handle a DELETE request. 419 * 420 * The DELETE operation allows a client to remove a document 421 * or Web page from the server. 422 * 423 * <p>This method does not need to be either safe 424 * or idempotent. Operations requested through 425 * DELETE can have side effects for which users 426 * can be held accountable. When using 427 * this method, it may be useful to save a copy of the 428 * affected URL in temporary storage. 429 * 430 * <p>If the HTTP DELETE request is incorrectly formatted, 431 * <code>doDelete</code> returns an HTTP "Bad Request" 432 * message. 433 * 434 * 435 * @param req the {@link HttpServletRequest} object that 436 * contains the request the client made of 437 * the servlet 438 * 439 * 440 * @param resp the {@link HttpServletResponse} object that 441 * contains the response the servlet returns 442 * to the client 443 * 444 * 445 * @exception IOException if an input or output error occurs 446 * while the servlet is handling the 447 * DELETE request 448 * 449 * @exception ServletException if the request for the 450 * DELETE cannot be handled 451 * 452 */ 453 454 protected void doDelete(HttpServletRequest req, 455 HttpServletResponse resp) 456 throws ServletException, IOException 457 { 458 String protocol = req.getProtocol(); 459 String msg = lStrings.getString("http.method_delete_not_supported"); 460 if (protocol.endsWith("1.1")) { 461 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); 462 } else { 463 resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); 464 } 465 } 466 467 468 private static Method[] getAllDeclaredMethods(Class c) { 469 470 if (c.equals(javax.servlet.http.HttpServlet.class)) { 471 return null; 472 } 473 474 Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass()); 475 Method[] thisMethods = c.getDeclaredMethods(); 476 477 if ((parentMethods != null) && (parentMethods.length > 0)) { 478 Method[] allMethods = 479 new Method[parentMethods.length + thisMethods.length]; 480 System.arraycopy(parentMethods, 0, allMethods, 0, 481 parentMethods.length); 482 System.arraycopy(thisMethods, 0, allMethods, parentMethods.length, 483 thisMethods.length); 484 485 thisMethods = allMethods; 486 } 487 488 return thisMethods; 489 } 490 491 492 /** 493 * Called by the server (via the <code>service</code> method) 494 * to allow a servlet to handle a OPTIONS request. 495 * 496 * The OPTIONS request determines which HTTP methods 497 * the server supports and 498 * returns an appropriate header. For example, if a servlet 499 * overrides <code>doGet</code>, this method returns the 500 * following header: 501 * 502 * <p><code>Allow: GET, HEAD, TRACE, OPTIONS</code> 503 * 504 * <p>There's no need to override this method unless the 505 * servlet implements new HTTP methods, beyond those 506 * implemented by HTTP 1.1. 507 * 508 * @param req the {@link HttpServletRequest} object that 509 * contains the request the client made of 510 * the servlet 511 * 512 * 513 * @param resp the {@link HttpServletResponse} object that 514 * contains the response the servlet returns 515 * to the client 516 * 517 * 518 * @exception IOException if an input or output error occurs 519 * while the servlet is handling the 520 * OPTIONS request 521 * 522 * @exception ServletException if the request for the 523 * OPTIONS cannot be handled 524 * 525 */ 526 527 protected void doOptions(HttpServletRequest req, HttpServletResponse resp) 528 throws ServletException, IOException 529 { 530 Method[] methods = getAllDeclaredMethods(this.getClass()); 531 532 boolean ALLOW_GET = false; 533 boolean ALLOW_HEAD = false; 534 boolean ALLOW_POST = false; 535 boolean ALLOW_PUT = false; 536 boolean ALLOW_DELETE = false; 537 boolean ALLOW_TRACE = true; 538 boolean ALLOW_OPTIONS = true; 539 540 for (int i=0; i<methods.length; i++) { 541 Method m = methods[i]; 542 543 if (m.getName().equals("doGet")) { 544 ALLOW_GET = true; 545 ALLOW_HEAD = true; 546 } 547 if (m.getName().equals("doPost")) 548 ALLOW_POST = true; 549 if (m.getName().equals("doPut")) 550 ALLOW_PUT = true; 551 if (m.getName().equals("doDelete")) 552 ALLOW_DELETE = true; 553 554 } 555 556 String allow = null; 557 if (ALLOW_GET) 558 if (allow==null) allow=METHOD_GET; 559 if (ALLOW_HEAD) 560 if (allow==null) allow=METHOD_HEAD; 561 else allow += ", " + METHOD_HEAD; 562 if (ALLOW_POST) 563 if (allow==null) allow=METHOD_POST; 564 else allow += ", " + METHOD_POST; 565 if (ALLOW_PUT) 566 if (allow==null) allow=METHOD_PUT; 567 else allow += ", " + METHOD_PUT; 568 if (ALLOW_DELETE) 569 if (allow==null) allow=METHOD_DELETE; 570 else allow += ", " + METHOD_DELETE; 571 if (ALLOW_TRACE) 572 if (allow==null) allow=METHOD_TRACE; 573 else allow += ", " + METHOD_TRACE; 574 if (ALLOW_OPTIONS) 575 if (allow==null) allow=METHOD_OPTIONS; 576 else allow += ", " + METHOD_OPTIONS; 577 578 resp.setHeader("Allow", allow); 579 } 580 581 582 583 584 /** 585 * Called by the server (via the <code>service</code> method) 586 * to allow a servlet to handle a TRACE request. 587 * 588 * A TRACE returns the headers sent with the TRACE 589 * request to the client, so that they can be used in 590 * debugging. There's no need to override this method. 591 * 592 * 593 * 594 * @param req the {@link HttpServletRequest} object that 595 * contains the request the client made of 596 * the servlet 597 * 598 * 599 * @param resp the {@link HttpServletResponse} object that 600 * contains the response the servlet returns 601 * to the client 602 * 603 * 604 * @exception IOException if an input or output error occurs 605 * while the servlet is handling the 606 * TRACE request 607 * 608 * @exception ServletException if the request for the 609 * TRACE cannot be handled 610 * 611 */ 612 613 protected void doTrace(HttpServletRequest req, HttpServletResponse resp) 614 throws ServletException, IOException 615 { 616 617 int responseLength; 618 619 String CRLF = "\r\n"; 620 String responseString = "TRACE "+ req.getRequestURI()+ 621 " " + req.getProtocol(); 622 623 Enumeration reqHeaderEnum = req.getHeaderNames(); 624 625 while( reqHeaderEnum.hasMoreElements() ) { 626 String headerName = (String)reqHeaderEnum.nextElement(); 627 responseString += CRLF + headerName + ": " + 628 req.getHeader(headerName); 629 } 630 631 responseString += CRLF; 632 633 responseLength = responseString.length(); 634 635 resp.setContentType("message/http"); 636 resp.setContentLength(responseLength); 637 ServletOutputStream out = resp.getOutputStream(); 638 out.print(responseString); 639 out.close(); 640 return; 641 } 642 643 644 645 646 647 /** 648 * 649 * Receives standard HTTP requests from the public 650 * <code>service</code> method and dispatches 651 * them to the <code>do</code><i>XXX</i> methods defined in 652 * this class. This method is an HTTP-specific version of the 653 * {@link javax.servlet.Servlet#service} method. There's no 654 * need to override this method. 655 * 656 * 657 * 658 * @param req the {@link HttpServletRequest} object that 659 * contains the request the client made of 660 * the servlet 661 * 662 * 663 * @param resp the {@link HttpServletResponse} object that 664 * contains the response the servlet returns 665 * to the client 666 * 667 * 668 * @exception IOException if an input or output error occurs 669 * while the servlet is handling the 670 * HTTP request 671 * 672 * @exception ServletException if the HTTP request 673 * cannot be handled 674 * 675 * @see javax.servlet.Servlet#service 676 * 677 */ 678 679 protected void service(HttpServletRequest req, HttpServletResponse resp) 680 throws ServletException, IOException 681 { 682 String method = req.getMethod(); 683 684 if (method.equals(METHOD_GET)) { 685 long lastModified = getLastModified(req); 686 if (lastModified == -1) { 687 // servlet doesn't support if-modified-since, no reason 688 // to go through further expensive logic 689 doGet(req, resp); 690 } else { 691 long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); 692 if (ifModifiedSince < (lastModified / 1000 * 1000)) { 693 // If the servlet mod time is later, call doGet() 694 // Round down to the nearest second for a proper compare 695 // A ifModifiedSince of -1 will always be less 696 maybeSetLastModified(resp, lastModified); 697 doGet(req, resp); 698 } else { 699 resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); 700 } 701 } 702 703 } else if (method.equals(METHOD_HEAD)) { 704 long lastModified = getLastModified(req); 705 maybeSetLastModified(resp, lastModified); 706 doHead(req, resp); 707 708 } else if (method.equals(METHOD_POST)) { 709 doPost(req, resp); 710 711 } else if (method.equals(METHOD_PUT)) { 712 doPut(req, resp); 713 714 } else if (method.equals(METHOD_DELETE)) { 715 doDelete(req, resp); 716 717 } else if (method.equals(METHOD_OPTIONS)) { 718 doOptions(req,resp); 719 720 } else if (method.equals(METHOD_TRACE)) { 721 doTrace(req,resp); 722 723 } else { 724 // 725 // Note that this means NO servlet supports whatever 726 // method was requested, anywhere on this server. 727 // 728 729 String errMsg = lStrings.getString("http.method_not_implemented"); 730 Object[] errArgs = new Object[1]; 731 errArgs[0] = method; 732 errMsg = MessageFormat.format(errMsg, errArgs); 733 734 resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); 735 } 736 } 737 738 739 740 741 742 /* 743 * Sets the Last-Modified entity header field, if it has not 744 * already been set and if the value is meaningful. Called before 745 * doGet, to ensure that headers are set before response data is 746 * written. A subclass might have set this header already, so we 747 * check. 748 */ 749 750 private void maybeSetLastModified(HttpServletResponse resp, 751 long lastModified) { 752 if (resp.containsHeader(HEADER_LASTMOD)) 753 return; 754 if (lastModified >= 0) 755 resp.setDateHeader(HEADER_LASTMOD, lastModified); 756 } 757 758 759 760 761 /** 762 * 763 * Dispatches client requests to the protected 764 * <code>service</code> method. There's no need to 765 * override this method. 766 * 767 * 768 * @param req the {@link HttpServletRequest} object that 769 * contains the request the client made of 770 * the servlet 771 * 772 * 773 * @param res the {@link HttpServletResponse} object that 774 * contains the response the servlet returns 775 * to the client 776 * 777 * 778 * @exception IOException if an input or output error occurs 779 * while the servlet is handling the 780 * HTTP request 781 * 782 * @exception ServletException if the HTTP request cannot 783 * be handled 784 * 785 * 786 * @see javax.servlet.Servlet#service 787 * 788 */ 789 790 public void service(ServletRequest req, ServletResponse res) 791 throws ServletException, IOException 792 { 793 HttpServletRequest request; 794 HttpServletResponse response; 795 796 try { 797 request = (HttpServletRequest) req; 798 response = (HttpServletResponse) res; 799 } catch (ClassCastException e) { 800 throw new ServletException("non-HTTP request or response"); 801 } 802 service(request, response); 803 } 804 } 805 806 807 808 809 /* 810 * A response that includes no body, for use in (dumb) "HEAD" support. 811 * This just swallows that body, counting the bytes in order to set 812 * the content length appropriately. All other methods delegate directly 813 * to the HTTP Servlet Response object used to construct this one. 814 */ 815 // file private 816 class NoBodyResponse implements HttpServletResponse { 817 private HttpServletResponse resp; 818 private NoBodyOutputStream noBody; 819 private PrintWriter writer; 820 private boolean didSetContentLength; 821 822 // file private 823 NoBodyResponse(HttpServletResponse r) { 824 resp = r; 825 noBody = new NoBodyOutputStream(); 826 } 827 828 // file private 829 void setContentLength() { 830 if (!didSetContentLength) 831 resp.setContentLength(noBody.getContentLength()); 832 } 833 834 835 // SERVLET RESPONSE interface methods 836 837 public void setContentLength(int len) { 838 resp.setContentLength(len); 839 didSetContentLength = true; 840 } 841 842 public void setCharacterEncoding(String charset) 843 { resp.setCharacterEncoding(charset); } 844 845 public void setContentType(String type) 846 { resp.setContentType(type); } 847 848 public String getContentType() 849 { return resp.getContentType(); } 850 851 public ServletOutputStream getOutputStream() throws IOException 852 { return noBody; } 853 854 public String getCharacterEncoding() 855 { return resp.getCharacterEncoding(); } 856 857 public PrintWriter getWriter() throws UnsupportedEncodingException 858 { 859 if (writer == null) { 860 OutputStreamWriter w; 861 862 w = new OutputStreamWriter(noBody, getCharacterEncoding()); 863 writer = new PrintWriter(w); 864 } 865 return writer; 866 } 867 868 public void setBufferSize(int size) throws IllegalStateException 869 { resp.setBufferSize(size); } 870 871 public int getBufferSize() 872 { return resp.getBufferSize(); } 873 874 public void reset() throws IllegalStateException 875 { resp.reset(); } 876 877 public void resetBuffer() throws IllegalStateException 878 { resp.resetBuffer(); } 879 880 public boolean isCommitted() 881 { return resp.isCommitted(); } 882 883 public void flushBuffer() throws IOException 884 { resp.flushBuffer(); } 885 886 public void setLocale(Locale loc) 887 { resp.setLocale(loc); } 888 889 public Locale getLocale() 890 { return resp.getLocale(); } 891 892 893 // HTTP SERVLET RESPONSE interface methods 894 895 public void addCookie(Cookie cookie) 896 { resp.addCookie(cookie); } 897 898 public boolean containsHeader(String name) 899 { return resp.containsHeader(name); } 900 901 /** @deprecated */ 902 public void setStatus(int sc, String sm) 903 { resp.setStatus(sc, sm); } 904 905 public void setStatus(int sc) 906 { resp.setStatus(sc); } 907 908 public void setHeader(String name, String value) 909 { resp.setHeader(name, value); } 910 911 public void setIntHeader(String name, int value) 912 { resp.setIntHeader(name, value); } 913 914 public void setDateHeader(String name, long date) 915 { resp.setDateHeader(name, date); } 916 917 public void sendError(int sc, String msg) throws IOException 918 { resp.sendError(sc, msg); } 919 920 public void sendError(int sc) throws IOException 921 { resp.sendError(sc); } 922 923 public void sendRedirect(String location) throws IOException 924 { resp.sendRedirect(location); } 925 926 public String encodeURL(String url) 927 { return resp.encodeURL(url); } 928 929 public String encodeRedirectURL(String url) 930 { return resp.encodeRedirectURL(url); } 931 932 public void addHeader(String name, String value) 933 { resp.addHeader(name, value); } 934 935 public void addDateHeader(String name, long value) 936 { resp.addDateHeader(name, value); } 937 938 public void addIntHeader(String name, int value) 939 { resp.addIntHeader(name, value); } 940 941 942 943 944 /** 945 * @deprecated As of Version 2.1, replaced by 946 * {@link HttpServletResponse#encodeURL}. 947 * 948 */ 949 950 951 public String encodeUrl(String url) 952 { return this.encodeURL(url); } 953 954 955 956 957 958 959 960 961 /** 962 * @deprecated As of Version 2.1, replaced by 963 * {@link HttpServletResponse#encodeRedirectURL}. 964 * 965 */ 966 967 968 public String encodeRedirectUrl(String url) 969 { return this.encodeRedirectURL(url); } 970 971 } 972 973 974 975 976 977 978 979 /* 980 * Servlet output stream that gobbles up all its data. 981 */ 982 983 // file private 984 class NoBodyOutputStream extends ServletOutputStream { 985 986 private static final String LSTRING_FILE = 987 "javax.servlet.http.LocalStrings"; 988 private static ResourceBundle lStrings = 989 ResourceBundle.getBundle(LSTRING_FILE); 990 991 private int contentLength = 0; 992 993 // file private 994 NoBodyOutputStream() {} 995 996 // file private 997 int getContentLength() { 998 return contentLength; 999 } 1000 1001 public void write(int b) { 1002 contentLength++; 1003 } 1004 1005 public void write(byte buf[], int offset, int len) 1006 throws IOException 1007 { 1008 if (len >= 0) { 1009 contentLength += len; 1010 } else { 1011 // XXX 1012 // isn't this really an IllegalArgumentException? 1013 1014 String msg = lStrings.getString("err.io.negativelength"); 1015 throw new IOException("negative length"); 1016 } 1017 } 1018 }