0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: package javax.servlet.http;
0018:
0019: import java.io.IOException;
0020: import java.io.PrintWriter;
0021: import java.io.OutputStreamWriter;
0022: import java.io.UnsupportedEncodingException;
0023: import java.lang.reflect.Method;
0024: import java.text.MessageFormat;
0025: import java.util.Enumeration;
0026: import java.util.Locale;
0027: import java.util.ResourceBundle;
0028:
0029: import javax.servlet.GenericServlet;
0030: import javax.servlet.ServletException;
0031: import javax.servlet.ServletOutputStream;
0032: import javax.servlet.ServletRequest;
0033: import javax.servlet.ServletResponse;
0034:
0035: /**
0036: *
0037: * Provides an abstract class to be subclassed to create
0038: * an HTTP servlet suitable for a Web site. A subclass of
0039: * <code>HttpServlet</code> must override at least
0040: * one method, usually one of these:
0041: *
0042: * <ul>
0043: * <li> <code>doGet</code>, if the servlet supports HTTP GET requests
0044: * <li> <code>doPost</code>, for HTTP POST requests
0045: * <li> <code>doPut</code>, for HTTP PUT requests
0046: * <li> <code>doDelete</code>, for HTTP DELETE requests
0047: * <li> <code>init</code> and <code>destroy</code>,
0048: * to manage resources that are held for the life of the servlet
0049: * <li> <code>getServletInfo</code>, which the servlet uses to
0050: * provide information about itself
0051: * </ul>
0052: *
0053: * <p>There's almost no reason to override the <code>service</code>
0054: * method. <code>service</code> handles standard HTTP
0055: * requests by dispatching them to the handler methods
0056: * for each HTTP request type (the <code>do</code><i>XXX</i>
0057: * methods listed above).
0058: *
0059: * <p>Likewise, there's almost no reason to override the
0060: * <code>doOptions</code> and <code>doTrace</code> methods.
0061: *
0062: * <p>Servlets typically run on multithreaded servers,
0063: * so be aware that a servlet must handle concurrent
0064: * requests and be careful to synchronize access to shared resources.
0065: * Shared resources include in-memory data such as
0066: * instance or class variables and external objects
0067: * such as files, database connections, and network
0068: * connections.
0069: * See the
0070: * <a href="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">
0071: * Java Tutorial on Multithreaded Programming</a> for more
0072: * information on handling multiple threads in a Java program.
0073: *
0074: * @author Various
0075: * @version $Version$
0076: *
0077: */
0078:
0079: public abstract class HttpServlet extends GenericServlet implements
0080: java.io.Serializable {
0081: private static final String METHOD_DELETE = "DELETE";
0082: private static final String METHOD_HEAD = "HEAD";
0083: private static final String METHOD_GET = "GET";
0084: private static final String METHOD_OPTIONS = "OPTIONS";
0085: private static final String METHOD_POST = "POST";
0086: private static final String METHOD_PUT = "PUT";
0087: private static final String METHOD_TRACE = "TRACE";
0088:
0089: private static final String HEADER_IFMODSINCE = "If-Modified-Since";
0090: private static final String HEADER_LASTMOD = "Last-Modified";
0091:
0092: private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
0093: private static ResourceBundle lStrings = ResourceBundle
0094: .getBundle(LSTRING_FILE);
0095:
0096: /**
0097: * Does nothing, because this is an abstract class.
0098: *
0099: */
0100:
0101: public HttpServlet() {
0102: }
0103:
0104: /**
0105: *
0106: * Called by the server (via the <code>service</code> method) to
0107: * allow a servlet to handle a GET request.
0108: *
0109: * <p>Overriding this method to support a GET request also
0110: * automatically supports an HTTP HEAD request. A HEAD
0111: * request is a GET request that returns no body in the
0112: * response, only the request header fields.
0113: *
0114: * <p>When overriding this method, read the request data,
0115: * write the response headers, get the response's writer or
0116: * output stream object, and finally, write the response data.
0117: * It's best to include content type and encoding. When using
0118: * a <code>PrintWriter</code> object to return the response,
0119: * set the content type before accessing the
0120: * <code>PrintWriter</code> object.
0121: *
0122: * <p>The servlet container must write the headers before
0123: * committing the response, because in HTTP the headers must be sent
0124: * before the response body.
0125: *
0126: * <p>Where possible, set the Content-Length header (with the
0127: * {@link javax.servlet.ServletResponse#setContentLength} method),
0128: * to allow the servlet container to use a persistent connection
0129: * to return its response to the client, improving performance.
0130: * The content length is automatically set if the entire response fits
0131: * inside the response buffer.
0132: *
0133: * <p>When using HTTP 1.1 chunked encoding (which means that the response
0134: * has a Transfer-Encoding header), do not set the Content-Length header.
0135: *
0136: * <p>The GET method should be safe, that is, without
0137: * any side effects for which users are held responsible.
0138: * For example, most form queries have no side effects.
0139: * If a client request is intended to change stored data,
0140: * the request should use some other HTTP method.
0141: *
0142: * <p>The GET method should also be idempotent, meaning
0143: * that it can be safely repeated. Sometimes making a
0144: * method safe also makes it idempotent. For example,
0145: * repeating queries is both safe and idempotent, but
0146: * buying a product online or modifying data is neither
0147: * safe nor idempotent.
0148: *
0149: * <p>If the request is incorrectly formatted, <code>doGet</code>
0150: * returns an HTTP "Bad Request" message.
0151: *
0152: *
0153: * @param req an {@link HttpServletRequest} object that
0154: * contains the request the client has made
0155: * of the servlet
0156: *
0157: * @param resp an {@link HttpServletResponse} object that
0158: * contains the response the servlet sends
0159: * to the client
0160: *
0161: * @exception IOException if an input or output error is
0162: * detected when the servlet handles
0163: * the GET request
0164: *
0165: * @exception ServletException if the request for the GET
0166: * could not be handled
0167: *
0168: *
0169: * @see javax.servlet.ServletResponse#setContentType
0170: *
0171: */
0172:
0173: protected void doGet(HttpServletRequest req,
0174: HttpServletResponse resp) throws ServletException,
0175: IOException {
0176: String protocol = req.getProtocol();
0177: String msg = lStrings
0178: .getString("http.method_get_not_supported");
0179: if (protocol.endsWith("1.1")) {
0180: resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED,
0181: msg);
0182: } else {
0183: resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
0184: }
0185: }
0186:
0187: /**
0188: *
0189: * Returns the time the <code>HttpServletRequest</code>
0190: * object was last modified,
0191: * in milliseconds since midnight January 1, 1970 GMT.
0192: * If the time is unknown, this method returns a negative
0193: * number (the default).
0194: *
0195: * <p>Servlets that support HTTP GET requests and can quickly determine
0196: * their last modification time should override this method.
0197: * This makes browser and proxy caches work more effectively,
0198: * reducing the load on server and network resources.
0199: *
0200: *
0201: * @param req the <code>HttpServletRequest</code>
0202: * object that is sent to the servlet
0203: *
0204: * @return a <code>long</code> integer specifying
0205: * the time the <code>HttpServletRequest</code>
0206: * object was last modified, in milliseconds
0207: * since midnight, January 1, 1970 GMT, or
0208: * -1 if the time is not known
0209: *
0210: */
0211:
0212: protected long getLastModified(HttpServletRequest req) {
0213: return -1;
0214: }
0215:
0216: /**
0217: *
0218: *
0219: * <p>Receives an HTTP HEAD request from the protected
0220: * <code>service</code> method and handles the
0221: * request.
0222: * The client sends a HEAD request when it wants
0223: * to see only the headers of a response, such as
0224: * Content-Type or Content-Length. The HTTP HEAD
0225: * method counts the output bytes in the response
0226: * to set the Content-Length header accurately.
0227: *
0228: * <p>If you override this method, you can avoid computing
0229: * the response body and just set the response headers
0230: * directly to improve performance. Make sure that the
0231: * <code>doHead</code> method you write is both safe
0232: * and idempotent (that is, protects itself from being
0233: * called multiple times for one HTTP HEAD request).
0234: *
0235: * <p>If the HTTP HEAD request is incorrectly formatted,
0236: * <code>doHead</code> returns an HTTP "Bad Request"
0237: * message.
0238: *
0239: *
0240: * @param req the request object that is passed
0241: * to the servlet
0242: *
0243: * @param resp the response object that the servlet
0244: * uses to return the headers to the clien
0245: *
0246: * @exception IOException if an input or output error occurs
0247: *
0248: * @exception ServletException if the request for the HEAD
0249: * could not be handled
0250: */
0251:
0252: protected void doHead(HttpServletRequest req,
0253: HttpServletResponse resp) throws ServletException,
0254: IOException {
0255: NoBodyResponse response = new NoBodyResponse(resp);
0256:
0257: doGet(req, response);
0258: response.setContentLength();
0259: }
0260:
0261: /**
0262: *
0263: * Called by the server (via the <code>service</code> method)
0264: * to allow a servlet to handle a POST request.
0265: *
0266: * The HTTP POST method allows the client to send
0267: * data of unlimited length to the Web server a single time
0268: * and is useful when posting information such as
0269: * credit card numbers.
0270: *
0271: * <p>When overriding this method, read the request data,
0272: * write the response headers, get the response's writer or output
0273: * stream object, and finally, write the response data. It's best
0274: * to include content type and encoding. When using a
0275: * <code>PrintWriter</code> object to return the response, set the
0276: * content type before accessing the <code>PrintWriter</code> object.
0277: *
0278: * <p>The servlet container must write the headers before committing the
0279: * response, because in HTTP the headers must be sent before the
0280: * response body.
0281: *
0282: * <p>Where possible, set the Content-Length header (with the
0283: * {@link javax.servlet.ServletResponse#setContentLength} method),
0284: * to allow the servlet container to use a persistent connection
0285: * to return its response to the client, improving performance.
0286: * The content length is automatically set if the entire response fits
0287: * inside the response buffer.
0288: *
0289: * <p>When using HTTP 1.1 chunked encoding (which means that the response
0290: * has a Transfer-Encoding header), do not set the Content-Length header.
0291: *
0292: * <p>This method does not need to be either safe or idempotent.
0293: * Operations requested through POST can have side effects for
0294: * which the user can be held accountable, for example,
0295: * updating stored data or buying items online.
0296: *
0297: * <p>If the HTTP POST request is incorrectly formatted,
0298: * <code>doPost</code> returns an HTTP "Bad Request" message.
0299: *
0300: *
0301: * @param req an {@link HttpServletRequest} object that
0302: * contains the request the client has made
0303: * of the servlet
0304: *
0305: * @param resp an {@link HttpServletResponse} object that
0306: * contains the response the servlet sends
0307: * to the client
0308: *
0309: * @exception IOException if an input or output error is
0310: * detected when the servlet handles
0311: * the request
0312: *
0313: * @exception ServletException if the request for the POST
0314: * could not be handled
0315: *
0316: *
0317: * @see javax.servlet.ServletOutputStream
0318: * @see javax.servlet.ServletResponse#setContentType
0319: *
0320: *
0321: */
0322:
0323: protected void doPost(HttpServletRequest req,
0324: HttpServletResponse resp) throws ServletException,
0325: IOException {
0326: String protocol = req.getProtocol();
0327: String msg = lStrings
0328: .getString("http.method_post_not_supported");
0329: if (protocol.endsWith("1.1")) {
0330: resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED,
0331: msg);
0332: } else {
0333: resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
0334: }
0335: }
0336:
0337: /**
0338: * Called by the server (via the <code>service</code> method)
0339: * to allow a servlet to handle a PUT request.
0340: *
0341: * The PUT operation allows a client to
0342: * place a file on the server and is similar to
0343: * sending a file by FTP.
0344: *
0345: * <p>When overriding this method, leave intact
0346: * any content headers sent with the request (including
0347: * Content-Length, Content-Type, Content-Transfer-Encoding,
0348: * Content-Encoding, Content-Base, Content-Language, Content-Location,
0349: * Content-MD5, and Content-Range). If your method cannot
0350: * handle a content header, it must issue an error message
0351: * (HTTP 501 - Not Implemented) and discard the request.
0352: * For more information on HTTP 1.1, see RFC 2616
0353: * <a href="http://www.ietf.org/rfc/rfc2616.txt"></a>.
0354: *
0355: * <p>This method does not need to be either safe or idempotent.
0356: * Operations that <code>doPut</code> performs can have side
0357: * effects for which the user can be held accountable. When using
0358: * this method, it may be useful to save a copy of the
0359: * affected URL in temporary storage.
0360: *
0361: * <p>If the HTTP PUT request is incorrectly formatted,
0362: * <code>doPut</code> returns an HTTP "Bad Request" message.
0363: *
0364: *
0365: * @param req the {@link HttpServletRequest} object that
0366: * contains the request the client made of
0367: * the servlet
0368: *
0369: * @param resp the {@link HttpServletResponse} object that
0370: * contains the response the servlet returns
0371: * to the client
0372: *
0373: * @exception IOException if an input or output error occurs
0374: * while the servlet is handling the
0375: * PUT request
0376: *
0377: * @exception ServletException if the request for the PUT
0378: * cannot be handled
0379: *
0380: */
0381:
0382: protected void doPut(HttpServletRequest req,
0383: HttpServletResponse resp) throws ServletException,
0384: IOException {
0385: String protocol = req.getProtocol();
0386: String msg = lStrings
0387: .getString("http.method_put_not_supported");
0388: if (protocol.endsWith("1.1")) {
0389: resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED,
0390: msg);
0391: } else {
0392: resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
0393: }
0394: }
0395:
0396: /**
0397: *
0398: * Called by the server (via the <code>service</code> method)
0399: * to allow a servlet to handle a DELETE request.
0400: *
0401: * The DELETE operation allows a client to remove a document
0402: * or Web page from the server.
0403: *
0404: * <p>This method does not need to be either safe
0405: * or idempotent. Operations requested through
0406: * DELETE can have side effects for which users
0407: * can be held accountable. When using
0408: * this method, it may be useful to save a copy of the
0409: * affected URL in temporary storage.
0410: *
0411: * <p>If the HTTP DELETE request is incorrectly formatted,
0412: * <code>doDelete</code> returns an HTTP "Bad Request"
0413: * message.
0414: *
0415: *
0416: * @param req the {@link HttpServletRequest} object that
0417: * contains the request the client made of
0418: * the servlet
0419: *
0420: *
0421: * @param resp the {@link HttpServletResponse} object that
0422: * contains the response the servlet returns
0423: * to the client
0424: *
0425: *
0426: * @exception IOException if an input or output error occurs
0427: * while the servlet is handling the
0428: * DELETE request
0429: *
0430: * @exception ServletException if the request for the
0431: * DELETE cannot be handled
0432: *
0433: */
0434:
0435: protected void doDelete(HttpServletRequest req,
0436: HttpServletResponse resp) throws ServletException,
0437: IOException {
0438: String protocol = req.getProtocol();
0439: String msg = lStrings
0440: .getString("http.method_delete_not_supported");
0441: if (protocol.endsWith("1.1")) {
0442: resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED,
0443: msg);
0444: } else {
0445: resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
0446: }
0447: }
0448:
0449: private static Method[] getAllDeclaredMethods(Class c) {
0450:
0451: if (c.equals(javax.servlet.http.HttpServlet.class)) {
0452: return null;
0453: }
0454:
0455: Method[] parentMethods = getAllDeclaredMethods(c
0456: .getSuperclass());
0457: Method[] this Methods = c.getDeclaredMethods();
0458:
0459: if ((parentMethods != null) && (parentMethods.length > 0)) {
0460: Method[] allMethods = new Method[parentMethods.length
0461: + this Methods.length];
0462: System.arraycopy(parentMethods, 0, allMethods, 0,
0463: parentMethods.length);
0464: System.arraycopy(this Methods, 0, allMethods,
0465: parentMethods.length, this Methods.length);
0466:
0467: this Methods = allMethods;
0468: }
0469:
0470: return this Methods;
0471: }
0472:
0473: /**
0474: * Called by the server (via the <code>service</code> method)
0475: * to allow a servlet to handle a OPTIONS request.
0476: *
0477: * The OPTIONS request determines which HTTP methods
0478: * the server supports and
0479: * returns an appropriate header. For example, if a servlet
0480: * overrides <code>doGet</code>, this method returns the
0481: * following header:
0482: *
0483: * <p><code>Allow: GET, HEAD, TRACE, OPTIONS</code>
0484: *
0485: * <p>There's no need to override this method unless the
0486: * servlet implements new HTTP methods, beyond those
0487: * implemented by HTTP 1.1.
0488: *
0489: * @param req the {@link HttpServletRequest} object that
0490: * contains the request the client made of
0491: * the servlet
0492: *
0493: *
0494: * @param resp the {@link HttpServletResponse} object that
0495: * contains the response the servlet returns
0496: * to the client
0497: *
0498: *
0499: * @exception IOException if an input or output error occurs
0500: * while the servlet is handling the
0501: * OPTIONS request
0502: *
0503: * @exception ServletException if the request for the
0504: * OPTIONS cannot be handled
0505: *
0506: */
0507:
0508: protected void doOptions(HttpServletRequest req,
0509: HttpServletResponse resp) throws ServletException,
0510: IOException {
0511: Method[] methods = getAllDeclaredMethods(this .getClass());
0512:
0513: boolean ALLOW_GET = false;
0514: boolean ALLOW_HEAD = false;
0515: boolean ALLOW_POST = false;
0516: boolean ALLOW_PUT = false;
0517: boolean ALLOW_DELETE = false;
0518: boolean ALLOW_TRACE = true;
0519: boolean ALLOW_OPTIONS = true;
0520:
0521: for (int i = 0; i < methods.length; i++) {
0522: Method m = methods[i];
0523:
0524: if (m.getName().equals("doGet")) {
0525: ALLOW_GET = true;
0526: ALLOW_HEAD = true;
0527: }
0528: if (m.getName().equals("doPost"))
0529: ALLOW_POST = true;
0530: if (m.getName().equals("doPut"))
0531: ALLOW_PUT = true;
0532: if (m.getName().equals("doDelete"))
0533: ALLOW_DELETE = true;
0534:
0535: }
0536:
0537: String allow = null;
0538: if (ALLOW_GET)
0539: if (allow == null)
0540: allow = METHOD_GET;
0541: if (ALLOW_HEAD)
0542: if (allow == null)
0543: allow = METHOD_HEAD;
0544: else
0545: allow += ", " + METHOD_HEAD;
0546: if (ALLOW_POST)
0547: if (allow == null)
0548: allow = METHOD_POST;
0549: else
0550: allow += ", " + METHOD_POST;
0551: if (ALLOW_PUT)
0552: if (allow == null)
0553: allow = METHOD_PUT;
0554: else
0555: allow += ", " + METHOD_PUT;
0556: if (ALLOW_DELETE)
0557: if (allow == null)
0558: allow = METHOD_DELETE;
0559: else
0560: allow += ", " + METHOD_DELETE;
0561: if (ALLOW_TRACE)
0562: if (allow == null)
0563: allow = METHOD_TRACE;
0564: else
0565: allow += ", " + METHOD_TRACE;
0566: if (ALLOW_OPTIONS)
0567: if (allow == null)
0568: allow = METHOD_OPTIONS;
0569: else
0570: allow += ", " + METHOD_OPTIONS;
0571:
0572: resp.setHeader("Allow", allow);
0573: }
0574:
0575: /**
0576: * Called by the server (via the <code>service</code> method)
0577: * to allow a servlet to handle a TRACE request.
0578: *
0579: * A TRACE returns the headers sent with the TRACE
0580: * request to the client, so that they can be used in
0581: * debugging. There's no need to override this method.
0582: *
0583: *
0584: *
0585: * @param req the {@link HttpServletRequest} object that
0586: * contains the request the client made of
0587: * the servlet
0588: *
0589: *
0590: * @param resp the {@link HttpServletResponse} object that
0591: * contains the response the servlet returns
0592: * to the client
0593: *
0594: *
0595: * @exception IOException if an input or output error occurs
0596: * while the servlet is handling the
0597: * TRACE request
0598: *
0599: * @exception ServletException if the request for the
0600: * TRACE cannot be handled
0601: *
0602: */
0603:
0604: protected void doTrace(HttpServletRequest req,
0605: HttpServletResponse resp) throws ServletException,
0606: IOException {
0607:
0608: int responseLength;
0609:
0610: String CRLF = "\r\n";
0611: String responseString = "TRACE " + req.getRequestURI() + " "
0612: + req.getProtocol();
0613:
0614: Enumeration reqHeaderEnum = req.getHeaderNames();
0615:
0616: while (reqHeaderEnum.hasMoreElements()) {
0617: String headerName = (String) reqHeaderEnum.nextElement();
0618: responseString += CRLF + headerName + ": "
0619: + req.getHeader(headerName);
0620: }
0621:
0622: responseString += CRLF;
0623:
0624: responseLength = responseString.length();
0625:
0626: resp.setContentType("message/http");
0627: resp.setContentLength(responseLength);
0628: ServletOutputStream out = resp.getOutputStream();
0629: out.print(responseString);
0630: out.close();
0631: return;
0632: }
0633:
0634: /**
0635: *
0636: * Receives standard HTTP requests from the public
0637: * <code>service</code> method and dispatches
0638: * them to the <code>do</code><i>XXX</i> methods defined in
0639: * this class. This method is an HTTP-specific version of the
0640: * {@link javax.servlet.Servlet#service} method. There's no
0641: * need to override this method.
0642: *
0643: *
0644: *
0645: * @param req the {@link HttpServletRequest} object that
0646: * contains the request the client made of
0647: * the servlet
0648: *
0649: *
0650: * @param resp the {@link HttpServletResponse} object that
0651: * contains the response the servlet returns
0652: * to the client
0653: *
0654: *
0655: * @exception IOException if an input or output error occurs
0656: * while the servlet is handling the
0657: * HTTP request
0658: *
0659: * @exception ServletException if the HTTP request
0660: * cannot be handled
0661: *
0662: * @see javax.servlet.Servlet#service
0663: *
0664: */
0665:
0666: protected void service(HttpServletRequest req,
0667: HttpServletResponse resp) throws ServletException,
0668: IOException {
0669: String method = req.getMethod();
0670:
0671: if (method.equals(METHOD_GET)) {
0672: long lastModified = getLastModified(req);
0673: if (lastModified == -1) {
0674: // servlet doesn't support if-modified-since, no reason
0675: // to go through further expensive logic
0676: doGet(req, resp);
0677: } else {
0678: long ifModifiedSince = req
0679: .getDateHeader(HEADER_IFMODSINCE);
0680: if (ifModifiedSince < (lastModified / 1000 * 1000)) {
0681: // If the servlet mod time is later, call doGet()
0682: // Round down to the nearest second for a proper compare
0683: // A ifModifiedSince of -1 will always be less
0684: maybeSetLastModified(resp, lastModified);
0685: doGet(req, resp);
0686: } else {
0687: resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
0688: }
0689: }
0690:
0691: } else if (method.equals(METHOD_HEAD)) {
0692: long lastModified = getLastModified(req);
0693: maybeSetLastModified(resp, lastModified);
0694: doHead(req, resp);
0695:
0696: } else if (method.equals(METHOD_POST)) {
0697: doPost(req, resp);
0698:
0699: } else if (method.equals(METHOD_PUT)) {
0700: doPut(req, resp);
0701:
0702: } else if (method.equals(METHOD_DELETE)) {
0703: doDelete(req, resp);
0704:
0705: } else if (method.equals(METHOD_OPTIONS)) {
0706: doOptions(req, resp);
0707:
0708: } else if (method.equals(METHOD_TRACE)) {
0709: doTrace(req, resp);
0710:
0711: } else {
0712: //
0713: // Note that this means NO servlet supports whatever
0714: // method was requested, anywhere on this server.
0715: //
0716:
0717: String errMsg = lStrings
0718: .getString("http.method_not_implemented");
0719: Object[] errArgs = new Object[1];
0720: errArgs[0] = method;
0721: errMsg = MessageFormat.format(errMsg, errArgs);
0722:
0723: resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED,
0724: errMsg);
0725: }
0726: }
0727:
0728: /*
0729: * Sets the Last-Modified entity header field, if it has not
0730: * already been set and if the value is meaningful. Called before
0731: * doGet, to ensure that headers are set before response data is
0732: * written. A subclass might have set this header already, so we
0733: * check.
0734: */
0735:
0736: private void maybeSetLastModified(HttpServletResponse resp,
0737: long lastModified) {
0738: if (resp.containsHeader(HEADER_LASTMOD))
0739: return;
0740: if (lastModified >= 0)
0741: resp.setDateHeader(HEADER_LASTMOD, lastModified);
0742: }
0743:
0744: /**
0745: *
0746: * Dispatches client requests to the protected
0747: * <code>service</code> method. There's no need to
0748: * override this method.
0749: *
0750: *
0751: * @param req the {@link HttpServletRequest} object that
0752: * contains the request the client made of
0753: * the servlet
0754: *
0755: *
0756: * @param res the {@link HttpServletResponse} object that
0757: * contains the response the servlet returns
0758: * to the client
0759: *
0760: *
0761: * @exception IOException if an input or output error occurs
0762: * while the servlet is handling the
0763: * HTTP request
0764: *
0765: * @exception ServletException if the HTTP request cannot
0766: * be handled
0767: *
0768: *
0769: * @see javax.servlet.Servlet#service
0770: *
0771: */
0772:
0773: public void service(ServletRequest req, ServletResponse res)
0774: throws ServletException, IOException {
0775: HttpServletRequest request;
0776: HttpServletResponse response;
0777:
0778: try {
0779: request = (HttpServletRequest) req;
0780: response = (HttpServletResponse) res;
0781: } catch (ClassCastException e) {
0782: throw new ServletException("non-HTTP request or response");
0783: }
0784: service(request, response);
0785: }
0786: }
0787:
0788: /*
0789: * A response that includes no body, for use in (dumb) "HEAD" support.
0790: * This just swallows that body, counting the bytes in order to set
0791: * the content length appropriately. All other methods delegate directly
0792: * to the HTTP Servlet Response object used to construct this one.
0793: */
0794: // file private
0795: class NoBodyResponse implements HttpServletResponse {
0796: private HttpServletResponse resp;
0797: private NoBodyOutputStream noBody;
0798: private PrintWriter writer;
0799: private boolean didSetContentLength;
0800:
0801: // file private
0802: NoBodyResponse(HttpServletResponse r) {
0803: resp = r;
0804: noBody = new NoBodyOutputStream();
0805: }
0806:
0807: // file private
0808: void setContentLength() {
0809: if (!didSetContentLength)
0810: resp.setContentLength(noBody.getContentLength());
0811: }
0812:
0813: // SERVLET RESPONSE interface methods
0814:
0815: public void setContentLength(int len) {
0816: resp.setContentLength(len);
0817: didSetContentLength = true;
0818: }
0819:
0820: public void setCharacterEncoding(String charset) {
0821: resp.setCharacterEncoding(charset);
0822: }
0823:
0824: public void setContentType(String type) {
0825: resp.setContentType(type);
0826: }
0827:
0828: public String getContentType() {
0829: return resp.getContentType();
0830: }
0831:
0832: public ServletOutputStream getOutputStream() throws IOException {
0833: return noBody;
0834: }
0835:
0836: public String getCharacterEncoding() {
0837: return resp.getCharacterEncoding();
0838: }
0839:
0840: public PrintWriter getWriter() throws UnsupportedEncodingException {
0841: if (writer == null) {
0842: OutputStreamWriter w;
0843:
0844: w = new OutputStreamWriter(noBody, getCharacterEncoding());
0845: writer = new PrintWriter(w);
0846: }
0847: return writer;
0848: }
0849:
0850: public void setBufferSize(int size) throws IllegalStateException {
0851: resp.setBufferSize(size);
0852: }
0853:
0854: public int getBufferSize() {
0855: return resp.getBufferSize();
0856: }
0857:
0858: public void reset() throws IllegalStateException {
0859: resp.reset();
0860: }
0861:
0862: public void resetBuffer() throws IllegalStateException {
0863: resp.resetBuffer();
0864: }
0865:
0866: public boolean isCommitted() {
0867: return resp.isCommitted();
0868: }
0869:
0870: public void flushBuffer() throws IOException {
0871: resp.flushBuffer();
0872: }
0873:
0874: public void setLocale(Locale loc) {
0875: resp.setLocale(loc);
0876: }
0877:
0878: public Locale getLocale() {
0879: return resp.getLocale();
0880: }
0881:
0882: // HTTP SERVLET RESPONSE interface methods
0883:
0884: public void addCookie(Cookie cookie) {
0885: resp.addCookie(cookie);
0886: }
0887:
0888: public boolean containsHeader(String name) {
0889: return resp.containsHeader(name);
0890: }
0891:
0892: /** @deprecated */
0893: public void setStatus(int sc, String sm) {
0894: resp.setStatus(sc, sm);
0895: }
0896:
0897: public void setStatus(int sc) {
0898: resp.setStatus(sc);
0899: }
0900:
0901: public void setHeader(String name, String value) {
0902: resp.setHeader(name, value);
0903: }
0904:
0905: public void setIntHeader(String name, int value) {
0906: resp.setIntHeader(name, value);
0907: }
0908:
0909: public void setDateHeader(String name, long date) {
0910: resp.setDateHeader(name, date);
0911: }
0912:
0913: public void sendError(int sc, String msg) throws IOException {
0914: resp.sendError(sc, msg);
0915: }
0916:
0917: public void sendError(int sc) throws IOException {
0918: resp.sendError(sc);
0919: }
0920:
0921: public void sendRedirect(String location) throws IOException {
0922: resp.sendRedirect(location);
0923: }
0924:
0925: public String encodeURL(String url) {
0926: return resp.encodeURL(url);
0927: }
0928:
0929: public String encodeRedirectURL(String url) {
0930: return resp.encodeRedirectURL(url);
0931: }
0932:
0933: public void addHeader(String name, String value) {
0934: resp.addHeader(name, value);
0935: }
0936:
0937: public void addDateHeader(String name, long value) {
0938: resp.addDateHeader(name, value);
0939: }
0940:
0941: public void addIntHeader(String name, int value) {
0942: resp.addIntHeader(name, value);
0943: }
0944:
0945: /**
0946: * @deprecated As of Version 2.1, replaced by
0947: * {@link HttpServletResponse#encodeURL}.
0948: *
0949: */
0950:
0951: public String encodeUrl(String url) {
0952: return this .encodeURL(url);
0953: }
0954:
0955: /**
0956: * @deprecated As of Version 2.1, replaced by
0957: * {@link HttpServletResponse#encodeRedirectURL}.
0958: *
0959: */
0960:
0961: public String encodeRedirectUrl(String url) {
0962: return this .encodeRedirectURL(url);
0963: }
0964:
0965: }
0966:
0967: /*
0968: * Servlet output stream that gobbles up all its data.
0969: */
0970:
0971: // file private
0972: class NoBodyOutputStream extends ServletOutputStream {
0973:
0974: private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
0975: private static ResourceBundle lStrings = ResourceBundle
0976: .getBundle(LSTRING_FILE);
0977:
0978: private int contentLength = 0;
0979:
0980: // file private
0981: NoBodyOutputStream() {
0982: }
0983:
0984: // file private
0985: int getContentLength() {
0986: return contentLength;
0987: }
0988:
0989: public void write(int b) {
0990: contentLength++;
0991: }
0992:
0993: public void write(byte buf[], int offset, int len)
0994: throws IOException {
0995: if (len >= 0) {
0996: contentLength += len;
0997: } else {
0998: // XXX
0999: // isn't this really an IllegalArgumentException?
1000:
1001: String msg = lStrings.getString("err.io.negativelength");
1002: throw new IOException("negative length");
1003: }
1004: }
1005: }
|