
org.codehaus.commons.compiler.IExpressionEvaluator Maven / Gradle / Ivy
/*
* Janino - An embedded Java[TM] compiler
*
* Copyright (c) 2001-2010, Arno Unkrig
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.codehaus.commons.compiler;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
/**
* An engine that evaluates expressions in Java™ 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 {@link IExpressionEvaluator} object, proceed as follows:
*
* -
* Create an {@link IExpressionEvaluator}-derived class
*
-
* Configure the {@link IExpressionEvaluator} by calling any of the following methods:
*
* - {@link #setExpressionType(Class)}
*
- {@link #setParameters(String[], Class[])}
*
- {@link #setThrownExceptions(Class[])}
*
- {@link #setParentClassLoader(ClassLoader)}
*
- {@link #setDefaultImports(String[])}
*
* -
* Call any of the {@link #cook(String, java.io.Reader)} methods to scan,
* parse, compile and load the expression into the JVM.
*
* After the {@link IExpressionEvaluator} object is set up, the expression can be evaluated as
* often with different parameter values (see {@link #evaluate(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
* {@link 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 {@link IExpressionEvaluator} by using the following methods:
*
* - {@link #setMethodNames(String[])}
*
- {@link #setParameters(String[][], Class[][])}
*
- {@link #setExpressionTypes(Class[])}
*
- {@link #setStaticMethod(boolean[])}
*
- {@link #setThrownExceptions(Class[][])}
*
- {@link #cook(String[], Reader[])}
*
- {@link #evaluate(int, Object[])}
*
* Notice that these methods have array parameters in contrast to their one-expression brethren.
*
* Notice that for functionally identical {@link IExpressionEvaluator}s,
* {@link java.lang.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".
*
* 'JLS7' refers to the Java Language Specification, Java SE 7
* Edition.
*/
@SuppressWarnings("rawtypes") public
interface IExpressionEvaluator extends IScriptEvaluator {
/** Special value for {@link #setExpressionType(Class)} that indicates that the expression may have any type. */
Class ANY_TYPE = null;
/**
* Define the type of the expression. The special type {@link #ANY_TYPE} allows the expression
* to return any type (primitive or reference).
*
* If expressionType
is {@link Void#TYPE}, then the expression must be an
* invocation of a void
method.
*
* Defaults to {@link #ANY_TYPE}.
*/
void setExpressionType(Class expressionType);
/** Same as {@link #setExpressionType(Class)}, but for multiple expressions. */
void setExpressionTypes(Class[] expressionTypes);
/**
* @deprecated Must not be used on an {@link IExpressionEvaluator}; use {@link #setExpressionType(Class)} instead.
*/
@Override @Deprecated void setReturnType(Class returnType);
/**
* @deprecated Must not be used on an {@link IExpressionEvaluator}; use {@link #setExpressionTypes(Class[])}
* instead.
*/
@Override @Deprecated void setReturnTypes(Class[] returnTypes);
/**
* Evaluates the expression with concrete parameter values.
*
* Each argument value must have the same type as specified through the "parameterTypes" parameter of {@link
* #setParameters(String[], Class[])}.
*
* Arguments of primitive type must passed with their wrapper class objects.
*
* The object returned has the class as specified through {@link #setExpressionType(Class)}.
*
* This method is thread-safe.
*
* @param arguments The actual parameter values.
*/
@Override Object evaluate(Object[] arguments) throws InvocationTargetException;
/**
* If the parameter and return types of the expression are known at compile time, then a "fast" expression evaluator
* can be instantiated through {@link #createFastEvaluator(String, Class, String[])}. Expression evaluation is
* faster than through {@link #evaluate(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.{@link #setClassName(String) setClassName}("Bar");
* ee.{@link #setDefaultImports(String[]) setDefaultImports}(new String[] { "java.util.*" });
* ee.{@link #setExtendedClass(Class) setExtendedClass}(SomeOtherClass.class);
* ee.{@link #setParentClassLoader(ClassLoader) 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 expression
*
* All 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 declared
* public
, or with protected
or default access in the package of the compiled class (see
* {@link #setClassName(String)}.
*/
@Override Object
createFastEvaluator(
String expression,
Class interfaceToImplement,
String[] parameterNames
) throws CompileException;
/** @see #createFastEvaluator(String, Class, String[]) */
@Override Object
createFastEvaluator(
Reader reader,
Class interfaceToImplement,
String[] parameterNames
) throws CompileException, IOException;
}