+ All Categories
Home > Documents > Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf ·...

Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf ·...

Date post: 21-Aug-2020
Category:
Upload: others
View: 6 times
Download: 0 times
Share this document with a friend
31
November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 1 Hacking Velocity – ApacheCon 2004 What is Velocity Velocity Tools Custom Directives Custom Resourceloaders Custom Introspector Adding Event Handlers Modifying Velocity Syntax Presenter Contact Info: Will Glass-Husain Menlo Park, California USA [email protected] + 1 415 440-7500
Transcript
Page 1: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 1

Hacking Velocity – ApacheCon 2004

• What is Velocity

• Velocity Tools

• Custom Directives

• Custom Resourceloaders

• Custom Introspector

• Adding Event Handlers

• Modifying Velocity Syntax

Presenter Contact Info:

Will Glass-Husain

Menlo Park, California USA

[email protected]

+ 1 415 440-7500

Page 2: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 2

What is Velocity?

• A templating engine that can generate any type of text output,

including HTML, email, SQL, or Java source code.

• Based on a "pull" approach in which a text file includes

"References" to data objects that are pulled from a provided

"Context".

$Date

Dear $Contact.FirstName $Contact.LastName,

Thank you for your recent purchase of

$Order.ProductName. The cost of the item was

$Order.TotalCost#if($Order.Tax > 0) including

a tax of $Order.TaxRate%#end.

Sincerely,

Biggest and Best Book Merchants, Inc.November 17, 2004

Dear Jennifer Glass,

Thank you for your recent purchase of Alice

in Wonderland, Annotated Edition. The cost

of the item was $29.95.

Sincerely,

Biggest and Best Book Merchants, Inc.

Order

Contact

Date

Page 3: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 3

Basic Velocity Concepts

• References

– References objects from the Velocity context. Starts with a "$".

– Can have Properties or Methods

– Common practice is to provide two types: data objects (with

properties) and "tools" (with methods).

– Examples:• $contact.FirstName

• $format("$#,##0.00",$order.price)

• Directives

– Control statements. Starts with a "#"

– Example block directive:• #if ($columncount > 0)

display a table

#end

– Example line directive:• #include('header.vm')

Page 4: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 4

How To Use Velocity

VelocityEngine ve = new VelocityEngine();

ve.setProperty("file.resource.loader.path","templates");

ve.init();

Context c = new VelocityContext();

c.add("order",order);

c.add("contact",contact);

Template t1 = ve.getTemplate("inputfile.vm");

StringWriter writer = new StringWriter();

t1.merge(c,writer);

String result = writer.toString();

Load a Template From a File

VelocityEngine ve = new VelocityEngine();

ve.init();

Context c = new VelocityContext().

c.add("order",order);

c.add("contact",contact);

StringWriter writer = new StringWriter();

ve.evaluate(c,writer,"velocity",inputstring);

String result = writer.toString()

Evaluate a Template stored as a String

Page 5: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 5

Improve Productivity with Velocity-Tools

• GenericTools

– GenericTools is a group of reuseable and documented tools that can be added to a Velocity context.

A tool is simply a class which can perform various tasks when made available to the Velocity engine.

Most tools are optimized for use with an automatically managed toolbox (see VelocityViewServlet).

• VelocityView

– VelocityView contains a standalone servlet (VelocityViewServlet) which can render templates for web

applications.

– Also included is a Toolbox Manager which can automatically make "view tools" and data available to

the templates. Any class with public methods can be used as a tool in the template.

– VelocityLayoutServlet is an extension of the basic VelocityViewServlet that can render screen content

into common layout templates.

• VelocityStruts

– VelocityStruts is a set of tools for using the Velocity template engine as the view layer for a web

application built upon the Jakarta Struts framework.

– This work leverages the VelocityViewServlet and additional tools which make it easy to integrate the

Velocity with Struts. Several example hybrid applications are included.

from the web site:

http://jakarta.apache.org/velocity/tools/index.html

VelocityTools is a collection of Velocity subprojects with a common goal of creating tools and

infrastructure for building both web and non-web applications using the Velocity template

engine.

Page 6: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 6

Example Tools

• DateTool

• IteratorTool

• MathTool

• NumberTool

• RenderTool

