Author: cbrisson Date: Tue Jun 26 10:02:24 2018 New Revision: 1834409 URL: http://svn.apache.org/viewvc?rev=1834409&view=rev Log: [site] Proper syntax coloring for VTL, Java, XML, ...
Modified: velocity/site/cms/trunk/content/engine/2.0/build.mdtext velocity/site/cms/trunk/content/engine/2.0/configuration.mdtext velocity/site/cms/trunk/content/engine/2.0/developer-guide.mdtext velocity/site/cms/trunk/content/engine/2.0/getting-started.mdtext velocity/site/cms/trunk/content/engine/2.0/source-repository.mdtext velocity/site/cms/trunk/content/engine/2.0/user-guide.mdtext velocity/site/cms/trunk/content/engine/2.0/vtl-reference.mdtext velocity/site/cms/trunk/content/engine/2.0/webapps.mdtext velocity/site/cms/trunk/content/engine/devel/build.mdtext velocity/site/cms/trunk/content/engine/devel/configuration.mdtext velocity/site/cms/trunk/content/engine/devel/developer-guide.mdtext velocity/site/cms/trunk/content/engine/devel/getting-started.mdtext velocity/site/cms/trunk/content/engine/devel/source-repository.mdtext velocity/site/cms/trunk/content/engine/devel/user-guide.mdtext velocity/site/cms/trunk/content/engine/devel/vtl-reference.mdtext velocity/site/cms/trunk/content/engine/devel/webapps.mdtext velocity/site/cms/trunk/content/tools/2.0/config-java.mdtext velocity/site/cms/trunk/content/tools/2.0/config-properties.mdtext velocity/site/cms/trunk/content/tools/2.0/config-xml.mdtext velocity/site/cms/trunk/content/tools/2.0/creating-tools.mdtext velocity/site/cms/trunk/content/tools/2.0/standalone.mdtext velocity/site/cms/trunk/content/tools/2.0/upgrading.mdtext velocity/site/cms/trunk/content/tools/2.0/view-layoutservlet.mdtext velocity/site/cms/trunk/content/tools/2.0/view-servlet.mdtext velocity/site/cms/trunk/content/tools/2.0/view-tag.mdtext velocity/site/cms/trunk/content/tools/devel/config-java.mdtext velocity/site/cms/trunk/content/tools/devel/config-properties.mdtext velocity/site/cms/trunk/content/tools/devel/config-xml.mdtext velocity/site/cms/trunk/content/tools/devel/creating-tools.mdtext velocity/site/cms/trunk/content/tools/devel/generic.mdtext velocity/site/cms/trunk/content/tools/devel/standalone.mdtext velocity/site/cms/trunk/content/tools/devel/upgrading.mdtext velocity/site/cms/trunk/content/tools/devel/view-layoutservlet.mdtext velocity/site/cms/trunk/content/tools/devel/view-servlet.mdtext velocity/site/cms/trunk/content/tools/devel/view-tag.mdtext Modified: velocity/site/cms/trunk/content/engine/2.0/build.mdtext URL: http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/2.0/build.mdtext?rev=1834409&r1=1834408&r2=1834409&view=diff ============================================================================== --- velocity/site/cms/trunk/content/engine/2.0/build.mdtext (original) +++ velocity/site/cms/trunk/content/engine/2.0/build.mdtext Tue Jun 26 10:02:24 2018 @@ -16,6 +16,7 @@ To build Velocity we require [Maven](htt In each case below, it is assumed that you were successful in [downloading](/download.cgi#engine) and unpacking the distribution source or [checking out the sources from Subversion](/download.cgi#source-code-repository): + :::shell svn checkout https://svn.apache.org/repos/asf/velocity/engine/tags/2.0 velocity-2.0 cd velocity-2.0 mvn install Modified: velocity/site/cms/trunk/content/engine/2.0/configuration.mdtext URL: http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/2.0/configuration.mdtext?rev=1834409&r1=1834408&r2=1834409&view=diff ============================================================================== --- velocity/site/cms/trunk/content/engine/2.0/configuration.mdtext (original) +++ velocity/site/cms/trunk/content/engine/2.0/configuration.mdtext Tue Jun 26 10:02:24 2018 @@ -152,6 +152,7 @@ The following resource management config > To illustrate, here is an example taken right from the default Velocity > properties, showing how setting up the FileResourceLoader is managed + :::properties resource.loader = file file.resource.loader.description = Velocity File Resource Loader @@ -295,15 +296,18 @@ Configuring the resource loaders for Vel The first step in configuring one or more resource loaders is do 'declare' them by name to Velocity. Use the property `resource.loader` and list one or more loader names. You can use anything you want - these names are used to associate configuration properties with a given loader. + :::properties resource.loader = file That entry declares that we will have a resource loader known as 'file'. The next thing to do is to set the important properties. The most critical is to declare the class to use as the loader: + :::properties file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader In this case, we are telling velocity that we are setting up a resource loadercalled 'file', and are using the class `org.apache.velocity.runtime.resource.loader.FileResourceLoader` to be the class to use. The next thing we do is set the properties important to this loader. + :::properties file.resource.loader.path = /opt/templates file.resource.loader.cache = true file.resource.loader.modificationCheckInterval = 2 @@ -314,6 +318,7 @@ Those are the basics. What follows are **Do-nothing Default Configuration: ** As the name says, there is nothing you have to do or configure to get the default configuration. This configuration uses the FileResourceLoader with the current directory as the default resource path, and caching is off. As a properties set, this is expressed as: + :::properties resource.loader = file file.resource.loader.description = Velocity File Resource Loader @@ -324,6 +329,7 @@ Those are the basics. What follows are **Multiple Template Path Configuration: ** This configuration uses the FileResourceLoader with several directories as 'nodes' on the template search path. We also want to use caching, and have the templates checked for changes in 10 second intervals. As a properties set, this is expressed as: + :::properties resource.loader = file file.resource.loader.description = Velocity File Resource Loader @@ -334,6 +340,7 @@ Those are the basics. What follows are **Multiple Loader Configuration :** This configuration sets up three loaders at the same time, the FileResourceLoader, the ClasspathResourceLoader, and the JarResourceLoader. The loaders are set-up such that the FileResourceLoader is consulted first, then the ClasspathResourceLoader, and finally the JarResourceLoader. This would allow you to qickly drop a template into the file template area to replace on of the templates found in the classpath (usually via a jar) without having to rebuild the jar. + :::properties # # specify three resource loaders to use # Modified: velocity/site/cms/trunk/content/engine/2.0/developer-guide.mdtext URL: http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/2.0/developer-guide.mdtext?rev=1834409&r1=1834408&r2=1834409&view=diff ============================================================================== --- velocity/site/cms/trunk/content/engine/2.0/developer-guide.mdtext (original) +++ velocity/site/cms/trunk/content/engine/2.0/developer-guide.mdtext Tue Jun 26 10:02:24 2018 @@ -79,6 +79,7 @@ When using Velocity in an application pr 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; @@ -129,6 +130,7 @@ Developers have two options for using th 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; @@ -156,6 +158,7 @@ This is the legacy pattern, where there 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; @@ -203,6 +206,7 @@ VelocityContext is suitable for all gene 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); @@ -224,6 +228,7 @@ In the case of the `Iterator` and `Enume 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"); @@ -232,6 +237,7 @@ There are good reasons to use the `java. 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. @@ -242,6 +248,7 @@ This above isn't meant to give the impre 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. @@ -252,6 +259,7 @@ An innovative feature of Velocity's cont This is best illustrated by an example: + :::java VelocityContext context1 = new VelocityContext(); context1.put("name","Velocity"); @@ -283,11 +291,13 @@ There are two common situations where th 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") @@ -326,6 +336,7 @@ Velocity contains an application utility 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. @@ -378,6 +389,7 @@ Once the runtime is initialized, you can 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; @@ -421,6 +433,7 @@ When we run this program, and have the t 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. @@ -459,6 +472,7 @@ While the above example used the default 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; @@ -478,6 +492,7 @@ If we wanted to use a different director And the same if you want to use a VelocityEngine object rather than the singleton engine: + :::java ... import java.util.Properties; @@ -838,12 +853,14 @@ This feature was designed for applicatio 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. @@ -860,6 +877,7 @@ All event handler interfaces available i > 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, @@ -867,7 +885,7 @@ All event handler interfaces available i > String currentResourcePath, > String directiveName ); > } -> +> > Available implementations include: > > + `org.apache.velocity.app.event.implement.IncludeNotFound` @@ -876,7 +894,8 @@ All event handler interfaces available i ### `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, @@ -904,7 +923,8 @@ All event handler interfaces available i ### `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, @@ -921,11 +941,12 @@ All event handler interfaces available i ### `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, +> String reference, > Object value ); > } > @@ -940,11 +961,12 @@ All event handler interfaces available i 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 `&`). 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.*/ @@ -954,6 +976,7 @@ Event handlers may also be attached to a The following code shows how to register an event handler with an EventCartridge and a context. + :::java ... import org.apache.velocity.app.event.EventCartridge; @@ -1351,6 +1374,7 @@ You can provide a custom conversion hand 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; @@ -1397,6 +1421,7 @@ Velocity's flexibility and simple templa 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> @@ -1406,7 +1431,7 @@ Generally, the pattern for dealing with Now make a little Java program that includes code similar to: - <div class="source"><pre> + :::java ... SAXBuilder builder; @@ -1429,6 +1454,7 @@ Now make a little Java program that incl Now, make a regular Velocity template: + :::html+velocity <html> <body> The document title is @@ -1443,6 +1469,7 @@ One real advantage of styling XML data i 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 @@ -1454,6 +1481,7 @@ One issue that arises with XML and Veloc 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) @@ -1464,12 +1492,14 @@ where the escapeEntities() is a method t 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. Alternatively, since Velocity makes it easy to implement custom Context objects, you could implement your own context which always applies the encoding to any string returned. Be careful to avoid rendering the output of method calls directly, as they could return objects or strings (which might need encoding). Place them first into the context with a #set() directive and the use that, for example: + :::html+velocity #set( $sometext = $jdomElement.getText() ) <text>$sometext</text> @@ -1483,12 +1513,12 @@ This section is a brief illustration of Hello World example: + :::java // get script manager, create a new Velocity script engine factory and get an engine from it ScriptEngineManager manager = new ScriptEngineManager(); manager.registerEngineName("velocity", new VelocityScriptEngineFactory()); ScriptEngine engine = manager.getEngineByName("velocity"); - - + System.setProperty(VelocityScriptEngine.VELOCITY_PROPERTIES, "path/to/velocity.properties"); String script = "Hello $world"; Writer writer = new StringWriter(); Modified: velocity/site/cms/trunk/content/engine/2.0/getting-started.mdtext URL: http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/2.0/getting-started.mdtext?rev=1834409&r1=1834408&r2=1834409&view=diff ============================================================================== --- velocity/site/cms/trunk/content/engine/2.0/getting-started.mdtext (original) +++ velocity/site/cms/trunk/content/engine/2.0/getting-started.mdtext Tue Jun 26 10:02:24 2018 @@ -27,6 +27,7 @@ Our API documentation is available [onli If you would like to create a full set of detailed API documentation for Velocity, go to the `build` directory and run: + :::shell ant javadocs The docs will be found in the `/bin/apidocs/` directory. Modified: velocity/site/cms/trunk/content/engine/2.0/source-repository.mdtext URL: http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/2.0/source-repository.mdtext?rev=1834409&r1=1834408&r2=1834409&view=diff ============================================================================== --- velocity/site/cms/trunk/content/engine/2.0/source-repository.mdtext (original) +++ velocity/site/cms/trunk/content/engine/2.0/source-repository.mdtext Tue Jun 26 10:02:24 2018 @@ -13,22 +13,26 @@ The following is a link to the online so The source can be checked out anonymously from SVN with this command: + :::shell $ svn checkout http://svn.apache.org/repos/asf/velocity/engine/trunk velocity ## Developer access Everyone can access the Subversion repository via HTTP, but Committers must checkout the Subversion repository via HTTPS. + :::shell $ svn checkout https://svn.apache.org/repos/asf/velocity/engine/trunk velocity To commit changes to the repository, execute the following command to commit your changes (svn will prompt you for your password) + :::shell $ svn commit --username your-username -m "A message" ## Access from behind a firewall For those users who are stuck behind a corporate firewall which is blocking HTTP access to the Subversion repository, you can try to access it via the developer connection: + :::shell $ svn checkout https://svn.apache.org/repos/asf/velocity/engine/trunk velocity ## Access through a proxy @@ -39,6 +43,7 @@ There are comments in the file explainin Example: Edit the 'servers' file and add something like: + :::properties [global] http-proxy-host = your.proxy.name http-proxy-port = 3128 Modified: velocity/site/cms/trunk/content/engine/2.0/user-guide.mdtext URL: http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/2.0/user-guide.mdtext?rev=1834409&r1=1834408&r2=1834409&view=diff ============================================================================== --- velocity/site/cms/trunk/content/engine/2.0/user-guide.mdtext (original) +++ velocity/site/cms/trunk/content/engine/2.0/user-guide.mdtext Tue Jun 26 10:02:24 2018 @@ -28,6 +28,7 @@ You meet with software engineers at your You could embed the following VTL statement in the web page: + :::html+velocity <html> <body> Hello $customer.Name! @@ -55,6 +56,7 @@ The Velocity Template Language (VTL) is VTL uses *references* to embed dynamic content in a web site, and a variable is one type of reference. Variables are one type of reference that can refer to something defined in the Java code, or it can get its value from a VTL *statement* in the web page itself. Here is an example of a VTL statement that could be embedded in an HTML document: + :::velocity #set( $a = "Velocity" ) This VTL statement, like all VTL statements, begins with the *#* character and contains a directive: *set*. When an online visitor requests your web page, the Velocity Templating Engine will search through your web page to find all *#* characters, then determine which mark the beginning of VTL statements, and which of the *#* characters that have nothing to do with VTL. @@ -72,6 +74,7 @@ In the example above, *#set* is used to Once a value has been assigned to a variable, you can reference the variable anywhere in your HTML document. In the following example, a value is assigned to *$foo* and later referenced. + :::html+velocity <html> <body> #set( $foo = "Velocity" ) @@ -88,24 +91,27 @@ To make statements containing VTL direct Comments allows descriptive text to be included that is not placed into the output of the template engine. Comments are a useful way of reminding yourself and explaining to others what your VTL statements are doing, or any other purpose you find useful. Below is an example of a comment in VTL. + :::velocity ## This is a single line comment. A single line comment begins with *##* and finishes at the end of the line. If you're going to write a few lines of commentary, there's no need to have numerous single line comments. Multi-line comments, which begin with *#** and end with **#*, are available to handle this scenario. + :::velocity This is text that is outside the multi-line comment. Online visitors can see it. - + #* Thus begins a multi-line comment. Online visitors won't see this text because the Velocity Templating Engine will ignore it. *# - + Here is text outside the multi-line comment; it is visible. Here are a few examples to clarify how single line and multi-line comments work: + :::velocity This text is visible. ## This text is not. This text is visible. This text is visible. #* This text, as part of a multi-line @@ -116,6 +122,7 @@ Here are a few examples to clarify how s There is a third type of comment, the VTL comment block, which may be used to store any sort of extra information you want to track in the template (e.g. javadoc-style author and versioning information): + :::velocity #** This is a VTL comment block and may be used to store such information @@ -139,6 +146,7 @@ The shorthand notation of a variable con Here are some examples of valid variable references in the VTL: + :::velocity $foo $mudSlinger $mud-slinger @@ -147,6 +155,7 @@ Here are some examples of valid variable When VTL references a variable, such as *$foo*, the variable can get its value from either a *set* directive in the template, or from the Java code. For example, if the Java variable *$foo* has the value *bar* at the time the template is requested, *bar* replaces all instances of *$foo* on the web page. Alternatively, if I include the statement + :::velocity #set( $foo = "bar" ) The output will be the same for all instances of *$foo* that follow this directive. @@ -155,6 +164,7 @@ The output will be the same for all inst The second flavor of VTL references are properties, and properties have a distinctive format. The shorthand notation consists of a leading *$* character followed a VTL Identifier, followed by a dot character (".") and another VTL Identifier. These are examples of valid property references in the VTL: + :::velocity $customer.Address $purchase.Total @@ -164,6 +174,7 @@ Take the first example, *$customer.Addre A method is defined in the Java code and is capable of doing something useful, like running a calculation or arriving at a decision. Methods are references that consist of a leading "$" character followed a VTL Identifier, followed by a VTL *Method Body*. A VTL Method Body consists of a VTL Identifier followed by an left parenthesis character ("("), followed by an optional parameter list, followed by right parenthesis character (")"). These are examples of valid method references in the VTL: + :::velocity $customer.getAddress() $purchase.getTotal() $page.setTitle( "My Home Page" ) @@ -175,37 +186,36 @@ VTL Properties can be used as a shorthan The shorthand notation can be used for the following Methods + :::velocity $sun.getPlanets() $annelid.getDirt() $album.getPhoto() We might expect these methods to return the names of planets belonging to the sun, feed our earthworm, or get a photograph from an album. Only the long notation works for the following Methods. + :::velocity $sun.getPlanet( ["Earth", "Mars", "Neptune"] ) ## Can't pass a parameter list with $sun.Planets - + $sisyphus.pushRock() ## Velocity assumes I mean $sisyphus.getRock() - + $book.setTitle( "Homage to Catalonia" ) ## Can't pass a parameter All array references are treated as if they are fixed-length lists. This means that you can call java.util.List methods and properties on array references. So, if you have a reference to an array (let's say this one is a String[] with three values), you can do: + :::velocity $myarray.isEmpty() or $myarray.empty - $myarray.size() - $myarray.get(2) - $myarray.set(1, 'test') Velocity also supports vararg methods. A method like `azpublic void setPlanets(String... planets)` or even just `public void setPlanets(String[] planets)` can now accept any number of arguments when called in a template. + :::velocity $sun.setPlanets('Earth', 'Mars', 'Neptune') - $sun.setPlanets('Mercury') - $sun.setPlanets() ## Will just pass in an empty, zero-length array @@ -235,6 +245,7 @@ The final value resulting from each and Using the notation of the form `$foo[0]` can be used to access a given index of an object. This form is synonymous with calling the get(Object) method on a given object i.e, `$foo.get(0)`, and provides essentially a syntactic shorthand for such operations. Since this simply calls the get method all of the following are valid uses: + :::velocity $foo[0] ## $foo takes in an Integer look up $foo[$i] ## Using another reference as the index $foo["bar"] ## Passing a string where $foo may be a Map @@ -243,12 +254,14 @@ The bracketed syntax also works with Jav The bracketed syntax is valid anywhere `.get` is valid, for example: + :::velocity $foo.bar[1].junk $foo.callMethod()[1] $foo["apple"][4] A reference can also be set using index notation, for example: + :::velocity #set($foo[0] = 1) #set($foo.bar[1] = 3) #set($map["apple"] = "orange") @@ -259,6 +272,7 @@ The specified element is set with the gi Shorthand notation for references was used for the examples listed above, but there is also a formal notation for references, which is demonstrated below: + :::velocity ${mudSlinger} ${customer.Address} ${purchase.getTotal()} @@ -267,10 +281,12 @@ In almost all cases you will use the sho Suppose you were constructing a sentence on the fly where *$vice* was to be used as the base word in the noun of a sentence. The goal is to allow someone to choose the base word and produce one of the two following results: "Jack is a pyromaniac." or "Jack is a kleptomaniac.". Using the shorthand notation would be inadequate for this task. Consider the following example: + :::velocity Jack is a $vicemaniac. There is ambiguity here, and Velocity assumes that *$vicemaniac*, not *$vice*, is the Identifier that you mean to use. Finding no value for *$vicemaniac*, it will return *$vicemaniac*. Using formal notation can resolve this problem. + :::velocity Jack is a ${vice}maniac. Now Velocity knows that *$vice*, not *$vicemaniac*, is the reference. Formal notation is often useful when references are directly adjacent to text in a template. @@ -279,16 +295,19 @@ Now Velocity knows that *$vice*, not *$v When Velocity encounters an undefined reference, its normal behavior is to output the image of the reference. For example, suppose the following reference appears as part of a VTL template. + :::html+velocity <input type="text" name="email" value="$email"/> When the form initially loads, the variable reference *$email* has no value, but you prefer a blank text field to one with a value of "$email". Using the quiet reference notation circumvents Velocity's normal behavior; instead of using *$email* in the VTL you would use *$!email*. So the above example would look like the following: + :::html+velocity <input type="text" name="email" value="$!email"/> Now when the form is initially loaded and *$email* still has no value, an empty string will be output instead of "$email". Formal and quiet reference notation can be used together, as demonstrated below. + :::html+velocity <input type="text" name="email" value="$!{email}"/> ## Strict Reference Mode @@ -299,6 +318,7 @@ With this setting references are require In the following examples $bar is defined but $foo is not, and all these statements will throw an exception: + :::velocity $foo ## Exception #set($bar = $foo) ## Exception #if($foo == $bar)#end ## Exception @@ -306,12 +326,14 @@ In the following examples $bar is define Also, The following statements show examples in which Velocity will throw an exception when attempting to call methods or properties that do not exist. In these examples $bar contains an object that defines a property 'foo' which returns a string, and 'retnull' which returns null. + :::velocity $bar.bogus ## $bar does not provide property bogus, Exception $bar.foo.bogus ## $bar.foo does not provide property bogus, Exception $bar.retnull.bogus ## cannot call a property on null, Exception</pre> In general strict reference behavior is true for all situations in which references are used except for a special case within the #if directive. If a reference is used within a #if or #elseif directive without any methods or properties, and if it is not being compared to another value, then undefined references are allowed. This behavior provides an easy way to test if a reference is defined before using it in a template. In the following example where $foo is not defined the statements will not throw an exception. + :::velocity #if ($foo)#end ## False #if ( ! $foo)#end ## True #if ($foo && $foo.bar)#end ## False and $foo.bar will not be evaluated @@ -322,6 +344,7 @@ Strict mode requires that comparisons of References that Velocity attempts to render but evaluate to null will cause an Exception. To simply render nothing in this case the reference can be preceded by '$!' instead of '$', similar to non strict mode. Keep in mind this is different from the reference not existing in the context which will always throw an exception when attempting to render it in strict mode. For example, below $foo has a value of null in the context + :::velocity this is $foo ## throws an exception because $foo is null this is $!foo ## renders to "this is " without an exception this is $!bogus ## bogus is not in the context so throws an exception @@ -330,6 +353,7 @@ References that Velocity attempts to ren Now that you are familiar with references, you can begin to apply them effectively in your templates. Velocity references take advantage of some Java principles that template designers will find easy to use. For example: + :::velocity $foo $foo.getBar() @@ -358,16 +382,19 @@ References allow template designers to g Directives always begin with a `#`. Like references, the name of the directive may be bracketed by a `{` and a `}` symbol. This is useful with directives that are immediately followed by text. For example the following produces an error: + :::velocity #if($a==1)true enough#elseno way!#end In such a case, use the brackets to separate `#else` from the rest of the line. + :::velocity #if($a==1)true enough#{else}no way!#end ### Set The *#set* directive is used for setting the value of a reference. A value can be assigned to either a variable reference or a property reference, and this occurs in brackets, as demonstrated: + :::velocity #set( $primate = "monkey" ) #set( $customer.Behavior = $primate ) @@ -383,6 +410,7 @@ The left hand side (LHS) of the assignme These examples demonstrate each of the aforementioned types: + :::velocity #set( $monkey = $bill ) ## variable reference #set( $monkey.Friend = "monica" ) ## string literal #set( $monkey.Blame = $whitehouse.Leak ) ## property reference @@ -397,6 +425,7 @@ Similarly, for the Map example, the elem The RHS can also be a simple arithmetic expression: + :::velocity #set( $value = $foo + 1 ) #set( $value = $bar - 1 ) #set( $value = $foo * $bar ) @@ -404,6 +433,7 @@ The RHS can also be a simple arithmetic If the RHS is a property or method reference that evaluates to *null*, it will <b>not</b> be assigned to the LHS. Depending on how Velocity is configured, it is usually not possible to remove an existing reference from the context via this mechanism. (Note that this can be permitted by changing one of the Velocity configuration properties). This can be confusing for newcomers to Velocity. For example: + :::velocity #set( $result = $query.criteria("name") ) The result of the first query is $result @@ -418,6 +448,7 @@ If *$query.criteria("name")* returns the This tends to confuse newcomers who construct *#foreach* loops that attempt to *#set* a reference via a property or method reference, then immediately test that reference with an *#if* directive. For example: + :::velocity #set( $criteria = ["name", "address"] ) #foreach( $criterion in $criteria ) @@ -434,6 +465,7 @@ In the above example, it would not be wi One solution to this would be to pre-set *$result* to *false*. Then if the *$query.criteria()* call fails, you can check. + :::velocity #set( $criteria = ["name", "address"] ) #foreach( $criterion in $criteria ) @@ -453,6 +485,7 @@ Unlike some of the other Velocity direct When using the *#set* directive, string literals that are enclosed in double quote characters will be parsed and rendered, as shown: + :::velocity #set( $directoryRoot = "www" ) #set( $templateName = "index.vm" ) #set( $template = "$directoryRoot/$templateName" ) @@ -464,6 +497,7 @@ The output will be However, when the string literal is enclosed in single quote characters, it will not be parsed: + :::velocity #set( $foo = "bar" ) $foo #set( $blargh = '$foo' ) @@ -478,6 +512,7 @@ By default, this feature of using single Alternately, the *#[[*don't parse me!*]]#* syntax allows the template designer to easily use large chunks of uninterpreted and unparsed content in VTL code. This can be especially useful in place of <a href="#EscapingVTLDirectives">escaping</a> multiple directives or escaping sections which have content that would otherwise be invalid (and thus unparseable) VTL. + :::velocity #[[ #foreach ($woogie in $boogie) nothing will happen to $woogie @@ -496,6 +531,7 @@ Renders as: The *#if* directive in Velocity allows for text to be included when the web page is generated, on the conditional that the if statement is true. For example: + :::velocity #if( $foo ) <strong>Velocity!</strong> #end @@ -515,6 +551,7 @@ The content between the *#if* and the *# An *#elseif* or *#else* element can be used with an *#if* element. Note that the Velocity Templating Engine will stop at the first expression that is found to be true. In the following example, suppose that *$foo* has a value of 15 and *$bar* has a value of 6. + :::velocity #if( $foo < 10 ) **Go North** #elseif( $foo == 10 ) @@ -531,6 +568,7 @@ In this example, *$foo* is greater than Velocity uses the equivalent operator to determine the relationships between variables. Here is a simple example to illustrate how the equivalent operator is used. + :::velocity #set ($foo = "deoxyribonucleic acid") #set ($bar = "ribonucleic acid") @@ -544,6 +582,7 @@ Note that the semantics of *==* are slig Velocity has logical AND, OR and NOT operators as well. Below are examples demonstrating the use of the logical AND, OR and NOT operators. + :::velocity ## logical AND #if( $foo && $bar ) @@ -554,6 +593,7 @@ The *#if()* directive will only evaluate Logical OR operators work the same way, except only one of the references need evaluate to true in order for the entire expression to be considered true. Consider the following example. + :::velocity ## logical OR #if( $foo || $bar ) @@ -564,6 +604,7 @@ If *$foo* is true, the Velocity Templati With logical NOT operators, there is only one argument : + :::velocity ##logical NOT #if( !$foo ) @@ -576,6 +617,7 @@ There are text versions of all logical o One more useful note. When you wish to include text immediately following a *#else* directive you will need to use curly brackets immediately surrounding the directive to differentiate it from the following text. (Any directive can be delimited by curly brackets, although this is most useful for *#else*). + :::velocity #if( $foo == $bar)it's true!#{else}it's not!#end ### Loops @@ -584,6 +626,7 @@ One more useful note. When you wish to The *#foreach* element allows for looping. For example: + :::html+velocity <ul> #foreach( $product in $allProducts ) <li>$product</li> @@ -596,6 +639,7 @@ The contents of the *$allProducts* varia Lets say that *$allProducts* is a Hashtable. If you wanted to retrieve the key values for the Hashtable as well as the objects within the Hashtable, you can use code like this: + :::html+velocity <ul> #foreach( $key in $allProducts.keySet() ) <li>Key: $key -> Value: $allProducts.get($key)</li> @@ -604,6 +648,7 @@ Lets say that *$allProducts* is a Hashta Velocity provides an easy way to get the loop counter so that you can do something like the following: + :::html+velocity <table> #foreach( $customer in $customerList ) <tr><td>$foreach.count</td><td>$customer.Name</td></tr> @@ -612,6 +657,7 @@ Velocity provides an easy way to get the Velocity also now provides an easy way to tell if you are on the last iteration of a loop: + :::velocity #foreach( $customer in $customerList ) $customer.Name#if( $foreach.hasNext ),#end #end @@ -620,11 +666,13 @@ If you want a zero-based index of the #f It's possible to set a maximum allowed number of times that a loop may be executed. By default there is no max (indicated by a value of 0 or less), but this can be set to an arbitrary number in the `velocity.properties` file. This is useful as a fail-safe. + :::properties # The maximum allowed number of loops. directive.foreach.maxloops = -1 If you want to stop looping in a foreach from within your template, you can now use the #break directive to stop looping at any time: + :::velocity ## list first 5 customers only #foreach( $customer in $customerList ) #if( $foreach.count > 5 ) @@ -637,10 +685,12 @@ If you want to stop looping in a foreach The *#include* script element allows the template designer to import a local file, which is then inserted into the location where the *#include* directive is defined. The contents of the file are not rendered through the template engine. For security reasons, the file to be included may only be under TEMPLATE_ROOT. + :::velocity #include( "one.txt" ) The file to which the *#include* directive refers is enclosed in quotes. If more than one file will be included, they should be separated by commas. + :::velocity #include( "one.gif","two.txt","three.htm" ) The file being included need not be referenced by name; in fact, it is often preferable to use a variable instead of a filename. This could be useful for targeting output according to criteria determined when the page request is submitted. Here is an example showing both a filename and a variable. @@ -651,12 +701,14 @@ The file being included need not be refe The *#parse* script element allows the template designer to import a local file that contains VTL. Velocity will parse the VTL and render the template specified. + :::velocity #parse( "me.vm" ) Like the *#include* directive, *#parse* can take a variable rather than a template. Any templates to which *#parse* refers must be included under TEMPLATE_ROOT. Unlike the *#include* directive, *#parse* will only take a single argument. VTL templates can have *#parse* statements referring to templates that in turn have *#parse* statements. By default set to 10, the *directive.parse.max.depth* line of the `velocity.properties` allows users to customize maximum number of *#parse* referrals that can occur from a single template. (Note: If the *directive.parse.max.depth* property is absent from the `velocity.properties` file, Velocity will set this default to 10.) Recursion is permitted, for example, if the template `dofoo.vm` contains the following lines: + :::velocity Count down. #set( $count = 8 ) #parse( "parsefoo.vm" ) @@ -664,6 +716,7 @@ VTL templates can have *#parse* statemen It would reference the template `parsefoo.vm`, which might contain the following VTL: + :::velocity $count #set( $count = $count - 1 ) #if( $count > 0 ) @@ -690,6 +743,7 @@ The *#evaluate* directive can be used to The example below will display `abc`. + :::velocity #set($source1 = "abc") #set($select = "1") #set($dynamicsource = "$source$select") @@ -703,6 +757,7 @@ The *#define* directive lets one assign The example below will display `Hello World!`. + :::velocity #define( $block )Hello $who#end #set( $who = 'World!' ) $block @@ -711,28 +766,33 @@ The example below will display `Hello Wo The *#macro* script element allows template designers to define a repeated segment of a VTL template. Velocimacros are very useful in a wide range of scenarios both simple and complex. This Velocimacro, created for the sole purpose of saving keystrokes and minimizing typographic errors, provides an introduction to the concept of Velocimacros. + :::html+velocity #macro( d ) <tr><td></td></tr> #end The Velocimacro being defined in this example is *d*, and it can be called in a manner analogous to any other VTL directive: + :::velocity #d() When this template is called, Velocity would replace *#d()* with a row containing a single, empty data cell. If we want to put something in that cell, we can alter the macro to allow for a body: + :::html+velocity #macro( d ) <tr><td>$!bodyContent</td></tr> #end Now, if we call the macro just a bit differently, using #@ before the name and providing a body and #end to the call, then Velocity will render the body when it gets to the $!bodyContent: + :::velocity #@d()Hello!#end You can still call the macro as you did before, and since we used the silent reference notation for the body reference ($!bodyContent instead of $bodyContent), it will still render a row with a single, empty data cell. A Velocimacro can also take any number of arguments -- even zero arguments, as demonstrated in the first example, is an option -- but when the Velocimacro is invoked, it must be called with the same number of arguments with which it was defined. Many Velocimacros are more involved than the one defined above. Here is a Velocimacro that takes two arguments, a color and an array. + :::html+velocity #macro( tablerows $color $somelist ) #foreach( $something in $somelist ) <tr><td bgcolor=$color>$something</td></tr> @@ -743,6 +803,7 @@ The Velocimacro being defined in this ex Anything that can be put into a VTL template can go into the body of a Velocimacro. The *tablerows* Velocimacro is a *foreach* statement. There are two *#end* statements in the definition of the *#tablerows* Velocimacro; the first belongs to the *#foreach*, the second ends the Velocimacro definition. + :::html+velocity #set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] ) #set( $color = "blue" ) <table> @@ -751,6 +812,7 @@ Anything that can be put into a VTL temp Notice that *$greatlakes* takes the place of *$somelist*. When the *#tablerows* Velocimacro is called in this situation, the following output is generated: + :::html <table> <tr><td bgcolor="blue">Superior</td></tr> <tr><td bgcolor="blue">Michigan</td></tr> @@ -763,6 +825,7 @@ Velocimacros can be defined *inline* in Were the *#tablerows($color $list)* Velocimacro defined in a Velocimacros template library, this macro could be used on any of the regular templates. It could be used many times and for many different purposes. In the template `mushroom.vm` devoted to all things fungi, the *#tablerows* Velocimacro could be invoked to list the parts of a typical mushroom: + :::html+velocity #set( $parts = ["volva","stipe","annulus","gills","pileus"] ) #set( $cellbgcol = "#CC00FF" ) <table> @@ -771,6 +834,7 @@ Were the *#tablerows($color $list)* Velo When fulfilling a request for `mushroom.vm`, Velocity would find the *#tablerows* Velocimacro in the template library (defined in the `velocity.properties` file) and generate the following output: + :::html+ <table> <tr><td bgcolor="#CC00FF">volva</td></tr> <tr><td bgcolor="#CC00FF">stipe</td></tr> @@ -793,6 +857,7 @@ Velocimacros can take as arguments any o When passing references as arguments to Velocimacros, please note that references are passed 'by name'. This means that their value is 'generated' at each use inside the Velocimacro. This feature allows you to pass references with method calls and have the method called at each use. For example, when calling the following Velocimacro as shown + :::velocity #macro( callme $a ) $a $a $a #end @@ -805,6 +870,7 @@ At first glance, this feature appears su If you need to circumvent this feature, you can always just get the value from the method as a new reference and pass that : + :::velocity #set( $myval = $foo.bar() ) #callme( $myval ) @@ -837,6 +903,7 @@ There is no problem writing "I bought a Cases may arise where you do not want to have a reference rendered by Velocity. *Escaping* special characters is the best way to output VTL's special characters in these situations, and this can be done using the backslash ( *\* ) character <i>when those special characters are part of a valid VTL reference</i>. + :::velocity #set( $email = "foo" ) $email @@ -844,6 +911,7 @@ If Velocity encounters a reference in y Suppose that *$email* is defined (for example, if it has the value *foo*), and that you want to output *$email*. There are a few ways of doing this, but the simplest is to use the escape character. Here is a demonstration: + :::velocity ## The following line defines $email in this template: #set( $email = "foo" ) $email @@ -856,6 +924,7 @@ renders as If, for some reason, you need a backslash before either line above, you can do the following: + :::velocity ## The following line defines $email in this template: #set( $email = "foo" ) \\$email @@ -868,6 +937,7 @@ which renders as Note that the *\* character bind to the *$* from the left. The bind-from-left rule causes *\\\$email* to render as *\$email*. Compare these examples to those in which *$email* is not defined. + :::velocity $email \$email \\$email @@ -882,6 +952,7 @@ renders as Notice Velocity handles references that are defined differently from those that have not been defined. Here is a set directive that gives *$foo* the value *gibbous*. + :::velocity #set( $foo = "gibbous" ) $moon = $foo @@ -891,15 +962,18 @@ The output will be: *$moon = gibbous* -- Sometimes Velocity has trouble parsing your template when it encounters an "invalid reference" that you never intended to be a reference at all. *Escaping* special characters is, again, the best way to handle these situations, but in these situations, the backslash will likely fail you. Instead of simply trying to escape the problematic `$` or `#`, you should probably just replace this: + :::velocity ${my:invalid:non:reference} with something like this + :::velocity #set( $D = '$' ) ${D}{my:invalid:non:reference} You can, of course, put your `$` or `#` string directly into the context from your java code (e.g. `context.put("D","$");`) to avoid the extra #set() directive in your template(s). Or, if you are using [VelocityTools](/tools/devel), you can just use the EscapeTool like this: + :::velocity ${esc.d}{my:invalid:non:reference} Escaping of both valid and invalid VTL directives is handled in much the same manner; this is described in more detail in the Directives section. @@ -908,6 +982,7 @@ Escaping of both valid and invalid VTL d VTL directives can be escaped with the backslash character ("\") in a manner similar to valid VTL references. + :::velocity ## #include( "a.txt" ) renders as <contents of a.txt> #include( "a.txt" ) @@ -919,6 +994,7 @@ VTL directives can be escaped with the b Extra care should be taken when escaping VTL directives that contain multiple script elements in a single directive (such as in an if-else-end statements). Here is a typical VTL if-statement: + :::velocity #if( $jazz ) Vyacheslav Ganelin #end @@ -929,6 +1005,7 @@ If *$jazz* is true, the output is If *$jazz* is false, there is no output. Escaping script elements alters the output. Consider the following case: + :::velocity \#if( $jazz ) Vyacheslav Ganelin \#end @@ -941,7 +1018,8 @@ This causes the directives to be escaped Suppose backslashes precede script elements that are legitimately escaped: - v\\#if( $jazz ) + :::velocity + \\#if( $jazz ) Vyacheslav Ganelin \\#end @@ -958,6 +1036,7 @@ If *$jazz* is false, the output is Note that things start to break if script elements are not properly escaped. + :::velocity \\\#if( $jazz ) Vyacheslave Ganelin \\#end @@ -968,6 +1047,7 @@ Here the *#if* is escaped, but there is Although VTL in this user guide is often displayed with newlines and whitespaces, the VTL shown below + :::velocity #set( $imperial = ["Munetaka","Koreyasu","Hisakira","Morikune"] ) #foreach( $shogun in $imperial ) $shogun @@ -975,10 +1055,12 @@ Although VTL in this user guide is often is equally valid as the following snippet that Geir Magnusson Jr. posted to the Velocity user mailing list to illustrate a completely unrelated point: + :::velocity Send me #set($foo=["$10 and ","a pie"])#foreach($a in $foo)$a#end please. Velocity's default behaviour is to gobble up excess whitespace. The preceding directive can be written as: + :::velocity Send me #set( $foo = ["$10 and ","a pie"] ) #foreach( $a in $foo ) @@ -988,6 +1070,7 @@ Velocity's default behaviour is to gobbl or as + :::velocity Send me #set($foo = ["$10 and ","a pie"]) #foreach ($a in $foo )$a @@ -1001,6 +1084,7 @@ In each case the output will be the same Velocity has a handful of built-in mathematical functions that can be used in templates with the *set* directive. The following equations are examples of addition, subtraction, multiplication and division, respectively: + :::velocity #set( $foo = $bar + 3 ) #set( $foo = $bar - 4 ) #set( $foo = $bar * 6 ) @@ -1008,16 +1092,19 @@ Velocity has a handful of built-in mathe When a division operation is performed between two integers, the result will be an integer, as the fractional portion is discarded. Any remainder can be obtained by using the modulus (*%*) operator. + :::velocity #set( $foo = $bar % 5 ) ### Range Operator The range operator can be used in conjunction with *#set* and *#foreach* statements. Useful for its ability to produce an object array containing integers, the range operator has the following construction: + :::velocity [n..m] Both *n* and *m* must either be or produce integers. Whether *m* is greater than or less than *n* will not matter; in this case the range will simply count down. Examples showing the use of the range operator as provided below: + :::velocity First example: #foreach( $foo in [1..5] ) $foo @@ -1059,6 +1146,7 @@ Web page designers concerned with making When a reference is silenced with the *!* character and the *!* character preceded by an *\* escape character, the reference is handled in a special way. Note the differences between regular escaping, and the special case where *\* precedes *!* follows it: + :::velocity #set( $foo = "bar" ) $\!foo $\!{foo} @@ -1074,6 +1162,7 @@ This renders as: Contrast this with regular escaping, where *\* precedes *$*: + :::velocity \$foo \$!foo \$!{foo} @@ -1101,15 +1190,18 @@ No. A directive isn't a valid argument *However...*, there are things you can do. One easy solution is to take advantage of the fact that 'doublequote' (") renders its contents. So you could do something like + :::velocity #set($stuff = "#bold('hello')" ) #center( $stuff ) You can save a step... + :::velocity #center( "#bold( 'hello' )" ) Please note that in the latter example the arg is evaluated <i>inside</i> the VM, not at the calling level. In other words, the argument to the VM is passed in in its entirety and evaluated within the VM it was passed into. This allows you to do things like : + :::velocity #macro( inner $foo ) inner : $foo #end @@ -1130,15 +1222,17 @@ because the evaluation of the "#inner($b This is an intentional and jealously guarded feature - args are passed 'by name' into VMs, so you can hand VMs things like stateful references such as + :::html+velocity #macro( foo $color ) - <tr bgcolor=$color><td>Hi</td></tr> - <tr bgcolor=$color><td>There</td></tr> + <tr bgcolor="$color"><td>Hi</td></tr> + <tr bgcolor="$color"><td>There</td></tr> #end #foo( $bar.rowColor() ) And have rowColor() called repeatedly, rather than just once. To avoid that, invoke the method outside of the VM, and pass the value into the VM. + :::velocity #set($color = $bar.rowColor()) #foo( $color ) @@ -1180,6 +1274,7 @@ To do concatenation of references in VTL In the regular 'schmoo' of a template (when you are mixing it in with regular content) : + :::velocity #set( $size = "Big" ) #set( $name = "Ben" ) @@ -1187,6 +1282,7 @@ In the regular 'schmoo' of a template (w and the output will render as 'The clock is BigBen'. For more interesting cases, such as when you want to concatenate strings to pass to a method, or to set a new reference, just do + :::velocity #set( $size = "Big" ) #set( $name = "Ben" ) @@ -1196,12 +1292,13 @@ and the output will render as 'The clock Which will result in the same output. As a final example, when you want to mix in 'static' strings with your references, you may need to use 'formal references' : - #set( $size = "Big" ) - #set( $name = "Ben" ) + :::velocity + #set( $size = "Big" ) + #set( $name = "Ben" ) - #set($clock = "${size}Tall$name" ) + #set($clock = "${size}Tall$name" ) - The clock is $clock. + The clock is $clock. Now the output is 'The clock is BigTallBen'. The formal notation is needed so the parser knows you mean to use the reference '$size' versus '$sizeTall' which it would if the '{}' weren't there. Modified: velocity/site/cms/trunk/content/engine/2.0/vtl-reference.mdtext URL: http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/2.0/vtl-reference.mdtext?rev=1834409&r1=1834408&r2=1834409&view=diff ============================================================================== --- velocity/site/cms/trunk/content/engine/2.0/vtl-reference.mdtext (original) +++ velocity/site/cms/trunk/content/engine/2.0/vtl-reference.mdtext Tue Jun 26 10:02:24 2018 @@ -121,6 +121,7 @@ Notes: 1. The == operator can be used to compare numbers, strings, objects of the same class, or objects of different classes. In the last case (when objects are of different classes), the toString() method is called on each object and the resulting Strings are compared. 2. You can also use brackets to delimit directives. This is especially useful when text immediately follows an `#else` directive. + :::velocity #if($foo == $bar)it's true!#{else}it's not!#end ### #foreach - Loops through a list of objects @@ -143,14 +144,16 @@ Examples of the #foreach(), omitting the Velocity provides an easy way to get the loop counter so that you can do something like the following: + :::html+velocity <table> #foreach( $customer in $customerList ) <tr><td>$foreach.count</td><td>$customer.Name</td></tr> #end </table> -Additionally, the maximum allowed number of loop iterations can be controlled engine-wide (an ability introduced in Velocity 1.5). By default, there is no limit: +Additionally, the maximum allowed number of loop iterations can be controlled engine-wide with `velocity.properties`. By default, there is no limit: + :::properties # The maximum allowed number of loops. directive.foreach.maxloops = -1 @@ -251,10 +254,12 @@ Usage: Once defined, the VM is used like any other VTL directive in a template. + :::velocity #vmname( $arg1 $arg2 ) **Except**, that when you wish to call a VM with a body, then you must prefix the name of the VM with @. The content of that body may be referenced in the macro definition via $!bodyContent as many or few times as you like. + :::velocity #@vmname( $arg1 $arg2 ) here is the body#end VMs can be defined in one of two places: @@ -270,12 +275,14 @@ Comments are not rendered at runtime. Example: + :::velocity ## This is a comment.** ### Multi Line Comments Example: + :::velocity #** This is a multiline comment. This is the second line. @@ -288,6 +295,7 @@ Unparsed content is rendered at runtime, Example: + :::velocity #[[ This has invalid syntax that would normally need Modified: velocity/site/cms/trunk/content/engine/2.0/webapps.mdtext URL: http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/2.0/webapps.mdtext?rev=1834409&r1=1834408&r2=1834409&view=diff ============================================================================== --- velocity/site/cms/trunk/content/engine/2.0/webapps.mdtext (original) +++ velocity/site/cms/trunk/content/engine/2.0/webapps.mdtext Tue Jun 26 10:02:24 2018 @@ -37,17 +37,19 @@ The simplest replacement for FileResourc If you are using the VelocityViewServlet, then it is automatically configured and ready to use the WebappResourceLoader. So if you want to change the configured path(s), you need only add a line like the following to your velocity.properties: + :::properties webapp.resource.loader.path=/WEB-INF/mytemplates/ If you need to set the WebappResourceLoader up on your own, then you can make your properties something like this: - + :::properties resource.loader=webapp webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader webapp.resource.loader.path=/WEB-INF/mytemplates/ You will **also need to put the ServletContext into your VelocityEngine's application attributes** before initializing that Engine. This is how the WebappResourceLoader knows how to find templates. + :::java myVelocityEngine.setApplicationAttribute("javax.servlet.ServletContext", servletContext); ### Changing Object State - Don't! @@ -56,10 +58,12 @@ Velocity provides the ability to call an For example, the following code safely calls the size() method of a list and displays the result. + :::velocity There are $users.size() currently logged in. An example of an unsafe operation concerns a financial web page with an object in the context that calculates data year by year. The method calculateNextYear() calculates data for the next year and advances an internal counter: + :::velocity 2005 data: $table.data $table.calculateNextYear() 2006 data: $table.data @@ -78,6 +82,7 @@ Any user-entered text that contains spec However, Velocity provides the ability to specify a `ReferenceInsertionEventHandler` which will alter the value of a reference before it is inserted into the page. Specifically, you can configure the `EscapeHtmlReference` handler into your `velocity.properties` file to escape all references (optionally) matching a regular expression. The following example will escape HTML entities in any reference that starts with "msg" (e.g. `$msgText`). + :::properties eventhandler.referenceinsertion.class = org.apache.velocity.app.event.implement.EscapeHtmlReference eventhandler.escape.html.match = /msg.*/ @@ -87,6 +92,7 @@ Note that other kinds of escaping are so Since a web application is running on a central server, that typically has multiple users and confidential resources, care must be taken to make certain that the web application is secure. Most standard web security principles apply to a web application built with Velocity. A few specific issues (such as system configuration, more on cross-site scripting, and method introspection) are written up in this article on [Building Secure Applications with Velocity](http://wiki.apache.org/velocity/BuildingSecureWebApplications). In particular, you may want to prevent template designers from including "dangerous" reflection-related methods by specifying the `SecureUberspector` to get/set properties and execute method calls. + :::properties runtime.introspector.uberspect = org.apache.velocity.util.introspection.SecureUberspector ### Logging @@ -105,10 +111,12 @@ For more information, consult the [Veloc 2. Build the Velocity Tools jar and the "simple" example by typing: + :::shell ant example.simple 3.Take a look at the "examples" directory. You will see a file "index.vm". Here's an excerpt: + :::html+velocity <html> <body> I'm a velocity template. @@ -133,6 +141,7 @@ For more information, consult the [Veloc You can copy any additional velocity files into this same directory. In `examples/WEB-INF` you will see a file "tools.xml". This specifies a list of "Tools" that are automatically included in the context. + :::xml <tools> <data type="boolean" key="xhtml" value="true"/> <data type="boolean" key="isSimple" value="true"/> @@ -149,6 +158,7 @@ You can copy any additional velocity fil And finally the web.xml file specifies the name of the servlet and location of toolbox.properties. + :::xml <web-app> <servlet> <servlet-name>velocity</servlet-name> Modified: velocity/site/cms/trunk/content/engine/devel/build.mdtext URL: http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/devel/build.mdtext?rev=1834409&r1=1834408&r2=1834409&view=diff ============================================================================== --- velocity/site/cms/trunk/content/engine/devel/build.mdtext (original) +++ velocity/site/cms/trunk/content/engine/devel/build.mdtext Tue Jun 26 10:02:24 2018 @@ -16,6 +16,7 @@ To build Velocity we require [Maven](htt In each case below, it is assumed that you were successful in [checking out the sources from Subversion](/download.cgi#source-code-repository): + :::shell svn checkout https://svn.apache.org/repos/asf/velocity/engine/trunk velocity cd velocity mvn install Modified: velocity/site/cms/trunk/content/engine/devel/configuration.mdtext URL: http://svn.apache.org/viewvc/velocity/site/cms/trunk/content/engine/devel/configuration.mdtext?rev=1834409&r1=1834408&r2=1834409&view=diff ============================================================================== --- velocity/site/cms/trunk/content/engine/devel/configuration.mdtext (original) +++ velocity/site/cms/trunk/content/engine/devel/configuration.mdtext Tue Jun 26 10:02:24 2018 @@ -152,6 +152,7 @@ The following resource management config > To illustrate, here is an example taken right from the default Velocity > properties, showing how setting up the FileResourceLoader is managed + :::properties resource.loader = file file.resource.loader.description = Velocity File Resource Loader @@ -295,15 +296,18 @@ Configuring the resource loaders for Vel The first step in configuring one or more resource loaders is do 'declare' them by name to Velocity. Use the property `resource.loader` and list one or more loader names. You can use anything you want - these names are used to associate configuration properties with a given loader. + :::properties resource.loader = file That entry declares that we will have a resource loader known as 'file'. The next thing to do is to set the important properties. The most critical is to declare the class to use as the loader: + :::properties file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader In this case, we are telling velocity that we are setting up a resource loadercalled 'file', and are using the class `org.apache.velocity.runtime.resource.loader.FileResourceLoader` to be the class to use. The next thing we do is set the properties important to this loader. + :::properties file.resource.loader.path = /opt/templates file.resource.loader.cache = true file.resource.loader.modificationCheckInterval = 2 @@ -314,6 +318,7 @@ Those are the basics. What follows are **Do-nothing Default Configuration: ** As the name says, there is nothing you have to do or configure to get the default configuration. This configuration uses the FileResourceLoader with the current directory as the default resource path, and caching is off. As a properties set, this is expressed as: + :::properties resource.loader = file file.resource.loader.description = Velocity File Resource Loader @@ -324,6 +329,7 @@ Those are the basics. What follows are **Multiple Template Path Configuration: ** This configuration uses the FileResourceLoader with several directories as 'nodes' on the template search path. We also want to use caching, and have the templates checked for changes in 10 second intervals. As a properties set, this is expressed as: + :::properties resource.loader = file file.resource.loader.description = Velocity File Resource Loader @@ -334,6 +340,7 @@ Those are the basics. What follows are **Multiple Loader Configuration :** This configuration sets up three loaders at the same time, the FileResourceLoader, the ClasspathResourceLoader, and the JarResourceLoader. The loaders are set-up such that the FileResourceLoader is consulted first, then the ClasspathResourceLoader, and finally the JarResourceLoader. This would allow you to qickly drop a template into the file template area to replace on of the templates found in the classpath (usually via a jar) without having to rebuild the jar. + :::properties # # specify three resource loaders to use #