Added: velocity/site/cms/trunk/content/engine/2.1/developer-guide.mdtext
URL: 
http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/2.1/developer-guide.mdtext?rev=1854714&view=auto
==============================================================================
--- velocity/site/cms/trunk/content/engine/2.1/developer-guide.mdtext (added)
+++ velocity/site/cms/trunk/content/engine/2.1/developer-guide.mdtext Sun Mar  
3 13:56:00 2019
@@ -0,0 +1,1538 @@
+Title: Apache Velocity Engine - Developer Guide
+
+## Developer Guide - Contents
+
+[TOC]
+
+
+## Introduction
+
+Velocity is a Java-based template engine, a simple and powerful development 
tool that allows you to easily create and render documents that format and 
present your data. In this guide, we hope to give an overview of the basics of 
development using Velocity.
+
+### Building Web Applications with Velocity
+
+Velocity is often used for building web applications. In order to use Velocity 
in a web app you'll need a servlet or servlet-based framework. The easiest way 
to get started is with [VelocityViewServlet](/tools/devel/view-servlet.html) in 
the [Velocity Tools](/tools/devel/) subproject. You can also use any of a 
number of [third party 
framework](http://wiki.apache.org/velocity/PoweredByVelocity) or build your own 
servlet using the techniques described in this document.
+
+We suggest you read this article on [getting started with web 
applications](webapps.html) for more detail on the various options.
+
+### Downloading Velocity
+
+You can download the latest release version of the [Velocity 
Engine](/download.cgi#engine) or [Velocity Tools](/download.cgi#tools) from the 
main Apache Velocity download site. For Velocity itself, source is included 
with the binary download.
+
+If you want to download the latest source, you can do so via the Subversion 
(svn) source control system.
+
+You can also find published snapshots on the [Apache Snapshot 
Repository](https://repository.apache.org/content/repositories/snapshots/org/apache/velocity/).
+
+Instructions for building Velocity from source can be found in the 
[Build](build.html) document.
+
+### Dependencies
+
+For compiling or at runtime, Velocity needs a Java runtime environment version 
of 1.7 or more recent.
+
+Velocity also depends upon a few packages for general functionality:
+
++ [**Apache Commons 
Collections**](https://commons.apache.org/proper/commons-collections/) - 
required for compilation only.
++ [**Apache Commons Lang**](http://commons.apache.org/proper/commons-lang/) - 
required for compilation only.
++ [** SLF4J API**](http://www.slf4j.org) - required for compilation and at 
runtime.
+
+At runtime, Velocity will require an SLF4J binding to be present in the path. 
Typically, one of:
+
++ [AVSL](http://software.clapper.org/avsl/)
++ [SLF4J JDK14 
Adapter](http://www.slf4j.org/api/org/slf4j/impl/JDK14LoggerAdapter.html)
++ [SLF4J Log4J 
Adapter](http://www.slf4j.org/api/org/slf4j/impl/Log4jLoggerAdapter.html)
++ [SLF4J Simple 
Logger](http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.html)
++ [SLF4J Android](http://www.slf4j.org/android/)
++ [LOGBack](http://logback.qos.ch/)
++ [WebApp SLF4J Logger](https://github.com/arkanovicz/webapp-slf4j-logger)
+
+## Resources
+
+There are quite a few resources and examples available to the programmer, and 
we recommend that you look at our examples, documentation and even the source 
code. Some great sources are:
+
++ The user and developer community: join us via the 
[mail-lists](/contact.html). Mail list archives are available from that page, 
too.
++ The [Velocity Wiki](http://wiki.apache.org/velocity/) contains articles, 
sample code, and other community-written content.
++ [Frequently Asked Questions 
(FAQ)](http://wiki.apache.org/velocity/VelocityFAQ) : please visit this page to 
read the latest FAQ and to contribute your own answers.
++ source code: `src/java/...`: all the source code to the Velocity project
++ application example 1: `examples/app_example1`: a simple example showing how 
to use Velocity in an application program.
++ application example 2: `examples/app_example2`: a simple example showing how 
to use Velocity in an application program using the Velocity application 
utility class.
++ XML example: `examples/xmlapp_example`: a simple example showing how to use 
JDOM to read and access XML document data from within a Velocity template.  It 
also includes a demonstration of a recursive Velocimacro that walks the 
document tree.
++ event example: `examples/event_example`: An example that demonstrates the 
use of the event handling API.
++ Anakia application: `examples/anakia`: example application showing how to 
use Velocity for creating stylesheet renderings of xml data
++ documentation: `docs`: all the generated documentation for the Velocity 
project in html
++ API documentation: `docs/api`: the generated Javadoc documentation for the 
Velocity project
++ templates: `test/templates`: a large collection of template examples in our 
testbed directory, these are a great source of useage examples of VTL, the 
Velocity Template Language
++ context example: `examples/context_example`: two examples showing how the 
Velocity context can be extended. For advanced users.
+
+All directory references above are relative to the distribution root directory.
+
+## How Velocity Works
+
+### 'The Fundamental Pattern'
+
+When using Velocity in an application program or in a servlet (or anywhere, 
actually), you will generally do the following:
+
+1. Initialize Velocity. This applies to both usage patterns for Velocity, the 
Singleton as well as the 'separate runtime instance' (see more on this below), 
and you only do this once.
+2. Create a Context object (more on what that is later).
+3. Add your data objects to the Context.
+4. Choose a template.
+5. 'Merge' the template and your data to produce the ouput.
+
+In code, using the singleton pattern via the 
`org.apache.velocity.app.Velocity` class, this looks like
+
+    :::java
+    import java.io.StringWriter;
+    import org.apache.velocity.VelocityContext;
+    import org.apache.velocity.Template;
+    import org.apache.velocity.app.Velocity;
+    import org.apache.velocity.exception.ResourceNotFoundException;
+    import org.apache.velocity.exception.ParseErrorException;
+    import org.apache.velocity.exception.MethodInvocationException;
+    
+    Velocity.init();
+    
+    VelocityContext context = new VelocityContext();
+    
+    context.put( "name", new String("Velocity") );
+    
+    Template template = null;
+    
+    try
+    {
+      template = Velocity.getTemplate("mytemplate.vm");
+    }
+    catch( ResourceNotFoundException rnfe )
+    {
+      // couldn't find the template
+    }
+    catch( ParseErrorException pee )
+    {
+      // syntax error: problem parsing the template
+    }
+    catch( MethodInvocationException mie )
+    {
+      // something invoked in the template
+      // threw an exception
+    }
+    catch( Exception e )
+    {}
+
+    StringWriter sw = new StringWriter();
+
+    template.merge( context, sw );
+
+That's the basic pattern. It is very simple, isn't it?  This is generally what 
happens when you use Velocity to render a template. You probably won't be 
writing code exactly like this - we provide a few tools to help make it even 
easier.  However, no matter how to use Velocity the above sequence is what is 
happening either explicitly, or behind the scenes.
+
+## To Singleton Or Not To Singleton...
+
+Developers have two options for using the Velocity engine, the singleton model 
and the separate instance model. The same core Velocity code is used for both 
approaches, which are provided to make Velocity easier to integrate into your 
Java application.
+
+### Singleton Model
+
+This is the legacy pattern, where there is only one instance of the Velocity 
engine in the JVM (or web application, depending) that is shared by all. This 
is very convenient as it allows localized configuration and sharing of 
resources.  For example, this is a very appropriate model for use in a Servlet 
2.2+ compliant web application as each web application can have its own 
instance of Velocity, allowing that web application's servlet to share 
resources like templates, a logger, etc. The singleton is accessable via the 
`org.apache.velocity.app.Velocity` class, and and example of use:
+
+    :::java
+    import org.apache.velocity.app.Velocity;
+    import org.apache.velocity.Template;
+    
+    ...
+    
+    /*
+     *  Configure the engine
+     */
+
+    Velocity.setProperty(
+        Velocity.RUNTIME_LOG_NAME, "mylog");
+
+    /*
+     *  now initialize the engine
+     */
+
+    Velocity.init();
+
+    ...
+
+    Template t = Velocity.getTemplate("foo.vm");
+
+
+### Separate Instance
+
+New in version 1.2, the separate instance allows you to create, configure and 
use as many instances of Velocity as you wish in the same JVM (or web 
application.)  This is useful when you wish to support separate configurations, 
such as template directories, loggers, etc in the same application.  To use 
separate instances, use the `org.apache.velocity.app.VelocityEngine` class.  An 
example, which parallels the above singleton example, looks like:
+
+    :::java
+    import org.apache.velocity.app.VelocityEngine;
+    import org.apache.velocity.Template;
+    
+    ...
+    
+    /*
+     *  create a new instance of the engine
+     */
+    
+    VelocityEngine ve = new VelocityEngine();
+    
+    /*
+     *  configure the engine.  In this case, we are using
+     *  a specific logger name
+     */
+    
+    ve.setProperty(
+        VelocityEngine.RUNTIME_LOG_NAME, "mylog");
+    
+    /*
+     *  initialize the engine
+     */
+    
+    ve.init();
+    
+    ...
+    
+    Template t = ve.getTemplate("foo.vm");
+
+As you can see, this is very simple and straightforward.  Except for some 
simple syntax changes, using Velocity as a singleton or as separate instances 
requires no changes to the high-level structure of your application or 
templates.
+
+As a programmer, the classes you should use to interact with the Velocity 
internals are the `org.apache.velocity.app.Velocity` class if using the 
singleton model, or `org.apache.velocity.app.VelocityEngine` if using the 
non-singleton model ('separate instance').
+
+At no time should an application use the internal `Runtime, RuntimeConstants, 
RuntimeSingleton or RuntimeInstance` classes in the 
`org.apache.velocity.runtime` package, as these are intended for internal use 
only and may change over time.  As mentioned above, the classes you should use 
are located in the `org.apache.velocity.app` package, and are the `Velocity` 
and `VelocityEngine` classes.  If anything is missing or needed from those 
classes, do not hesitate to suggest changes - these classes are intended for 
the application developer.
+
+## The Context
+
+### The Basics
+
+The concept of the 'context' is central to Velocity, and is a common technique 
for moving a container of data around between parts of a system. The idea is 
that the context is a 'carrier' of data between the Java layer (or you the 
programmer) and the template layer ( or the designer ). You as the programmer 
will gather objects of various types, whatever your application calls for, and 
place them in the context.  To the designer, these objects, and their methods 
and properties, will become accessable via template elements called <a 
href="vtl-reference.html"> references</a>. Generally, you will work with the 
designer to determine the data needs for the application. In a sense, this will 
become an 'API'  as you produce a data set for the designer to access in the 
template.  Therefore, in this phase of  the development process it is worth 
devoting some time and careful analysis.
+
+While Velocity allows you to create your own context classes to support 
special needs and techniques (like a context that accesses an LDAP server 
directly, for example), a good basic implementation class called 
VelocityContext is provided for you as part of the distribution.
+
+VelocityContext is suitable for all general purpose needs, and we strongly 
recommended that you use it. Only in exceptional and advanced cases will you 
need to extend or create your own context implementation.
+
+Using VelocityContext is as simple as using a normal Java Hashtable class. 
While the interface contains other useful methods, the two main methods you 
will use are
+
+    :::java
+    public Object put(String key, Object value);
+    public Object get(String key);
+
+Please note that like a Hashtable, the value must be derived from 
java.lang.Object, and must not be null. Fundamental types like int or float 
must be wrapped in the appropriate wrapper classes.
+
+That's really all there is to basic context operations. For more information, 
see the API documentation included in the distribution.
+
+### Support for Iterative Objects for #foreach()
+
+As a programmer, you have great freedom in the objects that you put into the 
context.  But as with most freedoms, this one comes with a little bit of 
responsibility, so understand what Velocity supports, and any issues that may 
arise.  Velocity supports serveral types of collection types  suitable for use 
in the VTL `#foreach()` directive.
++ `Object []`  Regular object array, not much needs to be said here. Velocity 
will internally wrap your array in a class that provides an Iterator interface, 
 but that shouldn't concern you as the programmer, or the template author.  Of 
more interest, is the fact that Velocity will now allow template authors to 
treat arrays as fixed-length lists. This means they may call methods like 
`size()`, `isEmpty()` and `get(int)` as well as the `empty` property on both 
arrays and standard java.util.List instances without concerning themselves 
about the difference.
++ `java.util.Collection`  Velocity will use the `iterator()` method to get an 
Iterator to use in the loop, so if you are implementing a Collection interface 
on your object, please ensure that `iterator()` returns a working  Iterator.
++ `java.util.Map ` Here, Velocity depends upon the `values()` method of the 
interface to get a `Collection` interface, on which `iterator()` is called to 
retrieve an Iterator for the loop.
++ `java.util.Iterator` USE WITH CAUTION: This is currently supported only 
provisionally - the issue of concern is the 'non-resettablity' of the Iterator. 
 If a 'naked' Iterator is placed into the context, and used in more than one 
#foreach(), subsequent #foreach() blocks after the first will fail, as the 
Iterator doesn't reset.
++ `java.util.Enumeration` USE WITH CAUTION: Like `java.util.Iterator`, this is 
currently supported only provisionally - the issue of concern is the 
'non-resettablity' of the Enumeration.  If a 'naked' Enumeration is placed into 
the context, and used in more than one #foreach(), subsequent #foreach() blocks 
after the first will fail, as the Enumeration doesn't reset.
++  Any public class with a `public Iterator iterator()` method that never 
returns `null`.  As a last resort, Velocity will look for an `iterator()` 
method. This provides great flexibility and automatic support for 
`java.util.Iterable` interface.
+
+In the case of the `Iterator` and `Enumeration`, it is recommended that they 
are placed in the context only when it cannot be avoided, and you should let 
Velocity find the appropriate reusable iterative interface when that is 
sufficient and possible.
+
+There are good reasons to use the `java.util.Iterator` interface directly 
(large data sets via JDBC, for example), but if it can be avoided, it might be 
better to use something else. By 'directly' , we meant doing something like:
+
+    :::java
+    Vector v = new Vector();
+    v.addElement("Hello");
+    v.addElement("There");
+    
+    context.put("words", v.iterator() );
+
+where the Iterator itself is placed into the context. Instead, if you simply 
did:
+
+    :::java
+    context.put("words", v );
+
+then all would be fine: Velocity would figure out that Vector implement 
Collection (via List), and therefore will find the `iterator()` method, and use 
that to get a 'fresh' Iterator for its use each time it needs to.  With just a 
plain Iterator (the first snippet above...), once velocity has used it in a 
`#foreach()`, Velocity has no way of getting a new one to use for the next 
`#foreach()` it is used in.  The result is no output from any subsequent 
`#foreach()` blocks using that reference.
+
+This above isn't meant to give the impression that iterating over collections 
in Velocity is something that requires great care and thought.  Rather, the 
opposite is true, in general.  Just be careful when you place an Iterator into 
the context.
+
+### Support for "Static Classes"
+
+Not all classes are instantiable.  Classes like `java.lang.Math` do not 
provide any public constructor, and yet may contain useful static methods. In 
order to access these static methods from a template, you can simply add the 
class itself to the context:
+
+    :::java
+    context.put("Math", Math.class);
+
+This will allow you to call any public static method in `java.lang.Math` on 
the `$Math` reference in the template.
+
+### Context Chaining
+
+An innovative feature of Velocity's context design is the concept of *context 
chaining*. Also sometimes referred to as *context wrapping*, this advanced 
feature allows you to connect separate contexts together in a manner that makes 
it appear as one 'contiguous' context to the template.
+
+This is best illustrated by an example:
+
+    :::java
+    VelocityContext context1 = new VelocityContext();
+    
+    context1.put("name","Velocity");
+    context1.put("project", "Jakarta");
+    context1.put("duplicate", "I am in context1");
+    
+    VelocityContext context2 = new VelocityContext( context1 );
+    
+    context2.put("lang", "Java" );
+    context2.put("duplicate", "I am in context2");
+    
+    template.merge( context2, writer );
+
+In the code above, we have set up context2 such that it *chains* context1.  
This means that in the template, you can access any of the items that were put 
into either of the two VelocityContext objects, as long as there is no 
duplication of the keys used to add objects. If that is the case, as it is 
above for the key 'duplicate', the object stored in the nearest context in the 
chain will be available.  In this example above, the object returned would be 
the string "I am in context2".
+
+Note that this duplication, or 'covering', of a context item does not in any 
way harm or alter the covered object.  So in the example above, the string "I 
am in context1" is alive and well, still accessable via 
context1.get("duplicate").  But in the example above, the value of the 
reference '$duplicate' in the template would be 'I am in context2', and the 
template has no access to the covered string 'I am in context1'.
+
+Note also that you have to be careful when you are relying on the template to 
add information to a context that you will examine later after the rendering.  
The changes to the context via `#set()` statements in a template will affect 
only the outer context.  So make sure that you don't discard the outer context, 
expecting the data from the template to have been placed onto the inner one.
+
+This feature has many uses, the most common so far is providing layered data 
access and toolsets.
+
+As mentioned before, the Velocity context mechanism is also extendable, but 
beyond the current scope of this guide. If you are interested, please see the 
classes in the package `org.apache.velocity.context` to see how the provided 
contexts are put together.  Futher, there are a few examples in the 
`examples/context_example` directory in the distribution which show alternate 
implementations, including [a goofy] one that uses a database as the backing 
storage.
+
+Please note that these examples are unsupported and are there for 
demonstration/educational purposes only.
+
+### Objects Created in the Template
+
+There are two common situations where the Java code must deal with objects 
created at runtime in the template:
+
+When a template author calls a method of an object placed into the context by 
Java code.
+
+    :::velocity
+    #set($myarr = ["a","b","c"] )
+    $foo.bar( $myarr )
+
+When a template adds objects to the context, the Java code can access those 
objects after the merge process is complete.
+
+    :::velocity
+    #set($myarr = ["a","b","c"] )
+    #set( $foo = 1 )
+    #set( $bar = "bar")
+
+Dealing with these cases if very straighforward, as there are just a few 
things to know:
+
++ The VTL RangeOperator  [ 1..10 ]  and  ObjectArray ["a","b"] are 
`java.util.ArrayList` objects when placed in the context or passed to methods.  
 Therefore, your methods that are designed to accept arrays created in the 
template should be written with this in mind.
++ VTL Map references are unsurprisingly stored as `java.util.Map`.
++ Decimal numbers will be Doubles or BigDecimals in the context, integer 
numbers will be Integer, Long, or BigIntegers, and strings will be, of course, 
Strings.
++ Since version 2.0, Velocity will convert method arguments between all main 
Java standard types (booleans, numbers and strings). If you want to revert to 
the Velocity 1.x behavior, where provided conversions were restricted to 
implicit Java conversions, you can set the property 
`runtime.conversion.handler` to `none`.
+
+### Other Context Issues
+
+One of the features provided by the VelocityContext (or any Context derived 
from AbstractContext) is node specific introspection caching.  Generally, you 
as a the developer don't need to worry about this when using the 
VelocityContext as your context.  However, there is currently one known usage 
pattern where you must be aware of this feature.
+
+The VelocityContext will accumulate intropection information about the syntax 
nodes in a template as it visits those nodes.  So, in the following situation:
+
++ You are iterating over the same template using the same VelocityContext 
object.
++ Template caching is off.
++ You request the Template from getTemplate() on each iteration.
+
+It is possible that your VelocityContext will appear to 'leak' memory (it is 
really just gathering more introspection information.)  What happens is that it 
accumulates template node introspection information for each template it 
visits, and as template caching is off, it appears to the VelocityContext that 
it is visiting a new template each time. Hence it gathers more introspection 
information and grows. It is highly recommended that you do one or more of the 
following:
+
++ Create a new VelocityContext for each excursion down through the template 
render process. This will prevent the accumulation of introspection cache data. 
 For the case where you want to reuse the VelocityContext because it's 
populated with data or objects, you can simply wrap the populated 
VelocityContext in another, and the 'outer' one will accumulate the 
introspection information, which you will just discard.  Ex. `VelocityContext 
useThis = new VelocityContext( populatedVC );` This works because the outer 
context will store the introspection cache data, and get any requested data 
from the inner context (as it is empty.) Be careful though - if your template 
places data into the context and it's expected that it will be used in the 
subsequent iterations, you will need to do one of the other fixes, as any 
template #set() statements will be stored in the outermost context. See the 
discussion in [**Context Chaining**](#context-chaining) for more information.
++ Turn on template caching.  This will prevent the template from being 
re-parsed on each iteration, resulting the the VelocityContext being able to 
not only avoid adding to the introspection cache information, but be able to 
use it resulting in a performance improvement.
++ Reuse the Template object for the duration of the loop iterations. Then you 
won't be forcing Velocity, if the cache is turned off, to reread and reparse 
the same template over and over, so the VelocityContext won't gather new 
introspection information each time.
+
+## Using Velocity
+
+If you are using [VelocityViewServlet](/tools/devel/view-servlet.html) or 
other web frameworks, you may never call Velocity directly.  However, if you 
use Velocity for non-web purposes, or create your own web framework you will 
need to directly call the Velocity Engine similar to [the fundamental 
pattern](#the-fundamental-pattern) shown earlier. One important additional 
thing to remember is to initialize the Velocity Engine before using it to merge 
templates.
+
+### The Velocity Helper Class
+
+Velocity contains an application utility class called Velocity ( 
`org.apache.velocity.app.Velocity` ).  The purpose of this class is to provide 
the necessary methods required to initialize Velocity, as well as useful 
utility routines to make life easier in using Velocity. This class is 
documented  in the project's javadoc, so please look there for definitive 
details. This documentation is intended to be of a tutorial nature; therefore 
for compete API information, the Javadoc is the definitive source.
+
+The Velocity runtime engine is a singleton instance that provides resource, 
logging and other services to all Velocity users running in the same JVM. 
Therefore, the runtime engine is initialized only once.  You can attempt to 
initialize Velocity more than once, but only the first initialization will 
apply.  The rest of the attempts will be ignored.  The Velocity utility class 
currently provides five methods used in configuration of the runtime engine.
+
+The five configuration methods are:
+
++ `setProperty( String key, Object o )`
+
+    Sets the property `key` with the value `o`. The value is typically a 
String, but in special cases can also be a comma-separated list of values (in a 
single String, ex."foo, bar, woogie") as well as other things that will arise.
+
++ `Object getProperty( String key )`
+
+    Returns the value of the property key.  Note that you must be aware of the 
type of the return value, as they can be things other than Strings.
+
++ `init()`
+
+    Initializes the runtime with the default properties provided in the 
distribution.(These are listed below in the section pertaining to properties.)
+
++ `init( Properties p )`
+
+    Initializes the runtime with the properties contained in the 
`java.util.Properties` object passed as an argument.
+
++ `init( String filename )`
+
+    initializes the runtime using the properties found in the properties file 
`filename`
+
+Note that in each case, the default properties will be used as a base 
configuration, and any additional properties specified by the application will 
replace individual defaults.  Any default properties not overwritten will 
remain in effect.  This has the benefit that only the properties you are 
interested in changing need to be specified, rather than a complete set.
+
+Another thing to note is that the `init()` calls may be called more than once 
without harm in an application. However, the first call to any of the `init()` 
functions will configure the engine with the configuration properties set at 
that point, and any further configuration changes or `init()` calls will be 
ignored.
+
+The most common approaches to initializing Velocity will be something like:
+
+1. Setup the configuration values you wish to set in a file in the same format 
as org/apache/velocity/runtime/defaults/velocity.properties (the default set),  
or in a `java.util.Properties`, and then call either `init( filename )` or 
`init( Properties )`
+2. Set the configuration values individually using `setProperty()` and then 
call `init()`.  This method is generally used by more advanced applications 
that already have their own configuration management system - this allows the 
application to configure Velocity based upon values it generates at runtime, 
for example.
+
+Once the runtime is initialized, you can do with it what you wish. This mostly 
revolves around rendering templates into an output stream, and the Velocity 
utility class allows you to do this easily.  Currently, here are the methods 
and a brief description of what they do:
+
++ ` evaluate( Context context,  Writer out, String logTag, String instring )`
+
+    `evaluate( Context context, Writer writer, String logTag, InputStream 
instream )`
+
+    These methods will render the input, in either the form of String or 
InputStream to an output Writer, using a Context that you provide. This is a 
very convenient method to use for token replacement of strings, or if you keep 
'templates' of VTL-containing content in a place like a database or other 
non-file storage, or simply generate such dynamically.
+
++ `invokeVelocimacro( String vmName, String namespace, String params[],
+    Context context, Writer writer )`
+
+    Allows direct access to Velocimacros.  This can also be accomplished via 
the `evaluate()` method above  if you wish.  Here you simply name the vm you 
wish to be called, create an array of args to the VM, a Context of data, and 
Writer for the output.  Note that the VM args must be the 'keys' of the data 
objects in the Context, rather than literal data to be used as the arg.  This 
will probably change.
+
++ `mergeTemplate( String templateName, Context context, Writer writer )`
+
+    Convenient access to the normal template handling and rendering services 
of Velocity.  This method will take care of getting and rendering the template. 
 It will take advantage of loading the template according to the properties 
setting for the file resource loader, and therefore provides the advantage of 
file and parsed template caching that Velocity offers.  This is the most 
efficient way to access templates, and is recommended unless you have special 
needs.
+
++ `boolean templateExists( String name )`
+
+    Determines if a template `name` is able to be found by the currently 
configured resource loaders.
+
+Once we know about these basic helpers, it is easy to write a Java program 
that uses Velocity.  Here it is:
+
+    :::java
+    import java.io.StringWriter;
+    import org.apache.velocity.app.Velocity;
+    import org.apache.velocity.VelocityContext;
+    
+    public class Example2
+    {
+        public static void main( String args[] )
+        {
+            /* first, we init the runtime engine.  Defaults are fine. */
+            
+            Velocity.init();
+            
+            /* lets make a Context and put data into it */
+            
+            VelocityContext context = new VelocityContext();
+            
+            context.put("name", "Velocity");
+            context.put("project", "Jakarta");
+            
+            /* lets render a template */
+            
+            StringWriter w = new StringWriter();
+            
+            Velocity.mergeTemplate("testtemplate.vm", context, w );
+            System.out.println(" template : " + w );
+            
+            /* lets make our own string to render */
+            
+            String s = "We are using $project $name to render this.";
+            w = new StringWriter();
+            Velocity.evaluate( context, w, "mystring", s );
+            System.out.println(" string : " + w );
+        }
+    }
+
+When we run this program, and have the template ` testtemplate.vm` in the same 
directory as our program (because we used the default configuration properties, 
and the defaul place to load templates from is the current directory...), our 
output should be:
+
+    template : Hi!  This Velocity from the Jakarta project.
+    
+    string : We are using Jakarta Velocity to render this.
+
+where the template we used, testtemplate.vm, is
+
+    :::velocity
+    Hi!  This $name from the $project project.
+
+That's all there is to it!  Note that we didn't have to use both 
`mergeTemplate()` and `evaluate()` in our program.  They are both included 
there for demonstration purposes. You will probably use only one of the 
methods, but depending on you application requirements,  you are free to do 
what you wish.
+
+This appears to be a little different from the 'fundamental pattern' that was 
mentioned at the beginning of this guide, but it really is the same thing.  
First, you are making a context and filling it with the data needed.  Where 
this examples differs is that in the part of the above example where 
`mergeTemplate()` is used, `mergeTemplate()` is doing the work of getting the 
template and merging it for you, using the lower-level calls in the Runtime 
class. In the second example, you are making your template dynamically via the 
String, so that is analgous to the 'choose template' part of the process, and 
the `evaluate()` method does the merging for you using lower level calls.
+
+So the example above sticks to the same simple pattern of using the Velocity 
template engine, but the utility functions do some of the repeated drudge work, 
or allow you other options for your template content other than template files.
+
+### Exceptions
+
+Velocity may throw one of several exceptions during the parse / merge cycle. 
These exceptions extend RuntimeException and do not need to explicitly caught, 
although each includes specific properties that may help in presenting useful 
error messages to the end user. The exceptions are found in the package 
`org.apache.velocity.exception` and are:
+
+1. `ResourceNotFoundException`
+
+    Thrown when the resource managment system cannot find a resource 
(template) that
+was requested.
+    
+2. `ParseErrorException`
+   
+   Thrown when a VTL syntax error is found when parsing a resource (template).
+   
+3. `TemplateInitException`
+   
+   Thrown during the first pass of template parsing; reports problems with 
macro and directive initialization.
+   
+4. `MethodInvocationException`
+   
+   Thrown when an object's method in the context throws an exception during 
render time.  This exception wraps the thrown exception and propagates it to 
the application.  This allows you to handle problems in your own objects at 
runtime.
+
+In each case, a message is put into the runtime log.  For more information,
+see the Javadoc API documentation.
+
+### Miscellaneous Details
+
+While the above example used the default properties, setting your own 
properties is very simple. All you have to do is make a properties file 
somewhere and pass the name of that file to the `init(String)` method of the 
Velocity utility class, or make a `java.util.Properties` object, add the 
desired properties and values, and pass that to the `init(Properties)` method. 
The latter method is convenient, because you can either fill it directly from a 
separate properties file via the `load()`  method, or even better, you can fill 
it dynamically from your own application / framework's property set at runtime. 
 This gives you the freedom to combine all of the properties for your app into 
one properties file.
+
+If we wanted to use a different directory than the current directory to load 
our template from, we could do something like this:
+
+    :::java
+     ...
+    
+    import java.util.Properties;
+     ...
+    
+    public static void main( String args[] )
+    {
+        /* first, we init the runtime engine.  */
+        
+        Properties p = new Properties();
+        p.setProperty("file.resource.loader.path", "/opt/templates");
+        Velocity.init( p );
+        
+        /* lets make a Context and put data into it */
+        
+        ...
+
+And the same if you want to use a VelocityEngine object rather than the 
singleton engine:
+
+    :::java
+     ...
+    
+    import java.util.Properties;
+     ...
+    
+    public static void main( String args[] )
+    {
+        /* first, we init the runtime engine.  */
+        
+        Properties p = new Properties();
+        p.setProperty("file.resource.loader.path", "/opt/templates");
+        VelocityEngine engine = new VelocityEngine();
+        engine.init( p );
+        
+        /* lets make a Context and put data into it */
+        
+        ...
+
+
+And, assuming you have a directory `/opt/templates` and the template 
`testtemplate.vm` is in there, then things would work just fine. If you try 
this and have a problem, be sure to look at the velocity.log for information - 
the error messages are pretty good for figuring out what is wrong.
+
+If you need to place objects into the Velocity properties, you may do so: the 
`java.util.Properties` class *does* accept Object values (which will only 
invalidate the use of its `load` and `store` methods).
+
+To combine multiple properties files, you may call several times 
`setProperties(Properties)`, `setProperty(String, Object)` or 
`addProperty(String, Object)` before calling `init()`.
+
+You may want to also consider using the Application Attributes feature 
described in the following section.
+
+## Logging
+
+Since version 2.0, Velocity has switched to the [SLF4J](http://www.slf4j.org/) 
logging facade.
+
+All you have to do to enable logging is to make sure that your classpath 
contains the slf4j-api jar, and one and only one slf4j binding jar towards your 
favourite logsystem or facade. See the [dependecies](#dependencies) section for 
a list of SLF4J bindings.
+
+By default, Velocity will use a base logger named `org.apache.velocity`, and 
several children loggers (whose name is appended to the base logger name):
+
++ `directive`, and `directive.`*`[directivename]`* for all logs related to VTL 
directives
++ `parser` for parser logs
++ `loader`, and `loader.`*`[loadername]`* for resource loaders logs
++ `macro` for macro-related logs
++ `rendering` for everything related to actual rendering of templates, 
including introspection and method calls
++ `event` for logs emitted by the event cartridge.
+
+You can customize this logger in two ways:
+
++ By programmatically giving Velocity a living instance of an orf.slf4j.Logger 
object, using the runtime.log.instance property key.
++ By configuring the name of the logger to be used by your velocity instance, 
using the runtime.log.name property key. It can be done from the 
velocity.properties file, if present.
+
+## Space Gobbling
+
+Since version 2.0, it's possible to control the whitespace and endline 
gobbling performed by Velocity during the rendering, so as to control the 
indentation of the generated code. Space gobbling only happens **around** 
directive and control elements (all elements starting with `#`).
+
+The `space.gobbling` configuration key can take the following values: `none`, 
`bc` (aka backward compatible), `lines` (the default) and `structured`, each 
detailed below.
+
+### No space gobbling
+
+In some special circumstances, you may want to supress all space gobbling.
+
+<table>
+  <tbody>
+    <tr>
+      <td>
+        <div class="codehilite">
+          <pre class="fixed">
+#set($foo = 'foo')<span style="color:green">&ldsh;</span>
+&lt;table&gt;<span style="color:green">&ldsh;</span>
+  &lt;tbody&gt;<span style="color:green">&ldsh;</span>
+#foreach($row in [1..2])<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+  #foreach($col in [1..2])<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+    #set($text = "row $row, col $col")<span style="color:green">&ldsh;</span>
+        $text<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+  #end<span style="color:green">&ldsh;</span>
+    &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+#end<span style="color:green">&ldsh;</span>
+  &lt;/tbody&gt;<span style="color:green">&ldsh;</span>
+&lt;/table&gt;<span style="color:green">&ldsh;</span>
+          </pre>
+        </div>
+      </td>
+      <td valign="center" style="padding:1em;">
+        produces
+      </td>
+      <td>
+        <div class="codehilite">
+          <pre class="fixed">
+<span style="color:green">&ldsh;</span>
+&lt;table&gt;<span style="color:green">&ldsh;</span>
+  &lt;tbody&gt;<span style="color:green">&ldsh;</span>
+<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+  <span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+    <span style="color:green">&ldsh;</span>
+        row 1, col 1<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+  <span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+    <span style="color:green">&ldsh;</span>
+        row 1, col 2<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+  <span style="color:green">&ldsh;</span>
+    &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+  <span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+    <span style="color:green">&ldsh;</span>
+        row 2, col 1<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+  <span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+    <span style="color:green">&ldsh;</span>
+        row 2, col 2<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+  <span style="color:green">&ldsh;</span>
+    &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+<span style="color:green">&ldsh;</span>
+  &lt;/tbody&gt;<span style="color:green">&ldsh;</span>
+&lt;/table&gt;<span style="color:green">&ldsh;</span>
+          </pre>
+        </div>
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+### Backward compatible space gobbling
+
+This space gobbling mode mimics Velocity 1.x space gobbling. Basically, it 
eats all extra endline characters **after** directives, plus extra whitespaces 
**before** the `#set` directive whenever the previous line already contains a 
directive.
+
+<table>
+  <tbody>
+    <tr>
+      <td>
+        <div class="codehilite">
+          <pre class="fixed">
+#set($foo = 'foo')<span style="color:green">&ldsh;</span>
+&lt;table&gt;<span style="color:green">&ldsh;</span>
+  &lt;tbody&gt;<span style="color:green">&ldsh;</span>
+#foreach($row in [1..2])<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+  #foreach($col in [1..2])<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+    #set($text = "row $row, col $col")<span style="color:green">&ldsh;</span>
+        $text<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+  #end<span style="color:green">&ldsh;</span>
+    &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+#end<span style="color:green">&ldsh;</span>
+  &lt;/tbody&gt;<span style="color:green">&ldsh;</span>
+&lt;/table&gt;<span style="color:green">&ldsh;</span>
+          </pre>
+        </div>
+      </td>
+      <td valign="center" style="padding:1em;">
+        produces
+      </td>
+      <td>
+        <div class="codehilite">
+          <pre class="fixed">
+&lt;table&gt;<span style="color:green">&ldsh;</span>
+  &lt;tbody&gt;<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+        &lt;td&gt;<span style="color:green">&ldsh;</span>
+            row 1, col 1<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+        &lt;td&gt;<span style="color:green">&ldsh;</span>
+            row 1, col 2<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+      &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+        &lt;td&gt;<span style="color:green">&ldsh;</span>
+            row 2, col 1<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+        &lt;td&gt;<span style="color:green">&ldsh;</span>
+            row 2, col 2<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+      &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+  &lt;/tbody&gt;<span style="color:green">&ldsh;</span>
+&lt;/table&gt;<span style="color:green">&ldsh;</span>
+          </pre>
+        </div>
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+As you can see, the output is a bit cleaner, but its indentation is not yet 
perfect since spaces used to indent the VTL code are found back in it.
+
+### Lines space gobbling
+
+This is the default space gobbling mode. It gobbles all whitespace and endline 
characters from lines containing only a single VTL directive.
+
+This is for instance the approriate mode if you use two distinct indentation 
frameworks in your templates, one for the VTL, and the other for the generated 
language (HTML in this example).
+
+<table>
+  <tbody>
+    <tr>
+      <td>
+        <div class="codehilite">
+          <pre class="fixed">
+#set($foo = 'foo')<span style="color:green">&ldsh;</span>
+&lt;table&gt;<span style="color:green">&ldsh;</span>
+  &lt;tbody&gt;<span style="color:green">&ldsh;</span>
+#foreach($row in [1..2])<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+  #foreach($col in [1..2])<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+    #set($text = "row $row, col $col")<span style="color:green">&ldsh;</span>
+        $text<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+  #end<span style="color:green">&ldsh;</span>
+    &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+#end<span style="color:green">&ldsh;</span>
+  &lt;/tbody&gt;<span style="color:green">&ldsh;</span>
+&lt;/table&gt;<span style="color:green">&ldsh;</span>
+          </pre>
+        </div>
+      </td>
+      <td valign="center" style="padding:1em;">
+        produces
+      </td>
+      <td>
+        <div class="codehilite">
+          <pre class="fixed">
+&lt;table&gt;
+  &lt;tbody&gt;<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+        row 1, col 1<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+        row 1, col 2<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+    &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+        row 2, col 1<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+        row 2, col 2<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+    &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+  &lt;/tbody&gt;<span style="color:green">&ldsh;</span>
+&lt;/table&gt;<span style="color:green">&ldsh;</span>
+          </pre>
+        </div>
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+### Structured space gobbling
+
+The lines gobbling mode is not enough if you want to use a single indentation 
framework for both VTL and the output language. Since you will want to further 
indent text portions contained inside a directive, this extra indentation has 
to be removed at runtime.
+
+Note: this is the only space gobbling mode that produces a bit of overhead at 
parsing time. Computationnaly speaking, the current implementation is in 
O(`depth`<sup>2</sup>) where `depth` is the VTL directive recursion depth.
+
+<table>
+  <tbody>
+    <tr>
+      <td>
+        <div class="codehilite">
+          <pre class="fixed">
+#set($foo = 'foo')<span style="color:green">&ldsh;</span>
+&lt;table&gt;<span style="color:green">&ldsh;</span>
+  &lt;tbody&gt;<span style="color:green">&ldsh;</span>
+    #foreach($row in [1..2])<span style="color:green">&ldsh;</span>
+      &lt;tr&gt;<span style="color:green">&ldsh;</span>
+        #foreach($col in [1..2])<span style="color:green">&ldsh;</span>
+          &lt;td&gt;<span style="color:green">&ldsh;</span>
+            #set($text = "row $row, col $col")<span 
style="color:green">&ldsh;</span>
+            $text<span style="color:green">&ldsh;</span>
+          &lt;/td&gt;<span style="color:green">&ldsh;</span>
+        #end<span style="color:green">&ldsh;</span>
+      &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+    #end<span style="color:green">&ldsh;</span>
+  &lt;/tbody&gt;<span style="color:green">&ldsh;</span>
+&lt;/table&gt;<span style="color:green">&ldsh;</span>
+          </pre>
+        </div>
+      </td>
+      <td valign="center" style="padding:1em;">
+        produces
+      </td>
+      <td>
+        <div class="codehilite">
+          <pre class="fixed">
+&lt;table&gt;
+  &lt;tbody&gt;<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+        row 1, col 1<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+        row 1, col 2<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+    &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+    &lt;tr&gt;<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+        row 2, col 1<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+      &lt;td&gt;<span style="color:green">&ldsh;</span>
+        row 2, col 2<span style="color:green">&ldsh;</span>
+      &lt;/td&gt;<span style="color:green">&ldsh;</span>
+    &lt;/tr&gt;<span style="color:green">&ldsh;</span>
+  &lt;/tbody&gt;<span style="color:green">&ldsh;</span>
+&lt;/table&gt;<span style="color:green">&ldsh;</span>
+          </pre>
+        </div>
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+
+## Resource Loaders
+
+One of the fundamental and important parts about Velocity is the resource 
management system and the resource loaders.  They are referred to as 
'resources' here rather than 'templates' because the resource management system 
will also handle non-template reasources, specifically things that are loaded 
via the #include() directive.
+
+The resource loader system if very flexible, allowing one or more resource 
loaders to be in operation at the same time.  This allows tremendous 
flexibility in configuration and resource managment, and futher allows you to 
write your own resource loaders for your special needs.
+
+There are currently four kinds of resource loaders that are included with 
Velocity, each described below.  Note that in the example configuration 
properties given, a common name for the loader is shown (ex.'file' in 
`file.resource.loader.path`). This 'common name' may not work for your 
configuration, as resource loaders common names are defined by the 
`resource.loader` configuration entry. Also, each of these loaders is located 
in the package `org.apache.velocity.runtime.resource.loader`.
+
++ **FileResourceLoader :** This loader gets resources from the filesystem. Its 
configuration properties include:
+
+    + `file.resource.loader.path` = &lt;path to root of templates&gt; [ , 
&lt;path to root of templates&gt; ... ]
+    + `file.resource.loader.cache` = true/false
+    + `file.resource.loader.modificationCheckInterval` = &lt;seconds between 
checks&gt;
+    
+    This is the default loader (except when using VelocityTools, see below), 
and is configured, by default to get templates from the 'current directory'.  
In the case of using Velocity with servlets, this can be a problem as you don't 
want to have to keep your templates in the directory from which you start your 
servlet engine.  See the documentation for your servlet or web framework (for 
example [VelocityViewServlet](/tools/devel/view-servlet.html)) for more info on 
how to configure the location of the Velocity templates.
+    
++ **JarResourceLoader :** This loader gets resource from specific jar files.  
It is very similar to the FileResourceLoader, except that you have the 
convenience of bundling your templates into jars.  The properties are 
identical, except for `jar.resource.loader.path`, where you provide the full 
location of the jar(s) you wish to load resources from.  To specify a jar for 
the loader.path you use the standard JAR URL syntax of 
`java.net.JarURLConnection`.
+    
++ **ClasspathResourceLoader :** This loader gets resources from the 
classloader. In general, this means that the ClasspathResourceLoader will load 
templates placed in the classpath (in jars, for example) While the classpath is 
a source of great pain and suffering in general, it is a very useful mechanism 
when working on a Servlet Spec 2.2 (or newer) compliant servlet runner. <a 
href="http://jakarta.apache.org/tomcat/"; class="externalLink">Tomcat</a> is an 
example of such.  To use this loader effectively, all you must do is jar your 
templates, and put that jar into the WEB-INF/lib directory of your webapp.  
There are no configuration options to worry about, nor is the absolute vs. 
relative path an issue, as it is with Jar and File resource loaders. Again, 
please note that the ClasspathResourceLoader is not only for use with a servlet 
container, but can be used in any application context.
+    
++ **URLResourceLoader :** This loader gets resources from a URL connection. 
Its configuration properties include:
+
+    + `url.resource.loader.root` = &lt;root URL path of templates&gt; [ , 
&lt;root URL path of templates&gt; ... ]
+    + `url.resource.loader.cache` = true/false
+    + `url.resource.loader.modificationCheckInterval` = &lt;seconds between 
checks&gt;
+    
+    This loader simply downloads resources from configured URLs.  It works 
much like the FileResourceLoader, however, it can pull templates down from any 
valid URL to which the application can create a connection.
+    
++ **DataSourceResourceLoader :**  This loader will load resources from a 
DataSource such as a database.  This loader is only available under JDK 1.4 and 
later. For more information on this loader, please see the javadoc for the 
class `org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader`.
+
+The [VelocityTools](/tools/devel/) project also defines a 
[WebappResourceLoader](/tools/devel/apidocs/org/apache/velocity/tools/view/WebappResourceLoader.html),
 active by default, which maps '/' to the root of the webapp.
+
+Advanced users may also want to replace the Resource Manager or the Resource 
Cache: the Resource Manager is the main part of the resource (template and 
static content) management system, and is responsible for taking application 
requests for templates, finding them in the available resource loaders, and 
then optionally caching the parsed template. The Resource Cache is the 
mechanism that the Resource Manager uses to cache templates for quick reuse. 
While the default versions of these two facilities are suitable for most 
applications, it is possible to replace the default resource manager and 
resource cache with custom implementations. See the (related configuration 
options)[configuration.html#resource-management].
+
+## Application Attributes
+
+*Application Attributes* are name-value pairs that can be associated with a 
RuntimeInstance (either via the `VelocityEngine` or the `Velocity` singleton) 
and accessed from any part of the Velocity engine that has access to the 
RuntimeInstance.
+
+This feature was designed for applications that need to communicate between 
the application layer and custom parts of the Velocity engine, such as loggers, 
resource loaders, resource managers, etc.
+
+The Application Attribute API is very simple.  From the application layer, 
there is a method of the `VelocityEngine` and the `Velocity` classes:
+
+    :::java
+    public void setApplicationAttribute( Object key, Object value );
+
+through which an application can store on Object under an application (or 
internal component) specified key.  There are no restrictions on the key or the 
value.  The value for a key may be set at any time - it is not required that 
this be set before init() is called.
+
+Internal components can access the key-value pairs if they have access to the 
object via the `RuntimeServices` interface, using the method
+
+    :::java
+    public Object getApplicationAttribute( Object key );
+
+Note that internal components cannot set the value of the key, just get it. if 
the internal component must communicate information to the application layer, 
it must do so via the Object passed as the value.
+
+## Event Handlers
+
+Velocity contains a fine-grained event handling system that allows you to 
customize the operation of the engine. Those events are synchronous, and act as 
callback handlers.
+
+For example, you may change the text of references that are inserted into a 
page, modify which templates are actually included with `#include` or `#parse`, 
or capture all invalid references.
+
+All event handler interfaces available in Velocity are in the package 
`org.apache.velocity.app.event`.  You may create your own implementation or use 
one of the sample implementations in the package 
`org.apache.velocity.app.event.implement`.  (See the javadocs for more details 
on the provided implementations).
+
+### `org.apache.velocity.app.event.IncludeEventHandler`
+
+> The `IncludeEventHandler` can be used to modify the template that is 
included in a page with `#include` or `#parse`.  For example, this may be used 
to make all includes relative to the current directory or to prevent access to 
unauthorized resources. Multiple `IncludeEventHandler`'s may be chained, with 
the return value of the final call used as the name of the template to retrieve.
+>
+>     :::java
+>     public IncludeEventHandler extends EventHandler
+>     {
+>         public String includeEvent( Context context,
+>                                     String includeResourcePath, 
+>                                     String currentResourcePath, 
+>                                     String directiveName );
+>     }
+>
+> Available implementations include:
+>
+> + `org.apache.velocity.app.event.implement.IncludeNotFound`
+> + `org.apache.velocity.app.event.implement.IncludeRelativePath`
+
+### `org.apache.velocity.app.event.InvalidReferenceEventHandler`
+
+> Normally, when a template contains a bad reference an error message is 
logged and (unless it is part of a `#set` or `#if`), the reference is included 
verbatim in a page.  With the `InvalidReferenceEventHandler` this behavior can 
be changed.  Substitute values can be inserted, invalid references may be 
logged, or an exception can be thrown.  Multiple 
`InvalidReferenceEventHandler`'s may be chained.  The exact manner in which 
chained method calls behave will differ per method.  (See the javadoc for the 
details).
+>
+>     :::java
+>     public InvalidReferenceEventHandler extends EventHandler
+>     {
+>         public Object invalidGetMethod( Context context, 
+>                                         String reference, 
+>                                         Object object, 
+>                                         String property, 
+>                                         Info info);
+>     
+>         public boolean invalidSetMethod( Context context, 
+>                                          String leftreference, 
+>                                          String rightreference, 
+>                                          Info info);
+>     
+>         public Object invalidMethod( Context context, 
+>                                      String reference,
+>                                      Object object, 
+>                                      String method, 
+>                                      Info info);
+>     }
+>
+> When a reference has an alternate value provided, as in `${foo.bar|'foo'}`, 
whenever `$foo.bar` is invalid, the invalid reference handler is called 
**before** the alternate value (and the alternate value will be used only if 
the value returned by the handler evaluates to null, false, empty or zero).
+>
+> Available implementations include:
+>
+> + `org.apache.velocity.app.event.implement.ReportInvalidReferences`
+
+### `org.apache.velocity.app.event.MethodExceptionEventHandler`
+
+> When a user-supplied method throws an exception, the 
`MethodExceptionEventHandler` is invoked with the Class, method name and thrown 
Exception.  The handler can either return a valid Object to be used as the 
return value of the method call or throw the passed-in or new Exception, which 
will be wrapped and propogated to the user as a `MethodInvocationException`.  
While `MethodExceptionEventHandler`'s can be chained only the first handler is 
actually called -- all others are ignored.
+>
+>     :::java
+>     public interface MethodExceptionEventHandler extends EventHandler
+>     {
+>         public Object methodException( Context context,
+>                                        Class claz, 
+>                                        String method, 
+>                                        Exception e )
+>              throws Exception;
+>     }
+> 
+> Available implementations include:
+>
+> + `org.apache.velocity.app.event.implement.PrintExceptions`
+
+### `org.apache.velocity.app.event.ReferenceInsertionEventHandler`
+
+> A `ReferenceInsertionEventHandler` allows the developer to intercept each 
write of a reference ($foo) value to the output stream and modify that output.  
Multiple `ReferenceInsertionEventHandler`'s may be chained with each step 
potentially altering the inserted reference.
+>
+>     :::java
+>     public interface  ReferenceInsertionEventHandler extends EventHandler
+>     {
+>         public Object referenceInsert( Context context,
+>                                        String reference, 
+>                                        Object value  );
+>     }
+> 
+> Available implementations include:
+>
+> + `org.apache.velocity.app.event.implement.EscapeHtmlReference`
+> + `org.apache.velocity.app.event.implement.EscapeJavascriptReference`
+> + `org.apache.velocity.app.event.implement.EscapeSqlReference`
+> + `org.apache.velocity.app.event.implement.EscapeXmlReference`
+
+### Registering Event Handlers
+
+You may register event handlers in either of two manners.  The easiest way to 
register event handlers is to specify them in velocity.properties.  (Event 
handlers configured in this manner are referred to as "global" event handlers). 
 For example, the following property will escape HTML entities in any inserted 
reference.
+
+    :::properties
+    eventhandler.referenceinsertion.class = 
org.apache.velocity.app.event.implement.EscapeHtmlReference
+
+Most event handler interfaces will also permit event handlers to be chained 
together.  Such a chain may be in a comma separated list or as additional lines 
with a property/value pair. For example, the following event handler properties 
install two `ReferenceInsertionEventHandler`'s.  The first will apply to 
references starting with "msg" (for example `$msgText`) and will escape HTML 
entities (e.g. turning `&` into `&amp;`).  The second will escape all 
references starting with "sql" (for example `$sqlText`) according to SQL 
escaping rules. (note that in these examples, the first two properties given 
relate to the event handler configuration while the second two properties are 
used by the specific event handler implementation).
+
+    :::properties
+    eventhandler.referenceinsertion.class = 
org.apache.velocity.app.event.implement.EscapeHtmlReference
+    eventhandler.referenceinsertion.class = 
org.apache.velocity.app.event.implement.EscapeSqlReference
+    eventhandler.escape.html.match = /msg.*/
+    eventhandler.escape.sql.match = /sql.*/
+
+Event handlers may also be attached to a context via an `EventCartridge`.  
This allows event handlers to be tied more closely to a specific template merge 
or group of merges.  The event handler will automatically be injected with the 
current context if it implements the `ContextAware` interface.  (Due to 
thread-safety reasons this is not possible with global event handlers).
+
+The following code shows how to register an event handler with an 
EventCartridge and a context.
+
+    :::java
+     ...
+    
+    import org.apache.velocity.app.event.EventCartridge;
+    import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
+    import org.apache.velocity.app.event.implement.EscapeHtmlReference;
+    import org.apache.velocity.app.event.implement.EscapeSqlReference;
+    
+     ...
+    
+    public class Test
+    {
+        public void myTest()
+        {
+         ...
+        
+        /**
+         * Make a cartridge to hold the event handlers 
+         */
+             EventCartridge ec = new EventCartridge();
+         
+        /*
+         * then register and chain two escape-related handlers 
+         */
+             ec.addEventHandler(new EscapeHtmlReference());
+             ec.addEventHandler(new EscapeSqlReference());
+
+        /*
+         * and then finally let it attach itself to the context
+         */
+             ec.attachToContext( context );
+
+        /*
+         * now merge your template with the context as you normally
+         * do
+         */
+
+         ...
+        }
+    }
+
+## Customizing Introspection
+
+The [`runtime.introspector.uberspect` configuration 
property](configuration.html#Pluggable-Introspection] property takes a list of 
Uberspector class names that constitute the Velocity introspection chain. By 
means it, you can change the way context objects are introspected at runtime to 
map VTL properties and methods to Java calls.
+
+Here is the list of provided uberspectors (which are found in the 
(org.apache.velocity.util.introspection)[apidocs/org/apache/velocity/util/introspection/package-summary.html]
 package).
+
+### Standard Uberspectors
+
+- 
[UberspectImpl](apidocs/org/apache/velocity/util/introspection/UberspectImpl.html)
+> this is the default uberspector. It successively tries to resolve `$foo.bar` 
into `foo.getBar()`, `foo.get('bar')` or `foo.isBar()` (plus some case 
variants), and tries to match methods using arguments count and type. Unless 
you want to fondamentaly change the way Velocity resolves references methods 
and properties, this uberspector should appear somewhere within the 
introspection chain.
+- 
[ChainableUberspector](apidocs/org/apache/velocity/util/introspection/ChainableUberspector.html)
 (interface) and 
[AbstractChainableUberspector](apidocs/org/apache/velocity/util/introspection/AbstractChainableUberspector.html)
 (meant to be inherited)
+> A Chainable uberspector is an uberspector that wraps the previous 
uberspector in the introspection chain.
+- 
[LinkingUberspector](apidocs/org/apache/velocity/util/introspection/LinkingUberspector.html)
+> The Linking uberspector is meant for internal use only. It provides 
introspection chaining when the left uberspector of two following uberspectors 
of the introspection chain is not a ChainableUberspector. It first tries to 
delegate introspection to the left uberspector, and only calls the right one in 
case of failure.
+- 
[UberspectLoggable](apidocs/org/apache/velocity/util/introspection/UberspectLoggable.html)
 interface
+> When an uberspector implements the UberspectLoggable interface, it is 
provided a logger during initialization via the `setLog(Logger)` method.
+
+If an Uberspector implements the 
[RuntimeServicesAware](apidocs/org/apache/velocity/util/RuntimeServicesAware.html)
 interface, it will be provided a Velocity 
[RuntimeServices](apidocs/org/apache/velocity/runtime/RuntimeServices.html) 
instance during initialization, via the `setRuntimeServices(RuntimeServices)` 
method.
+
+### Uberspectors providing extra features
+
+- 
[DeprecatedCheckUberspector](apidocs/org/apache/velocity/util/introspection/DeprecatedCheckUberspector.html)
+> This uberspector will emit warnings in the log whenever a VTL fragment uses 
a deprecated Java method. It is a Chainable uberspector that must be declared 
*after* its wrapped uberspector.
+- 
[SecureUberspector](apidocs/org/apache/velocity/util/introspection/SecureUberspector.html)
+> This uberspector prevents classloader related method calls. Use this 
introspector for situations in which template writers are numerous or 
untrusted. Specifically, this introspector prevents creation of arbitrary 
objects or reflection on objects. It is a standalone uberspector.
+- 
[UberspectPublicFields](apidocs/org/apache/velocity/util/introspection/UberspectPublicFields)
+> This uberspector exposes the public fields of objects. It can be prepended 
or suffixed to other uberspectors, depending on whether you want to priorize or 
not public fields versus potentially matching methods.
+
+### Method arguments conversions
+
+Since Velocity 2.0, besides the default conversions implicitly provided by 
Java (aka [automatic boxing and 
unboxing](https://en.wikipedia.org/wiki/Object_type_%28object-oriented_programming%29),
 and widening number conversions), method arguments will be converted as needed 
by the UberspectorImpl or SecureUberspector using the following conversions:
+
+- boolean to number: `true` is converted to 1, false to 0
+- boolean to string: `true` and `false` are respectively converted to "true" 
and "false"
+- number to boolean: zero numbers are converted to `false`, everything else to 
`true`
+- number to string
+- string to boolean: "true" is converted to `true`, every other string 
(including the null string) are converted to `false`
+- string to number: if the string does not represent a number or doesn't fit 
into the expected number type, an exception is thrown
+- narrowing number conversion: if the number doesn't fit into the expected 
number type, an exception is thrown
+- string to enum constant: will throw if the string doesn't represent a 
constant of the expected enum
+- string to locale (since 2.1)
+
+<span class="conversions">The following table resumes the possible conversions 
between a provided argument type (which is never a primary type) and an 
expected argument type, which can be <span class="strict">strict</span> when 
the expected type is assignable from the provided type without unboxing, <span 
class="implicit">implicit</span> when Java will take care of the necessary 
conversion or unboxing, <span class="explicit">explicit</span> when the 
conversion is provided by the default 2.0 conversion handler, and <span 
class="none">none</span> when no default conversion is possible.</span>
+
+<table class="conversions">
+  <thead>
+    <tr>
+      <th>
+        provided &rarr;<br/>
+        expected &darr;
+      </th>
+      <th>Boolean</th>
+      <th>Character</th>
+      <th>Byte</th>
+      <th>Short</th>
+      <th>Integer</th>
+      <th>Long</th>
+      <th>Float</th>
+      <th>Double</th>
+      <th>Number</th>
+      <th>String</th>
+      <th>Object</th>
+      <th>null</th>
+    </tr>
+    <tr>
+      <th>boolean</th>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+    </tr>
+    <tr>
+      <th>char</th>
+      <td><span class="none">none</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+    </tr>
+    <tr>
+      <th>byte</th>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+    </tr>
+    <tr>
+      <th>short</th>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+    </tr>
+    <tr>
+      <th>int</th>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+    </tr>
+    <tr>
+      <th>long</th>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+    </tr>
+    <tr>
+      <th>float</th>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+    </tr>
+    <tr>
+      <th>double</th>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="implicit">implicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+    </tr>
+    <tr>
+      <th>Boolean</th>
+      <td><span class="strict">strict</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+    <tr>
+      <th>Character</th>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+    <tr>
+      <th>Byte</th>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+    <tr>
+      <th>Short</th>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+    <tr>
+      <th>Integer</th>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+    <tr>
+      <th>Long</th>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+    <tr>
+      <th>Float</th>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+    <tr>
+      <th>Double</th>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+    <tr>
+      <th>Number</th>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="none">none</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+    <tr>
+      <th>String</th>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="explicit">explicit</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+    <tr>
+      <th>Object</th>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+      <td><span class="strict">strict</span></td>
+    </tr>
+  </thead>
+  <tbody>
+  </tbody>
+</table>
+
+You can provide a custom conversion handler class by use of the 
`runtime.conversion.handler` property. The class must implement the 
[`org.apache.Velocity.util.introspection.ConversionHandler`](apidocs/org/apache/velocity/util/introspection/ConversionHandler.html)
 interface. Set it to `none` to only accept default Java conversions, as for 
Velocity 1.x.
+
+You can also provide custom 
[`Converter<T>`](apidocs/org/apache/velocity/util/introspection/Converter.html) 
objects that handle a conversion towards a specific type:
+
+    :::java
+    package mypackage;
+    
+    import java.util.Date;
+    import org.apache.velocity.util.introspection.*;
+    
+    public class MyUberspector extends UberspectorImpl
+    {
+        public void init()
+        {
+            super.init();
+            getConversionHandler().addConverter(Integer.class, Date.class, new 
ConvertToDate());
+            getConversionHandler().addConverter(Long.class, Date.class, new 
ConvertToDate());
+        }
+        
+        public static class ConvertToDate extends Converter<Date>
+        {
+            @Override
+            public Date convert(Object o)
+            {
+                return new Date(((Number)o).longValue());
+            }
+        }
+    }
+
+You'll then need to register your uberspector with 
`runtime.introspection.uberspect = mypackage.MyUberspector`. Another approach 
would be to inherit from ConversionHandlerImpl, add converters within its 
constructor and register your conversion handler using the 
`runtime.conversion.handler` configuration property.
+
+## Template Encoding for Internationalization
+
+Velocity allows you to specify the character encoding of your template 
resources on a template by template basis.  The normal resource API's have been 
extended to take the encoding as an argument:
+
+`org.apache.velocity.app.Velocity`
+
+> *`public static Template getTemplate(String name, String encoding)`*
+>
+> *`public static boolean mergeTemplate( String templateName, String encoding, 
Context context, Writer writer )`*
+
+The value for the *encoding* argument is the conventional encoding 
specification supported by your JVM, for example "UTF-8" or "ISO-8859-1".  For 
the official names for character sets, see 
[here](http://www.iana.org/assignments/character-sets).
+
+Note that this applies only to the encoding of the template itself - the 
output encoding is an application specific issue.
+
+## Velocity and XML
+
+Velocity's flexibility and simple template language makes it an ideal 
environment for working with XML data.
+
+Generally, the pattern for dealing with XML in Velocity is to use something 
like [JDOM](http://www.jdom.org/) to process your XML into a data structure 
with convenient Java access.  Then, you produce templates that access data 
directly out of the XML document - directly though the JDOM tree.  For example, 
start with an XML document such as:
+
+    ::xml
+    <document>
+      <properties>
+        <title>Developer's Guide</title>
+        <author email="[email protected]">Velocity Doc Team</author>
+      </properties>
+    </document>
+
+Now make a little Java program that includes code similar to:
+
+    :::java
+    ...
+    
+    SAXBuilder builder;
+    Document root = null;
+    
+    try
+    {
+        builder = new SAXBuilder(
+            "org.apache.xerces.parsers.SAXParser" );
+        root = builder.build("test.xml");
+    }
+    catch( Exception ee)
+    {}
+    
+    VelocityContext vc = new VelocityContext();
+    vc.put("root", root.getRootElement());
+    
+    
+    ...
+
+Now, make a regular Velocity template:
+
+    :::html+velocity
+    <html>
+      <body>
+        The document title is
+          $root.getChild("document").getChild("properties")
+                  .getChild("title").getText()
+      </body>
+  </html>
+
+and render that template as you normally would, using the Context containing 
the JDOM tree. Of course, this isn't the prettiest of examples, but it shows 
the basics - that you can easily access XML data directly from a Velocity 
template.
+
+One real advantage of styling XML data in Velocity is that you have access to 
any other object or data that the application provides. You aren't limited to 
just using the data present in the XML document. You may add anything you want 
to the context to provide additional information for your output, or provide 
tools to help make working with the XML data easier. Bob McWhirter's [Werken 
XPath](http://sourceforge.net/projects/werken-xpath/) is one such useful tool.
+
+One issue that arises with XML and Velocity is how to deal with XML entities. 
One technique is to combine the use of Velocimacros when you need to render an 
entity into the output stream:
+
+    :::html+velocity
+    ## first, define the Velocimacro somewhere
+    
+    #macro(xenc $sometext)$tools.escapeEntities($sometext)#end
+    
+    ## and use it as
+    
+    #set( $sometext = " < " )
+    <text>#xenc($sometext)</text>
+
+where the escapeEntities() is a method that does the escaping for you. Another 
trick would be to create an encoding utility that takes the context as a 
constructor parameter and only implements a method:
+
+    :::java
+    public String get(String key)
+    {
+        Object obj = context.get(key)
+        return (obj != null)
+            ? Escape.getText( obj.toString() )
+            : "";
+    }
+
+Put it into the context as "xenc". Then you can use it as:
+
+    :::html+velocity
+    <text>$xenc.sometext</text>
+
+This takes advantage of Velocity's introspection process - it will try to call 
get("sometext") on the $xenc object in the Context - then the xenc object can 
then get the value from the Context, encode it, and return it.
+

[... 37 lines stripped ...]

Reply via email to