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