1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.ginp;
20
21 import java.io.IOException;
22 import java.io.PrintWriter;
23 import java.util.Enumeration;
24 import java.util.List;
25 import java.util.Iterator;
26 import java.util.Random;
27 import java.util.Vector;
28
29 import javax.servlet.ServletException;
30 import javax.servlet.http.HttpServlet;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33
34 import net.sf.ginp.config.Configuration;
35 import net.sf.ginp.config.ModelUtil;
36 import org.apache.log4j.Logger;
37
38
39 import org.apache.commons.fileupload.FileItem;
40 import org.apache.commons.fileupload.FileUpload;
41 import org.apache.commons.fileupload.servlet.ServletRequestContext;
42 import org.apache.commons.fileupload.servlet.ServletFileUpload;
43
44 /**
45 * The Controller servlet of the Model View Controller Architecture.
46 *
47 *@author Doug Culnane
48 *@author Justin Sher
49 *@version $Revision: 306 $
50 */
51 public class GinpServlet extends HttpServlet {
52
53
54 /**
55 *
56 */
57 private static final long serialVersionUID = -3290204438867284907L;
58 private static Logger log = Logger.getLogger(GinpServlet.class);
59
60 public void init(){
61 Configuration.setConfigfilelocation(getServletContext().getRealPath(
62 Configuration.PATH_TO_CONFIG_FROM_WEBROOT));
63 }
64
65 /**
66 * Called by HTTP GET, feeds doHttpMethod.
67 *
68 *@param req HTTP GET Request
69 *@param res HTTP Response
70 *@exception IOException Description of the Exception
71 */
72 public void doGet(HttpServletRequest req,
73 HttpServletResponse res)
74 throws IOException {
75 doHttpMethod(req, res);
76 }
77
78
79 /**
80 * Called by HTTP POST, feeds doHttpMethod.
81 *
82 *@param req HTTP POST Request
83 *@param res HTTP Response
84 *@exception IOException Description of the Exception
85 */
86 public void doPost(HttpServletRequest req,
87 HttpServletResponse res)
88 throws IOException {
89 doHttpMethod(req, res);
90 }
91
92
93
94
95
96 /**
97 * Central Processor of HTTP Methods. This method gets the model for the
98 * users session, extracts the Command Parameters and preforms the command
99 * specified in the request. It then redirects or if cookies are used
100 * forwards the response to the JSP govened by the new state. If a
101 * significant error occurs it should be throwned up to here so that a
102 * debug page can be displayed. If a user sees a debug page then that is
103 * bad so lets try to find out about it and so we can fix it.
104 *
105 *@param req HTTP Request
106 *@param res HTTP Response
107 *@exception IOException Description of the Exception
108 */
109 public void doHttpMethod(HttpServletRequest req,
110 HttpServletResponse res)
111 throws IOException {
112
113
114
115 try {
116 req.setCharacterEncoding(Configuration.getCharacterEncoding());
117
118 res.setContentType("text/html; charset=\""
119 + Configuration.getCharacterEncoding() + "\"");
120 setNoCache(res);
121
122
123 log.debug("req.getContentType(): " + req.getContentType());
124 log.debug("Request Charactor Encoding:" + req.getCharacterEncoding());
125 } catch (java.io.UnsupportedEncodingException e) {
126 log.error("Error setting Character Encoding. Check Configuration", e);
127 }
128
129 try {
130
131
132 GinpModel model = ModelUtil.getModel(req);
133
134
135 executeCommand(req, model);
136
137
138 String url = model.getCurrentPage();
139
140
141 if (log.isDebugEnabled()) {
142 log.debug("doHttpMethod url=" + url + " " + model.getDebugInfo());
143 }
144
145
146 forwardToPage(req, res, url);
147
148
149 if (log.isDebugEnabled()) {
150 log.debug("DONE");
151 }
152
153 } catch (Exception ex) {
154 log.error("doHttpMethod", ex);
155 handleError(req, res, ex);
156 }
157 }
158
159
160 /**
161 * Deliver the view that the controller has selected. Do this in a way that
162 * the page is not cached. Also works around a bug in Session URL Encdoing in
163 * Tomcat
164 * @param req The Servlet Request
165 * @param res The Servlet response
166 * @param url The URL To send to
167 * @throws IOException if there is an error retrieving or sending the page
168 * @throws ServletException if there is some other error
169 */
170 private void forwardToPage(HttpServletRequest req, HttpServletResponse res, String url) throws IOException, ServletException {
171
172 Random rnd = new Random();
173
174
175 if (url.indexOf("?") == -1) {
176 url = res.encodeRedirectURL(url + "?nocache=" + rnd.nextInt(999999999));
177 } else {
178
179 url = res.encodeRedirectURL(url + "&nocache=" + rnd.nextInt(999999999));
180 }
181
182
183 if (!url.startsWith("/")) {
184 String serPath = req.getServletPath();
185 url = serPath.substring(0, serPath.lastIndexOf("/")) + "/" + url;
186 }
187
188
189
190 if (url.indexOf(";jsessionid=") != -1) {
191
192
193 if (log.isDebugEnabled()) {
194 log.debug("redirect to new page url=" + url);
195 }
196
197
198 res.sendRedirect(url);
199 } else {
200
201
202 if (log.isDebugEnabled()) {
203 log.debug("forward to new page url=" + url);
204 }
205
206 getServletConfig().getServletContext().getRequestDispatcher(
207 url).forward(req, res);
208 }
209 }
210
211
212 /**
213 * Dump an error message to the web browser if there was an unexpected error
214 * while trying to use the ginp servlet
215 * @param req the servlet request
216 * @param res the servlet response
217 * @param ex the exception thrown
218 * @throws IOException If there was an error sending the error message
219 */
220 private void handleError(HttpServletRequest req, HttpServletResponse res, Exception ex) throws IOException {
221 log.error("Show error page with debug info", ex);
222
223
224 res.setContentType("text/html");
225 PrintWriter out = res.getWriter();
226 out.print("<html>\n"
227 + "<body>\n"
228 + "<head>\n"
229 + "<title>ginp - ERROR!</title>\n"
230 + "</head>\n"
231 + "<body>\n"
232 + "<h1>ginp - ERROR!</h1>\n"
233 + "<p>If you are seeing this page and do not understand "
234 + "it then there is someone who is sorry and will try "
235 + "to fix the fault of the software. To inform them of "
236 + "the fault please <a href=\"mailto:"
237 + "ginp-users@lists.sourceforge.net"
238 + "?subject=Error Report&body=");
239 ex.printStackTrace(res.getWriter());
240 out.print("\">click Here.</a></p>"
241 + "<h2>Debug info for Developers</h2>\n"
242 + "<pre>\n");
243 ex.printStackTrace(res.getWriter());
244 out.print("</pre>\n"
245 + "<h2>Model State</h2>\n"
246 + "<pre>\n");
247 try {
248 GinpModel model = ModelUtil.getModel(req);
249 out.print(model.getDebugDump());
250 } catch (Exception e) {
251 log.error("Error showing error page",e);
252 }
253 out.print("</pre>\n"
254 + "</body>\n"
255 + "</html>\n");
256 }
257
258
259 /**
260 * Run the controller. The model will be able to tell you what view to use
261 * with model.getCurrentPage() after this is run and the request and model
262 * will have the information needed for the view
263 * @param req the servlet request
264 * @param model the model
265 */
266 private void executeCommand(HttpServletRequest req, GinpModel model) {
267
268
269 String command = req.getParameter("cmd");
270 if (command != null) {
271 if (command.length() > 0) {
272 Vector params = extractParameters(req);
273
274 model.doCommand(command, params);
275 }
276 }
277 }
278
279
280 /**
281 * Sets the headers on the servlet request such that the page is not cached
282 * @param res the servlet response
283 */
284 private void setNoCache(HttpServletResponse res) {
285
286 res.setHeader("Expires", "-1");
287 res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
288 res.addHeader("Cache-Control", "post-check=0, pre-check=0");
289 res.setHeader("Pragma", "no-cache");
290 }
291
292
293 /**
294 * Extract Command Parameter NAmes and Values from the HTTP Request.
295 *
296 *@param req HTTP Request.
297 *@return A vector of Command Parameters.
298 */
299 Vector extractParameters(HttpServletRequest req) {
300
301 Vector params = new Vector();
302 Enumeration names = req.getParameterNames();
303 while (names.hasMoreElements()) {
304 String name = (String) names.nextElement();
305 params.add(new CommandParameter(name, req.getParameter(name)));
306 log.debug("new CommandParameter(" + name + ", " + req.getParameter(name) + ")");
307 }
308 ServletRequestContext reqContext = new ServletRequestContext(req);
309 if (FileUpload.isMultipartContent(reqContext)) {
310 try {
311
312 ServletFileUpload upload = new ServletFileUpload();
313
314
315
316
317
318
319
320 List items = upload.parseRequest(req);
321 Iterator iter = items.iterator();
322 while (iter.hasNext()) {
323 FileItem item = (FileItem) iter.next();
324 if (item.isFormField()) {
325 params.add(new CommandParameter(item.getFieldName(), item.getString()));
326 } else {
327 CommandParameter fileParam = new CommandParameter(item.getFieldName(), item.getName());
328
329 fileParam.setObject(item.getInputStream());
330
331 params.add(fileParam);
332 }
333 }
334 } catch (Exception ex) {
335 log.error("extract parameters error getting input stream from file upload", ex);
336 }
337 }
338 return params;
339 }
340 }
341
342