View Javadoc

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 = "&lt;";
159 					break;
160 				case '>':
161 					filtered = "&gt;";
162 					break;
163 				case '&':
164 					filtered = "&amp;";
165 					break;
166 				case '"':
167 					filtered = "&quot;";
168 					break;
169 				case '\'':
170 					filtered = "&#39;";
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 		// log message
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 		// send error
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 		// save servle context for later use
236 		context = config.getServletContext();
237 
238 		// look for configuration source file name
239 		String cfgsrc = config.getInitParameter("configFileName");
240 		if (cfgsrc != null && cfgsrc.length() > 0) {
241 			// configuration source file name found
242 			log.info("Configuration source file specified: " + cfgsrc);
243 			// build configuration factory using source file name
244 			ConfigurationFactory factory = new ConfigurationFactory(cfgsrc);
245 			try {
246 				// get configuration from factory
247 				Configuration configuration = factory.getConfiguration();
248 				// store configuration in servlet context for future use
249 				context.setAttribute("configuration", configuration);
250 				// log success
251 				log.info("Configuration loaded using bootstrap file " + cfgsrc);
252 			} catch (ConfigurationException e) {
253 				// log the error
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 }