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