• AbstractSearchTool

• CookieTool

• ImportTool

• LinkTool

• ParameterParser

• ViewRenderTool

Generic Tools VelocityView (web) Tools

Context c = new VelocityContext();c.add("date",new DateTool());

Template t1 = ve.getTemplate("inputfile.vm");StringWriter writer = new StringWriter();t1.merge(c,writer);String result = writer.toString();

Using a Tool

Page 7: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 7

VelocityViewServlet: Serve Velocity Pages Over the Web

• Quick and easy way to build a web app.

• Serves Velocity pages just like HTM or JSP files.

• Tools are automatically placed in the Velocity context

according to "toolbox.xml" config file. Excerpt:

<tool> <key>math</key> <scope>application</scope> <class>org.apache.velocity.tools.generic.MathTool</class></tool>

Note: VelocityViewServlet replaces deprecated VelocityServlet distributed with Velocity project

• Any tool that has a scope of session or request is passed session

and/or request info when it is initialized. (if the tool implements

ViewContext).

• VelocityViewServlet can be subclassed to add additionalfunctionality. Example (in distribution): VelocityLayoutServlet,which uses a 2 pass render in order to apply a common layout toall web pages.

Page 8: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 8

VelocityViewServlet: Configuration Example (web.xml)

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<display-name>Example application</display-name>

<!-- Define Velocity template compiler -->

<servlet>

<servlet-name>velocity</servlet-name>

<servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet

</servlet-class>

<init-param>

<param-name>org.apache.velocity.toolbox</param-name>

<param-value>/WEB-INF/toolbox.xml</param-value>

</init-param>

<init-param>

<param-name>org.apache.velocity.properties</param-name>

<param-value>/WEB-INF/velocity.properties</param-value>

</init-param>

</servlet>

<!-- Map *.vm files to Velocity -->

<servlet-mapping>

<servlet-name>velocity</servlet-name>

<url-pattern>*.vm</url-pattern>

</servlet-mapping>

</web-app>

WEB-INF/web.xml

Page 9: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 9

VelocityViewServlet: Configuration Example (toolbox.xml)

<?xml version="1.0"?>

<toolbox>

<tool>

<key>date</key>

<scope>application</scope>

<class>org.apache.velocity.tools.generic.DateTool</class>

</tool>

<tool>

<key>params</key>

<scope>request</scope>

<class>org.apache.velocity.tools.view.tools.ParameterParser</class>

</tool>

<tool>

<key>cookie</key>

<scope>request</scope>

<class>org.apache.velocity.tools.view.tools.CookieTool</class>

</tool>

<data type="number">

<key>app_version</key>

<value>1.5</value>

</data>

<data type="string">

<key>app_name</key>

<value>A Carroll Compendium</value>

</data>

</toolbox>

WEB-INF/toolbox.xml

Page 10: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 10

VelocityViewServlet: Configuration Example (velocity.properties)

# all optional

velocimacro.library = /WEB-INF/VM_global_library.vm

velocimacro.permissions.allow.inline = true

velocimacro.permissions.allow.inline.to.replace.global = false

velocimacro.permissions.allow.inline.local.scope = false

velocimacro.context.localscope = false

WEB-INF/velocity.properties

Page 11: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 11

VelocityViewStruts: An Alternative To JSP

• ActionMessagesTool

• ErrorsTool

• FormTool

• MessageTool

VelocityStruts Tools

• StrutsLinkTool

• SecureLinkTool

• TilesTool

• ValidatorTool

Page 12: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 12

Controlling Velocity Template Generation with a Custom Directive

• Consider – can the problem you are trying to solve be done

more simply with a Tool or VelocityMacro?

• If not, Velocity allows you to code your own custom directives by

doing the following:

– Create a class that extends

org.apache.velocity.runtime.directive.Directive

– Add the following to velocity.properties

userdirective = yourdirectiveclass

• Review the directives in the velocity source code for good

examples. For example, review

org.apache.velocity.runtime.directive.ForEach

Page 13: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 13

Custom Directive Example: Generate Endnotes

#endNotes

All in the golden afternoon

(*1:In these prefatory verses Carroll recalls that "golden afternoon" in 1862 when heand his friend the Reverend Robinson Duckworth (then a fellow of Trinity College,Oxford, later canon of Westminster) took the three charming Liddell sisters on a rowingexpedition up the Thames. *)

