1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.jumpmind.symmetric.web;
24
25 import java.io.BufferedReader;
26 import java.io.ByteArrayInputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.InputStreamReader;
30 import java.io.OutputStream;
31 import java.net.SocketException;
32 import java.util.zip.GZIPInputStream;
33
34 import javax.servlet.ServletException;
35 import javax.servlet.http.HttpServlet;
36 import javax.servlet.http.HttpServletRequest;
37 import javax.servlet.http.HttpServletResponse;
38
39 import org.apache.commons.lang.StringUtils;
40 import org.apache.commons.lang.math.NumberUtils;
41 import org.apache.commons.logging.Log;
42 import org.springframework.context.ApplicationContext;
43 import org.springframework.web.context.support.WebApplicationContextUtils;
44
45 abstract public class AbstractServlet extends HttpServlet {
46
47 protected abstract Log getLogger();
48
49 protected OutputStream createOutputStream(HttpServletResponse resp) throws IOException {
50 return resp.getOutputStream();
51 }
52
53 protected InputStream createInputStream(HttpServletRequest req) throws IOException {
54 InputStream is = null;
55 String contentType = req.getHeader("Content-Type");
56 boolean useCompression = contentType != null && contentType.equalsIgnoreCase("gzip");
57
58 if (getLogger().isDebugEnabled()) {
59 StringBuilder b = new StringBuilder();
60 BufferedReader reader = null;
61 if (useCompression) {
62 getLogger().debug("Received compressed stream");
63 reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(req.getInputStream())));
64 } else {
65 reader = req.getReader();
66 }
67
68 String line = null;
69 do {
70 line = reader.readLine();
71 if (line != null) {
72 b.append(line);
73 b.append("\n");
74 }
75 } while (line != null);
76
77 getLogger().debug("Received: \n" + b);
78 is = new ByteArrayInputStream(b.toString().getBytes());
79 } else {
80 is = req.getInputStream();
81 if (useCompression) {
82 is = new GZIPInputStream(is);
83 }
84 }
85
86 return is;
87 }
88
89 protected ApplicationContext getDefaultApplicationContext() {
90 return WebApplicationContextUtils.getWebApplicationContext(getServletContext());
91 }
92
93 @Override
94 protected final void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
95 try {
96 handleGet(req, resp);
97 } catch (SocketException e) {
98 if (getLogger().isWarnEnabled()) {
99 getLogger().warn("Socket issue while processing GET method ", e);
100 }
101 } catch (Exception e) {
102 if (getLogger().isErrorEnabled()) {
103 getLogger().error("uncaught exception on GET method", e);
104 }
105 if (!resp.isCommitted()) {
106 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
107 }
108 }
109 }
110
111 /***
112 * Override me to do real work. Remember that a GET should be idempotent and
113 * safe. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.
114 *
115 * @param req
116 * @param resp
117 * @throws IOException
118 * @throws ServletException
119 * @throws Exception
120 * everything else that could go wrong!
121 *
122 */
123 protected void handleGet(HttpServletRequest req, HttpServletResponse resp) throws Exception {
124 sendError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED);
125 }
126
127 @Override
128 protected final void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
129 try {
130 handlePost(req, resp);
131 } catch (SocketException e) {
132 if (getLogger().isWarnEnabled()) {
133 getLogger().warn("Socket issue while processing POST method ", e);
134 }
135 } catch (Exception e) {
136 if (getLogger().isErrorEnabled()) {
137 getLogger().error("uncaught exception on POST method", e);
138 }
139 sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
140 }
141 }
142
143 /***
144 * Override me to do real work. See
145 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.
146 *
147 * @param req
148 * @param resp
149 * @throws IOException
150 * @throws ServletException
151 * @throws Exception
152 * everything else that could go wrong!
153 */
154 protected void handlePost(HttpServletRequest req, HttpServletResponse resp) throws Exception {
155 sendError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED);
156 }
157
158 @Override
159 protected final void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
160 try {
161 handlePut(req, resp);
162 } catch (SocketException e) {
163 if (getLogger().isWarnEnabled()) {
164 getLogger().warn("Socket issue while processing PUT method ", e);
165 }
166 } catch (Exception e) {
167 if (getLogger().isErrorEnabled()) {
168 getLogger().error("uncaught exception on PUT method", e);
169 }
170 sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
171 }
172 }
173
174 /***
175 * Override me to do real work. Remember that a PUT should be idempotent.
176 * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.
177 *
178 * @param req
179 * @param resp
180 * @throws IOException
181 * @throws ServletException
182 * @throws Exception
183 * everything else that could go wrong!
184 */
185 protected void handlePut(HttpServletRequest req, HttpServletResponse resp) throws Exception {
186 sendError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED);
187 }
188
189 @Override
190 protected final void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
191 IOException {
192 try {
193 handleDelete(req, resp);
194 } catch (SocketException e) {
195 if (getLogger().isWarnEnabled()) {
196 getLogger().warn("Socket issue while processing DELETE method ", e);
197 }
198 } catch (Exception e) {
199 if (getLogger().isErrorEnabled()) {
200 getLogger().error("uncaught exception on DELETE method", e);
201 }
202 sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
203 }
204 }
205
206 /***
207 * Override me to do real work. Remember that a DELETE should be idempotent.
208 * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.
209 *
210 * @param req
211 * @param resp
212 * @throws IOException
213 * @throws ServletException
214 * @throws Exception
215 * everything else that could go wrong!
216 */
217 protected void handleDelete(HttpServletRequest req, HttpServletResponse resp) throws Exception {
218 resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
219 }
220
221 @Override
222 protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
223 try {
224 handleHead(req, resp);
225 } catch (SocketException e) {
226 if (getLogger().isWarnEnabled()) {
227 getLogger().warn("Socket issue while processing HEAD method ", e);
228 }
229 } catch (Exception e) {
230 if (getLogger().isErrorEnabled()) {
231 getLogger().error("uncaught exception on HEAD method", e);
232 }
233 sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
234 }
235 }
236
237 /***
238 * Override me to do real work. Remember that a HEAD should be idempotent
239 * and safe. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.
240 *
241 * @param req
242 * @param resp
243 * @throws IOException
244 * @throws ServletException
245 * @throws Exception
246 * everything else that could go wrong!
247 */
248 protected void handleHead(HttpServletRequest req, HttpServletResponse resp) throws Exception {
249 sendError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED);
250 }
251
252 @Override
253 protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
254 try {
255 handleOptions(req, resp);
256 } catch (SocketException e) {
257 if (getLogger().isWarnEnabled()) {
258 getLogger().warn("Socket issue while processing data ", e);
259 }
260 } catch (Exception e) {
261 if (getLogger().isErrorEnabled()) {
262 getLogger().error("uncaught exception on OPTIONS method", e);
263 }
264 sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
265 }
266 }
267
268 /***
269 * Override me to do real work. Remember that a OPTIONS should be idempotent
270 * and safe. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.
271 *
272 * @param req
273 * @param resp
274 * @throws IOException
275 * @throws ServletException
276 * @throws Exception
277 * everything else that could go wrong!
278 */
279 protected void handleOptions(HttpServletRequest req, HttpServletResponse resp) throws Exception {
280 sendError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED);
281 }
282
283 @Override
284 protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
285 try {
286 handleTrace(req, resp);
287 } catch (SocketException e) {
288 if (getLogger().isWarnEnabled()) {
289 getLogger().warn("Socket issue while processing TRACE method ", e);
290 }
291 } catch (Exception e) {
292 if (getLogger().isErrorEnabled()) {
293 getLogger().error("uncaught exception on TRACE method", e);
294 }
295 sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
296 }
297 }
298
299 /***
300 * Override me to do real work. Remember that a TRACE should be idempotent.
301 * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.
302 *
303 * @param req
304 * @param resp
305 * @throws IOException
306 * @throws ServletException
307 * @throws Exception
308 * everything else that could go wrong!
309 */
310 protected void handleTrace(HttpServletRequest req, HttpServletResponse resp) throws Exception {
311 sendError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED);
312 }
313
314 /***
315 * Because you can't send an error when the response is already committed,
316 * this helps to avoid unnecessary errors in the logs.
317 *
318 * @param resp
319 * @param statusCode
320 * @throws IOException
321 */
322 protected boolean sendError(HttpServletResponse resp, int statusCode) throws IOException {
323 return ServletUtils.sendError(resp, statusCode);
324 }
325
326 /***
327 * Because you can't send an error when the response is already committed,
328 * this helps to avoid unnecessary errors in the logs.
329 *
330 * @param resp
331 * @param statusCode
332 * @param message
333 * a message to put in the body of the response
334 * @throws IOException
335 */
336 protected boolean sendError(HttpServletResponse resp, int statusCode, String message) throws IOException {
337 return ServletUtils.sendError(resp, statusCode, message);
338 }
339
340 /***
341 * Returns the parameter with that name, trimmed to null
342 *
343 * @param request
344 * @param name
345 * @return
346 */
347 protected String getParameter(HttpServletRequest request, String name) {
348 return StringUtils.trimToNull(request.getParameter(name));
349 }
350
351 /***
352 * Returns the parameter with that name, trimmed to null. If the trimmed
353 * string is null, defaults to the defaultValue.
354 *
355 * @param request
356 * @param name
357 * @return
358 */
359 protected String getParameter(HttpServletRequest request, String name, String defaultValue) {
360 return StringUtils.defaultIfEmpty(StringUtils.trimToNull(request.getParameter(name)), defaultValue);
361 }
362
363 protected long getParameterAsNumber(HttpServletRequest request, String name) {
364 return NumberUtils.toLong(StringUtils.trimToNull(request.getParameter(name)));
365 }
366
367 }