Coverage Report - org.webmacro.servlet.WMServlet
 
Classes in this File Line Coverage Branch Coverage Complexity
WMServlet
0%
0/164
0%
0/26
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