org.codehaus.janino
public class ScriptEvaluator extends ClassBodyEvaluator
The syntax of the script to compile is a sequence of import declarations (not allowed if you compile many scripts at a time, see below) followed by a sequence of statements, as defined in the Java Language Specification, 2nd edition, sections 7.5 and 14.
Example:
import java.text.*; System.out.println("HELLO"); System.out.println(new DecimalFormat("####,###.##").format(a));(Notice that this expression refers to a parameter "a", as explained below.)
The script may complete abnormally, e.g. through a RETURN statement:
if (a == null) { System.out.println("Oops!"); return; }Optionally, the script may be declared with a non-void return type. In this case, the last statement of the script must be a RETURN statement (or a THROW statement), and all RETURN statements in the script must return a value with the given type.
The script evaluator is implemented by creating and compiling a temporary compilation unit defining one class with one method the body of which consists of the statements of the script.
To set up a ScriptEvaluator object, proceed as follows:
(Object[])
). This execution 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 script, the exceptions that this method (i.e. the script) is allowed to throw, and the ClassLoader that is used to define the generated class and to load classes referenced by the script.
Alternatively, a number of "convenience constructors" exist that execute the steps described above instantly. Their use is discouraged.
If you want to compile many scripts at the same time, you have the option to cook an array of scripts in one ScriptEvaluator by using the following methods:
Notice that these methods have array parameters in contrast to their one-script brethren.Field Summary | |
---|---|
protected String[] | optionalMethodNames |
protected String[][] | optionalParameterNames |
protected Class[][] | optionalParameterTypes |
protected Class[] | optionalReturnTypes |
protected boolean[] | optionalStaticMethod |
protected Class[][] | optionalThrownExceptions |
Constructor Summary | |
---|---|
ScriptEvaluator(String script)
Equivalent to ScriptEvaluator se = new ScriptEvaluator(); se.cook(script); | |
ScriptEvaluator(String script, Class returnType)
Equivalent to ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.cook(script); | |
ScriptEvaluator(String script, Class returnType, String[] parameterNames, Class[] parameterTypes)
Equivalent to ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.cook(script); | |
ScriptEvaluator(String script, Class returnType, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions)
Equivalent to ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.cook(script); | |
ScriptEvaluator(String optionalFileName, InputStream is, Class returnType, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, ClassLoader optionalParentClassLoader)
Equivalent to ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.setParentClassLoader(optionalParentClassLoader); se.cook(optionalFileName, is); | |
ScriptEvaluator(String optionalFileName, Reader reader, Class returnType, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, ClassLoader optionalParentClassLoader)
Equivalent to ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.setParentClassLoader(optionalParentClassLoader); se.cook(reader); | |
ScriptEvaluator(Scanner scanner, Class returnType, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, ClassLoader optionalParentClassLoader)
Equivalent to ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.setParentClassLoader(optionalParentClassLoader); se.cook(scanner); | |
ScriptEvaluator(Scanner scanner, Class optionalExtendedType, Class[] implementedTypes, Class returnType, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, ClassLoader optionalParentClassLoader)
Equivalent to ScriptEvaluator se = new ScriptEvaluator(); se.setExtendedType(optionalExtendedType); se.setImplementedTypes(implementedTypes); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.setParentClassLoader(optionalParentClassLoader); se.cook(scanner); | |
ScriptEvaluator(Scanner scanner, String className, Class optionalExtendedType, Class[] implementedTypes, boolean staticMethod, Class returnType, String methodName, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, ClassLoader optionalParentClassLoader)
Equivalent to ScriptEvaluator se = new ScriptEvaluator(); se.setClassName(className); se.setExtendedType(optionalExtendedType); se.setImplementedTypes(implementedTypes); se.setStaticMethod(staticMethod); se.setReturnType(returnType); se.setMethodName(methodName); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.setParentClassLoader(optionalParentClassLoader); se.cook(scanner); | |
ScriptEvaluator() |
Method Summary | |
---|---|
protected void | compileToMethods(Java.CompilationUnit compilationUnit, String[] methodNames, Class[][] parameterTypes) |
void | cook(Scanner scanner) |
void | cook(Scanner[] scanners)
Like cook, but cooks a set of scripts into one class. |
void | cook(Reader[] readers) |
void | cook(String[] optionalFileNames, Reader[] readers) |
void | cook(String[] strings)
Cook tokens from java.lang.Strings. |
static Object | createFastEvaluator(ScriptEvaluator se, String s, String[] parameterNames, Class interfaceToImplement) |
static Object | createFastEvaluator(ScriptEvaluator se, Scanner scanner, String[] parameterNames, Class interfaceToImplement)
Create and return an object that implements the exactly one method of the given
interfaceToImplement .
|
static Object | createFastScriptEvaluator(String script, Class interfaceToImplement, String[] parameterNames)
Simplified version of
(Scanner, Class, String[], ClassLoader) .
|
static Object | createFastScriptEvaluator(Scanner scanner, Class interfaceToImplement, String[] parameterNames, ClassLoader optionalParentClassLoader)
If the parameter and return types of the expression are known at compile time,
then a "fast" script evaluator can be instantiated through this method.
|
static Object | createFastScriptEvaluator(Scanner scanner, String className, Class optionalExtendedType, Class interfaceToImplement, String[] parameterNames, ClassLoader optionalParentClassLoader)
Like (Scanner, Class, String[], ClassLoader) ,
but gives you more control over the generated class (rarely needed in practice).
|
static Object | createFastScriptEvaluator(Scanner scanner, String[] optionalDefaultImports, String className, Class optionalExtendedType, Class interfaceToImplement, String[] parameterNames, ClassLoader optionalParentClassLoader) |
Object | evaluate(Object[] parameterValues)
Calls the generated method with concrete parameter values.
|
Object | evaluate(int idx, Object[] parameterValues)
Calls the generated method with concrete parameter values.
|
protected Class | getDefaultReturnType() |
Method | getMethod()
Returns the loaded java.lang.reflect.Method.
|
Method | getMethod(int idx)
Returns the loaded java.lang.reflect.Method.
|
static String[] | guessParameterNames(Scanner scanner)
Guess the names of the parameters used in the given expression. |
protected Java.Block | makeBlock(int idx, Scanner scanner)
Fill the given block by parsing statements until EOF and adding
them to the block. |
protected Java.MethodDeclarator | makeMethodDeclaration(Location location, boolean staticMethod, Class returnType, String methodName, Class[] parameterTypes, String[] parameterNames, Class[] thrownExceptions, Java.Block optionalBody)
To the given ClassDeclaration, add
|
void | setMethodName(String methodName)
Define the name of the generated method. |
void | setMethodNames(String[] methodNames)
Define the names of the generated methods. |
void | setParameters(String[] parameterNames, Class[] parameterTypes)
Define the names and types of the parameters of the generated method. |
void | setParameters(String[][] parameterNames, Class[][] parameterTypes)
Define the names and types of the parameters of the generated methods. |
void | setReturnType(Class returnType)
Define the return type of the generated method. |
void | setReturnTypes(Class[] returnTypes)
Define the return types of the scripts. |
void | setStaticMethod(boolean staticMethod)
Define whether the generated method should be STATIC or not. |
void | setStaticMethod(boolean[] staticMethod)
Define whether the methods implementing each script should be STATIC or not. |
void | setThrownExceptions(Class[] thrownExceptions)
Define the exceptions that the generated method may throw. |
void | setThrownExceptions(Class[][] thrownExceptions)
Define the exceptions that the generated methods may throw. |
ScriptEvaluator se = new ScriptEvaluator(); se.cook(script);
See Also: ScriptEvaluator cook
ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.cook(script);
See Also: ScriptEvaluator setReturnType cook
ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.cook(script);
See Also: ScriptEvaluator setReturnType (String[], Class[])
cook
ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.cook(script);
See Also: ScriptEvaluator setReturnType (String[], Class[])
(Class[])
cook
ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.setParentClassLoader(optionalParentClassLoader); se.cook(optionalFileName, is);
See Also: ScriptEvaluator setReturnType (String[], Class[])
(Class[])
setParentClassLoader Cookable
ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.setParentClassLoader(optionalParentClassLoader); se.cook(reader);
See Also: ScriptEvaluator setReturnType (String[], Class[])
(Class[])
setParentClassLoader Cookable
ScriptEvaluator se = new ScriptEvaluator(); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.setParentClassLoader(optionalParentClassLoader); se.cook(scanner);
See Also: ScriptEvaluator setReturnType (String[], Class[])
(Class[])
setParentClassLoader cook
ScriptEvaluator se = new ScriptEvaluator(); se.setExtendedType(optionalExtendedType); se.setImplementedTypes(implementedTypes); se.setReturnType(returnType); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.setParentClassLoader(optionalParentClassLoader); se.cook(scanner);
See Also: ScriptEvaluator setExtendedType (Class[])
setReturnType (String[], Class[])
(Class[])
setParentClassLoader cook
ScriptEvaluator se = new ScriptEvaluator(); se.setClassName(className); se.setExtendedType(optionalExtendedType); se.setImplementedTypes(implementedTypes); se.setStaticMethod(staticMethod); se.setReturnType(returnType); se.setMethodName(methodName); se.setParameters(parameterNames, parameterTypes); se.setThrownExceptions(thrownExceptions); se.setParentClassLoader(optionalParentClassLoader); se.cook(scanner);
See Also: ScriptEvaluator setClassName setExtendedType (Class[])
ScriptEvaluator setReturnType setMethodName (String[], Class[])
(Class[])
setParentClassLoader cook
optionalFileName
argument of Scanner to
distinguish between the individual token sources.
On a 2 GHz Intel Pentium Core Duo under Windows XP with an IBM 1.4.2 JDK, compiling 10000 expressions "a + b" (integer) takes about 4 seconds and 56 MB of main memory. The generated class file is 639203 bytes large.
The number and the complexity of the scripts is restricted by the Limitations of the Java Virtual Machine, where the most limiting factor is the 64K entries limit of the constant pool. Since every method with a distinct name requires one entry there, you can define at best 32K (very simple) scripts. If and only if the number of scanners is one, then that single script may contain leading IMPORT directives.
Throws: IllegalStateException if any of the preceeding set...()
had an array size different from that of scanners
Parameters: optionalFileNames Used when reporting errors and warnings.
interfaceToImplement
.
Parameters: se A pre-configured ScriptEvaluator object scanner Source of tokens to read parameterNames The names of the parameters of the one abstract method of interfaceToImplement
interfaceToImplement A type with exactly one abstract method
Returns: an instance of the created Object
(Scanner, Class, String[], ClassLoader)
.
Parameters: script Contains the sequence of script tokens interfaceToImplement Must declare exactly the one method that defines the expression's signature parameterNames The expression references the parameters through these names
Returns: an object that implements the given interface and extends the optionalExtendedType
Script evaluation is faster than through (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) ScriptEvaluator.createFastScriptEvaluator( new Scanner(null, new StringReader("return a + b;")), Foo.class, new String[] { "a", "b" }, (ClassLoader) null // Use current thread's context class loader ); System.out.println("1 + 2 = " + f.bar(1, 2));Notice: The
interfaceToImplement
must either be declared public
,
or with package scope in the root package (i.e. "no" package).
Parameters: scanner Source of script tokens interfaceToImplement Must declare exactly one method parameterNames optionalParentClassLoader
Returns: an object that implements the given interface
(Scanner, 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 script 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 Used to load referenced classes, defaults to the current thread's "context class loader"
Returns: an object that implements the given interface and extends the optionalExtendedType
Each parameter value must have the same type as specified through
the "parameterTypes" parameter of
(String[], Class[])
.
Parameters of primitive type must passed with their wrapper class objects.
The object returned has the class as specified through setReturnType.
This method is thread-safe.
Parameters: parameterValues The concrete parameter values.
Each parameter value must have the same type as specified through
the "parameterTypes" parameter of
(String[], Class[])
.
Parameters of primitive type must passed with their wrapper class objects.
The object returned has the class as specified through setReturnType.
This method is thread-safe.
Parameters: idx The index of the script (0 ... scripts.length - 1
) parameterValues The concrete parameter values.
This method must only be called after cook.
This method must not be called for instances of derived classes.
This method must only be called after cook.
This method must not be called for instances of derived classes.
Parameters: idx The index of the script (0 ... scripts.length - 1
)
See Also: Scanner
block
by parsing statements until EOF and adding
them to the block.Parameters: returnType Return type of the declared method
If two scripts have the same name, then they must have different parameter types
(see (String[][], Class[][])
).
void.class
.true
.