Package org.apache.commons.jexl2

Provides a framework for evaluating JEXL expressions.

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.
 

Package org.apache.commons.jexl2 Description

Provides a framework for evaluating JEXL expressions.

Introduction

JEXL is a library intended to facilitate the implementation of dynamic and scripting features in applications and frameworks.

A Brief Example

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);
        

Using JEXL

The API is composed of three levels addressing different functional needs:

Important note

The only public packages you should use are: The following packages follow a "use at your own maintenance cost" policy. Their classes and methods are not guaranteed to remain compatible in subsequent versions. If you think you need to use some of their features, it might be a good idea to check with the community through the mailing list first.

Dynamic invocation

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:

The following example illustrate their usage:
            // 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);
        

JEXL script expression

If your needs require simple expression evaluation capabilities, the core JEXL features will most likely fit. The main methods are:

The following example illustrates their usage:
            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);
        

UnifiedJEXL script expressions

If you are looking for JSP-EL like and basic templating features, you can use UnifiedJEXL.

The main methods are: The following example illustrates their usage:
            JexlEngine jexl = new JexlEngine();
            UnifiedJEXL ujexl = new UnifiedJEXL(jexl);
            UnifiedJEXL.Expression expr = ujexl.parse("Hello ${user}");
            String hello = expr.evaluate(context, expr).toString();
        

Expressions Script and UnifiedJEXL.Expression: differences

Expression

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.

Script

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.

UnifiedJEXL.Expression

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.

JEXL Configuration

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.

This can be used as in:

            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.

JEXL Customization

If you need to make JEXL treat some objects in a specialized manner or tweak how it reacts to some settings, you can derive most of its inner-workings.

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.



Copyright © 2001-2011 The Apache Software Foundation. All Rights Reserved.