Web Site

org.codehaus.janino
Class ExpressionEvaluator

java.lang.Object
  extended byorg.codehaus.janino.EvaluatorBase
      extended byorg.codehaus.janino.ExpressionEvaluator

public class ExpressionEvaluator
extends EvaluatorBase

An expression evaluator that evaluates expressions in JavaTM bytecode.

The syntax of the expression to compile is that of a JavaTM expression, as defined in the Java Language Specification, 2nd edition, section 15. Notice that a JavaTM expression does not have a concluding semicolon.

Example:

   a + 7 * b
 
(Notice that this expression refers to two parameters "a" and "b", as explained below.)

The expression may optionally be preceeded with a sequence of import directives like

   import java.text.*;
   new DecimalFormat("####,###.##").format(10200020.345345)
 
(Notice that the import directive is concluded with a semicolon, while the expression is not.)

The expression is compiled when the ExpressionEvaluator object is instantiated. The expression, its type, and its parameter names and types are specified at compile time.

The expression evaluator is implemented by creating and compiling a temporary compilation unit defining one class with one static method with one return statement.

After the ExpressionEvaluator object is created, the expression can be evaluated as often with different parameter values (see evaluate(Object[])). This evaluation is very fast, compared to the compilation.

The more elaborate constructors of ExpressionEvaluator also allow for the specification of the name of the generated class, the class it extends, the interfaces it implements, the name of the method that evaluates the expression, the exceptions that this method is allowed to throw, and the ClassLoader that is used to define the generated class and to load classes referenced by the expression. This degree of flexibility is usually not required; the most commonly used constructor is ExpressionEvaluator(String, Class, String[], Class[]).

Notice that for functionally identical ExpressionEvaluators, Object.equals(java.lang.Object) will return true. E.g. "a+b" and "c + d" are functionally identical if "a" and "c" have the same type, and so do "b" and "d".


Constructor Summary
ExpressionEvaluator(Scanner scanner, String className, Class optionalExtendedType, Class[] implementedTypes, boolean staticMethod, Class optionalExpressionType, String methodName, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, ClassLoader optionalParentClassLoader)
          Parse an expression from a sequence of Scanner.Tokens delivered by the given scanner and compile it.
ExpressionEvaluator(String expression, Class optionalExpressionType, String[] parameterNames, Class[] parameterTypes)
          Parse an expression from a String and compile it.
ExpressionEvaluator(String expression, Class optionalExpressionType, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, Class optionalExtendedType, Class[] implementedTypes, ClassLoader optionalParentClassLoader)
          Parse an expression from a String and compile it into a public static method "eval" with the given return and parameter types.
ExpressionEvaluator(String expression, Class optionalExpressionType, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, ClassLoader optionalParentClassLoader)
          Parse an expression from a String and compile it.
 
Method Summary
static Object createFastExpressionEvaluator(Scanner scanner, String className, Class optionalExtendedType, Class interfaceToImplement, String[] parameterNames, ClassLoader optionalParentClassLoader)
          Like createFastExpressionEvaluator(String, Class, String[], ClassLoader), but gives you more control over the generated class (rarely needed in practice).
static Object createFastExpressionEvaluator(String expression, Class interfaceToImplement, String[] parameterNames, ClassLoader optionalClassLoader)
          If the parameter and return types of the expression are known at compile time, then a "fast" expression evaluator can be instantiated through this method.
 Object evaluate(Object[] parameterValues)
          Evaluates an expression with concrete parameter values.
 Method getMethod()
          If, for any reason, somebody needs the Method object...
 
Methods inherited from class org.codehaus.janino.EvaluatorBase
addClassMethodBlockDeclaration, addPackageMemberClassDeclaration, classesToTypes, classToType, compileAndLoad, compileAndLoad, makeFormalParameters, parseImportDeclarations
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

ExpressionEvaluator

public ExpressionEvaluator(String expression,
                           Class optionalExpressionType,
                           String[] parameterNames,
                           Class[] parameterTypes)
                    throws CompileException,
                           Parser.ParseException,
                           Scanner.ScanException
Parse an expression from a String and compile it.

The expression must not throw any Exceptions other than RuntimeException.

See Also:
ExpressionEvaluator(Scanner, String, Class, Class[], boolean, Class, String, String[], Class[], Class[], ClassLoader)

ExpressionEvaluator

public ExpressionEvaluator(String expression,
                           Class optionalExpressionType,
                           String[] parameterNames,
                           Class[] parameterTypes,
                           Class[] thrownExceptions,
                           ClassLoader optionalParentClassLoader)
                    throws CompileException,
                           Parser.ParseException,
                           Scanner.ScanException
Parse an expression from a String and compile it.

See Also:
ExpressionEvaluator(Scanner, String, Class, Class[], boolean, Class, String, String[], Class[], Class[], ClassLoader)

ExpressionEvaluator

public ExpressionEvaluator(String expression,
                           Class optionalExpressionType,
                           String[] parameterNames,
                           Class[] parameterTypes,
                           Class[] thrownExceptions,
                           Class optionalExtendedType,
                           Class[] implementedTypes,
                           ClassLoader optionalParentClassLoader)
                    throws CompileException,
                           Parser.ParseException,
                           Scanner.ScanException
Parse an expression from a String and compile it into a public static method "eval" with the given return and parameter types.

See Also:
ExpressionEvaluator(Scanner, String, Class, Class[], boolean, Class, String, String[], Class[], Class[], ClassLoader)

ExpressionEvaluator

