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