Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
WMServlet |
|
| 2.064516129032258;2.065 |
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 | ||
24 | package org.webmacro.servlet; | |
25 | ||
26 | import java.io.IOException; | |
27 | import java.io.OutputStream; | |
28 | import java.io.UnsupportedEncodingException; | |
29 | import java.io.Writer; | |
30 | import java.lang.reflect.Method; | |
31 | import java.util.Locale; | |
32 | ||
33 | import javax.servlet.ServletConfig; | |
34 | import javax.servlet.ServletException; | |
35 | import javax.servlet.http.HttpServlet; | |
36 | import javax.servlet.http.HttpServletRequest; | |
37 | import javax.servlet.http.HttpServletResponse; | |
38 | ||
39 | import org.slf4j.Logger; | |
40 | import org.slf4j.LoggerFactory; | |
41 | ||
42 | import org.webmacro.Broker; | |
43 | import org.webmacro.Context; | |
44 | import org.webmacro.FastWriter; | |
45 | import org.webmacro.InitException; | |
46 | import org.webmacro.NotFoundException; | |
47 | import org.webmacro.PropertyException; | |
48 | import org.webmacro.ResourceException; | |
49 | import org.webmacro.Template; | |
50 | import org.webmacro.WM; | |
51 | import org.webmacro.WMConstants; | |
52 | import org.webmacro.WebMacro; | |
53 | ||
54 | /** | |
55 | * This is an abstract base class which can be used | |
56 | * to implement a kind of WebMacro servlet. | |
57 | * | |
58 | * You can either subclass from it directly, or make use of one of the | |
59 | * generic subclasses provided. | |
60 | * <p> | |
61 | * It's primary function is to create a WebContext and manage a | |
62 | * Broker. It also provides a couple of convenience functions | |
63 | * that access the Broker and/or WebContext to make some commonly | |
64 | * accessed services more readily available. | |
65 | * <p> | |
66 | * @see org.webmacro.Broker | |
67 | */ | |
68 | 0 | abstract public class WMServlet extends HttpServlet implements WebMacro |
69 | { | |
70 | ||
71 | private static final long serialVersionUID = -4903102471116106113L; | |
72 | 0 | static Logger _log = LoggerFactory.getLogger(WMServlet.class); |
73 | ||
74 | 0 | private WebMacro _wm = null; |
75 | 0 | private Broker _broker = null; |
76 | 0 | private boolean _started = false; |
77 | /** | |
78 | * The name of the config entry we look for to find out what to | |
79 | * call the variable used in the ERROR_TEMPLATE. | |
80 | */ | |
81 | final static String ERROR_VARIABLE = "ErrorVariable"; | |
82 | ||
83 | /** | |
84 | * The name of the error template we will use if something | |
85 | * goes wrong. | |
86 | */ | |
87 | final static String ERROR_TEMPLATE = "ErrorTemplate"; | |
88 | ||
89 | /** | |
90 | * Defaults for error variable and error template. | |
91 | */ | |
92 | final static String ERROR_TEMPLATE_DEFAULT = "error.wm"; | |
93 | final static String ERROR_VARIABLE_DEFAULT = "error"; | |
94 | ||
95 | /** | |
96 | * Null means all OK. | |
97 | */ | |
98 | 0 | private String _problem = "Not yet initialized: " + |
99 | "Your servlet API tried to access WebMacro without first calling init()!!!"; | |
100 | ||
101 | /** | |
102 | * This is the old-style init method, it just calls init(), after | |
103 | * handing the ServletConfig object to the superclass. | |
104 | * @exception ServletException if it failed to initialize | |
105 | */ | |
106 | public synchronized void init (ServletConfig sc) | |
107 | throws ServletException | |
108 | { | |
109 | 0 | super.init(sc); |
110 | 0 | init(); |
111 | 0 | } |
112 | ||
113 | /** | |
114 | * This method is called by the servlet runner--do not call it. It | |
115 | * must not be overidden because it manages a shared instance | |
116 | * of the broker--you can overide the start() method instead, which | |
117 | * is called just after the broker is initialized. | |
118 | */ | |
119 | public synchronized void init () | |
120 | { | |
121 | ||
122 | 0 | if (_started) |
123 | { | |
124 | 0 | return; |
125 | } | |
126 | ||
127 | // locate a Broker | |
128 | ||
129 | 0 | if (_wm == null) |
130 | { | |
131 | try | |
132 | { | |
133 | 0 | _wm = initWebMacro(); |
134 | 0 | _broker = _wm.getBroker(); |
135 | } | |
136 | 0 | catch (InitException e) |
137 | { | |
138 | 0 | _problem = "Could not initialize the broker!\n\n" |
139 | + "*** Check that WebMacro.properties was in your servlet\n" | |
140 | + "*** classpath, in a similar place to webmacro.jar \n" | |
141 | + "*** and that all values were set correctly.\n\n" | |
142 | + e.getMessage(); | |
143 | 0 | _log.error(_problem, e); |
144 | 0 | return; |
145 | 0 | } |
146 | } | |
147 | ||
148 | try | |
149 | { | |
150 | 0 | if (_log.isDebugEnabled()) |
151 | { | |
152 | 0 | java.net.URL url = getBroker().getResource(Broker.WEBMACRO_PROPERTIES); |
153 | 0 | if (url != null) |
154 | 0 | _log.debug("Using properties from " + url.toExternalForm()); |
155 | else | |
156 | 0 | _log.debug("No WebMacro.properties file was found."); |
157 | } | |
158 | 0 | start(); |
159 | 0 | _problem = null; |
160 | } | |
161 | 0 | catch (ServletException e) |
162 | { | |
163 | 0 | _problem = "WebMacro application code failed to initialize: \n" |
164 | + e + "\n" + "This error is the result of a failure in the\n" | |
165 | + "code supplied by the application programmer.\n"; | |
166 | 0 | _log.error(_problem, e); |
167 | 0 | } |
168 | 0 | _log.info("started: " + this); |
169 | 0 | _started = true; |
170 | ||
171 | 0 | } |
172 | ||
173 | /** | |
174 | * This method is called by the servlet runner--do not call it. It | |
175 | * must not be overidden because it manages a shared instance of | |
176 | * the broker--you can overide the stop() method instead, which | |
177 | * will be called just before the broker is shut down. Once the | |
178 | * stop() method has been called, the nested WM will be destroyed | |
179 | * and then the parent destroy() method will be invoked. | |
180 | * @see WM#destroy() | |
181 | */ | |
182 | public synchronized void destroy () | |
183 | { | |
184 | 0 | stop(); |
185 | 0 | _wm.destroy(); |
186 | 0 | _log.info("stopped: " + this); |
187 | 0 | _wm = null; |
188 | 0 | _started = false; |
189 | 0 | super.destroy(); |
190 | 0 | } |
191 | ||
192 | ||
193 | // SERVLET API METHODS | |
194 | ||
195 | /** | |
196 | * Process an incoming GET request: Builds a WebContext up and then | |
197 | * passes it to the handle() method. You can overide this if you want, | |
198 | * though for most purposes you are expected to overide handle() | |
199 | * instead. | |
200 | * <p> | |
201 | * @param req the request we got | |
202 | * @param resp the response we are generating | |
203 | * @exception ServletException if we can't get our configuration | |
204 | * @exception IOException if we can't write to the output stream | |
205 | */ | |
206 | protected void doGet (HttpServletRequest req, HttpServletResponse resp) | |
207 | throws ServletException, IOException | |
208 | { | |
209 | 0 | doRequest(req, resp); |
210 | 0 | } |
211 | ||
212 | /** | |
213 | * Behaves exactly like doGet() except that it reads data from POST | |
214 | * before doing exactly the same thing. This means that you can use | |
215 | * GET and POST interchangeably with WebMacro. You can overide this if | |
216 | * you want, though for most purposes you are expected to overide | |
217 | * handle() instead. | |
218 | * <p> | |
219 | * @param req the request we got | |
220 | * @param resp the response we are generating | |
221 | * @exception ServletException if we can't get our configuration | |
222 | * @exception IOException if we can't read/write to the streams we got | |
223 | */ | |
224 | protected void doPost (HttpServletRequest req, HttpServletResponse resp) | |
225 | throws ServletException, IOException | |
226 | { | |
227 | 0 | doRequest(req, resp); |
228 | 0 | } |
229 | ||
230 | final private void doRequest ( | |
231 | HttpServletRequest req, HttpServletResponse resp) | |
232 | throws IOException | |
233 | { | |
234 | ||
235 | 0 | WebContext context = null; |
236 | ||
237 | 0 | if (_problem != null) |
238 | { | |
239 | 0 | init(); |
240 | 0 | if (_problem != null) |
241 | { | |
242 | try | |
243 | { | |
244 | 0 | resp.setContentType("text/html"); |
245 | 0 | Writer out = resp.getWriter(); |
246 | ||
247 | 0 | out.write("<html><head><title>WebMacro Error</title></head>"); |
248 | 0 | out.write("<body><h1><font color=\"red\">WebMacro Error: "); |
249 | 0 | out.write("</font></h1><pre>"); |
250 | 0 | out.write(_problem); |
251 | 0 | out.write("</pre>"); |
252 | 0 | out.write("Please contact the server administrator"); |
253 | 0 | out.flush(); |
254 | 0 | out.close(); |
255 | } | |
256 | 0 | catch (Exception e) |
257 | { | |
258 | 0 | _log.error(_problem, e); |
259 | 0 | } |
260 | 0 | return; |
261 | } | |
262 | } | |
263 | ||
264 | ||
265 | 0 | context = newWebContext(req, resp); |
266 | try | |
267 | { | |
268 | Template t; | |
269 | 0 | t = handle(context); |
270 | ||
271 | 0 | if (t != null) |
272 | { | |
273 | 0 | execute(t, context); |
274 | } | |
275 | 0 | destroyContext(context); |
276 | } | |
277 | 0 | catch (HandlerException e) |
278 | { | |
279 | 0 | _log.error("Your handler failed to handle the request:" + this, e); |
280 | 0 | Template tmpl = error(context, |
281 | "Your handler was unable to process the request successfully " + | |
282 | "for some reason. Here are the details:<p>" + | |
283 | "<pre>" + e + "</pre>"); | |
284 | 0 | execute(tmpl, context); |
285 | } | |
286 | 0 | catch (Exception e) |
287 | { | |
288 | 0 | _log.error("Your handler failed to handle the request:" + this, e); |
289 | 0 | Template tmpl = error(context, |
290 | "The handler WebMacro used to handle this request failed for " + | |
291 | "some reason. This is likely a bug in the handler written " + | |
292 | "for this application. Here are the details:<p>" + | |
293 | "<pre>" + e + "</pre>"); | |
294 | 0 | execute(tmpl, context); |
295 | 0 | } |
296 | 0 | } |
297 | ||
298 | ||
299 | // CONVENIENCE METHODS & ACCESS TO THE BROKER | |
300 | ||
301 | /** | |
302 | * Create an error template using the built in error handler. | |
303 | * This is useful for returning error messages on failure; | |
304 | * it is used by WMServlet to display errors resulting from | |
305 | * any exception that you may throw from the handle() method. | |
306 | * @param context will add error variable to context (see Config) | |
307 | * @param error a string explaining what went wrong | |
308 | */ | |
309 | protected Template error (WebContext context, String error) | |
310 | { | |
311 | 0 | Template tmpl = null; |
312 | //Handler hand = new ErrorHandler(); | |
313 | try | |
314 | { | |
315 | 0 | context.put(getErrorVariableName(), |
316 | error); | |
317 | //tmpl = hand.accept(context); | |
318 | 0 | tmpl = getErrorTemplate(); |
319 | } | |
320 | 0 | catch (Exception e2) |
321 | { | |
322 | 0 | _log.error("Unable to use ErrorHandler", e2); |
323 | 0 | } |
324 | 0 | return tmpl; |
325 | } | |
326 | ||
327 | /** | |
328 | * Returns the name of the error variable, as per the config. | |
329 | * @return Name to use for the error variable in templates | |
330 | */ | |
331 | protected String getErrorVariableName () | |
332 | { | |
333 | 0 | return getConfig(ERROR_VARIABLE, ERROR_VARIABLE_DEFAULT); |
334 | } | |
335 | ||
336 | /** | |
337 | * This object is used to access components that have been plugged | |
338 | * into WebMacro; it is shared between all instances of this class and | |
339 | * its subclasses. It is created when the first instance is initialized, | |
340 | * and deleted when the last instance is shut down. If you attempt to | |
341 | * access it after the last servlet has been shutdown, it will either | |
342 | * be in a shutdown state or else null. | |
343 | */ | |
344 | public Broker getBroker () | |
345 | { | |
346 | // this method can be unsynch. because the broker manages its own | |
347 | // state, plus the only time the _broker will be shutdown or null | |
348 | // is after the last servlet has shutdown--so why would anyone be | |
349 | // accessing us then? if they do the _broker will throw exceptions | |
350 | // complaining that it has been shut down, or they'll get a null here. | |
351 | 0 | return _broker; |
352 | } | |
353 | ||
354 | /** | |
355 | * Retrieve a template from the "template" provider. Equivalent to | |
356 | * getBroker().get(TemplateProvider.TYPE,key) | |
357 | * @exception NotFoundException if the template was not found | |
358 | * @exception ResourceException if the template coult not be loaded | |
359 | */ | |
360 | public Template getTemplate (String key) | |
361 | throws ResourceException | |
362 | { | |
363 | 0 | return _wm.getTemplate(key); |
364 | } | |
365 | ||
366 | /** | |
367 | * Retrieve a URL. This is largely equivalent to creating a URL | |
368 | * object and requesting its content, though it will sit in | |
369 | * WebMacro's cache rather than re-requesting each time. | |
370 | * The content will be returned as an Object. | |
371 | */ | |
372 | public String getURL (String url) | |
373 | throws ResourceException | |
374 | { | |
375 | 0 | return _wm.getURL(url); |
376 | } | |
377 | ||
378 | ||
379 | /** | |
380 | * Retrieve configuration information from the "config" provider. | |
381 | * Equivalent to getBroker().get(Config.TYPE,key) | |
382 | * @exception NotFoundException could not locate requested information | |
383 | */ | |
384 | public String getConfig (String key) | |
385 | throws NotFoundException | |
386 | { | |
387 | 0 | return _wm.getConfig(key); |
388 | } | |
389 | ||
390 | /** | |
391 | * Retrieve configuration information from the "config" provider. | |
392 | * Return specified default if key could not be found | |
393 | */ | |
394 | public String getConfig (String key, String defaultValue) | |
395 | { | |
396 | try | |
397 | { | |
398 | 0 | return _wm.getConfig(key); |
399 | } | |
400 | 0 | catch (NotFoundException e) |
401 | { | |
402 | 0 | return defaultValue; |
403 | } | |
404 | } | |
405 | ||
406 | /** | |
407 | * Create a new Context object. | |
408 | */ | |
409 | public Context getContext () | |
410 | { | |
411 | 0 | return _wm.getContext(); |
412 | } | |
413 | ||
414 | /** | |
415 | * Create a new WebContext object; can be overridden. | |
416 | */ | |
417 | public WebContext getWebContext (HttpServletRequest req, HttpServletResponse res) | |
418 | { | |
419 | 0 | return _wm.getWebContext(req, res); |
420 | } | |
421 | ||
422 | /** | |
423 | * Convenience method for writing a template to an OutputStream. | |
424 | * This method takes care of all the typical work involved | |
425 | * in writing a template.<p> | |
426 | * | |
427 | * This method uses the default <code>TemplateOutputEncoding</code> specified in | |
428 | * WebMacro.defaults or your custom WebMacro.properties. | |
429 | * | |
430 | * @param templateName name of Template to write. Must be accessible | |
431 | * via TemplatePath | |
432 | * @param out where the output of the template should go | |
433 | * @param context The Context (can be a WebContext too) used | |
434 | * during the template evaluation phase | |
435 | * @throws java.io.IOException if the template cannot be written to the | |
436 | * specified output stream | |
437 | * @throws ResourceException if the template name specified cannot be found | |
438 | * @throws PropertyException if a fatal error occured during the Template | |
439 | * evaluation phase | |
440 | */ | |
441 | public void writeTemplate (String templateName, java.io.OutputStream out, | |
442 | Context context) | |
443 | throws java.io.IOException, ResourceException, PropertyException | |
444 | { | |
445 | ||
446 | 0 | writeTemplate(templateName, out, |
447 | getConfig(WMConstants.TEMPLATE_OUTPUT_ENCODING), | |
448 | context); | |
449 | 0 | } |
450 | ||
451 | /** | |
452 | * Convienence method for writing a template to an OutputStream. | |
453 | * This method takes care of all the typical work involved | |
454 | * in writing a template. | |
455 | * | |
456 | * @param templateName name of Template to write. Must be accessible | |
457 | * via TemplatePath | |
458 | * @param out where the output of the template should go | |
459 | * @param encoding character encoding to use when writing the template | |
460 | * if the encoding is <code>null</code>, the default | |
461 | * <code>TemplateOutputEncoding</code> is used | |
462 | * @param context The Context (can be a WebContext too) used | |
463 | * during the template evaluation phase | |
464 | * @throws java.io.IOException if the template cannot be written to the | |
465 | * specified output stream | |
466 | * @throws ResourceException if the template name specified cannot be found | |
467 | * @throws PropertyException if a fatal error occured during the Template | |
468 | * evaluation phase | |
469 | */ | |
470 | public void writeTemplate (String templateName, java.io.OutputStream out, | |
471 | String encoding, Context context) | |
472 | throws java.io.IOException, ResourceException, PropertyException | |
473 | { | |
474 | ||
475 | 0 | if (encoding == null) |
476 | 0 | encoding = getConfig(WMConstants.TEMPLATE_OUTPUT_ENCODING); |
477 | ||
478 | 0 | Template tmpl = getTemplate(templateName); |
479 | 0 | tmpl.write(out, encoding, context); |
480 | 0 | } |
481 | ||
482 | ||
483 | // DELEGATE-TO METHODS -- COMMON THINGS MADE EASIER | |
484 | ||
485 | /** | |
486 | * This method takes a populated context and a template and | |
487 | * writes out the interpreted template to the context's output | |
488 | * stream. | |
489 | */ | |
490 | protected void execute (Template tmpl, WebContext c) | |
491 | throws IOException | |
492 | { | |
493 | try | |
494 | { | |
495 | 0 | HttpServletResponse resp = c.getResponse(); |
496 | ||
497 | 0 | Locale locale = (Locale) tmpl.getParam( |
498 | WMConstants.TEMPLATE_LOCALE); | |
499 | 0 | _log.debug("TemplateLocale=" + locale); |
500 | 0 | if (locale != null) |
501 | { | |
502 | 0 | setLocale(resp, locale); |
503 | } | |
504 | ||
505 | 0 | String encoding = (String) tmpl.getParam( |
506 | WMConstants.TEMPLATE_OUTPUT_ENCODING); | |
507 | 0 | if (encoding == null) |
508 | { | |
509 | 0 | encoding = resp.getCharacterEncoding(); |
510 | } | |
511 | ||
512 | 0 | _log.debug("Using output encoding " + encoding); |
513 | ||
514 | // get the bytes before calling getOutputStream | |
515 | // this is necessary to be compatible with JSDK 2.3 | |
516 | // where you can't call setContentType() after getOutputStream(), | |
517 | // which could be happening during the template evaluation | |
518 | 0 | byte[] bytes = tmpl.evaluateAsBytes(encoding, c); |
519 | ||
520 | ||
521 | // now write the FW buffer to the response output stream | |
522 | 0 | writeResponseBytes(resp, bytes, encoding); |
523 | } | |
524 | 0 | catch (UnsupportedEncodingException e) |
525 | { | |
526 | // can be thrown by FastWriter.getInstance | |
527 | // rethrow it, because otherwise it would be ignored | |
528 | // as an IOException | |
529 | 0 | _log.error("tried to use an unsupported encoding", e); |
530 | 0 | throw e; |
531 | } | |
532 | 0 | catch (IOException e) |
533 | { | |
534 | // ignore disconnect | |
535 | } | |
536 | 0 | catch (Exception e) |
537 | { | |
538 | 0 | String error = |
539 | "WebMacro encountered an error while executing a template:\n" | |
540 | + ((tmpl != null) ? (tmpl + ": " + e + "\n") : | |
541 | ("The template failed to load; double check the " | |
542 | + "TemplatePath in your webmacro.properties file.")); | |
543 | 0 | _log.error(error, e); |
544 | try | |
545 | { | |
546 | 0 | Template errorTemplate = error(c, |
547 | "WebMacro encountered an error while executing a template:\n" | |
548 | + ((tmpl != null) ? (tmpl + ": ") | |
549 | : ("The template failed to load; double check the " | |
550 | + "TemplatePath in your webmacro.properties file.")) | |
551 | + "\n<pre>" + e + "</pre>\n"); | |
552 | ||
553 | 0 | String err = errorTemplate.evaluateAsString(c); |
554 | 0 | c.getResponse().getWriter().write(err); |
555 | } | |
556 | 0 | catch (Exception errExcept) |
557 | { | |
558 | 0 | _log.error("Error writing error template!", errExcept); |
559 | 0 | } |
560 | 0 | } |
561 | 0 | } |
562 | ||
563 | /** | |
564 | * Helper method to write out a FastWriter (that has bufferd | |
565 | * the response) to a ServletResponse. This method will try to use | |
566 | * the response's OutputStream first and if this fails, fall back | |
567 | * to its Writer. | |
568 | * @param response where to write fast writer to | |
569 | * @param bytes the bytes to write | |
570 | */ | |
571 | private void writeResponseBytes (HttpServletResponse response, byte[] bytes, String encoding) | |
572 | throws IOException | |
573 | { | |
574 | OutputStream out; | |
575 | // We'll check, if the OutputStream is available | |
576 | try | |
577 | { | |
578 | 0 | out = response.getOutputStream(); |
579 | } | |
580 | 0 | catch (IllegalStateException e) |
581 | { | |
582 | // Here comes a quick hack, we need a cleaner | |
583 | // solution in a future release. (skanthak) | |
584 | ||
585 | // this means, that the ServletOutputStream is | |
586 | // not available, because the Writer has already | |
587 | // be used. We have to use it, although its | |
588 | // much slower, especially, because we need to | |
589 | // revert the encoding process now | |
590 | 0 | out = null; |
591 | 0 | _log.debug("Using Writer instead of OutputStream"); |
592 | 0 | } |
593 | 0 | response.setContentLength(bytes.length); |
594 | 0 | if (out != null) |
595 | { | |
596 | 0 | out.write(bytes); |
597 | } | |
598 | else | |
599 | { | |
600 | 0 | response.getWriter().write(new String(bytes, encoding)); |
601 | } | |
602 | 0 | } |
603 | ||
604 | ||
605 | // FRAMEWORK TEMPLATE METHODS--PLUG YOUR CODE IN HERE | |
606 | ||
607 | ||
608 | /** | |
609 | * This method is called at the beginning of a request and is | |
610 | * responsible for providing a Context for the request. The | |
611 | * default implementation calls WebContext.newInstance(req,resp) | |
612 | * on the WebContext prototype returned by the initWebContext() method. | |
613 | * This is probably suitable for most servlets, though you can override | |
614 | * it and do something different if you like. You can throw a | |
615 | * HandlerException if something goes wrong. | |
616 | */ | |
617 | public WebContext newContext ( | |
618 | HttpServletRequest req, HttpServletResponse resp) | |
619 | throws HandlerException | |
620 | { | |
621 | 0 | return _wm.getWebContext(req, resp); |
622 | //return _wcPrototype.newInstance(req, resp); | |
623 | } | |
624 | ||
625 | /** | |
626 | * This method is called to handle the processing of a request. It | |
627 | * should analyze the data in the request, put whatever values are | |
628 | * required into the context, and return the appropriate view. | |
629 | * @param context contains all relevant data structures, incl builtins. | |
630 | * @return the template to be rendered by the WebMacro engine | |
631 | * @throws HandlerException throw this to produce vanilla error messages | |
632 | */ | |
633 | public abstract Template handle (WebContext context) | |
634 | throws HandlerException; | |
635 | ||
636 | ||
637 | /** | |
638 | * This method is called at the end of a request and is responsible | |
639 | * for cleaning up the Context at the end of the request. You may | |
640 | * not need to do anything here, but it is sometimes important if | |
641 | * you have an open database connection in your context that you | |
642 | * need to close. The default implementation calls wc.clear(). | |
643 | */ | |
644 | public void destroyContext (WebContext wc) | |
645 | throws HandlerException | |
646 | { | |
647 | 0 | } |
648 | ||
649 | ||
650 | /** | |
651 | * Override this method to implement any startup/init code | |
652 | * you require. The broker will have been created before this | |
653 | * method is called; the default implementation does nothing. | |
654 | * This is called when the servlet environment initializes | |
655 | * the servlet for use via the init() method. | |
656 | * @exception ServletException to indicate initialization failed | |
657 | */ | |
658 | protected void start () throws ServletException | |
659 | { | |
660 | 0 | } |
661 | ||
662 | /** | |
663 | * Override this method to implement any shutdown code you require. | |
664 | * The broker may be destroyed just after this method exits. This | |
665 | * is called when the servlet environment shuts down the servlet | |
666 | * via the shutdown() method. The default implementation does nothing. | |
667 | */ | |
668 | protected void stop () | |
669 | { | |
670 | 0 | } |
671 | ||
672 | ||
673 | /** | |
674 | * This method returns the WebMacro object which will be used to load, | |
675 | * access, and manage the Broker. The default implementation is to | |
676 | * return a new WM() object. You could override it and return a WM | |
677 | * object constructed with a particular configuration file, or some | |
678 | * other implementation of the WebMacro interface. | |
679 | */ | |
680 | public WebMacro initWebMacro () throws InitException | |
681 | { | |
682 | 0 | return new WM(this); |
683 | } | |
684 | ||
685 | /** | |
686 | * NO LONGER USED | |
687 | * Exists only to catch implementations that use it. | |
688 | * Use newWebContext instead. | |
689 | * @deprecated | |
690 | */ | |
691 | public final WebContext initWebContext () throws InitException | |
692 | { | |
693 | 0 | return null; |
694 | } | |
695 | ||
696 | public WebContext newWebContext(HttpServletRequest req, HttpServletResponse resp) { | |
697 | 0 | return new WebContext(_broker, req, resp); |
698 | } | |
699 | ||
700 | /** | |
701 | * Set the locale on the response. The reflection trickery is because | |
702 | * this is only defined for JSDK 2.2+ | |
703 | */ | |
704 | protected void setLocale (HttpServletResponse resp, Locale locale) | |
705 | { | |
706 | try | |
707 | { | |
708 | 0 | Method m = HttpServletResponse.class.getMethod( |
709 | "setLocale", | |
710 | new Class[] | |
711 | {Locale.class}); | |
712 | 0 | m.invoke(resp, (Object[])new Locale[]{locale}); |
713 | 0 | _log.debug("Successfully set locale to " + locale); |
714 | } | |
715 | 0 | catch (Exception e) |
716 | { | |
717 | 0 | _log.debug("Error set locale to " + locale + ": " + e.getClass()); |
718 | 0 | } |
719 | 0 | } |
720 | ||
721 | /** | |
722 | * Get a new FastWriter. | |
723 | * A FastWriter is used when writing templates to an output stream | |
724 | * | |
725 | * @param out The output stream the FastWriter should write to. Typically | |
726 | * this will be your ServletOutputStream | |
727 | * @param enctype the Encoding type to use | |
728 | * @deprecated | |
729 | */ | |
730 | public FastWriter getFastWriter (OutputStream out, String enctype) | |
731 | throws UnsupportedEncodingException | |
732 | { | |
733 | 0 | return _wm.getFastWriter(out, enctype); |
734 | } | |
735 | ||
736 | ||
737 | private static final String DEFAULT_ERROR_TEXT = | |
738 | "<HTML><HEAD><TITLE>Error</TITLE></HEAD>\n" | |
739 | + "#set $Response.ContentType = \"text/html\"\n" | |
740 | + "<BODY><H1>Error</H1>" | |
741 | + "<HR>$error</BODY></HTML>"; | |
742 | ||
743 | 0 | private Template _errorTemplate = null; |
744 | ||
745 | /** | |
746 | * Gets a template for displaying an error message. | |
747 | * Tries to get configured template, then default template | |
748 | * and lastly constructs a string template. | |
749 | * @return A Template which can be used to format an error message | |
750 | */ | |
751 | public Template getErrorTemplate () | |
752 | { | |
753 | 0 | String templateName = getErrorTemplateName(); |
754 | ||
755 | try | |
756 | { | |
757 | 0 | _errorTemplate = (Template) _broker.get("template", templateName); |
758 | } | |
759 | 0 | catch (ResourceException e) |
760 | { | |
761 | 0 | _errorTemplate = new org.webmacro.engine.StringTemplate(_broker, DEFAULT_ERROR_TEXT, |
762 | "WebMacro default error template"); | |
763 | 0 | } |
764 | 0 | return _errorTemplate; |
765 | } | |
766 | ||
767 | protected String getErrorTemplateName () | |
768 | { | |
769 | String templateName; | |
770 | ||
771 | try | |
772 | { | |
773 | 0 | templateName = (String) _broker.get("config", ERROR_TEMPLATE); |
774 | } | |
775 | 0 | catch (ResourceException e) |
776 | { | |
777 | 0 | templateName = ERROR_TEMPLATE_DEFAULT; |
778 | 0 | } |
779 | 0 | return templateName; |
780 | } | |
781 | ||
782 | ||
783 | } | |
784 |