View Javadoc

    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    841     NoBodyResponse(HttpServletResponse r) {
    842 	resp = r;
    843 	noBody = new NoBodyOutputStream();
    844     }
    845
    846     // file private
    847     void setContentLength() {
    848 	if (!didSetContentLength)
    849 	  resp.setContentLength(noBody.getContentLength());
    850     }
    851
    852
    853     // SERVLET RESPONSE interface methods
    854
    855     public void setContentLength(int len) {
    856 	resp.setContentLength(len);
    857 	didSetContentLength = true;
    858     }
    859
    860     public void setCharacterEncoding(String charset)
    861       { resp.setCharacterEncoding(charset); }
    862
    863     public void setContentType(String type)
    864       { resp.setContentType(type); }
    865
    866     public String getContentType()
    867       { return resp.getContentType(); }
    868
    869     public ServletOutputStream getOutputStream() throws IOException
    870       { return noBody; }
    871
    872     public String getCharacterEncoding()
    873 	{ return resp.getCharacterEncoding(); }
    874
    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
    886     public void setBufferSize(int size) throws IllegalStateException
    887       { resp.setBufferSize(size); }
    888
    889     public int getBufferSize()
    890       { return resp.getBufferSize(); }
    891
    892     public void reset() throws IllegalStateException
    893       { resp.reset(); }
    894
    895       public void resetBuffer() throws IllegalStateException
    896       { resp.resetBuffer(); }
    897
    898     public boolean isCommitted()
    899       { return resp.isCommitted(); }
    900
    901     public void flushBuffer() throws IOException
    902       { resp.flushBuffer(); }
    903
    904     public void setLocale(Locale loc)
    905       { resp.setLocale(loc); }
    906
    907     public Locale getLocale()
    908       { return resp.getLocale(); }
    909
    910
    911     // HTTP SERVLET RESPONSE interface methods
    912
    913     public void addCookie(Cookie cookie)
    914       { resp.addCookie(cookie); }
    915
    916     public boolean containsHeader(String name)
    917       { return resp.containsHeader(name); }
    918
    919     /** @deprecated */
    920     public void setStatus(int sc, String sm)
    921       { resp.setStatus(sc, sm); }
    922
    923     public void setStatus(int sc)
    924       { resp.setStatus(sc); }
    925
    926     public void setHeader(String name, String value)
    927       { resp.setHeader(name, value); }
    928
    929     public void setIntHeader(String name, int value)
    930       { resp.setIntHeader(name, value); }
    931
    932     public void setDateHeader(String name, long date)
    933       { resp.setDateHeader(name, date); }
    934
    935     public void sendError(int sc, String msg) throws IOException
    936       { resp.sendError(sc, msg); }
    937
    938     public void sendError(int sc) throws IOException
    939       { resp.sendError(sc); }
    940
    941     public void sendRedirect(String location) throws IOException
    942       { resp.sendRedirect(location); }
    943
    944     public String encodeURL(String url)
    945       { return resp.encodeURL(url); }
    946
    947     public String encodeRedirectURL(String url)
    948       { return resp.encodeRedirectURL(url); }
    949
    950     public void addHeader(String name, String value)
    951       { resp.addHeader(name, value); }
    952
    953     public void addDateHeader(String name, long value)
    954       { resp.addDateHeader(name, value); }
    955
    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
    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
    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
    1012     NoBodyOutputStream() {}
    1013
    1014     // file private
    1015     int getContentLength() {
    1016 	return contentLength;
    1017     }
    1018
    1019     public void write(int b) {
    1020 	contentLength++;
    1021     }
    1022
    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 }