Coverage Report - org.apache.fulcrum.template.velocity.DefaultVelocityService
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultVelocityService
0%
0/123
0%
0/40
3
 
 1  
 package org.apache.fulcrum.template.velocity;
 2  
 
 3  
 
 4  
 /*
 5  
  * Licensed to the Apache Software Foundation (ASF) under one
 6  
  * or more contributor license agreements.  See the NOTICE file
 7  
  * distributed with this work for additional information
 8  
  * regarding copyright ownership.  The ASF licenses this file
 9  
  * to you under the Apache License, Version 2.0 (the
 10  
  * "License"); you may not use this file except in compliance
 11  
  * with the License.  You may obtain a copy of the License at
 12  
  *
 13  
  *   http://www.apache.org/licenses/LICENSE-2.0
 14  
  *
 15  
  * Unless required by applicable law or agreed to in writing,
 16  
  * software distributed under the License is distributed on an
 17  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 18  
  * KIND, either express or implied.  See the License for the
 19  
  * specific language governing permissions and limitations
 20  
  * under the License.
 21  
  */
 22  
 
 23  
 
 24  
 import java.io.ByteArrayOutputStream;
 25  
 import java.io.File;
 26  
 import java.io.IOException;
 27  
 import java.io.OutputStream;
 28  
 import java.io.OutputStreamWriter;
 29  
 import java.io.Writer;
 30  
 import java.util.ArrayList;
 31  
 import java.util.Collections;
 32  
 import java.util.Iterator;
 33  
 import java.util.List;
 34  
 import java.util.Vector;
 35  
 
 36  
 import org.apache.avalon.framework.activity.Initializable;
 37  
 import org.apache.avalon.framework.configuration.Configuration;
 38  
 import org.apache.avalon.framework.configuration.ConfigurationException;
 39  
 import org.apache.commons.configuration.ConfigurationConverter;
 40  
 import org.apache.fulcrum.template.BaseTemplateEngineService;
 41  
 import org.apache.fulcrum.template.TemplateContext;
 42  
 import org.apache.fulcrum.template.TemplateException;
 43  
 import org.apache.velocity.VelocityContext;
 44  
 import org.apache.velocity.app.VelocityEngine;
 45  
 import org.apache.velocity.app.event.EventCartridge;
 46  
 import org.apache.velocity.app.event.MethodExceptionEventHandler;
 47  
 import org.apache.velocity.app.event.NullSetEventHandler;
 48  
 import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
 49  
 import org.apache.velocity.context.Context;
 50  
 import org.apache.velocity.context.InternalEventContext;
 51  
 import org.apache.velocity.exception.MethodInvocationException;
 52  
 
 53  
 /**
 54  
  * This is a Service that can process Velocity templates from within a
 55  
  * Turbine Screen.  Here's an example of how you might use it from a
 56  
  * screen:<br>
 57  
  *
 58  
  * <code><pre>
 59  
  * Context context = new VelocityContext();
 60  
  * context.put("message", "Hello from Turbine!");
 61  
  * String results = VelocityServiceFacade.handleRequest(context,"HelloWorld.vm");
 62  
  * </pre></code>
 63  
  *
 64  
  * Character sets map codes to glyphs, while encodings map between
 65  
  * chars/bytes and codes.
 66  
  * <i>bytes -> [encoding] -> charset -> [rendering] -> glyphs</i>
 67  
  *
 68  
  * @author <a href="mailto:epugh@opensourceconnections.com">Eric Pugh</a>
 69  
  * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
 70  
  * @author <a href="mailto:krzewski@e-point.pl">Rafal Krzewski</a>
 71  
  * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
 72  
  * @author <a href="mailto:sean@informage.ent">Sean Legassick</a>
 73  
  * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
 74  
  * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
 75  
  * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
 76  
  * @author <a href="mailto:james@jamestaylor.org">James Taylor</a>
 77  
  * @version $Id: DefaultVelocityService.java 535465 2007-05-05 06:58:06Z tv $
 78  
  */
 79  0
 public class DefaultVelocityService
 80  
     extends BaseTemplateEngineService
 81  
     implements VelocityService, Initializable
 82  
 {
 83  
     /**
 84  
      * The generic resource loader path property in velocity.
 85  
      */
 86  
     private static final String RESOURCE_LOADER_PATH =
 87  
         ".resource.loader.path";
 88  
 
 89  
     /**
 90  
      * Default character set to use if not specified by caller.
 91  
      */
 92  
     private static final String DEFAULT_CHAR_SET = "ISO-8859-1";
 93  
 
 94  
     /**
 95  
      * The prefix used for URIs which are of type <code>jar</code>.
 96  
      */
 97  
     private static final String JAR_PREFIX = "jar:";
 98  
 
 99  
     /**
 100  
      * The prefix used for URIs which are of type <code>absolute</code>.
 101  
      */
 102  
     private static final String ABSOLUTE_PREFIX = "file://";
 103  
 
 104  
     /**
 105  
      * The EventCartridge that is used against all contexts
 106  
      */
 107  
     private EventCartridge eventCartridge;
 108  
 
 109  
     /**
 110  
      * Whether or not to use the eventCartridge. Defaults to true.
 111  
      * Can be used to turn off EC processing.
 112  
      */
 113  0
     private boolean eventCartridgeEnabled = true;
 114  
 
 115  
 
 116  
     // put conf into object to pass to the velocity engine
 117  
     org.apache.commons.configuration.Configuration velocityConf;
 118  
 
 119  
     /**
 120  
      * The VelocityEngine used by the service to merge templates
 121  
      */
 122  
     private VelocityEngine velocityEngine;
 123  
 
 124  
     /**
 125  
      * @see org.apache.fulcrum.velocity.VelocityService
 126  
      */
 127  
     public String handleRequest(TemplateContext context, String template)
 128  
         throws TemplateException
 129  
     {
 130  0
         return handleRequest(new ContextAdapter(context), template);
 131  
     }
 132  
 
 133  
     /**
 134  
      * @see org.apache.fulcrum.velocity.VelocityService
 135  
      */
 136  
     public String handleRequest(Context context, String filename)
 137  
         throws TemplateException
 138  
     {
 139  0
         return handleRequest(context, filename, (String)null, null);
 140  
     }
 141  
 
 142  
     /**
 143  
      * @see org.apache.fulcrum.velocity.VelocityService
 144  
      */
 145  
     public String handleRequest(Context context, String filename,
 146  
                                 String charset, String encoding)
 147  
         throws TemplateException
 148  
     {
 149  0
         String results = null;
 150  0
         ByteArrayOutputStream bytes = null;
 151  
 
 152  
         try
 153  
         {
 154  0
             bytes = new ByteArrayOutputStream();
 155  0
             charset = decodeRequest(context, filename, bytes, charset,
 156  
                                     encoding);
 157  0
             results = bytes.toString(charset);
 158  
         }
 159  0
         catch (Exception e)
 160  
         {
 161  0
             renderingError(filename, e);
 162  
         }
 163  
         finally
 164  
         {
 165  0
             try
 166  
             {
 167  0
                 if (bytes != null)
 168  
                 {
 169  0
                     bytes.close();
 170  
                 }
 171  
             }
 172  0
             catch (IOException ignored)
 173  
             {
 174  0
             }
 175  0
         }
 176  0
         return results;
 177  
     }
 178  
 
 179  
     /**
 180  
      * @see org.apache.fulcrum.template.TemplateEngineService
 181  
      */
 182  
     public void handleRequest(TemplateContext context, String template,
 183  
                               OutputStream outputStream)
 184  
         throws TemplateException
 185  
     {
 186  0
         handleRequest(new ContextAdapter(context), template, outputStream);
 187  0
     }
 188  
 
 189  
     /**
 190  
      * @see org.apache.fulcrum.velocity.VelocityService
 191  
      */
 192  
     public void handleRequest(Context context, String filename,
 193  
                               OutputStream output)
 194  
         throws TemplateException
 195  
     {
 196  0
         handleRequest(context, filename, output, null, null);
 197  0
     }
 198  
 
 199  
     /**
 200  
      * @see org.apache.fulcrum.velocity.VelocityService
 201  
      */
 202  
     public void handleRequest(Context context, String filename,
 203  
                               OutputStream output, String charset,
 204  
                               String encoding)
 205  
         throws TemplateException
 206  
     {
 207  0
         decodeRequest(context, filename, output, charset, encoding);
 208  0
     }
 209  
 
 210  
     /**
 211  
      * @see BaseTemplateEngineService#handleRequest(TemplateContext, String, Writer)
 212  
      */
 213  
     public void handleRequest(TemplateContext context,
 214  
                                        String template, Writer writer)
 215  
         throws TemplateException
 216  
     {
 217  0
         handleRequest(new ContextAdapter(context), template, writer);
 218  0
     }
 219  
 
 220  
     /**
 221  
      * @see VelocityService#handleRequest(Context, String, Writer)
 222  
      */
 223  
     public void handleRequest(Context context, String filename,
 224  
                               Writer writer)
 225  
         throws TemplateException
 226  
     {
 227  0
         handleRequest(context, filename, writer, null);
 228  0
     }
 229  
 
 230  
     /**
 231  
      * @see VelocityService#handleRequest(Context, String, Writer, String)
 232  
      */
 233  
     public void handleRequest(Context context, String filename,
 234  
                               Writer writer, String encoding)
 235  
         throws TemplateException
 236  
     {
 237  
         try
 238  
         {
 239  
             // If the context is not already an instance of
 240  
             // InternalEventContext, wrap it in a VeclocityContext so that
 241  
             // event cartridges will work. Unfortunately there is no interface
 242  
             // that extends both Context and InternalEventContext, so this
 243  
             // is not as clear as it could be.
 244  
 
 245  
             Context eventContext;
 246  
 
 247  0
             if ( context instanceof InternalEventContext )
 248  
             {
 249  0
                 eventContext = context;
 250  
             }
 251  
             else
 252  
             {
 253  0
                 eventContext = new VelocityContext( context );
 254  
             }
 255  
 
 256  
             // Attach the EC to the context
 257  0
             EventCartridge ec = getEventCartridge();
 258  0
             if (ec != null && eventCartridgeEnabled)
 259  
             {
 260  0
                 ec.attachToContext(eventContext);
 261  
             }
 262  
 
 263  0
             if (encoding != null)
 264  
             {
 265  
                 // Request scoped encoding first supported by Velocity 1.1.
 266  0
                 velocityEngine.mergeTemplate(filename, encoding,
 267  
                                              eventContext, writer);
 268  
             }
 269  
             else
 270  
             {
 271  0
                 velocityEngine.mergeTemplate(filename, eventContext, writer);
 272  
             }
 273  
         }
 274  0
         catch (Exception e)
 275  
         {
 276  0
             renderingError(filename, e);
 277  0
         }
 278  0
     }
 279  
 
 280  
     /**
 281  
      * By default, this is true if there is configured event cartridges.
 282  
      * You can disable EC processing if you first disable it and then call
 283  
      * handleRequest.
 284  
      */
 285  
     public void setEventCartridgeEnabled(boolean value)
 286  
     {
 287  0
         this.eventCartridgeEnabled = value;
 288  0
     }
 289  
 
 290  
     /**
 291  
      * @return EventCartridge the event cartridge
 292  
      */
 293  
     public EventCartridge getEventCartridge()
 294  
     {
 295  0
         return eventCartridge;
 296  
     }
 297  
 
 298  
     /**
 299  
      * Processes the request and fill in the template with the values
 300  
      * you set in the the supplied Context. Applies the specified
 301  
      * character and template encodings.
 302  
      *
 303  
      * @param context A context to use when evaluating the specified
 304  
      * template.
 305  
      * @param filename The file name of the template.
 306  
      * @param output The stream to which we will write the processed
 307  
      * template as a String.
 308  
      * @return The character set applied to the resulting text.
 309  
      *
 310  
      * @throws ServiceException Any exception trown while processing
 311  
      * will be wrapped into a ServiceException and rethrown.
 312  
      */
 313  
     private String decodeRequest(Context context, String filename,
 314  
                                  OutputStream output, String charset,
 315  
                                  String encoding)
 316  
         throws TemplateException
 317  
     {
 318  
         // TODO: Push this method of getting character set & encoding
 319  
         // from RunData back into Turbine.
 320  
         // charset  = ((RunData) data).getCharSet();
 321  
         // encoding = ((RunData) data).getTemplateEncoding();
 322  
 
 323  0
         if (charset == null)
 324  
         {
 325  0
             charset = DEFAULT_CHAR_SET;
 326  
         }
 327  
 
 328  0
         OutputStreamWriter writer = null;
 329  
         try
 330  
         {
 331  
             try
 332  
             {
 333  0
                 writer = new OutputStreamWriter(output, charset);
 334  
             }
 335  0
             catch (Exception e)
 336  
             {
 337  0
                 renderingError(filename, e);
 338  0
             }
 339  0
             handleRequest(context, filename, writer, encoding);
 340  
         }
 341  
         finally
 342  
         {
 343  0
             try
 344  
             {
 345  0
                 if (writer != null)
 346  
                 {
 347  0
                     writer.flush();
 348  
                 }
 349  
             }
 350  0
             catch (Exception ignored)
 351  
             {
 352  0
             }
 353  0
         }
 354  0
         return charset;
 355  
     }
 356  
 
 357  
     /**
 358  
      * Macro to handle rendering errors.
 359  
      *
 360  
      * @param filename The file name of the unrenderable template.
 361  
      * @param e        The error.
 362  
      *
 363  
      * @exception ServiceException Thrown every time.  Adds additional
 364  
      *                             information to <code>e</code>.
 365  
      */
 366  
     private final void renderingError(String filename, Throwable e)
 367  
         throws TemplateException
 368  
     {
 369  0
         String err = "Error rendering Velocity template: " + filename;
 370  0
         getLogger().error(err + ": " + e.getMessage());
 371  
         // if the Exception is a MethodInvocationException, the underlying
 372  
         // Exception is likely to be more informative, so rewrap that one.
 373  0
         if (e instanceof MethodInvocationException)
 374  
         {
 375  0
             e = ((MethodInvocationException)e).getWrappedThrowable();
 376  
         }
 377  
 
 378  0
         throw new TemplateException(err, e);
 379  
     }
 380  
 
 381  
     /**
 382  
      * Find out if a given template exists. Velocity
 383  
      * will do its own searching to determine whether
 384  
      * a template exists or not.
 385  
      *
 386  
      * @param String template to search for
 387  
      * @return boolean
 388  
      */
 389  
     public boolean templateExists(String template)
 390  
     {
 391  0
         return velocityEngine.templateExists(template);
 392  
     }
 393  
 
 394  
     // ---------------- Avalon Lifecycle Methods ---------------------
 395  
 
 396  
     /**
 397  
      * Avalon component lifecycle method
 398  
      */
 399  
     public void configure(Configuration conf)
 400  
         throws ConfigurationException
 401  
     {
 402  
         // put conf into object to pass to the velocity engine
 403  0
         velocityConf =
 404  
             new org.apache.commons.configuration.BaseConfiguration();
 405  0
         List ecconfig = null;
 406  0
         String logPath = null;
 407  0
         List templatePathKeys = new ArrayList();
 408  0
         List templatePaths = new ArrayList();
 409  
 
 410  
         if (1==2)
 411  
         {
 412  
             /* ### FIXME: Why is this both setup in a block which
 413  
                ### won't be compiled, and commented out?
 414  
             org.apache.commons.configuration.Configuration oldConf =
 415  
                 getConfiguration();
 416  
 
 417  
             ecconfig = oldConf
 418  
                 .getVector("eventCartridge.classes", new Vector(0));
 419  
             if (ecconfig.isEmpty())
 420  
             {
 421  
                 getLogger().info("No Velocity EventCartridges configured.");
 422  
             }
 423  
 
 424  
             // Now we have to perform a couple of path translations
 425  
             // for our log file and template paths.
 426  
             logPath =
 427  
                 oldConf.getString(VelocityEngine.RUNTIME_LOG, null);
 428  
             if (logPath == null || logPath.length() == 0)
 429  
             {
 430  
                 String msg = VelocityService.SERVICE_NAME+" runtime log file "+
 431  
                     "is misconfigured: '" + logPath + "' is not a valid log file";
 432  
                 throw new Error(msg);
 433  
             }
 434  
 
 435  
             // Get all the template paths where the velocity
 436  
             // runtime should search for templates and
 437  
             // collect them into a separate vector
 438  
             // to avoid concurrent modification exceptions.
 439  
             for (Iterator i = oldConf.getKeys(); i.hasNext();)
 440  
             {
 441  
                 String key = (String) i.next();
 442  
                 if (key.endsWith(RESOURCE_LOADER_PATH))
 443  
                 {
 444  
                     templatePathKeys.add(key);
 445  
                     templatePaths.add(oldConf.getVector(key));
 446  
                 }
 447  
             }
 448  
             */
 449  
         }
 450  
         else
 451  
         {
 452  
             // trick compiler
 453  
             if (true)
 454  
             {
 455  0
                 throw new ConfigurationException(
 456  
                     "Use of avalon-style configuration not completed yet");
 457  
             }
 458  
 
 459  
             final Configuration eventCartridgeConfs =
 460  
                 conf.getChild("event-cartriges", false);
 461  
             if (eventCartridgeConfs == null)
 462  
             {
 463  
                 ecconfig = Collections.EMPTY_LIST;
 464  
             }
 465  
             else
 466  
             {
 467  
                 Configuration[] classNameConfs =
 468  
                     eventCartridgeConfs.getChildren("classname");
 469  
                 if (classNameConfs == null)
 470  
                 {
 471  
                     ecconfig = Collections.EMPTY_LIST;
 472  
                 }
 473  
                 else
 474  
                 {
 475  
                     ecconfig = new ArrayList(classNameConfs.length);
 476  
                     for (int i=0; i < classNameConfs.length; i++)
 477  
                     {
 478  
                         ecconfig.add(classNameConfs[i].getValue());
 479  
                     }
 480  
                 }
 481  
             }
 482  
 
 483  
             /*
 484  
              *            final Configuration pathConfs =
 485  
              *                conf.getChild("event-cartriges", false);
 486  
              *            if (pathConfs != null)
 487  
              *            {
 488  
              *                Configuration[] nameVal = ecConfs.getChildren();
 489  
              *                for (int i=0; i < nameVal.length; i++)
 490  
              *                {
 491  
              *                    String key = nameVal[i].getName();
 492  
              *                    String val = nameVal[i].getValue();
 493  
              *                }
 494  
              *            }
 495  
              */
 496  
         }
 497  
 
 498  
         initEventCartridges(ecconfig);
 499  
 
 500  
         // check if path to logfile needs translation to webapp root
 501  
         if ( !(new File(logPath).isAbsolute()) )
 502  
         {
 503  
             logPath = getRealPath(logPath);
 504  
         }
 505  
         velocityConf.setProperty(VelocityEngine.RUNTIME_LOG, logPath);
 506  
 
 507  
         configureTemplatePaths(templatePathKeys, templatePaths);
 508  
 
 509  
         // Register with the template service.
 510  
         registerConfiguration(conf, "vm");
 511  
     }
 512  
 
 513  
     /**
 514  
      * This method is responsible for initializing the various Velocity
 515  
      * EventCartridges. You just add a configuration like this:
 516  
      * <code>
 517  
      * services.VelocityService.eventCartridge.classes = org.tigris.scarab.util.ReferenceInsertionFilter
 518  
      * </code>
 519  
      * and list out (comma separated) the list of EC's that you want to
 520  
      * initialize.
 521  
      */
 522  
     private void initEventCartridges(List ecconfig)
 523  
         throws ConfigurationException
 524  
     {
 525  0
         eventCartridge = new EventCartridge();
 526  0
         Object obj = null;
 527  0
         String className = null;
 528  0
         for (Iterator i = ecconfig.iterator() ; i.hasNext() ;)
 529  
         {
 530  0
             className = (String)i.next();
 531  
             try
 532  
             {
 533  0
                 boolean result = false;
 534  
 
 535  0
                 obj = Class.forName(className).newInstance();
 536  
 
 537  0
                 if (obj instanceof ReferenceInsertionEventHandler)
 538  
                 {
 539  0
                     result = getEventCartridge()
 540  
                         .addEventHandler((ReferenceInsertionEventHandler)obj);
 541  
                 }
 542  0
                 else if (obj instanceof NullSetEventHandler)
 543  
                 {
 544  0
                     result = getEventCartridge()
 545  
                         .addEventHandler((NullSetEventHandler)obj);
 546  
                 }
 547  0
                 else if (obj instanceof MethodExceptionEventHandler)
 548  
                 {
 549  0
                     result = getEventCartridge()
 550  
                         .addEventHandler((MethodExceptionEventHandler)obj);
 551  
                 }
 552  0
                 getLogger().info("Added EventCartridge: " +
 553  
                     obj.getClass().getName() + " : " + result);
 554  
             }
 555  0
             catch (Exception h)
 556  
             {
 557  0
                 throw new ConfigurationException(
 558  
                     "Could not configure EventCartridge: " +
 559  
                     className, h);
 560  0
             }
 561  
         }
 562  0
     }
 563  
 
 564  
     /**
 565  
      * Setup the velocity runtime by using a subset of the
 566  
      * Turbine configuration which relates to velocity.
 567  
      *
 568  
      * @exception ConfigurationException For any errors during initialization.
 569  
      */
 570  
     private void configureTemplatePaths(
 571  
         List templatePathKeys, List templatePaths)
 572  
     {
 573  
         // Loop through all template paths, clear the corresponding
 574  
         // velocity properties and translate them all to the webapp space.
 575  0
         for (int i=0; i<templatePathKeys.size(); i++)
 576  
         {
 577  0
             String key = (String) templatePathKeys.get(i);
 578  0
             Vector paths = (Vector) templatePaths.get(i);
 579  0
             if (paths != null)
 580  
             {
 581  
                 String entry;
 582  0
                 for (Iterator j = paths.iterator(); j.hasNext();)
 583  
                 {
 584  0
                     String path = (String) j.next();
 585  0
                     if (path.startsWith(JAR_PREFIX + "file"))
 586  
                     {
 587  
                         // A local jar resource URL path is a bit more
 588  
                         // complicated, but we can translate it as well.
 589  0
                         int ind = path.indexOf("!/");
 590  0
                         if (ind >= 0)
 591  
                         {
 592  0
                             entry = path.substring(ind);
 593  0
                             path = path.substring(9,ind);
 594  
                         }
 595  
                         else
 596  
                         {
 597  0
                             entry = "!/";
 598  0
                             path = path.substring(9);
 599  
                         }
 600  0
                         path = JAR_PREFIX + "file:" + getRealPath(path) +
 601  
                             entry;
 602  0
                     }
 603  0
                     else if (path.startsWith(ABSOLUTE_PREFIX))
 604  
                     {
 605  0
                         path = path.substring (ABSOLUTE_PREFIX.length(),
 606  
                                                path.length());
 607  
                     }
 608  0
                     else if (!path.startsWith(JAR_PREFIX))
 609  
                     {
 610  
                         // But we don't translate remote jar URLs.
 611  0
                         path = getRealPath(path);
 612  
                     }
 613  
                     // Put the translated paths back to the configuration.
 614  0
                     velocityConf.addProperty(key,path);
 615  0
                 }
 616  
             }
 617  
         }
 618  0
     }
 619  
 
 620  
     // ---------------- Avalon Lifecycle Methods ---------------------
 621  
 
 622  
     /**
 623  
      * Avalon component lifecycle method
 624  
      */
 625  
     public void initialize()
 626  
         throws Exception
 627  
     {
 628  
         try
 629  
         {
 630  0
             velocityEngine = new VelocityEngine();
 631  
 
 632  
             // clear the property to prepare for new value,
 633  
             //is this needed?
 634  0
             Iterator i = velocityConf.getKeys();
 635  0
             while (i.hasNext())
 636  
             {
 637  0
                 velocityEngine.clearProperty((String)i.next());
 638  
             }
 639  
 
 640  0
             velocityEngine.setExtendedProperties(ConfigurationConverter
 641  
                     .getExtendedProperties(velocityConf));
 642  0
             velocityEngine.init();
 643  0
             velocityConf = null;
 644  
 
 645  
         }
 646  0
         catch (Exception e)
 647  
         {
 648  0
             e.printStackTrace();
 649  0
             throw new Exception(
 650  
                 "Failed to initialize DefaultVelocityService", e);
 651  0
         }
 652  0
     }
 653  
 
 654  
 }