1 package javax.servlet.http;
2
3 import java.io.IOException;
4 import java.io.Serializable;
5 import java.lang.reflect.Method;
6 import java.text.MessageFormat;
7 import java.util.Enumeration;
8 import java.util.ResourceBundle;
9 import javax.servlet.GenericServlet;
10 import javax.servlet.ServletException;
11 import javax.servlet.ServletOutputStream;
12 import javax.servlet.ServletRequest;
13 import javax.servlet.ServletResponse;
14
15 public abstract class HttpServlet extends GenericServlet implements Serializable {
17 private static final long serialVersionUID = 1L;
18 private static final String METHOD_DELETE = "DELETE";
19 private static final String METHOD_HEAD = "HEAD";
20 private static final String METHOD_GET = "GET";
21 private static final String METHOD_OPTIONS = "OPTIONS";
22 private static final String METHOD_POST = "POST";
23 private static final String METHOD_PUT = "PUT";
24 private static final String METHOD_TRACE = "TRACE";
25 private static final String HEADER_IFMODSINCE = "If-Modified-Since";
26 private static final String HEADER_LASTMOD = "Last-Modified";
27 private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
28 private static ResourceBundle lStrings = ResourceBundle
29 .getBundle("javax.servlet.http.LocalStrings");
30
31 protected long getLastModified(HttpServletRequest req) {
32 return -1L;
33 }
34
35 protected void doHead(HttpServletRequest req, HttpServletResponse resp)
36 throws ServletException, IOException {
37 NoBodyResponse response = new NoBodyResponse(resp);
38 doGet(req, response);
39 response.setContentLength();
40 }
41
42 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
43 throws ServletException, IOException {
44 String protocol = req.getProtocol();
45 String msg = lStrings.getString("http.method_post_not_supported");
46 if (protocol.endsWith("1.1"))
47 resp.sendError(405, msg);
48 else
49 resp.sendError(400, msg);
50 }
51
52 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
53 throws ServletException, IOException {
54 String protocol = req.getProtocol();
55 String msg = lStrings.getString("http.method_get_not_supported");
56 if (protocol.endsWith("1.1"))
57 resp.sendError(405, msg);
58 else
59 resp.sendError(400, msg);
60 }
61
62 protected void doPut(HttpServletRequest req, HttpServletResponse resp)
63 throws ServletException, IOException {
64 String protocol = req.getProtocol();
65 String msg = lStrings.getString("http.method_put_not_supported");
66 if (protocol.endsWith("1.1"))
67 resp.sendError(405, msg);
68 else
69 resp.sendError(400, msg);
70 }
71
72 protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
73 throws ServletException, IOException {
74 String protocol = req.getProtocol();
75 String msg = lStrings.getString("http.method_delete_not_supported");
76 if (protocol.endsWith("1.1"))
77 resp.sendError(405, msg);
78 else
79 resp.sendError(400, msg);
80 }
81
82 private static Method[] getAllDeclaredMethods(Class c) {
83 if (c.equals(HttpServlet.class)) {
84 return null;
85 }
86 Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
87 Method[] thisMethods = c.getDeclaredMethods();
88
89 if ((parentMethods != null) && (parentMethods.length > 0)) {
90 Method[] allMethods = new Method[parentMethods.length
91 + thisMethods.length];
92
93 System.arraycopy(parentMethods, 0, allMethods, 0,
94 parentMethods.length);
95
96 System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
97 thisMethods.length);
98
99 thisMethods = allMethods;
100 }
101 return thisMethods;
102 }
103
104 protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
105 throws ServletException, IOException {
106 Method[] methods = getAllDeclaredMethods(getClass());
107
108 boolean ALLOW_GET = false;
109 boolean ALLOW_HEAD = false;
110 boolean ALLOW_POST = false;
111 boolean ALLOW_PUT = false;
112 boolean ALLOW_DELETE = false;
113 boolean ALLOW_TRACE = true;
114 boolean ALLOW_OPTIONS = true;
115
116 for (int i = 0; i < methods.length; i++) {
117 Method m = methods[i];
118
119 if (m.getName().equals("doGet")) {
120 ALLOW_GET = true;
121 ALLOW_HEAD = true;
122 }
123 if (m.getName().equals("doPost"))
124 ALLOW_POST = true;
125 if (m.getName().equals("doPut"))
126 ALLOW_PUT = true;
127 if (m.getName().equals("doDelete")) {
128 ALLOW_DELETE = true;
129 }
130 }
131 String allow = null;
132 if ((ALLOW_GET) && (allow == null))
133 allow = "GET";
134 if (ALLOW_HEAD)
135 if (allow == null)
136 allow = "HEAD";
137 else
138 allow = allow + ", HEAD";
139 if (ALLOW_POST)
140 if (allow == null)
141 allow = "POST";
142 else
143 allow = allow + ", POST";
144 if (ALLOW_PUT)
145 if (allow == null)
146 allow = "PUT";
147 else
148 allow = allow + ", PUT";
149 if (ALLOW_DELETE)
150 if (allow == null)
151 allow = "DELETE";
152 else
153 allow = allow + ", DELETE";
154 if (ALLOW_TRACE)
155 if (allow == null)
156 allow = "TRACE";
157 else
158 allow = allow + ", TRACE";
159 if (ALLOW_OPTIONS) {
160 if (allow == null)
161 allow = "OPTIONS";
162 else
163 allow = allow + ", OPTIONS";
164 }
165 resp.setHeader("Allow", allow);
166 }
167
168 protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
169 throws ServletException, IOException {
170 String CRLF = "\r\n";
171 String responseString = "TRACE " + req.getRequestURI() + " "
172 + req.getProtocol();
173
174 Enumeration reqHeaderEnum = req.getHeaderNames();
175
176 while (reqHeaderEnum.hasMoreElements()) {
177 String headerName = (String) reqHeaderEnum.nextElement();
178 responseString = responseString + CRLF + headerName + ": "
179 + req.getHeader(headerName);
180 }
181
182 responseString = responseString + CRLF;
183
184 int responseLength = responseString.length();
185
186 resp.setContentType("message/http");
187 resp.setContentLength(responseLength);
188 ServletOutputStream out = resp.getOutputStream();
189 out.print(responseString);
190 out.close();
191 }
192
193 protected void service(HttpServletRequest req, HttpServletResponse resp)
194 throws ServletException, IOException {
195 String method = req.getMethod();
196
197 if (method.equals("GET")) {
198 long lastModified = getLastModified(req);
199 if (lastModified == -1L) {
200 doGet(req, resp);
201 } else {
202 long ifModifiedSince = req.getDateHeader("If-Modified-Since");
203 if (ifModifiedSince < lastModified / 1000L * 1000L) {
204 maybeSetLastModified(resp, lastModified);
205 doGet(req, resp);
206 } else {
207 resp.setStatus(304);
208 }
209 }
210 } else if (method.equals("HEAD")) {
211 long lastModified = getLastModified(req);
212 maybeSetLastModified(resp, lastModified);
213 doHead(req, resp);
214 } else if (method.equals("POST")) {
215 doPost(req, resp);
216 } else if (method.equals("PUT")) {
217 doPut(req, resp);
218 } else if (method.equals("DELETE")) {
219 doDelete(req, resp);
220 } else if (method.equals("OPTIONS")) {
221 doOptions(req, resp);
222 } else if (method.equals("TRACE")) {
223 doTrace(req, resp);
224 } else {
225 String errMsg = lStrings.getString("http.method_not_implemented");
226 Object[] errArgs = new Object[1];
227 errArgs[0] = method;
228 errMsg = MessageFormat.format(errMsg, errArgs);
229
230 resp.sendError(501, errMsg);
231 }
232 }
233
234 private void maybeSetLastModified(HttpServletResponse resp,
235 long lastModified) {
236 if (resp.containsHeader("Last-Modified"))
237 return;
238 if (lastModified >= 0L)
239 resp.setDateHeader("Last-Modified", lastModified);
240 }
241
242 public void service(ServletRequest req, ServletResponse res)
243 throws ServletException, IOException {
244 HttpServletRequest request;
245 HttpServletResponse response;
246 try {
247 request = (HttpServletRequest) req;
248 response = (HttpServletResponse) res;
249 } catch (ClassCastException e) {
250 throw new ServletException("non-HTTP request or response");
251 }
252 service(request, response);
253 }
254 }