Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
WMEval |
|
| 1.5416666666666667;1.542 |
1 | /* | |
2 | * Copyright (C) 1998-2000 Semiotek Inc. All Rights Reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted under the terms of either of the following | |
6 | * Open Source licenses: | |
7 | * | |
8 | * The GNU General Public License, version 2, or any later version, as | |
9 | * published by the Free Software Foundation | |
10 | * (http://www.fsf.org/copyleft/gpl.html); | |
11 | * | |
12 | * or | |
13 | * | |
14 | * The Semiotek Public License (http://webmacro.org/LICENSE.) | |
15 | * | |
16 | * This software is provided "as is", with NO WARRANTY, not even the | |
17 | * implied warranties of fitness to purpose, or merchantability. You | |
18 | * assume all risks and liabilities associated with its use. | |
19 | * | |
20 | * See www.webmacro.org for more information on the WebMacro project. | |
21 | */ | |
22 | ||
23 | package org.webmacro.util; | |
24 | ||
25 | import java.io.FileOutputStream; | |
26 | import java.io.InputStream; | |
27 | import java.io.OutputStream; | |
28 | ||
29 | import javax.servlet.Servlet; | |
30 | import javax.servlet.ServletException; | |
31 | import javax.servlet.http.HttpServletRequest; | |
32 | import javax.servlet.http.HttpServletResponse; | |
33 | ||
34 | import org.slf4j.Logger; | |
35 | import org.slf4j.LoggerFactory; | |
36 | ||
37 | import org.webmacro.Context; | |
38 | import org.webmacro.Template; | |
39 | import org.webmacro.WM; | |
40 | import org.webmacro.WMConstants; | |
41 | import org.webmacro.WebMacro; | |
42 | import org.webmacro.engine.StreamTemplate; | |
43 | import org.webmacro.resource.AbstractTemplateLoader; | |
44 | import org.webmacro.servlet.WMServlet; | |
45 | import org.webmacro.servlet.WebContext; | |
46 | ||
47 | ||
48 | /** | |
49 | * WMEval encapsulates an instance of WebMacro for reuse in any java application. | |
50 | * <p> | |
51 | * It's main benefits are a number of convenience methods for evaluating a template | |
52 | * and directing output either to a supplied output stream or to a file. | |
53 | * <p> | |
54 | * It can parse a single template stream and then evaluate that template | |
55 | * over a number of different contexts. And, it can maintain a single context | |
56 | * and evaluate different templates over the same context. Each time a context | |
57 | * or a template is provided, it is retained as state. | |
58 | * <p> | |
59 | * The context can therefore be preserved over multiple "writes" of different | |
60 | * templates. | |
61 | * <p> | |
62 | * The template stream can be any text stream but is often a rule stream containing | |
63 | * wm script directives. | |
64 | * <p> | |
65 | * This helper class is useful for evaluating WebMacro templates for which | |
66 | * flexibility in managing the evaluation options is key. | |
67 | * | |
68 | * @author Lane Sharman | |
69 | * @version 3.0 | |
70 | */ | |
71 | public class WMEval | |
72 | { | |
73 | ||
74 | //-------public members----- | |
75 | ||
76 | //-------private and protected members----- | |
77 | private WebMacro wm; | |
78 | ||
79 | 0 | static Logger _log = LoggerFactory.getLogger(WMEval.class); |
80 | ||
81 | private Template currentTemplate; | |
82 | ||
83 | //private OutputStream out = System.out; | |
84 | ||
85 | private Context context; | |
86 | ||
87 | /** | |
88 | * If an output file is not specified as an argument, it | |
89 | * must be found in the context under this key. | |
90 | */ | |
91 | public static final String outputContextKey = "OutputFileName"; | |
92 | ||
93 | //-------constructor(s)----- | |
94 | /** | |
95 | * Constructor. | |
96 | * Build a WebMacro environment for currentTemplate execution. | |
97 | */ | |
98 | public WMEval() | |
99 | 0 | { |
100 | try { | |
101 | 0 | wm = new WM(); |
102 | 0 | init(); |
103 | 0 | } catch (Exception e) { |
104 | 0 | throw new IllegalStateException(e); |
105 | 0 | } |
106 | 0 | } |
107 | ||
108 | /** | |
109 | * Build a WebMacro environment to evaluate a template given it's name. | |
110 | */ | |
111 | public WMEval(String templateName) | |
112 | 0 | { |
113 | try { | |
114 | 0 | wm = new WM(); |
115 | 0 | init(); |
116 | 0 | parseLocalTemplate(templateName); |
117 | 0 | } catch (Exception e) { |
118 | 0 | throw new IllegalStateException(e); |
119 | 0 | } |
120 | 0 | } |
121 | ||
122 | /** | |
123 | * The constructor for WebMacro decorator in a servlet context. | |
124 | * Build a WebMacro environment for currentTemplate execution. | |
125 | */ | |
126 | public WMEval(Servlet servlet) | |
127 | 0 | { |
128 | try { | |
129 | 0 | if (servlet == null) |
130 | 0 | wm = new WM(); |
131 | else | |
132 | 0 | wm = new WM(servlet); |
133 | 0 | init(); |
134 | 0 | } catch (Exception e) { |
135 | 0 | throw new IllegalStateException(e); |
136 | 0 | } |
137 | 0 | } |
138 | ||
139 | private void init() { | |
140 | 0 | context = wm.getContext(); |
141 | 0 | } |
142 | /** | |
143 | * Return the settings associated with this WebMacro instance. | |
144 | */ | |
145 | public Settings getSettings () | |
146 | { | |
147 | 0 | return wm.getBroker().getSettings(); |
148 | } | |
149 | ||
150 | /** | |
151 | * Return the log associated with this instance of WMEval. | |
152 | */ | |
153 | public Logger getLog () | |
154 | { | |
155 | 0 | return _log; |
156 | } | |
157 | ||
158 | //-------public initializers/destroyers----- | |
159 | /** | |
160 | * Initializes WMEval so that it can perform currentTemplate evaluation | |
161 | * on multiple contexts. Init parses the currentTemplate supplied. | |
162 | * <p> | |
163 | * The argument to init() is the currentTemplate as a stream allowing the | |
164 | * currentTemplate to come from pretty much anywhere such as a url, | |
165 | * a file, or a db field. | |
166 | * <p> | |
167 | * Care must be given to the fact that in parsing the currentTemplate, | |
168 | * the current vm is able to resolve locations of other currentTemplates | |
169 | * referenced within the supplied currentTemplate. | |
170 | * <p> | |
171 | * Note, once this is complete, the parsed currentTemplate can be applied | |
172 | * to successive new object contexts. In other words, the application context | |
173 | * can assert new objects for currentTemplate application and remove others. | |
174 | * | |
175 | * @param template The stream containing the top-level, unparsed currentTemplate. | |
176 | * | |
177 | */ | |
178 | public Template init (InputStream template) throws Exception | |
179 | { | |
180 | 0 | Template t = new StreamTemplate(wm.getBroker(), |
181 | template); | |
182 | 0 | t.parse(); |
183 | 0 | this.currentTemplate = t; |
184 | 0 | return t; |
185 | } | |
186 | ||
187 | public void error (String msg, Exception e) | |
188 | { | |
189 | 0 | _log.error(msg, e); |
190 | 0 | } |
191 | ||
192 | /** | |
193 | * Provides for a new context to be established. | |
194 | */ | |
195 | public Context getNewContext () | |
196 | { | |
197 | 0 | Context c = wm.getContext(); |
198 | 0 | this.context = c; |
199 | 0 | return c; |
200 | } | |
201 | ||
202 | public WebContext getNewContext (HttpServletRequest req, | |
203 | HttpServletResponse resp) | |
204 | { | |
205 | 0 | WebContext c = wm.getWebContext(req, resp); |
206 | 0 | this.context = c; |
207 | 0 | return c; |
208 | } | |
209 | ||
210 | /** | |
211 | * Gets the current context. | |
212 | */ | |
213 | public Context getCurrentContext () | |
214 | { | |
215 | 0 | return this.context; |
216 | } | |
217 | ||
218 | /** | |
219 | * Gets the current template. | |
220 | */ | |
221 | public Template getCurrentTemplate () | |
222 | { | |
223 | 0 | return this.currentTemplate; |
224 | } | |
225 | ||
226 | /** | |
227 | * A convenience method to find and parse a template in the local template path. | |
228 | * FIXME Do not set currentTemplate here | |
229 | */ | |
230 | public Template parseLocalTemplate (String templateName) throws Exception | |
231 | { | |
232 | 0 | Template t = wm.getTemplate(templateName); |
233 | 0 | this.currentTemplate = t; |
234 | 0 | return t; |
235 | } | |
236 | ||
237 | /** | |
238 | * Supplies the parsed currentTemplate directly. | |
239 | * @param parsedTemplate The currentTemplate parsed possibly from a previous run. | |
240 | */ | |
241 | public void setCurrentTemplate (Template parsedTemplate) | |
242 | { | |
243 | 0 | this.currentTemplate = parsedTemplate; |
244 | 0 | } |
245 | ||
246 | /** | |
247 | * Supplies a context to be parsed currentTemplate directly. | |
248 | * @param c The context to be used for the evaluation. | |
249 | */ | |
250 | public void setCurrentContext (Context c) | |
251 | { | |
252 | 0 | this.context = c; |
253 | 0 | } |
254 | ||
255 | /** | |
256 | * Sets the output stream to be different than the default, System.out. | |
257 | * @param out The new output stream for any output during currentTemplate evaluation. | |
258 | */ | |
259 | //public void setOutputStream (OutputStream out) | |
260 | //{ | |
261 | // this.out = out; | |
262 | //} | |
263 | ||
264 | /** | |
265 | * Evaluates the context of this instance and the instance's | |
266 | * current template and current output stream using UTF8. | |
267 | */ | |
268 | public String eval () throws Exception | |
269 | { | |
270 | 0 | return eval(context, currentTemplate); |
271 | } | |
272 | ||
273 | /** | |
274 | * Evaluate the context supplied against the current template. | |
275 | * @param context The WebMacro context. | |
276 | */ | |
277 | public String eval (Context context) throws Exception | |
278 | { | |
279 | 0 | return eval(context, currentTemplate); |
280 | } | |
281 | ||
282 | /** | |
283 | * Evaluate the supplied template against the supplied context and | |
284 | * return the result as a string. | |
285 | */ | |
286 | public String eval (Context context, Template template) throws Exception | |
287 | { | |
288 | 0 | return template.evaluateAsString(context); |
289 | } | |
290 | ||
291 | /** | |
292 | * Evaluates the string template against the current context | |
293 | * and returns the value. | |
294 | * @param templateName The name of the template. | |
295 | * @return The output from the evaluated template | |
296 | */ | |
297 | public String eval (String templateName) throws Exception | |
298 | { | |
299 | 0 | return eval(context, templateName, null, null); |
300 | } | |
301 | ||
302 | /** | |
303 | * Evaluate the named template against the given context | |
304 | * and return the result as a String. | |
305 | * If an output stream is specified, the return value is | |
306 | * also written out to the stream. | |
307 | * | |
308 | * @param templateName The name of the template. | |
309 | * @param out An optional output stream. | |
310 | * @return The output from the evaluated template | |
311 | */ | |
312 | public String eval (Context context, String templateName, OutputStream out) | |
313 | throws Exception | |
314 | { | |
315 | 0 | return eval(context, templateName, out, null); |
316 | } | |
317 | ||
318 | /** | |
319 | * Evaluates the context using a file template sending the output to a disk file. | |
320 | * <p> | |
321 | * This method is the preferred method when an output stream is to be written | |
322 | * as well as the value of the string is to be returned. | |
323 | * | |
324 | * @param context The context to use. | |
325 | * @param templateName The input template file in the resource path. | |
326 | * @param out The output stream. If null, an attempt will be made to locate | |
327 | * the outputstream in the context using the output stream key if | |
328 | * in the context. If no output stream can be resolved, the method does not | |
329 | * throw an exception. | |
330 | * @param encoding If null, the platform's encoding will be used. | |
331 | * @return The output from the evaluation of the template. | |
332 | */ | |
333 | public String eval (Context context, String templateName, OutputStream out, | |
334 | String encoding) throws Exception | |
335 | { | |
336 | 0 | Template t = wm.getTemplate(templateName); |
337 | 0 | String value = t.evaluateAsString(context); |
338 | // output the file | |
339 | 0 | if (out == null) { |
340 | 0 | String outputFileName = (String) context.get(outputContextKey); |
341 | 0 | if (outputFileName != null) { |
342 | 0 | out = new FileOutputStream(outputFileName); |
343 | } | |
344 | } | |
345 | 0 | if (out != null) // write it to out |
346 | { | |
347 | 0 | if (encoding == null) { |
348 | 0 | out.write(value.getBytes()); |
349 | } else { | |
350 | 0 | out.write(value.getBytes(encoding)); |
351 | } | |
352 | 0 | out.close(); |
353 | } | |
354 | 0 | this.currentTemplate = t; |
355 | 0 | this.context = context; |
356 | 0 | return value; |
357 | } | |
358 | /** | |
359 | * Evaluates the string template against a new context and writes | |
360 | * it to the http Response output stream using the proper encoding. | |
361 | * <p> | |
362 | * This is an exceptionally useful method for a servlet to use to | |
363 | * write out a template. | |
364 | * <p> | |
365 | * @param context The WM context to use. | |
366 | * @param templateName The name of the template. | |
367 | * @param resp The servlet response from which the encoding will be derived. | |
368 | * @return The output from the evaluated template. | |
369 | */ | |
370 | public String eval (WebContext context, String templateName, | |
371 | HttpServletResponse resp) throws ServletException | |
372 | { | |
373 | 0 | String value = null; |
374 | try { | |
375 | 0 | resp.setContentType("text/html"); |
376 | 0 | String encoding = wm |
377 | .getConfig(WMConstants.TEMPLATE_OUTPUT_ENCODING); | |
378 | 0 | value = eval(context, templateName, resp.getOutputStream(), |
379 | encoding); | |
380 | 0 | } catch (Exception e) { |
381 | 0 | throw new ServletException(e); |
382 | 0 | } |
383 | 0 | return value; |
384 | } | |
385 | ||
386 | ||
387 | /** | |
388 | * Evaluate the named template against the given context. | |
389 | * Writes the output to the given output file. | |
390 | * | |
391 | * @param context the context to evaluate the template against | |
392 | * @param templateName the name of the template to evaluate | |
393 | * @param outputFileName name of file to output to | |
394 | * @param append whether to apppend output | |
395 | * @param encoding the encoding to use, may be null | |
396 | * @return the String resulting from evaluating the template against the context | |
397 | * @throws Exception | |
398 | */ | |
399 | public String eval (Context context, String templateName, | |
400 | String outputFileName, boolean append, String encoding) | |
401 | throws Exception | |
402 | { | |
403 | 0 | OutputStream out = new FileOutputStream(outputFileName, append); |
404 | 0 | return eval(context, templateName, out, encoding); |
405 | } | |
406 | ||
407 | /** | |
408 | * Free up resources when no longer needed. | |
409 | */ | |
410 | public void destroy () | |
411 | { | |
412 | 0 | wm = null; |
413 | 0 | currentTemplate = null; |
414 | 0 | context = null; |
415 | 0 | } |
416 | } |