1 package org.restafarian.core.servlets;
2
3 import java.io.IOException;
4
5 import javax.servlet.ServletConfig;
6 import javax.servlet.ServletContext;
7 import javax.servlet.ServletException;
8 import javax.servlet.http.HttpServlet;
9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11
12 import org.apache.commons.configuration.Configuration;
13 import org.apache.commons.configuration.ConfigurationException;
14 import org.apache.commons.configuration.ConfigurationFactory;
15 import org.apache.commons.logging.Log;
16 import org.apache.commons.logging.LogFactory;
17
18 /***
19 * <p>This is the base class for all of the REST servlets.</p>
20 */
21 public abstract class RestServletBase extends HttpServlet {
22 private static final long serialVersionUID = 1;
23 protected ServletContext context = null;
24 protected Log log = LogFactory.getLog(getClass());
25
26 /***
27 * <p>The Servlet "service" method.</p>
28 *
29 * @param req the <code>HttpServletRequest</code> object
30 * @param res the <code>HttpServletResponse</code> object
31 * @throws ServletException
32 * @throws IOException
33 */
34 public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
35 res.setContentType("text/xml");
36
37 String method = req.getMethod();
38 if ("get".equalsIgnoreCase(method)) {
39 doGet(req, res);
40 } else if ("post".equalsIgnoreCase(method)) {
41 doPost(req, res);
42 } else if ("put".equalsIgnoreCase(method)) {
43 doPut(req, res);
44 } else if ("delete".equalsIgnoreCase(method)) {
45 doDelete(req, res);
46 } else {
47 res.sendError(405, "Method Not Allowed. The \"" + method.toUpperCase() + "\" is not appropriate for this resource.");
48 }
49 }
50
51 /***
52 * <p>The Servlet "doGet()" method.</p>
53 *
54 * @param req the <code>HttpServletRequest</code> object
55 * @param res the <code>HttpServletResponse</code> object
56 * @throws ServletException
57 * @throws IOException
58 */
59 public abstract void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException;
60
61 /***
62 * <p>The Servlet "doPost()" method.</p>
63 *
64 * @param req the <code>HttpServletRequest</code> object
65 * @param res the <code>HttpServletResponse</code> object
66 * @throws ServletException
67 * @throws IOException
68 */
69 public abstract void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException;
70
71 /***
72 * <p>The Servlet "doPut()" method.</p>
73 *
74 * @param req the <code>HttpServletRequest</code> object
75 * @param res the <code>HttpServletResponse</code> object
76 * @throws ServletException
77 * @throws IOException
78 */
79 public abstract void doPut(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException;
80
81 /***
82 * <p>The Servlet "doDelete()" method.</p>
83 *
84 * @param req the <code>HttpServletRequest</code> object
85 * @param res the <code>HttpServletResponse</code> object
86 * @throws ServletException
87 * @throws IOException
88 */
89 public abstract void doDelete(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException;
90
91 /***
92 * <p>Returns the id present in the URL, if any, as an <code>int</code>.</p>
93 *
94 * @param req the <code>HttpServletRequest</code> object
95 * @param servletPath the path to the servlet, including both the leading and trailing "/"
96 * @return the id present in the URL, if any
97 */
98 protected int getNumericIdFromUrl(HttpServletRequest req, String servletPath) {
99 int id = 0;
100
101 try {
102 id = Integer.parseInt(getIdFromUrl(req, servletPath));
103 } catch (NumberFormatException e) {
104
105 }
106
107 return id;
108 }
109
110 /***
111 * <p>Returns the id present in the URL, if any.</p>
112 *
113 * @param req the <code>HttpServletRequest</code> object
114 * @param servletPath the path to the servlet, including both the leading and trailing "/"
115 * @return the id present in the URL, if any
116 */
117 protected String getIdFromUrl(HttpServletRequest req, String servletPath) {
118 String id = null;
119
120 String basePath = req.getContextPath() + servletPath;
121 if (req.getRequestURI().length() > basePath.length()) {
122 id = req.getRequestURI().substring(basePath.length());
123 }
124
125 return id;
126 }
127
128 /***
129 * <p>Returns the name space url.</p>
130 *
131 * @param req the <code>HttpServletRequest</code> object
132 * @return the name space url
133 */
134 protected String getNameSpaceUrl(HttpServletRequest req) {
135 return (req.getRequestURL().toString().substring(0, req.getRequestURL().toString().indexOf(req.getContextPath())) + req.getContextPath()).toLowerCase();
136 }
137
138 /***
139 * Filter the specified string for characters that are sensitive to
140 * HTML interpreters, returning the string with these characters replaced
141 * by the corresponding character entities. Lifted from Struts ResponseUtils
142 *
143 * @param value The string to be filtered and returned
144 * @return The filtered string
145 */
146 protected static String filter(String value) {
147
148 if (value == null || value.length() == 0) {
149 return value;
150 }
151
152 StringBuffer result = null;
153 String filtered = null;
154 for (int i = 0; i < value.length(); i++) {
155 filtered = null;
156 switch (value.charAt(i)) {
157 case '<':
158 filtered = "<";
159 break;
160 case '>':
161 filtered = ">";
162 break;
163 case '&':
164 filtered = "&";
165 break;
166 case '"':
167 filtered = """;
168 break;
169 case '\'':
170 filtered = "'";
171 break;
172 }
173
174 if (result == null) {
175 if (filtered != null) {
176 result = new StringBuffer(value.length() + 50);
177 if (i > 0) {
178 result.append(value.substring(0, i));
179 }
180 result.append(filtered);
181 }
182 } else {
183 if (filtered == null) {
184 result.append(value.charAt(i));
185 } else {
186 result.append(filtered);
187 }
188 }
189 }
190
191 return result == null ? value : result.toString();
192 }
193
194 /***
195 * <p>Sends the HTTP error code and message, and logs the code and message if enabled.</p>
196 *
197 * @param req the <code>HttpServletRequest</code> object
198 * @param res the <code>HttpServletResponse</code> object
199 * @param errorCode the error code to send
200 * @param errorMessage the error message to send
201 */
202 protected void sendError(HttpServletRequest req, HttpServletResponse res, int errorCode, String errorMessage) throws IOException {
203 sendError(req, res, errorCode, errorMessage, null);
204 }
205
206 /***
207 * <p>Sends the HTTP error code and message, and logs the code and message if enabled.</p>
208 *
209 * @param req the <code>HttpServletRequest</code> object
210 * @param res the <code>HttpServletResponse</code> object
211 * @param errorCode the error code to send
212 * @param errorMessage the error message to send
213 * @param throwable an optional exception
214 */
215 protected void sendError(HttpServletRequest req, HttpServletResponse res, int errorCode, String errorMessage, Throwable throwable) throws IOException {
216
217 if (throwable != null) {
218 log.error("Sending error " + errorCode + "; message=" + errorMessage, throwable);
219 } else if (log.isDebugEnabled()) {
220 log.debug("Sending error " + errorCode + "; message=" + errorMessage);
221 }
222
223
224 res.sendError(errorCode, errorMessage);
225 }
226
227 /***
228 * <p>Servlet init method.</p>
229 *
230 * @param config the ServletConfig object
231 */
232 public void init(ServletConfig config) {
233 log.info("Initializing " + getClass().getName());
234
235
236 context = config.getServletContext();
237
238
239 String cfgsrc = config.getInitParameter("configFileName");
240 if (cfgsrc != null && cfgsrc.length() > 0) {
241
242 log.info("Configuration source file specified: " + cfgsrc);
243
244 ConfigurationFactory factory = new ConfigurationFactory(cfgsrc);
245 try {
246
247 Configuration configuration = factory.getConfiguration();
248
249 context.setAttribute("configuration", configuration);
250
251 log.info("Configuration loaded using bootstrap file " + cfgsrc);
252 } catch (ConfigurationException e) {
253
254 log.error("Exception encountered when attempting to obtain current configuration: " + e, e);
255 }
256 }
257 }
258
259 /***
260 * <p>Servlet destroy method.</p>
261 */
262 public void destroy() {
263 }
264 }