Jose,
Could a wrapper around the objects you are placing at the
context be a solution?
Since Velocity can use a class with a get() method like:
class MyWrapper
{ private Object theWrappedObject;
public MyWrapper(Object anObjectToWrap)
{ super();
theWrappedObject = anObjectToWrap;
...
}
public Object get(String name)
{
...
}
}
calling
get("somevalue")
for an in-template
$escapedObject.somevalue
The wrapper class could use some introspection in the get()
method (in a similar way to what Velocity usually does) in
order to introspect the wrapped object, get the value for
its "somevalue" property, convert it into a string and
escape it, giving it back to Velocity.
So, you would place the objects which have values to escape
using something like:
myContext.put("escapedObject", new MyWrapper(myOriginalObject));
Of course that, if ALL your objects need to be escaped, you
could also derive a new version of context that does just that.
For escaping simple values, like in
$simple
you can just convert them to an escaped String just when putting
them in the context, with some method like:
String escapeObject(Object obj)
{ return (null == obj) ? "" : escape(obj.toString());
}
and then
myContext.put("simple", MyUtils.escapeObject(simpleObject));
Of course that you could create a VelocityContext descendent with
new methods like:
public void putSimple(String name, Object value)
that would make this last simple escaping and then use the
inherited put(), and like
public void putWrap(String name, Object value)
that would do the wrapping thing I first talked about.
And, of course, you are still in trouble if you use things like:
$more.levels.toget.it
But if these cases are just 10% of the thing, you might allow
them to go like:
$tool.escape($more.levels.toget.it)
=:o)
All this looks simpler to me than tell the template engine when
to behave different (although an listener/escaper could be passed
through the context).
Have fun,
Paulo Gaspar