Clover coverage report - Maven Clover report
Coverage timestamp: Sun Aug 20 2006 04:03:57 PDT
file stats: LOC: 1,018   Methods: 51
NCLOC: 344   Classes: 3
 
 Source file Conditionals Statements Methods TOTAL
HttpServlet.java 0% 0% 0% 0%
coverage
 1    /*
 2    * Copyright 2004 The Apache Software Foundation
 3    *
 4    * Licensed under the Apache License, Version 2.0 (the "License");
 5    * you may not use this file except in compliance with the License.
 6    * You may obtain a copy of the License at
 7    *
 8    * http://www.apache.org/licenses/LICENSE-2.0
 9    *
 10    * Unless required by applicable law or agreed to in writing, software
 11    * distributed under the License is distributed on an "AS IS" BASIS,
 12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13    * See the License for the specific language governing permissions and
 14    * limitations under the License.
 15    */
 16    package javax.servlet.http;
 17   
 18    import java.io.IOException;
 19    import java.io.PrintWriter;
 20    import java.io.OutputStreamWriter;
 21    import java.io.UnsupportedEncodingException;
 22    import java.lang.reflect.Method;
 23    import java.text.MessageFormat;
 24    import java.util.Enumeration;
 25    import java.util.Locale;
 26    import java.util.ResourceBundle;
 27   
 28    import javax.servlet.GenericServlet;
 29    import javax.servlet.ServletException;
 30    import javax.servlet.ServletOutputStream;
 31    import javax.servlet.ServletRequest;
 32    import javax.servlet.ServletResponse;
 33   
 34   
 35    /**
 36    *
 37    * Provides an abstract class to be subclassed to create
 38    * an HTTP servlet suitable for a Web site. A subclass of
 39    * <code>HttpServlet</code> must override at least
 40    * one method, usually one of these:
 41    *
 42    * <ul>
 43    * <li> <code>doGet</code>, if the servlet supports HTTP GET requests
 44    * <li> <code>doPost</code>, for HTTP POST requests
 45    * <li> <code>doPut</code>, for HTTP PUT requests
 46    * <li> <code>doDelete</code>, for HTTP DELETE requests
 47    * <li> <code>init</code> and <code>destroy</code>,
 48    * to manage resources that are held for the life of the servlet
 49    * <li> <code>getServletInfo</code>, which the servlet uses to
 50    * provide information about itself
 51    * </ul>
 52    *
 53    * <p>There's almost no reason to override the <code>service</code>
 54    * method. <code>service</code> handles standard HTTP
 55    * requests by dispatching them to the handler methods
 56    * for each HTTP request type (the <code>do</code><i>XXX</i>
 57    * methods listed above).
 58    *
 59    * <p>Likewise, there's almost no reason to override the
 60    * <code>doOptions</code> and <code>doTrace</code> methods.
 61    *
 62    * <p>Servlets typically run on multithreaded servers,
 63    * so be aware that a servlet must handle concurrent
 64    * requests and be careful to synchronize access to shared resources.
 65    * Shared resources include in-memory data such as
 66    * instance or class variables and external objects
 67    * such as files, database connections, and network
 68    * connections.
 69    * See the
 70    * <a href="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">
 71    * Java Tutorial on Multithreaded Programming</a> for more
 72    * information on handling multiple threads in a Java program.
 73    *
 74    * @author Various
 75    * @version $Version$
 76    *
 77    */
 78   
 79   
 80   
 81    public abstract class HttpServlet extends GenericServlet
 82    implements java.io.Serializable
 83    {
 84    private static final String METHOD_DELETE = "DELETE";
 85    private static final String METHOD_HEAD = "HEAD";
 86    private static final String METHOD_GET = "GET";
 87    private static final String METHOD_OPTIONS = "OPTIONS";
 88    private static final String METHOD_POST = "POST";
 89    private static final String METHOD_PUT = "PUT";
 90    private static final String METHOD_TRACE = "TRACE";
 91   
 92    private static final String HEADER_IFMODSINCE = "If-Modified-Since";
 93    private static final String HEADER_LASTMOD = "Last-Modified";
 94   
 95    private static final String LSTRING_FILE =
 96    "javax.servlet.http.LocalStrings";
 97    private static ResourceBundle lStrings =
 98    ResourceBundle.getBundle(LSTRING_FILE);
 99   
 100   
 101   
 102   
 103    /**
 104    * Does nothing, because this is an abstract class.
 105    *
 106    */
 107   
 108  0 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  0 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 182    throws ServletException, IOException
 183    {
 184  0 String protocol = req.getProtocol();
 185  0 String msg = lStrings.getString("http.method_get_not_supported");
 186  0 if (protocol.endsWith("1.1")) {
 187  0 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
 188    } else {
 189  0 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  0 protected long getLastModified(HttpServletRequest req) {
 223  0 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  0 protected void doHead(HttpServletRequest req, HttpServletResponse resp)
 266    throws ServletException, IOException
 267    {
 268  0 NoBodyResponse response = new NoBodyResponse(resp);
 269   
 270  0 doGet(req, response);
 271  0 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  0 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
 341    throws ServletException, IOException
 342    {
 343  0 String protocol = req.getProtocol();
 344  0 String msg = lStrings.getString("http.method_post_not_supported");
 345  0 if (protocol.endsWith("1.1")) {
 346  0 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
 347    } else {
 348  0 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  0 protected void doPut(HttpServletRequest req, HttpServletResponse resp)
 401    throws ServletException, IOException
 402    {
 403  0 String protocol = req.getProtocol();
 404  0 String msg = lStrings.getString("http.method_put_not_supported");
 405  0 if (protocol.endsWith("1.1")) {
 406  0 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
 407    } else {
 408  0 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  0 protected void doDelete(HttpServletRequest req,
 455    HttpServletResponse resp)
 456    throws ServletException, IOException
 457    {
 458  0 String protocol = req.getProtocol();
 459  0 String msg = lStrings.getString("http.method_delete_not_supported");
 460  0 if (protocol.endsWith("1.1")) {
 461  0 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
 462    } else {
 463  0 resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
 464    }
 465    }
 466   
 467   
 468  0 private static Method[] getAllDeclaredMethods(Class c) {
 469   
 470  0 if (c.equals(javax.servlet.http.HttpServlet.class)) {
 471  0 return null;
 472    }
 473   
 474  0 Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
 475  0 Method[] thisMethods = c.getDeclaredMethods();
 476   
 477  0 if ((parentMethods != null) && (parentMethods.length > 0)) {
 478  0 Method[] allMethods =
 479    new Method[parentMethods.length + thisMethods.length];
 480  0 System.arraycopy(parentMethods, 0, allMethods, 0,
 481    parentMethods.length);
 482  0 System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
 483    thisMethods.length);
 484   
 485  0 thisMethods = allMethods;
 486    }
 487   
 488  0 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  0 protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
 528    throws ServletException, IOException
 529    {
 530  0 Method[] methods = getAllDeclaredMethods(this.getClass());
 531   
 532  0 boolean ALLOW_GET = false;
 533  0 boolean ALLOW_HEAD = false;
 534  0 boolean ALLOW_POST = false;
 535  0 boolean ALLOW_PUT = false;
 536  0 boolean ALLOW_DELETE = false;
 537  0 boolean ALLOW_TRACE = true;
 538  0 boolean ALLOW_OPTIONS = true;
 539   
 540  0 for (int i=0; i<methods.length; i++) {
 541  0 Method m = methods[i];
 542   
 543  0 if (m.getName().equals("doGet")) {
 544  0 ALLOW_GET = true;
 545  0 ALLOW_HEAD = true;
 546    }
 547  0 if (m.getName().equals("doPost"))
 548  0 ALLOW_POST = true;
 549  0 if (m.getName().equals("doPut"))
 550  0 ALLOW_PUT = true;
 551  0 if (m.getName().equals("doDelete"))
 552  0 ALLOW_DELETE = true;
 553   
 554    }
 555   
 556  0 String allow = null;
 557  0 if (ALLOW_GET)
 558  0 if (allow==null) allow=METHOD_GET;
 559  0 if (ALLOW_HEAD)
 560  0 if (allow==null) allow=METHOD_HEAD;
 561  0 else allow += ", " + METHOD_HEAD;
 562  0 if (ALLOW_POST)
 563  0 if (allow==null) allow=METHOD_POST;
 564  0 else allow += ", " + METHOD_POST;
 565  0 if (ALLOW_PUT)
 566  0 if (allow==null) allow=METHOD_PUT;
 567  0 else allow += ", " + METHOD_PUT;
 568  0 if (ALLOW_DELETE)
 569  0 if (allow==null) allow=METHOD_DELETE;
 570  0 else allow += ", " + METHOD_DELETE;
 571  0 if (ALLOW_TRACE)
 572  0 if (allow==null) allow=METHOD_TRACE;
 573  0 else allow += ", " + METHOD_TRACE;
 574  0 if (ALLOW_OPTIONS)
 575  0 if (allow==null) allow=METHOD_OPTIONS;
 576  0 else allow += ", " + METHOD_OPTIONS;
 577   
 578  0 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  0 protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
 614    throws ServletException, IOException
 615    {
 616   
 617  0 int responseLength;
 618   
 619  0 String CRLF = "\r\n";
 620  0 String responseString = "TRACE "+ req.getRequestURI()+
 621    " " + req.getProtocol();
 622   
 623  0 Enumeration reqHeaderEnum = req.getHeaderNames();
 624   
 625  0 while( reqHeaderEnum.hasMoreElements() ) {
 626  0 String headerName = (String)reqHeaderEnum.nextElement();
 627  0 responseString += CRLF + headerName + ": " +
 628    req.getHeader(headerName);
 629    }
 630   
 631  0 responseString += CRLF;
 632   
 633  0 responseLength = responseString.length();
 634   
 635  0 resp.setContentType("message/http");
 636  0 resp.setContentLength(responseLength);
 637  0 ServletOutputStream out = resp.getOutputStream();
 638  0 out.print(responseString);
 639  0 out.close();
 640  0 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  0 protected void service(HttpServletRequest req, HttpServletResponse resp)
 680    throws ServletException, IOException
 681    {
 682  0 String method = req.getMethod();
 683   
 684  0 if (method.equals(METHOD_GET)) {
 685  0 long lastModified = getLastModified(req);
 686  0 if (lastModified == -1) {
 687    // servlet doesn't support if-modified-since, no reason
 688    // to go through further expensive logic
 689  0 doGet(req, resp);
 690    } else {
 691  0 long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
 692  0 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  0 maybeSetLastModified(resp, lastModified);
 697  0 doGet(req, resp);
 698    } else {
 699  0 resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
 700    }
 701    }
 702   
 703  0 } else if (method.equals(METHOD_HEAD)) {
 704  0 long lastModified = getLastModified(req);
 705  0 maybeSetLastModified(resp, lastModified);
 706  0 doHead(req, resp);
 707   
 708  0 } else if (method.equals(METHOD_POST)) {
 709  0 doPost(req, resp);
 710   
 711  0 } else if (method.equals(METHOD_PUT)) {
 712  0 doPut(req, resp);
 713   
 714  0 } else if (method.equals(METHOD_DELETE)) {
 715  0 doDelete(req, resp);
 716   
 717  0 } else if (method.equals(METHOD_OPTIONS)) {
 718  0 doOptions(req,resp);
 719   
 720  0 } else if (method.equals(METHOD_TRACE)) {
 721  0 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  0 String errMsg = lStrings.getString("http.method_not_implemented");
 730  0 Object[] errArgs = new Object[1];
 731  0 errArgs[0] = method;
 732  0 errMsg = MessageFormat.format(errMsg, errArgs);
 733   
 734  0 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  0 private void maybeSetLastModified(HttpServletResponse resp,
 751    long lastModified) {
 752  0 if (resp.containsHeader(HEADER_LASTMOD))
 753  0 return;
 754  0 if (lastModified >= 0)
 755  0 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  0 public void service(ServletRequest req, ServletResponse res)
 791    throws ServletException, IOException
 792    {
 793  0 HttpServletRequest request;
 794  0 HttpServletResponse response;
 795   
 796  0 try {
 797  0 request = (HttpServletRequest) req;
 798  0 response = (HttpServletResponse) res;
 799    } catch (ClassCastException e) {
 800  0 throw new ServletException("non-HTTP request or response");
 801    }
 802  0 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  0 NoBodyResponse(HttpServletResponse r) {
 824  0 resp = r;
 825  0 noBody = new NoBodyOutputStream();
 826    }
 827   
 828    // file private
 829  0 void setContentLength() {
 830  0 if (!didSetContentLength)
 831  0 resp.setContentLength(noBody.getContentLength());
 832    }
 833   
 834   
 835    // SERVLET RESPONSE interface methods
 836   
 837  0 public void setContentLength(int len) {
 838  0 resp.setContentLength(len);
 839  0 didSetContentLength = true;
 840    }
 841   
 842  0 public void setCharacterEncoding(String charset)
 843  0 { resp.setCharacterEncoding(charset); }
 844   
 845  0 public void setContentType(String type)
 846  0 { resp.setContentType(type); }
 847   
 848  0 public String getContentType()
 849  0 { return resp.getContentType(); }
 850   
 851  0 public ServletOutputStream getOutputStream() throws IOException
 852  0 { return noBody; }
 853   
 854  0 public String getCharacterEncoding()
 855  0 { return resp.getCharacterEncoding(); }
 856   
 857  0 public PrintWriter getWriter() throws UnsupportedEncodingException
 858    {
 859  0 if (writer == null) {
 860  0 OutputStreamWriter w;
 861   
 862  0 w = new OutputStreamWriter(noBody, getCharacterEncoding());
 863  0 writer = new PrintWriter(w);
 864    }
 865  0 return writer;
 866    }
 867   
 868  0 public void setBufferSize(int size) throws IllegalStateException
 869  0 { resp.setBufferSize(size); }
 870   
 871  0 public int getBufferSize()
 872  0 { return resp.getBufferSize(); }
 873   
 874  0 public void reset() throws IllegalStateException
 875  0 { resp.reset(); }
 876   
 877  0 public void resetBuffer() throws IllegalStateException
 878  0 { resp.resetBuffer(); }
 879   
 880  0 public boolean isCommitted()
 881  0 { return resp.isCommitted(); }
 882   
 883  0 public void flushBuffer() throws IOException
 884  0 { resp.flushBuffer(); }
 885   
 886  0 public void setLocale(Locale loc)
 887  0 { resp.setLocale(loc); }
 888   
 889  0 public Locale getLocale()
 890  0 { return resp.getLocale(); }
 891   
 892   
 893    // HTTP SERVLET RESPONSE interface methods
 894   
 895  0 public void addCookie(Cookie cookie)
 896  0 { resp.addCookie(cookie); }
 897   
 898  0 public boolean containsHeader(String name)
 899  0 { return resp.containsHeader(name); }
 900   
 901    /** @deprecated */
 902  0 public void setStatus(int sc, String sm)
 903  0 { resp.setStatus(sc, sm); }
 904   
 905  0 public void setStatus(int sc)
 906  0 { resp.setStatus(sc); }
 907   
 908  0 public void setHeader(String name, String value)
 909  0 { resp.setHeader(name, value); }
 910   
 911  0 public void setIntHeader(String name, int value)
 912  0 { resp.setIntHeader(name, value); }
 913   
 914  0 public void setDateHeader(String name, long date)
 915  0 { resp.setDateHeader(name, date); }
 916   
 917  0 public void sendError(int sc, String msg) throws IOException
 918  0 { resp.sendError(sc, msg); }
 919   
 920  0 public void sendError(int sc) throws IOException
 921  0 { resp.sendError(sc); }
 922   
 923  0 public void sendRedirect(String location) throws IOException
 924  0 { resp.sendRedirect(location); }
 925   
 926  0 public String encodeURL(String url)
 927  0 { return resp.encodeURL(url); }
 928   
 929  0 public String encodeRedirectURL(String url)
 930  0 { return resp.encodeRedirectURL(url); }
 931   
 932  0 public void addHeader(String name, String value)
 933  0 { resp.addHeader(name, value); }
 934   
 935  0 public void addDateHeader(String name, long value)
 936  0 { resp.addDateHeader(name, value); }
 937   
 938  0 public void addIntHeader(String name, int value)
 939  0 { 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  0 public String encodeUrl(String url)
 952  0 { 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  0 public String encodeRedirectUrl(String url)
 969  0 { 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  0 NoBodyOutputStream() {}
 995   
 996    // file private
 997  0 int getContentLength() {
 998  0 return contentLength;
 999    }
 1000   
 1001  0 public void write(int b) {
 1002  0 contentLength++;
 1003    }
 1004   
 1005  0 public void write(byte buf[], int offset, int len)
 1006    throws IOException
 1007    {
 1008  0 if (len >= 0) {
 1009  0 contentLength += len;
 1010    } else {
 1011    // XXX
 1012    // isn't this really an IllegalArgumentException?
 1013   
 1014  0 String msg = lStrings.getString("err.io.negativelength");
 1015  0 throw new IOException("negative length");
 1016    }
 1017    }
 1018    }