public ExpressionEvaluator(Scanner scanner,
                           String className,
                           Class optionalExtendedType,
                           Class[] implementedTypes,
                           boolean staticMethod,
                           Class optionalExpressionType,
                           String methodName,
                           String[] parameterNames,
                           Class[] parameterTypes,
                           Class[] thrownExceptions,
                           ClassLoader optionalParentClassLoader)
                    throws Scanner.ScanException,
                           Parser.ParseException,
                           CompileException,
                           IOException
Parse an expression from a sequence of Scanner.Tokens delivered by the given scanner and compile it.

The expression may refer to a set of parameters with the given parameterNames and parameterTypes.

parameterNames and parameterTypes must have the same number of elements.

The parameters and/or the return value can be of primitive type, e.g. Double.TYPE.

The optionalClassLoader serves two purposes:

If the optionalClassLoader is null, then the current thread's context class loader is used.

A number of constructors exist that provide useful default values for the various parameters, or parse their script from a String instead of a Scanner. (You hardly want to use a scanner other than the default scanner.)

If the type of the expression is not fixed, you can pass a null optionalExpressionType argument; in this case, references are returned as Objects, and primitive values are wrapped in their wrapper classes.

If optionalExpressionType is Void.TYPE, then the expression must be an invocation of a void method.

Parameters:
scanner - Source of tokens to parse
className - The name of the temporary class (uncritical)
optionalExtendedType - The base class of the generated object or null
implementedTypes - The interfaces that the the generated object implements (all methods must be implemented by the optionalExtendedType)
staticMethod - Whether the generated method should be declared "static"
optionalExpressionType - The type of the expression, e.g. Double.TYPE, double.class, String.class, Void.TYPE, or null.
methodName - The name of the temporary method (uncritical)
parameterNames - The names of the expression parameters, e.g. "i" and "j".
parameterTypes - The types of the expression parameters, e.g. Integer.TYPE, Writer.class or Double.TYPE.
thrownExceptions - The exceptions that the expression is allowed to throw, e.g. IOException.class.
optionalParentClassLoader - Loads referenced classes
Method Detail

createFastExpressionEvaluator

public static Object createFastExpressionEvaluator(String expression,
                                                   Class interfaceToImplement,
                                                   String[] parameterNames,
                                                   ClassLoader optionalClassLoader)
                                            throws CompileException,
                                                   Parser.ParseException,
                                                   Scanner.ScanException
If the parameter and return types of the expression are known at compile time, then a "fast" expression evaluator can be instantiated through this method.

Expression evaluation is faster than through evaluate(Object[]), because it is not done through reflection but through direct method invocation.

Example:

 public interface Foo {
     int bar(int a, int b);
 }
 ...
 Foo f = (Foo) ExpressionEvaluator.createFastExpressionEvaluator(
     "a + b",                    // expression to evaluate
     Foo.class,                  // interface that describes the expression's signature
     new String[] { "a", "b" },  // the parameters' names
     (ClassLoader) null          // Use current thread's context class loader
 );
 System.out.println("1 + 2 = " + f.bar(1, 2)); // Evaluate the expression
 
Notice: The interfaceToImplement must either be declared public, or with package scope in the root package (i.e. "no" package).

On my system (Intel P4, 2 GHz, MS Windows XP, JDK 1.4.1), expression "x + 1" evaluates as follows:

Server JVMClient JVM
Normal EE23.7 ns64.0 ns
Fast EE31.2 ns42.2 ns
(How can it be that interface method invocation is slower than reflection for the server JVM?)

Parameters:
expression - Uses the parameters of the method declared by "interfaceToImplement"
interfaceToImplement - Must declare exactly one method
parameterNames - The expression references the parameters through these names
optionalClassLoader -
Returns:
an object that implements the given interface
Throws:
CompileException
Parser.ParseException
Scanner.ScanException

createFastExpressionEvaluator

public static Object createFastExpressionEvaluator(Scanner scanner,
                                                   String className,
                                                   Class optionalExtendedType,
                                                   Class interfaceToImplement,
                                                   String[] parameterNames,
                                                   ClassLoader optionalParentClassLoader)
                                            throws CompileException,
                                                   Parser.ParseException,
                                                   Scanner.ScanException,
                                                   IOException
Like createFastExpressionEvaluator(String, Class, String[], ClassLoader), but gives you more control over the generated class (rarely needed in practice).

Notice: The interfaceToImplement must either be declared public, or with package scope in the same package as className.

Parameters:
scanner - Source of expression tokens
className - Name of generated class
optionalExtendedType - Class to extend
interfaceToImplement - Must declare exactly the one method that defines the expression's signature
parameterNames - The expression references the parameters through these names
optionalParentClassLoader - Loads referenced classes
Returns:
an object that implements the given interface and extends the optionalExtendedType
Throws:
CompileException
Parser.ParseException
Scanner.ScanException
IOException

evaluate

public Object evaluate(Object[] parameterValues)
                throws InvocationTargetException
Evaluates an expression with concrete parameter values.

Each parameter value must have the same type as specified through the "parameterTypes" parameter of ExpressionEvaluator(String, Class, String[], Class[], Class[], ClassLoader).

Parameters of primitive type must passed with their wrapper class objects.

The object returned has the class specified through the "returnType" parameter of ExpressionEvaluator(String, Class, String[], Class[], Class[], ClassLoader). If the "returnType" is primitive (e.g. "int.class"), the return value is returned through a wrapper object ("Integer").

Parameters:
parameterValues - The concrete parameter values.
Throws:
InvocationTargetException

getMethod

public Method getMethod()
If, for any reason, somebody needs the Method object...


Web Site