|
||||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
See:
Description
Interface Summary | |
---|---|
Expression | Represents a single JEXL expression. |
JexlContext | Manages variables which can be referenced in a JEXL expression. |
JexlInfo | Interface for objects carrying information usefull to debugging. |
NamespaceResolver | This interface declares how to resolve a namespace from its name; it is used by the interpreter during evalutation. |
Script | A JEXL Script. |
Class Summary | |
---|---|
DebugInfo | Helper class to carry in info such as a url/file name, line and column for debugging information reporting. |
ExpressionImpl | Instances of ExpressionImpl are created by the JexlEngine ,
and this is the default implementation of the Expression and
Script interface. |
Interpreter | An interpreter of JEXL syntax. |
JexlArithmetic | Perform arithmetic. |
JexlEngine | Creates and evaluates Expression and Script objects. |
JexlEngine.Frame | A call frame, created from a scope, stores the arguments and local variables as "registers". |
JexlEngine.Scope | A script scope, stores the declaration of parameters and local variables. |
JexlThreadedArithmetic | A derived arithmetic that allows different threads to operate with different strict/lenient/math modes using the same JexlEngine. |
Main | Test application for JEXL. |
MapContext | Wraps a map in a context. |
ObjectContext<T> | Wraps an Object as a Jexl context. |
ReadonlyContext | A readonly context wrapper. |
UnifiedJEXL | An evaluator similar to the Unified EL evaluator used in JSP/JSF based on JEXL. |
Exception Summary | |
---|---|
JexlException | Wraps any error that might occur during interpretation of a script or expression. |
JexlException.Cancel | Thrown to cancel a script execution. |
JexlException.Method | Thrown when a method or ctor is unknown, ambiguous or inaccessible. |
JexlException.Parsing | Thrown when parsing fails. |
JexlException.Property | Thrown when a property is unknown. |
JexlException.Return | Thrown to return a value. |
JexlException.Tokenization | Thrown when tokenization fails. |
JexlException.Variable | Thrown when a variable is unknown. |
UnifiedJEXL.Exception | The sole type of (runtime) exception the UnifiedJEXL can throw. |
Provides a framework for evaluating JEXL expressions.
JEXL is a library intended to facilitate the implementation of dynamic and scripting features in applications and frameworks.
When evaluating expressions, JEXL merges an
Expression
with a
JexlContext
.
An Expression is created using
JexlEngine.createExpression(java.lang.String)
,
passing a String containing valid JEXL syntax. A simple JexlContext can be created using
a MapContext
instance;
a map of variables that will be internally wrapped can be optionally provided through its constructor.
The following example, takes a variable named foo, and
invokes the bar() method on the property innerFoo:
// Create a JexlEngine (could reuse one instead) JexlEngine jexl = new JexlEngine(); // Create an expression object String jexlExp = "foo.innerFoo.bar()"; Expression e = jexl.createExpression( jexlExp ); // Create a context and add data JexlContext jc = new MapContext(); jc.set("foo", new Foo() ); // Now evaluate the expression, getting the result Object o = e.evaluate(jc);
These functionalities are close to the core level utilities found in BeanUtils. For basic dynamic property manipulations and method invocation, you can use the following set of methods:
JexlEngine.newInstance(java.lang.Class extends T>, java.lang.Object...)
JexlEngine.setProperty(java.lang.Object, java.lang.String, java.lang.Object)
JexlEngine.getProperty(java.lang.Object, java.lang.String)
JexlEngine.invokeMethod(java.lang.Object, java.lang.String, java.lang.Object...)
// test outer class public static class Froboz { int value; public Froboz(int v) { value = v; } public void setValue(int v) { value = v; } public int getValue() { return value; } } // test inner class public static class Quux { String str; Froboz froboz; public Quux(String str, int fro) { this.str = str; froboz = new Froboz(fro); } public Froboz getFroboz() { return froboz; } public void setFroboz(Froboz froboz) { this.froboz = froboz; } public String getStr() { return str; } public void setStr(String str) { this.str = str; } } // test API JexlEngine jexl = nex JexlEngine(); Quux quux = jexl.newInstance(Quux.class, "xuuq", 100); jexl.setProperty(quux, "froboz.value", Integer.valueOf(100)); Object o = jexl.getProperty(quux, "froboz.value"); assertEquals("Result is not 100", new Integer(100), o); jexl.setProperty(quux, "['froboz'].value", Integer.valueOf(1000)); o = jexl.getProperty(quux, "['froboz']['value']"); assertEquals("Result is not 1000", new Integer(1000), o);
If your needs require simple expression evaluation capabilities, the core JEXL features will most likely fit. The main methods are:
JexlEngine.createExpression(org.apache.commons.jexl2.parser.ASTJexlScript, java.lang.String)
JexlEngine.createScript(java.lang.String)
Expression.evaluate(org.apache.commons.jexl2.JexlContext)
JexlEngine jexl = nex JexlEngine(); JexlContext jc = new MapContext(); jc.set("quuxClass", quux.class); Expression create = jexl.createExpression("quux = new(quuxClass, 'xuuq', 100)"); Expression assign = jexl.createExpression("quux.froboz.value = 10"); Expression check = jexl.createExpression("quux[\"froboz\"].value"); Quux quux = (Quux) create.evaluate(jc); Object o = assign.evaluate(jc); assertEquals("Result is not 10", new Integer(10), o); o = check.evaluate(jc); assertEquals("Result is not 10", new Integer(10), o);
If you are looking for JSP-EL like and basic templating features, you can use UnifiedJEXL.
The main methods are:UnifiedJEXL.parse(java.lang.String)
UnifiedJEXL.Expression.evaluate(org.apache.commons.jexl2.JexlContext)
UnifiedJEXL.Expression.prepare(org.apache.commons.jexl2.JexlContext)
JexlEngine jexl = new JexlEngine(); UnifiedJEXL ujexl = new UnifiedJEXL(jexl); UnifiedJEXL.Expression expr = ujexl.parse("Hello ${user}"); String hello = expr.evaluate(context, expr).toString();
This only allows for a single command to be executed and the result from that is returned. If you try to use multiple commands it ignores everything after the first semi-colon and just returns the result from the first command.
This allows you to put multiple commands in the expression and you can use variable assignments, loops, calculations, etc. The result from the last command is returned from the script.
This is ideal to produce text. To get a calculation you use the EL-like syntax as in ${someVariable}. The expression that goes between the brackets behaves like a script, not an expression. You can use semi-colons to execute multiple commands and the result from the last command is returned from the script. You also have the ability to use a 2-pass evaluation using the #{someScript} syntax.
The JexlEngine can be configured through a few parameters that will drive how it reacts in case of errors. These configuration methods are best called at JEXL engine initialization time; it is recommended to derive from JexlEngine to call those in a constructor.
JexlEngine.setLenient(boolean)
configures when JEXL considers 'null' as an error or not in various situations;
when facing an unreferenceable variable, using null as an argument to an arithmetic operator or failing to call
a method or constructor. The lenient mode is close to JEXL-1.1 behavior.
JexlEngine.setSilent(boolean)
configures how JEXL reacts to errors; if silent, the engine will not throw exceptions
but will warn through loggers and return null in case of errors. Note that when non-silent, JEXL throws
JexlException which are unchecked exception.
JexlEngine.setDebug(boolean)
makes stacktraces carried by JExlException more meaningfull; in particular, these
traces will carry the exact caller location the Expression was created from.
JexlEngine.setClassLoader(java.lang.ClassLoader)
indicates to a JexlEngine which class loader to use to solve a class name; this affects
how JexlEngine.newInstance and the 'new' script method operates. This is mostly usefull in cases where
you rely on JEXL to dynamically load and call plugins for your application.
JexlEngine and UnifiedJEXL expression caches can be configured as well. If you intend to use JEXL repeatedly in your application, these are worth configuring since expression parsing is quite heavy. Note that all caches created by JEXL are held through SoftReference; under high memory pressure, the GC will be able to reclaim those caches and JEXL will rebuild them if needed. By default, a JexlEngine does not create a cache whilst UnifiedJEXL does.
Both JexlEngine and UnifiedJEXL are thread-safe; the same instance can be shared between different threads and proper synchronization is enforced in critical areas.
JexlEngine.setCache(int)
will set how many expressions can be simultaneously cached by the
JEXL engine. UnifiedJEXL allows to define the cache size through its constructor.
JexlEngine.setFunctions(java.util.Map
extends JEXL scripting by registering functions in
namespaces.
public static MyMath {
public double cos(double x) {
return Math.cos(x);
}
}
Map<String, Object> funcs = new HashMap<String, Object>();
funcs.put("math", new MyMath());
JexlEngine jexl = new JexlEngine();
jexl.setFunctions(funcs);
JexlContext jc = new MapContext();
jc.set("pi", Math.PI);
e = JEXL.createExpression("math:cos(pi)");
o = e.evaluate(jc);
assertEquals(Double.valueOf(-1),o);
If the namespace is a Class and that class declares a constructor that takes a JexlContext (or
a class extending JexlContext), one namespace instance is created on first usage in an
expression; this instance lifetime is limited to the expression evaluation.
JexlEngine
is meant to be
extended and lets you capture your own configuration defaults wrt cache sizes and various flags.
Implementing your own cache - instead of the basic LinkedHashMap based one - would be
another possible extension.
JexlArithmetic
is the class to derive if you need to change how operators behave. For example, this would
be the case if you wanted '+' to operate on arrays; you'd need to derive JexlArithmetic and
implement your own version of Add.
Interpreter
is the class to derive if you need to add more features to the evaluation
itself; for instance, you want pre- and post- resolvers for variables or nested scopes for
for variable contexts or add factory based support to the 'new' operator.
UberspectImpl
is the class to derive if you need to add introspection or reflection capabilities for some objects.
The code already reflects public fields as properties on top of Java-beans conventions.
|
||||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |