Interface IExpressionEvaluator
-
- All Superinterfaces:
ICookable
,IMultiCookable
- All Known Implementing Classes:
ExpressionEvaluator
,ExpressionEvaluator
public interface IExpressionEvaluator extends ICookable, IMultiCookable
An engine that evaluates expressions in JVM bytecode.The syntax of the expression to compile is that of a Java expression, as defined in JLS7, section 15. Notice that a Java 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.) This feature is not available if you compile many expressions at a time (see below).
To set up an
IExpressionEvaluator
object, proceed as follows:- Create an
IExpressionEvaluator
-derived class - Configure the
IExpressionEvaluator
by calling any of the following methods: setExpressionType(Class)
setParameters(String[], Class[])
setThrownExceptions(Class[])
setParentClassLoader(ClassLoader)
setDefaultImports(String[])
-
Call any of the
ICookable.cook(String, java.io.Reader)
methods to scan, parse, compile and load the expression into the JVM.
After the
IExpressionEvaluator
object is set up, the expression can be evaluated as often with different parameter values (seeevaluate(Object[])
). This evaluation is very fast, compared to the compilation.Less common methods exist that 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 executes the expression, the exceptions that this method (i.e. the expression) is allowed to throw, and the
ClassLoader
that is used to define the generated class and to load classes referenced by the expression.If you want to compile many expressions at the same time, you have the option to cook an array of expressions in one
IExpressionEvaluator
by using the following methods:setMethodNames(String[])
setParameters(String[][], Class[][])
setExpressionTypes(Class[])
setStaticMethod(boolean[])
setThrownExceptions(Class[][])
IMultiCookable.cook(String[], Reader[])
evaluate(int, Object[])
Notice that these methods have array parameters in contrast to their one-expression brethren.
Notice that for functionally identical
IExpressionEvaluator
s,Object.equals(java.lang.Object)
will returntrue
. E.g. "a+b" and "c + d" are functionally identical if "a" and "c" have the same type, and so do "b" and "d".'JLS7' refers to the Java Language Specification, Java SE 7 Edition.
-
-
Field Summary
Fields Modifier and Type Field Description static java.lang.Class<?>
ANY_TYPE
Deprecated.Since autoboxing was introduced in JANINO, this feature is no longer necessary because you can use expression typeObject
.class
static java.lang.String
DEFAULT_CLASS_NAME
The fully qualified name of the generated class, iff not reconfigured bysetClassName(String)
.static java.lang.Class<?>
DEFAULT_EXPRESSION_TYPE
The type of all expressions that were not reconfigured withsetExpressionTypes(Class[])
.
-
Method Summary
All Methods Instance Methods Abstract Methods Deprecated Methods Modifier and Type Method Description <T> T
createFastEvaluator(java.io.Reader reader, java.lang.Class<? extends T> interfaceToImplement, java.lang.String... parameterNames)
<T> T
createFastEvaluator(java.lang.String expression, java.lang.Class<? extends T> interfaceToImplement, java.lang.String... parameterNames)
If the parameter and return types of the expression are known at compile time, then a "fast" expression evaluator can be instantiated throughcreateFastEvaluator(String, Class, String[])
.java.lang.Object
evaluate()
Shorthand forevaluate
(new Object[0])
.java.lang.Object
evaluate(int idx, java.lang.Object[] arguments)
Same asevaluate(Object[])
, but for multiple expressions.java.lang.Object
evaluate(java.lang.Object[] arguments)
Evaluates the expression with concrete parameter values.java.lang.Class<?>
getClazz()
java.lang.Class<?>
getDefaultExpressionType()
java.lang.String[]
getDefaultImports()
java.lang.reflect.Method
getMethod()
java.lang.reflect.Method
getMethod(int idx)
Same asgetMethod()
, but for multiple expressions.java.lang.reflect.Method[]
getResult()
void
setClassName(java.lang.String className)
Sets the name of the generated class.void
setCompileErrorHandler(ErrorHandler compileErrorHandler)
Installs anErrorHandler
which is invoked during compilation on each error.void
setDebuggingInformation(boolean debugSource, boolean debugLines, boolean debugVars)
Determines what kind of debugging information is included in the generates classes.void
setDefaultExpressionType(java.lang.Class<?> defaultExpressionType)
Reconfigures the "default expression type"; if no expression type is configured for an expression, then, when cooking thisIExpressionEvaluator
, the "default expression type" is used for the expressionvoid
setDefaultImports(java.lang.String... defaultImports)
"Default imports" add to the system import "java.lang", i.e. the evaluator may refer to classes imported by default imports without having to explicitly declare IMPORT statements.void
setExpressionType(java.lang.Class<?> expressionType)
Defines the type of the expression.void
setExpressionTypes(java.lang.Class<?>[] expressionTypes)
Configures the types of the expressions.void
setExtendedClass(java.lang.Class<?> extendedType)
Sets a particular superclass that the generated class will extend.void
setImplementedInterfaces(java.lang.Class<?>[] implementedTypes)
Configures the interfaces that the generated class implements.void
setMethodName(java.lang.String methodName)
Defines the name of the generated method.void
setMethodNames(java.lang.String[] methodNames)
Same assetMethodName(String)
, but for multiple expressions.void
setOverrideMethod(boolean overrideMethod)
Defines whether the generated method overrides a methods declared in a supertype.void
setOverrideMethod(boolean[] overrideMethod)
Same assetOverrideMethod(boolean)
, but for multiple expressions.void
setParameters(java.lang.String[][] parameterNames, java.lang.Class<?>[][] parameterTypes)
Same assetParameters(String[], Class[])
, but for multiple expressions.void
setParameters(java.lang.String[] parameterNames, java.lang.Class<?>[] parameterTypes)
Defines the names and types of the parameters of the generated method.void
setParentClassLoader(java.lang.ClassLoader parentClassLoader)
The "parent class loader" is used to load referenced classes.void
setReturnType(java.lang.Class<?> returnType)
Deprecated.UsesetExpressionType(Class)
insteadvoid
setStaticMethod(boolean staticMethod)
Defines whether the generated method should be STATIC or not.void
setStaticMethod(boolean[] staticMethod)
Same assetStaticMethod(boolean)
, but for multiple expressions.void
setThrownExceptions(java.lang.Class<?>[] thrownExceptions)
Defines the exceptions that the generated method may throw.void
setThrownExceptions(java.lang.Class<?>[][] thrownExceptions)
Same assetThrownExceptions(Class[])
, but for multiple expressions.void
setWarningHandler(WarningHandler warningHandler)
By default, warnings are discarded, but an application my install a customWarningHandler
.
-
-
-
Field Detail
-
DEFAULT_CLASS_NAME
static final java.lang.String DEFAULT_CLASS_NAME
The fully qualified name of the generated class, iff not reconfigured bysetClassName(String)
.- See Also:
- Constant Field Values
-
DEFAULT_EXPRESSION_TYPE
static final java.lang.Class<?> DEFAULT_EXPRESSION_TYPE
The type of all expressions that were not reconfigured withsetExpressionTypes(Class[])
.
-
ANY_TYPE
@Deprecated static final java.lang.Class<?> ANY_TYPE
Deprecated.Since autoboxing was introduced in JANINO, this feature is no longer necessary because you can use expression typeObject
.class
Special value forsetExpressionType(Class)
that indicates that the expression may have any type.
-
-
Method Detail
-
setParentClassLoader
void setParentClassLoader(@Nullable java.lang.ClassLoader parentClassLoader)
The "parent class loader" is used to load referenced classes. Useful values are:System.getSystemClassLoader()
The running JVM's class path Thread.currentThread().getContextClassLoader()
ornull
The class loader effective for the invoking thread ClassLoaders.BOOTCLASSPATH_CLASS_LOADER
The running JVM's boot class path The parent class loader defaults to the current thread's context class loader.
-
setDebuggingInformation
void setDebuggingInformation(boolean debugSource, boolean debugLines, boolean debugVars)
Determines what kind of debugging information is included in the generates classes. The default is typically "-g:none
".
-
setCompileErrorHandler
void setCompileErrorHandler(@Nullable ErrorHandler compileErrorHandler)
Installs anErrorHandler
which is invoked during compilation on each error. (By default, the compilation throws aCompileException
on the first error and terminates.)If the given
ErrorHandler
throws aCompileException
, then the compilation terminates and the exception is propagated.If the given
ErrorHandler
does not throw aCompileException
but completes normally, then the compilation may or may not continue, depending on the error. Iff the compilation completes normally but errors were reported, then it will throw aCompileException
indicating the number of errors.In other words: The
ErrorHandler
may throw aCompileException
or not, but the compilation will definitely throw aCompileException
if one or more compile errors have occurred.- Parameters:
compileErrorHandler
-null
to restore the default behavior (throwing aCompileException
)
-
setWarningHandler
void setWarningHandler(@Nullable WarningHandler warningHandler)
By default, warnings are discarded, but an application my install a customWarningHandler
.- Parameters:
warningHandler
-null
to indicate that no warnings be issued
-
evaluate
@Nullable java.lang.Object evaluate() throws java.lang.reflect.InvocationTargetException
Shorthand forevaluate
(new Object[0])
.- Throws:
java.lang.reflect.InvocationTargetException
-
evaluate
@Nullable java.lang.Object evaluate(@Nullable java.lang.Object[] arguments) throws java.lang.reflect.InvocationTargetException
Evaluates the expression with concrete parameter values.Each argument value must have the same type as specified through the "parameterTypes" parameter of
setParameters(String[], Class[])
.Arguments of primitive type must passed with their wrapper class objects.
The object returned has the class as specified through
setExpressionType(Class)
.This method is thread-safe.
Null
arguments is equivalent withnew Object[0]
.Notice: In version 3.1.8, the arguments parameter was changed from
Object[]
toObject...
, which turned out to be a really bad decision because it caused a very ugly invocation ambiguity withevaluate(int, Object[])
. Thus, with version 3.1.10, the parameter was changed back toObject[]
.- Parameters:
arguments
- The actual parameter values- Throws:
java.lang.reflect.InvocationTargetException
-
setDefaultExpressionType
void setDefaultExpressionType(java.lang.Class<?> defaultExpressionType)
Reconfigures the "default expression type"; if no expression type is configured for an expression, then, when cooking thisIExpressionEvaluator
, the "default expression type" is used for the expression
-
getDefaultExpressionType
java.lang.Class<?> getDefaultExpressionType()
- Returns:
- The currently configured "default expression type"
- See Also:
setDefaultExpressionType(Class)
-
setImplementedInterfaces
void setImplementedInterfaces(java.lang.Class<?>[] implementedTypes)
Configures the interfaces that the generated class implements.
-
setReturnType
@Deprecated void setReturnType(@Deprecated java.lang.Class<?> returnType)
Deprecated.UsesetExpressionType(Class)
instead
-
setExpressionType
void setExpressionType(java.lang.Class<?> expressionType)
Defines the type of the expression.Defaults to
Object
.class
, which, thanks to autoboxing, allows for any expression type (including primitive types).If
expressionType
isvoid.class
, then the expression must be an invocation of avoid
method.
-
setExpressionTypes
void setExpressionTypes(java.lang.Class<?>[] expressionTypes)
Configures the types of the expressions.Unless this method is called, all expressions have type
Object
.class
.If any expression has type
void.class
, then it must be an invocation of avoid
method.
-
setOverrideMethod
void setOverrideMethod(boolean overrideMethod)
Defines whether the generated method overrides a methods declared in a supertype.
-
setOverrideMethod
void setOverrideMethod(boolean[] overrideMethod)
Same assetOverrideMethod(boolean)
, but for multiple expressions.
-
setParameters
void setParameters(java.lang.String[] parameterNames, java.lang.Class<?>[] parameterTypes)
Defines the names and types of the parameters of the generated method.names
.length
and types.length
must be equal. This invariant may be checked immediately, or later when the expression is cooked.The parameters can be of primitive type, e.g.
double.class
.The default is to have zero parameters.
-
setParameters
void setParameters(java.lang.String[][] parameterNames, java.lang.Class<?>[][] parameterTypes)
Same assetParameters(String[], Class[])
, but for multiple expressions.
-
setClassName
void setClassName(java.lang.String className)
Sets the name of the generated class. Defaults toDEFAULT_CLASS_NAME
. In most cases, there is no need to set this name, because the generated class is loaded into its ownClassLoader
where its name cannot collide with classes generated by other evaluators.One reason to use this function is to have a class name in a non-default package, which can be relevant when types and members with DEFAULT accessibility are accessed.
-
setExtendedClass
void setExtendedClass(java.lang.Class<?> extendedType)
Sets a particular superclass that the generated class will extend. If extendedClass isnull
, the generated class will extendObject
.The usual reason to set a base class for an evaluator is that the generated class can directly access the superclass's (non-private) members.
-
setDefaultImports
void setDefaultImports(java.lang.String... defaultImports)
"Default imports" add to the system import "java.lang", i.e. the evaluator may refer to classes imported by default imports without having to explicitly declare IMPORT statements.Notice that JDK 5 "static imports" are also supported, as shown here:
sc.setDefaultImports( "java.util.Map", // Single type import "java.io.*", // Type-import-on-demand "static java.util.Collections.EMPTY_MAP", // Single static import "static java.util.Collections.*", // Static-import-on-demand );
-
getDefaultImports
java.lang.String[] getDefaultImports()
- Returns:
- The default imports that were previously configured with
setDefaultImports(String...)
-
setStaticMethod
void setStaticMethod(boolean staticMethod)
Defines whether the generated method should be STATIC or not. Defaults totrue
.
-
setStaticMethod
void setStaticMethod(boolean[] staticMethod)
Same assetStaticMethod(boolean)
, but for multiple expressions.
-
setMethodName
void setMethodName(java.lang.String methodName)
Defines the name of the generated method. Initially, the method name is "eval*".- Parameters:
methodName
-null
means reset to default name- See Also:
IScriptEvaluator.DEFAULT_METHOD_NAME
-
setMethodNames
void setMethodNames(java.lang.String[] methodNames)
Same assetMethodName(String)
, but for multiple expressions.Define the names of the generated methods. By default the methods have distinct and implementation-specific names.
If two expressions have the same name, then they must have different parameter types (see
setParameters(String[][], Class[][])
).
-
setThrownExceptions
void setThrownExceptions(java.lang.Class<?>[] thrownExceptions)
Defines the exceptions that the generated method may throw.
-
setThrownExceptions
void setThrownExceptions(java.lang.Class<?>[][] thrownExceptions)
Same assetThrownExceptions(Class[])
, but for multiple expressions.
-
evaluate
@Nullable java.lang.Object evaluate(int idx, @Nullable java.lang.Object[] arguments) throws java.lang.reflect.InvocationTargetException
Same asevaluate(Object[])
, but for multiple expressions.Notice: In version 3.1.8, the arguments parameter was changed from
Object[]
toObject...
, which turned out to be a really bad decision because it caused a very ugly invocation ambiguity withevaluate(int, Object[])
. Thus, with version 3.1.10, the parameter was changed back toObject[]
.- Throws:
java.lang.reflect.InvocationTargetException
-
createFastEvaluator
<T> T createFastEvaluator(java.lang.String expression, java.lang.Class<? extends T> interfaceToImplement, java.lang.String... parameterNames) throws CompileException
If the parameter and return types of the expression are known at compile time, then a "fast" expression evaluator can be instantiated throughcreateFastEvaluator(String, Class, String[])
. Expression evaluation is faster than throughevaluate(Object[])
, because it is not done through reflection but through direct method invocation.Example:
public interface Foo { int bar(int a, int b); } ... ExpressionEvaluator ee = CompilerFactoryFactory.getDefaultCompilerFactory().newExpressionEvaluator(); // Optionally configure the EE here... ee.
setClassName
("Bar"); ee.setDefaultImports
(new String[] { "java.util.*" }); ee.setExtendedClass
(SomeOtherClass.class); ee.setParentClassLoader
(someClassLoader); // Optionally configure the EE here... Foo f = (Foo) ee.createFastEvaluator( "a + b", // expression to evaluate Foo.class, // interface that describes the expression's signature new String[] { "a", "b" } // the parameters' names ); System.out.println("1 + 2 = " + f.bar(1, 2)); // Evaluate the expressionAll other configuration (implemented type, static method, return type, method name, parameter names and types, thrown exceptions) are predetermined by the interfaceToImplement.
Notice: The
interfaceToImplement
must be accessible by the compiled class, i.e. either be declaredpublic
, or withprotected
or default access in the package of the compiled class (seesetClassName(String)
.- Throws:
CompileException
-
createFastEvaluator
<T> T createFastEvaluator(java.io.Reader reader, java.lang.Class<? extends T> interfaceToImplement, java.lang.String... parameterNames) throws CompileException, java.io.IOException
- Throws:
CompileException
java.io.IOException
- See Also:
createFastEvaluator(String, Class, String[])
-
getMethod
java.lang.reflect.Method getMethod()
- Returns:
- The generated and loaded
Method
- Throws:
java.lang.IllegalStateException
- This IExpressionEvaluator is not yet cooked
-
getMethod
java.lang.reflect.Method getMethod(int idx)
Same asgetMethod()
, but for multiple expressions.
-
getClazz
java.lang.Class<?> getClazz()
- Returns:
- The generated
Class
- Throws:
java.lang.IllegalStateException
- ThisIClassBodyEvaluator
is not yet cooked
-
getResult
java.lang.reflect.Method[] getResult()
- Returns:
- The generated and loaded methods that implement the cooked expressions
- Throws:
java.lang.IllegalStateException
- ThisIScriptEvaluator
is not yet cooked
-
-