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