Full leisurely we glide;For both our oars, with little skill, By little arms are plied,While little hands make vain pretence Our wanderings to guide.

(* 2:Note how this stanza puns three times with the word "little." "Liddle" waspronounced to rhyme with "fiddle." *)#end

Usage:

All in the golden afternoon

Full leisurely we glide;For both our oars, with little skill, By little arms are plied,While little hands make vain pretence Our wanderings to guide.

NOTES

1: In these prefatory verses Carroll recalls that "golden afternoon" in 1862 when he andhis friend the Reverend Robinson Duckworth (then a fellow of Trinity College, Oxford,later canon of Westminster) took the three charming Liddell sisters on a rowingexpedition up the Thames.

2:Note how this stanza puns three times with the word "little." "Liddle" was pronouncedto rhyme with "fiddle."

Results:

Page 14: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 14

Custom Directive Example: Code Excerpt

public class EndNoteDirective extends Directive {

public String getName() { return "endNotes"; }

public int getType() { return BLOCK; }

public boolean render(InternalContextAdapter context, java.io.Writer writer,Node node)

throws ResourceNotFoundException,ParseErrorException,MethodInvocationException

{

// first, parse the entire block and retrieve the content

StringWriter internalwriter = new StringWriter();

// the node's children are the arguments and the body.

// here there should be only one child, since there are no arguments

node.jjtGetChild(0).render(context, internalwriter);

String sourcecontent = internalwriter.toString();

internalwriter.close();

// missing code creates new "finalcontent" based on "sourcecontent"

writer.write(finalcontent.toString());

return true;

}

}

Full code listings available at:

http://jlamp.com/apachecon2004/

Page 15: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 15

Custom Directive Example: Configuration

## Load templates from classpath

resource.loader = class

class.resource.loader.class =

org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader

## Specify the user directive

userdirective=com.jlamp.directive.EndNoteDirective

## Log messages displayed with log4j

runtime.log.logsystem.class = org.apache.velocity.runtime.log.SimpleLog4JLogSystem

runtime.log.logsystem.log4j.category = com.jlamp.velocity

Complete sample app available at:

http://jlamp.com/apachecon2004/

Page 16: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 16

Custom ResourceLoaders

• A ResourceLoader is a mechanism to load a template. Velocity

provides these built in ResourceLoaders:

– ClasspathResourceLoader

– DataSourceResourceLoader

– FileResourceLoader

– JarResourceLoader

• To implement your own resource loader, extend

org.apache.velocity.runtime.resource.loader.ResourceLoader

Page 17: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 17

Custom ResourceLoader Example: Excerpt (FTP resource loader)

public class FtpResourceLoader extends ResourceLoader {

String username; String password; String hostname; String rootDirectory;

public void init (ExtendedProperties configuration)

{ username = configuration.getString("username");

password = configuration.getString("password");

hostname = configuration.getString("host");

rootDirectory = configuration.getString("root");

}

public long getLastModified (Resource resource)

{ String name = resource.getName();

if (name.startsWith("/")) name = name.substring(1);

return getFileModificationDate(username,password,hostname,rootDirectory + name).getTime();

}

public boolean isSourceModified (Resource resource)

{

long date = getLastModified(resource);

return (date == 0) || (date != resource.getLastModified());

}

public InputStream getResourceStream (String source) throws ResourceNotFoundException

{

if (source.startsWith("/")) source = source.substring(1);

InputStream i = getFileStream(username,password,hostname,rootDirectory + source);

if (i == null)

throw new ResourceNotFoundException(source);

else

return i;

}

}

Complete sample app available at:

http://jlamp.com/apachecon2004/

Page 18: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 18

Custom ResourceLoader Example: Configuration

## Load templates from FTP site

resource.loader = ftp

ftp.resource.loader.class = com.jlamp.resourceloader.FtpResourceLoader

ftp.resource.loader.username = templateuser

ftp.resource.loader.password = apricots

ftp.resource.loader.host = www.jlamp.com

ftp.resource.loader.root = /app/templates

## Log messages displayed with log4j

