Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
TemplateServlet |
|
| 3.4444444444444446;3.444 |
1 | /* | |
2 | * @(#)TemplateServlet.java | |
3 | * | |
4 | * Copyright (c) 1995-2000 Open Doors Software, Inc. All Rights Reserved. | |
5 | * | |
6 | * This software is the confidential and proprietary information of Open Doors Software | |
7 | * Inc. ("Confidential Information"). You shall not | |
8 | * disclose such Confidential Information and shall use it only in | |
9 | * accordance with the terms of the license agreement you entered into | |
10 | * with Open Doors Software. | |
11 | * | |
12 | * Open Doors Software MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE | |
13 | * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | |
14 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | |
15 | * PURPOSE, OR NON-INFRINGEMENT. OPEN DOORS SOFTWARE SHALL NOT BE LIABLE FOR ANY DAMAGES | |
16 | * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING | |
17 | * THIS SOFTWARE OR ITS DERIVATIVES. | |
18 | * | |
19 | * | |
20 | */ | |
21 | package org.webmacro.servlet; | |
22 | ||
23 | import javax.servlet.ServletConfig; | |
24 | import javax.servlet.ServletException; | |
25 | import javax.servlet.http.HttpServlet; | |
26 | import javax.servlet.http.HttpServletRequest; | |
27 | import javax.servlet.http.HttpServletResponse; | |
28 | ||
29 | import org.slf4j.Logger; | |
30 | ||
31 | import org.webmacro.Context; | |
32 | import org.webmacro.util.Settings; | |
33 | import org.webmacro.util.WMEval; | |
34 | ||
35 | /** | |
36 | * <p> | |
37 | * TemplateServlet provides a servlet to evaluate templates directly as long | |
38 | * as the template type or types is mapped to this servlet. (Yes, you can | |
39 | * map more than one type in a web.xml file to the same servlet). | |
40 | * </p> | |
41 | * <p> | |
42 | * TemplateServlet offers delegation and global processing. You do not need to subclass | |
43 | * this servlet. Implement ServletRouter by setting a configuration attribute. | |
44 | * Populate the context in a delegate, not a subclass. | |
45 | * This servlet provides pre-processing of a | |
46 | * global and request-level template. | |
47 | * On servlet initialization, a global template is evaluated once. (This can be refreshed). | |
48 | * Since the template may just be creating static blocks, these blocks are then automatically | |
49 | * in the context under the name you assign for global processing. Therefore, in your | |
50 | * template, you could refer to $Global.CreditCardForm with parameters and evaluate that | |
51 | * form as a block. See the wiki page BlockLevelExpressionism for more information on this. | |
52 | * Similarly, if your configuration of this servlet specifies a per-Request level template, | |
53 | * it will be evaluated and the context placed into the working context prior to evaluation | |
54 | * of the actual template. | |
55 | * </p> | |
56 | * <p> | |
57 | * These configuration options make it possible to create automatically | |
58 | * a global context and a per request context. | |
59 | * A global context means that there is no longer any processing | |
60 | * associated with the globals: it is evaluated once. A per-request means that | |
61 | * you can always assume that a certain template gets evaluated for every request. | |
62 | * </p> | |
63 | * <p> | |
64 | * This Servlet extends the base class of the JSDK definition eliminating any | |
65 | * magic in a super-class. | |
66 | * </p> | |
67 | * | |
68 | * @since 24 Jan 2004 | |
69 | * @author lanesharman | |
70 | */ | |
71 | 0 | public class TemplateServlet extends HttpServlet { |
72 | ||
73 | private static final long serialVersionUID = 1L; | |
74 | ||
75 | /** | |
76 | * The thread-safe evaluator of all templates. | |
77 | */ | |
78 | protected WMEval wm; | |
79 | ||
80 | /** | |
81 | * The global context. | |
82 | */ | |
83 | protected Context globalContext; | |
84 | ||
85 | /** | |
86 | * The global context name to place in the context. | |
87 | */ | |
88 | protected String globalName; | |
89 | ||
90 | /** | |
91 | * The global template. | |
92 | */ | |
93 | protected String globalTemplate; | |
94 | ||
95 | /** | |
96 | * The name that identifies the per-request context. | |
97 | */ | |
98 | protected String requestName; | |
99 | ||
100 | /** | |
101 | * The per-request template. | |
102 | */ | |
103 | protected String requestTemplate; | |
104 | ||
105 | /** | |
106 | * The default template to load in a directory such as index.wm, index.wmt, index.tml | |
107 | */ | |
108 | 0 | private static String defaultTemplate = "index.tml"; |
109 | ||
110 | /** | |
111 | * The delegate to populate the context for the application. | |
112 | */ | |
113 | private ServletRouter servletRouter; | |
114 | ||
115 | protected Logger log; | |
116 | ||
117 | ||
118 | /** | |
119 | * Looks for a global template to evaluate (defined in WebMacro.properties). | |
120 | * If defined, the global context is made available to every request as a | |
121 | * var specified in WebMacro.properties. | |
122 | */ | |
123 | public void init(ServletConfig conf) throws ServletException { | |
124 | 0 | super.init(conf); |
125 | // run the application template, Application.tml. | |
126 | try { | |
127 | 0 | wm = new WMEval(this); |
128 | 0 | log = wm.getLog(); |
129 | 0 | Settings settings = wm.getSettings(); |
130 | 0 | log("Settings: " + settings.getAsProperties()); |
131 | 0 | globalName = settings.getSetting("GlobalTemplate.ContextName", null); |
132 | 0 | globalTemplate = settings.getSetting("GlobalTemplate.Resource", |
133 | null); | |
134 | 0 | requestName = settings.getSetting("RequestTemplate.ContextName", |
135 | null); | |
136 | 0 | requestTemplate = settings.getSetting("RequestTemplate.Resource", |
137 | null); | |
138 | 0 | String w = settings.getSetting("TemplateServlet.DefaultTemplate"); |
139 | 0 | if (w != null) { |
140 | 0 | defaultTemplate = w; |
141 | } | |
142 | 0 | String sr = settings.getSetting("TemplateServlet.ServletRouter"); |
143 | 0 | if (sr != null) { |
144 | 0 | this.servletRouter = (ServletRouter) Class.forName(sr).newInstance(); |
145 | } | |
146 | 0 | refreshGlobalContext(); |
147 | 0 | log("TemplateServlet initialized."); |
148 | 0 | } catch (Exception e) { |
149 | 0 | wm.error("Unable to initialize", e); |
150 | 0 | e.printStackTrace(System.err); |
151 | 0 | log("TemplateServlet failed to initialize: " + e.toString()); |
152 | 0 | throw new ServletException(e.toString()); |
153 | 0 | } |
154 | 0 | } |
155 | ||
156 | /** | |
157 | * Calls locateTemplate() and then getTemplate(), a base method, to find the | |
158 | * template and render it. | |
159 | */ | |
160 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) | |
161 | throws ServletException, java.io.IOException { | |
162 | try { | |
163 | 0 | doResponse(req, resp); |
164 | 0 | } catch (Exception e) { |
165 | 0 | this.log("Unable to return a template using " + req, e); |
166 | 0 | e.printStackTrace(System.err); |
167 | 0 | throw new ServletException(e.toString()); |
168 | 0 | } |
169 | 0 | } |
170 | ||
171 | /** | |
172 | * Calls locateTemplate() and then getTemplate(), a base method, to find the | |
173 | * template and render it. | |
174 | */ | |
175 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) | |
176 | throws ServletException, java.io.IOException { | |
177 | 0 | doGet(req, resp); |
178 | 0 | } |
179 | ||
180 | /** | |
181 | * Method which prepares the response and sends it. | |
182 | * <p> | |
183 | * The default implementation is as follows: | |
184 | * | |
185 | * <pre> | |
186 | * 1) Locate the template as the URI. | |
187 | * 2) Create a new context; if there is a global context | |
188 | * populate the context with it according to the parameters | |
189 | * in WebMacro.properties. | |
190 | * 3) If there is a per-request context, perform the equivalent | |
191 | * action of (2) above. | |
192 | * 4) If there is a | |
193 | * </pre> | |
194 | * | |
195 | * Override this method to perform your own response handling. | |
196 | * | |
197 | * @param request The request which has a uri such as /en/welcome.tml | |
198 | * @param response The response object | |
199 | * @return The template to evaluate and return as the response. | |
200 | */ | |
201 | protected String doResponse(HttpServletRequest request, | |
202 | HttpServletResponse response) throws ServletException { | |
203 | 0 | String templateName = locateTemplate(request); |
204 | 0 | WebContext context = wm.getNewContext(request, response); |
205 | 0 | loadGlobalContext(context); |
206 | 0 | loadRequestContext(context, templateName, request, response); |
207 | 0 | loadDelegationContext(context, templateName, request, response); |
208 | 0 | return wm.eval(context, templateName, response); |
209 | } | |
210 | ||
211 | /** | |
212 | * Default implenentation for locating the template. | |
213 | */ | |
214 | protected String locateTemplate(HttpServletRequest request) { | |
215 | 0 | String value = null; // request.getPathInfo().substring(1); // strip out the |
216 | 0 | value = (String) request.getAttribute("javax.servlet.include.servlet_path"); |
217 | 0 | if (value == null) value = request.getServletPath(); |
218 | 0 | log.info("request.getPathInfo(): " + request.getPathInfo()); |
219 | 0 | log.info("javax.servlet.include.servlet_path: " + request.getAttribute("javax.servlet.include.servlet_path")); |
220 | 0 | log.info("request.getServletPath(): " + request.getServletPath()); |
221 | 0 | if (value == null || value.trim().length() == 0) { |
222 | 0 | return defaultTemplate; |
223 | 0 | } else if (value.endsWith("/")) { |
224 | 0 | return (value + defaultTemplate); |
225 | } else { | |
226 | 0 | return value; |
227 | } | |
228 | } | |
229 | ||
230 | /** | |
231 | * Implementation for populating the context: handles a default per request | |
232 | * context. | |
233 | * <p> | |
234 | * Override as required. | |
235 | */ | |
236 | protected void loadRequestContext(WebContext context, String template, | |
237 | HttpServletRequest request, HttpServletResponse resp) | |
238 | throws ServletException { | |
239 | 0 | if (this.requestName != null) { |
240 | try { | |
241 | 0 | Context c = wm.getNewContext(); |
242 | 0 | wm.eval(c, requestTemplate, null); |
243 | 0 | context.put(this.requestName, c); |
244 | 0 | } catch (Exception e) { |
245 | 0 | this.log("Unable to evaluate request template " + requestName, |
246 | e); | |
247 | 0 | throw new ServletException(e.toString()); |
248 | 0 | } |
249 | } | |
250 | 0 | } |
251 | ||
252 | /** | |
253 | * Implementation for populating the context by a runtime defined delegate. | |
254 | * <p> | |
255 | * Override as required. | |
256 | */ | |
257 | protected void loadDelegationContext(WebContext context, String template, | |
258 | HttpServletRequest request, HttpServletResponse resp) | |
259 | throws ServletException { | |
260 | 0 | if (this.servletRouter != null) { |
261 | try { | |
262 | 0 | servletRouter.handleWebRequest(this, context, template); |
263 | 0 | } catch (Exception e) { |
264 | 0 | this.log("Unable to process router " + servletRouter.getClass().getName(), |
265 | e); | |
266 | 0 | throw new ServletException(e.toString()); |
267 | 0 | } |
268 | } | |
269 | 0 | } |
270 | ||
271 | /** | |
272 | * Loads the global context if present. | |
273 | */ | |
274 | private void loadGlobalContext(WebContext context) { | |
275 | 0 | if (globalName == null) |
276 | 0 | return; |
277 | 0 | context.put(globalName, globalContext); |
278 | 0 | } |
279 | ||
280 | /** | |
281 | * Call this to refresh the global context. | |
282 | */ | |
283 | protected void refreshGlobalContext() throws Exception { | |
284 | 0 | if (globalName == null) |
285 | 0 | return; |
286 | 0 | Context c = wm.getNewContext(); |
287 | 0 | wm.eval(c, globalTemplate, null); |
288 | 0 | globalContext = c; |
289 | 0 | } |
290 | ||
291 | } |