Source code: org/scopemvc/controller/servlet/ServletContext.java
1 /*
2 * Scope: a generic MVC framework.
3 * Copyright (c) 2000-2002, Steve Meyfroidt
4 * All rights reserved.
5 * Email: smeyfroi@users.sourceforge.net
6 *
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * Neither the name "Scope" nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 *
37 * $Id: ServletContext.java,v 1.9 2002/01/27 12:01:06 smeyfroi Exp $
38 */
39
40
41 package org.scopemvc.controller.servlet;
42
43
44 import java.io.IOException;
45 import java.io.PrintStream;
46 import java.io.PrintWriter;
47 import java.io.StringWriter;
48 import java.util.HashMap;
49 import javax.servlet.http.HttpServletRequest;
50 import javax.servlet.http.HttpServletResponse;
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogSource;
53 import org.scopemvc.controller.basic.ViewContext;
54 import org.scopemvc.core.View;
55
56
57 /**
58 * <P>
59 * A {@link org.scopemvc.controller.basic.ViewContext ViewContext}
60 * that handles showView(), hideView() and showError() for servlet implementations.
61 * </P>
62 * <P>
63 * The showView() expects a ServletView that
64 * is asked to stream the currently visible Page to the HTTP Response's
65 * OutputStream.
66 * </P>
67 * <P>
68 * Two interesting behaviours can be customized with a ServletContext subclass:
69 * <UL>
70 * <LI>
71 * To handle errors with a global error page override {@link #showError}
72 * to implement the required behaviour.
73 * </LI>
74 * </UL>
75 * Custom ServletContexts can be used for requests by overriding
76 * {@link ScopeServlet#createServletContext} in the application's
77 * ScopeServlet subclass to return an instance of the custom ServletContext.
78 * </P>
79 *
80 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A>
81 * @version $Revision: 1.9 $ $Date: 2002/01/27 12:01:06 $
82 * @see org.scopemvc.controller.servlet.jsp.JSPContext
83 * @see org.scopemvc.controller.servlet.xml.XSLServletContext
84 */
85 public abstract class ServletContext extends ViewContext {
86
87
88 private static final Log LOG = LogSource.getInstance(ServletContext.class);
89
90
91 /**
92 * The HttpServletResponse to use on showView.
93 * Set on creation then nulled after showView/showError.
94 */
95 protected HttpServletResponse response;
96
97
98 protected HttpServletRequest request;
99
100
101 protected HashMap formParameters;
102
103
104 protected ScopeServlet servlet;
105
106
107 /**
108 * Create with an HttpServletResponse to use on a showView
109 * during initialisation, and a HttpServletRequest accessible
110 * to application code.
111 */
112 public ServletContext(ScopeServlet inServlet,
113 HttpServletRequest inRequest,
114 HttpServletResponse inResponse,
115 HashMap inFormParameters) {
116 servlet = inServlet;
117 request = inRequest;
118 setHttpResponse(inResponse);
119 formParameters = inFormParameters;
120 }
121
122
123 /**
124 * The response to use for showView. Set in ctor and then
125 * nulled after showing a view.
126 */
127 protected final void setHttpResponse(HttpServletResponse inResponse) {
128 if (LOG.isDebugEnabled()) LOG.debug("setHttpResponse: " + this);
129 response = inResponse;
130 }
131
132
133 /**
134 * Allow access to the response object. Should rarely be used.
135 */
136 public final HttpServletResponse getHttpResponse() {
137 return response;
138 }
139
140
141 /**
142 * Allow access to the request object. Can be used to get access
143 * to cookies, session etc.
144 */
145 public final HttpServletRequest getHttpRequest() {
146 return request;
147 }
148
149
150 /**
151 * Return the ScopeServlet that handled this context's request.
152 */
153 public final ScopeServlet getServlet() {
154 return servlet;
155 }
156
157
158 /**
159 * @return the form parameters for the current request.
160 */
161 public final HashMap getFormParameters() {
162 return formParameters;
163 }
164
165
166 /**
167 * Show the ServletView passed.
168 */
169 public abstract void showView(View inView);
170
171
172 /**
173 * Got an error while streaming the view into the
174 * response OutputStream. The stream could be corrupt by
175 * this point, but it hasn't been closed so do the best you can.
176 */
177 protected void handleInternalError(Throwable t) throws IOException {
178 if (LOG.isDebugEnabled()) LOG.debug("handleInternalError: ", t);
179
180 try {
181 StringWriter stringWriter = new StringWriter();
182 PrintWriter writer = new PrintWriter(stringWriter);
183 t.printStackTrace(writer);
184 String dump = stringWriter.toString();
185
186 String formattedMessage = formatMessageToHTML(dump);
187
188 PrintStream ps = new PrintStream(response.getOutputStream());
189 ps.println("<HTML><H1>Internal error:</H1>" + formattedMessage + "</HTML>");
190 ps.flush();
191 response.getOutputStream().close();
192 }
193 finally {
194 setHttpResponse(null);
195 }
196 }
197
198
199 /**
200 * Replace all low ASCII chars (<32) in the message with
201 * <BR />.
202 */
203 protected String formatMessageToHTML(String inMessage) {
204 StringBuffer formattedMessage = new StringBuffer();
205 boolean addBreak = false;
206 for (int i = 0; i < inMessage.length(); ++i) {
207 char c = inMessage.charAt(i);
208 if (c < 32) {
209 addBreak = true;
210 } else {
211 if (addBreak) {
212 formattedMessage.append("<BR />");
213 addBreak = false;
214 }
215 formattedMessage.append(c);
216 }
217 }
218 return formattedMessage.toString();
219 }
220
221
222 /**
223 * Don't do anything in this impl.
224 * <P>
225 * ***** A nicer impl of this view manager would maintain a "stack" of shown views
226 * and implement "doHideView" to step back through the stack
227 * if available. Could be tied to some rudimentary
228 * state management in ScopeServlet.
229 * </P>
230 */
231 public void hideView(View inView) {
232 if (LOG.isDebugEnabled()) LOG.debug("hideView: " + inView);
233 // noop
234 }
235
236
237 /**
238 * This is a very simple default error handler. To implement
239 * your own error handler, override this method and also
240 * override {@link ScopeServlet#createServletContext}
241 * to return an instance of your custom ServletContext that
242 * will handle servlet requests.
243 */
244 public void showError(String inErrorTitle, String inErrorMessage) {
245 if (LOG.isDebugEnabled()) LOG.debug("showError: " + inErrorTitle + ", " + inErrorMessage);
246
247 response.setContentType("text/html");
248 try {
249 PrintStream ps = new PrintStream(response.getOutputStream());
250 ps.println("<HTML><H1>Error</H1><H3>"
251 + formatMessageToHTML(inErrorTitle) + "</H3><P>"
252 + formatMessageToHTML(inErrorMessage)
253 + "</P></HTML>");
254 ps.flush();
255 response.getOutputStream().close();
256 } catch(IOException e) {
257 LOG.fatal("Failed to showError", e);
258 } finally {
259 setHttpResponse(null);
260 }
261 }
262
263
264 public final boolean hasShownView() {
265 return (getHttpResponse() == null);
266 }
267
268
269 /**
270 * Used by default BasicController's handler for the EXIT Control.
271 * Doesn't do anything in a servlet context.
272 */
273 public void exit() {
274 // noop for servlets
275 }
276
277
278 public void startProgress() {
279 // noop for servlets
280 }
281
282
283 public void stopProgress() {
284 // noop for servlets
285 }
286 }