runtime.log.logsystem.class = org.apache.velocity.runtime.log.SimpleLog4JLogSystem

runtime.log.logsystem.log4j.category = com.jlamp.velocity

Complete sample app available at:

http://jlamp.com/apachecon2004/

Page 19: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 19

Adding an Event Handler

• Velocity provides a mechanism to intercept and modify parsingoperation.

• Currently, three event handlers available:

– ReferenceInsertionEventHandler: Modify the text that gets insertedfrom a reference (e.g. $date)

– NullSetEventHandler: Prevents logging of null #set operations

– MethodExceptionEventHandler: Intercept a method thrown by atool in the context.

• Event handlers are instantiated for each page that is parsed,and are "attached" to the context before the template ismerged:

EventCartridge ec = new EventCartridge();ec.addEventHandler(new CustomReferenceInsertionHandler());ec.attachToContext( context );

// now merge the template

Page 20: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 20

Event Handler Example: Escape XML Entities (excerpt)

/**

* Escape all XML Entities in the reference insertion. Specifically, the following

* conversions are performed:

* <DL>

* <DT>&amp;</DT><DD>&amp;amp;</DD>

* <DT>&lt;</DT><DD>&amp;lt;</DD>

* <DT>&gt;</DT><DD>&amp;gt;</DD>

* <DT>&quot;</DT><DD>&amp;quot;</DD>

* </DL>

*/

public class EscapeXMLEntities implements ReferenceInsertionEventHandler {

/**

* Escape the XML entities for all inserted references.

*/

public Object referenceInsert(String reference, Object value) {

String val = value.toString();

return escapeText(val);

}

}

Complete sample app available at:

http://jlamp.com/apachecon2004/

Page 21: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 21

Custom Introspector

• The introspector is used to discover and execute reference

properties and method calls.

• The build in introspector calls get/set methods when accessing

properties, and does all method calls.

• Possible custom introspectors:

– Access public fields directly instead of calling get/set methods

– Prevent access of "dangerous" methods by untrusted template

designer such as getClassLoader() and newInstance.

(dirty little secret – any class can be instantiated in a Velocity

Template).

• A custom introspector is fairly complex to implement. The built-in

introspector includes 9 classes in two packages.

• Introspector needs to implement

org.apache.velocity.util.introspection.Uberspect

Page 22: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 22

An Evil Velocity Template

Today's date: $today

Date class: $today.Class

## Let's do some mischief and instantiate an arbitrary class

#set ($fileclass = $today.Class.forName("java.io.File"))

#set ($stringclass = $today.Class.forName("java.lang.String"))

#set ($paramlist = [".."])

#set ($paramarray = $paramlist.toArray())

#set ($constructors = $fileclass.Constructors)

## Call the constructor java.io.File(String)

#foreach ($c in $constructors)

#if ($c.toString() == "public java.io.File(java.lang.String)")

#set ($file = $c.newInstance($paramarray))

$file

#end

#end

## Now, get the File list. Think about what else you could do!

## Bad, Bad, Bad!

#set ($files = $file.list())

App Directory contents:

#foreach ($f in $files)

$f

#end

Please! Use this knowledge to further the cause of the good, not of those with evil intent.

Page 23: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 23

An Evil Velocity Template: Result (standard introspector)

Today's date: Mon Oct 18 01:26:06 PDT 2004

Date class: class java.util.Date

..

App Directory contents:

bin

build

classes_src

java

lib

results

Page 24: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 24

An Evil Velocity Template: Result (custom introspector)

Today's date: Mon Oct 18 01:33:35 PDT 2004

Date class: class java.util.Date

App Directory contents:

Page 25: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 25

Custom Introspector: Code Excerpt

/**

* Property getter

*/

public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i)

throws Exception

{

if (!checkObjectExecutePermission(obj,null))

{

rlog.warn ("Cannot retrieve get method from object of class " +

obj.getClass().getName() +

" due to execute security restrictions. ["

+ i.getLine() + "," + i.getColumn() + "]"

+ " in template " + i.getTemplateName()

+ ".");

return null;

}

Complete sample app available at:

http://jlamp.com/apachecon2004/

Page 26: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 26

Custom Introspector Example: Configuration

## Custom introspector

runtime.introspector.uberspect = com.jlamp.introspection.CustomIntrospector

## Load templates from classpath

resource.loader = class

class.resource.loader.class =

org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader

## Log messages displayed with log4j

runtime.log.logsystem.class = org.apache.velocity.runtime.log.SimpleLog4JLogSystem

runtime.log.logsystem.log4j.category = com.jlamp.velocity

Complete sample app available at:

http://jlamp.com/apachecon2004/

Page 27: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 27

Modifying Velocity Syntax

• Velocity Template Language (VTL) is specified in a grammar file

designed to be used with JavaCC (javacc.dev.java.net).

• Change the language syntax by editing Parser.jjt.

• Run jjtree and javacc to generate new Parser.java files

• Add new capabilities by creating new Node files and copying

into the package org.apache.velocity.runtime.parser.node

Page 28: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 28

Modifying Velocity Syntax: Adding #{else}

• Problem: Adding text without a space in #if statement is difficult.

• Bad syntax:#if($condition)text1#elsetext2#end

• Use block comments #* *# to split #else and text (unreadable)#if($condition)text1#else#**#text2#end

• Proposed syntax – use optional brackets around directive#if($condition)text1#{else}text2#end

Page 29: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 29

Modifying Velocity Syntax: Old Parser.jjt (excerpt)

<PRE_DIRECTIVE>

TOKEN :

{

<END: "end" ( ( " " | "\t" )* ( "\n" | "\r" | "\r\n" ) )? >

{

inDirective = false;

stateStackPop();

}

| <IF_DIRECTIVE: "if">

{

SwitchTo(DIRECTIVE);

}

| <ELSEIF_DIRECTIVE: "elseif">

{

SwitchTo(DIRECTIVE);

}

| <ELSE_DIRECTIVE: "else" ( ( " " | "\t" )* ( "\n" | "\r" | "\r\n" ) )? >

{

inDirective = false;

stateStackPop();

}

| <STOP_DIRECTIVE: "stop">

{

matchedToken.kind = EOF;

fileDepth = 0;

}

}

Full modification available as patch:

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=7189

Page 30: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 30

Modifying Velocity Syntax: Old Parser.jjt (excerpt)

<PRE_DIRECTIVE>

TOKEN :

{

<END: ( "end" ( ( " " | "\t" )* ( "\n" | "\r" | "\r\n" ) )? )

| ("{end}" ( ( " " | "\t" )* ( "\n" | "\r" | "\r\n" ) )? ) >

{

inDirective = false;

stateStackPop();

}

| <IF_DIRECTIVE: "if" | "{if}">

{

SwitchTo(DIRECTIVE);

}

| <ELSEIF_DIRECTIVE: "elseif" | "{elseif}">

{

SwitchTo(DIRECTIVE);

}

| <ELSE_DIRECTIVE:

( "else" ( ( " " | "\t" )* ( "\n" | "\r" | "\r\n" ) )? )

| ( "{else}" ( ( " " | "\t" )* ( "\n" | "\r" | "\r\n" ) )? ) > {

inDirective = false;

stateStackPop();

}

| <STOP_DIRECTIVE: "stop" | "{stop}" > {

matchedToken.kind = EOF;

fileDepth = 0;

} }

Complete sample app available at:

http://jlamp.com/apachecon2004/

Page 31: Hacking Velocity – ApacheCon 2004people.apache.org/~jim/ApacheCons/ApacheCon2004/pdf/WE05.pdf · Hacking Velocity – ApacheCon 2004 • What is Velocity • Velocity Tools •

November 17, 2004 (c) 2004 Will Glass-Husain. Non-commercial redistribution permitted freely. 31

Modifying Velocity Syntax: Summary of Steps

1. Download project "jakarta-velocity" from Jakarta CVS

2. Modify "Parser.jjt"

3. Execute shell script "build":

4. If necessary (new functionality added), add new node files topackage org.apache.velocity.runtime.parser.node.

#!/bin/sh

echo "Running JJTree ..."

jjtree Parser.jjt

echo "Running JavaCC ..."

javacc Parser.jj

# Remove the generated nodes as they are now

# in a package of their own.

rm -f AST*

rm -f Node.java

rm -f SimpleNode.java

rm -f ParserVisitor.java


Recommended