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 extends HttpServletResponseWrapper {
821 private NoBodyOutputStream noBody;
822 private PrintWriter writer;
823 private boolean didSetContentLength;
824
825 // file private
826 NoBodyResponse(HttpServletResponse r) {
827 super(r);
828 noBody = new NoBodyOutputStream();
829 }
830
831 // file private
832 void setContentLength() {
833 if (!didSetContentLength)
834 super.setContentLength(noBody.getContentLength());
835 }
836
837
838 // SERVLET RESPONSE interface methods
839
840 public void setContentLength(int len) {
841 super.setContentLength(len);
842 didSetContentLength = true;
843 }
844
845 public ServletOutputStream getOutputStream() throws IOException
846 { return noBody; }
847
848 public PrintWriter getWriter() throws UnsupportedEncodingException
849 {
850 if (writer == null) {
851 OutputStreamWriter w;
852
853 w = new OutputStreamWriter(noBody, getCharacterEncoding());
854 writer = new PrintWriter(w);
855 }
856 return writer;
857 }
858
859 }
860
861
862
863
864
865
866
867 /*
868 * Servlet output stream that gobbles up all its data.
869 */
870
871 // file private
872 class NoBodyOutputStream extends ServletOutputStream {
873
874 private static final String LSTRING_FILE =
875 "javax.servlet.http.LocalStrings";
876 private static ResourceBundle lStrings =
877 ResourceBundle.getBundle(LSTRING_FILE);
878
879 private int contentLength = 0;
880
881 // file private
882 NoBodyOutputStream() {}
883
884 // file private
885 int getContentLength() {
886 return contentLength;
887 }
888
889 public void write(int b) {
890 contentLength++;
891 }
892
893 public void write(byte buf[], int offset, int len)
894 throws IOException
895 {
896 if (len >= 0) {
897 contentLength += len;
898 } else {
899 // XXX
900 // isn't this really an IllegalArgumentException?
901
902 String msg = lStrings.getString("err.io.negativelength");
903 throw new IOException("negative length");
904 }
905 }
906 }