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