org.mvel2.MVEL Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tbel Show documentation
Show all versions of tbel Show documentation
TBEL is a powerful expression language for ThingsBoard platform user-defined functions.
Original implementation is based on MVEL.
/**
* MVEL 2.0
* Copyright (C) 2007 MVFLEX/Valhalla Project and the Codehaus
* Mike Brock, Dhanji Prasanna, John Graham, Mark Proctor
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mvel2;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import org.mvel2.compiler.CompiledAccExpression;
import org.mvel2.compiler.CompiledExpression;
import org.mvel2.compiler.ExecutableStatement;
import org.mvel2.compiler.ExpressionCompiler;
import org.mvel2.integration.Interceptor;
import org.mvel2.integration.VariableResolverFactory;
import org.mvel2.integration.impl.CachedMapVariableResolverFactory;
import org.mvel2.integration.impl.CachingMapVariableResolverFactory;
import org.mvel2.integration.impl.ClassImportResolverFactory;
import org.mvel2.integration.impl.ImmutableDefaultFactory;
import org.mvel2.integration.impl.MapVariableResolverFactory;
import org.mvel2.optimizers.impl.refl.nodes.GetterAccessor;
import org.mvel2.util.ArgsRepackUtil;
import static java.lang.Boolean.getBoolean;
import static java.lang.String.valueOf;
import static org.mvel2.DataConversion.convert;
import static org.mvel2.MVELRuntime.execute;
import static org.mvel2.util.ParseTools.loadFromFile;
import static org.mvel2.util.ParseTools.optimizeTree;
/**
* The MVEL convienence class is a collection of static methods that provides a set of easy integration points for
* MVEL. The vast majority of MVEL's core functionality can be directly accessed through methods in this class.
*/
public class MVEL {
public static final String NAME = "MVEL (MVFLEX Expression Language)";
public static final String VERSION = "2.3";
public static final String VERSION_SUB = "0";
public static final String CODENAME = "liberty";
static boolean DEBUG_FILE = getBoolean("mvel2.debug.fileoutput");
static String ADVANCED_DEBUGGING_FILE = System.getProperty("mvel2.debugging.file") == null ? "mvel_debug.txt" : System.getProperty("mvel2.debugging.file");
static boolean ADVANCED_DEBUG = getBoolean("mvel2.advanced_debugging");
static boolean WEAK_CACHE = getBoolean("mvel2.weak_caching");
static boolean NO_JIT = getBoolean("mvel2.disable.jit");
public static boolean INVOKED_METHOD_EXCEPTIONS_BUBBLE = getBoolean("mvel2.invoked_meth_exceptions_bubble");
public static boolean COMPILER_OPT_ALLOW_NAKED_METH_CALL = getBoolean("mvel2.compiler.allow_naked_meth_calls");
public static boolean COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING = getBoolean("mvel2.compiler.allow_override_all_prophandling");
public static boolean COMPILER_OPT_ALLOW_RESOLVE_INNERCLASSES_WITH_DOTNOTATION = getBoolean("mvel2.compiler.allow_resolve_inner_classes_with_dotnotation");
public static boolean COMPILER_OPT_SUPPORT_JAVA_STYLE_CLASS_LITERALS = getBoolean("mvel2.compiler.support_java_style_class_literals");
public static boolean COMPILER_OPT_ALLOCATE_TYPE_LITERALS_TO_SHARED_SYMBOL_TABLE = getBoolean("mvel2.compiler.allocate_type_literals_to_shared_symbol_table");
public static boolean RUNTIME_OPT_THREAD_UNSAFE = getBoolean("mvel2.runtime.thread_unsafe");
static boolean OPTIMIZER = true;
static {
if (System.getProperty("mvel2.optimizer") != null) {
OPTIMIZER = getBoolean("mvel2.optimizer");
}
}
private MVEL() {
}
public static boolean isAdvancedDebugging() {
return ADVANCED_DEBUG;
}
public static String getDebuggingOutputFileName() {
return ADVANCED_DEBUGGING_FILE;
}
public static boolean isFileDebugging() {
return DEBUG_FILE;
}
/**
* Evaluate an expression and return the value.
*
* @param expression A String containing the expression to be evaluated.
* @return the resultant value
*/
public static Object eval(String expression) {
return new MVELInterpretedRuntime(expression, new ImmutableDefaultFactory()).parse();
}
/**
* Evaluate an expression against a context object. Expressions evaluated against a context object are designed
* to treat members of that context object as variables in the expression. For example:
*
* MVEL.eval("foo == 1", ctx);
*
* In this case, the identifier foo would be resolved against the ctx object. So it would have
* the equivalent of: ctc.getFoo() == 1 in Java.
*
* @param expression A String containing the expression to be evaluated.
* @param ctx The context object to evaluate against.
* @return The resultant value
*/
public static Object eval(String expression, Object ctx) {
return new MVELInterpretedRuntime(expression, ctx, new ImmutableDefaultFactory()).parse();
}
/**
* Evaluate an expression with externally injected variables via a {@link VariableResolverFactory}. A factory
* provides the means by which MVEL can resolve external variables. MVEL contains a straight-forward implementation
* for wrapping Maps: {@link MapVariableResolverFactory}, which is used implicitly when calling overloaded methods
* in this class that use Maps.
*
* An example:
*
* Map varsMap = new HashMap();
* varsMap.put("x", 5);
* varsMap.put("y", 2);
*
* VariableResolverFactory factory = new MapVariableResolverFactory(varsMap);
*
* Integer i = (Integer) MVEL.eval("x * y", factory);
*
* assert i == 10;
*
*
* @param expression A String containing the expression to be evaluated.
* @param resolverFactory The instance of the VariableResolverFactory to be used.
* @return The resultant value.
*/
public static Object eval(String expression, VariableResolverFactory resolverFactory) {
return new MVELInterpretedRuntime(expression, resolverFactory).parse();
}
/**
* Evaluates an expression against a context object and injected variables from a {@link VariableResolverFactory}.
* This method of execution will prefer to find variables from the factory and then from the context.
*
* @param expression A string containing the expression to be evaluated
* @param ctx The context object to evaluate against.
* @param resolverFactory The instance of the VariableResolverFactory to be used.
* @return The resultant value
* @see #eval(String, org.mvel2.integration.VariableResolverFactory)
*/
public static Object eval(String expression, Object ctx, VariableResolverFactory resolverFactory) {
return new MVELInterpretedRuntime(expression, ctx, resolverFactory).parse();
}
/**
* Evaluates an expression against externally injected variables. This is a wrapper convenience method which
* wraps the provided Map of vars in a {@link MapVariableResolverFactory}
*
* @param expression A string containing the expression to be evaluated.
* @param vars A map of vars to be injected
* @return The resultant value
* @see #eval(String, org.mvel2.integration.VariableResolverFactory)
*/
public static Object eval(String expression, Map vars) {
CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars);
try {
return new MVELInterpretedRuntime(expression, null, factory).parse();
}
finally {
factory.externalize();
}
}
/**
* Evaluates an expression against a context object and externally injected variables. This is a wrapper
* convenience method which wraps the provided Map of vars in a {@link MapVariableResolverFactory}
*
* @param expression A string containing the expression to be evaluated.
* @param ctx The context object to evaluate against.
* @param vars A map of vars to be injected
* @return The resultant value
* @see #eval(String, VariableResolverFactory)
*/
public static Object eval(String expression, Object ctx, Map vars) {
CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars);
try {
return new MVELInterpretedRuntime(expression, ctx, factory).parse();
}
finally {
factory.externalize();
}
}
/**
* Evaluates an expression and, if necessary, coerces the resultant value to the specified type. Example:
*
* Float output = MVEL.eval("5 + 5", Float.class);
*
*
* This converts an expression that would otherwise return an Integer to a Float.
*
* @param expression A string containing the expression to be evaluated.
* @param toType The target type that the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value.
*/
public static T eval(String expression, Class toType) {
return convert(new MVELInterpretedRuntime(expression).parse(), toType);
}
/**
* Evaluates an expression against a context object and, if necessary, coerces the resultant value to the specified
* type.
*
* @param expression A string containing the expression to be evaluated.
* @param ctx The context object to evaluate against.
* @param toType The target type that the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value
* @see #eval(String, Class)
*/
public static T eval(String expression, Object ctx, Class toType) {
return convert(new MVELInterpretedRuntime(expression, ctx).parse(), toType);
}
/**
* Evaluates an expression against externally injected variables and, if necessary, coerces the resultant value
* to the specified type.
*
* @param expression A string containing the expression to be evaluated
* @param vars The variables to be injected
* @param toType The target type that the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value
* @see #eval(String, VariableResolverFactory)
* @see #eval(String, Class)
*/
public static T eval(String expression, VariableResolverFactory vars, Class toType) {
return convert(new MVELInterpretedRuntime(expression, null, vars).parse(), toType);
}
/**
* Evaluates an expression against externally injected variables. The resultant value is coerced to the specified
* type if necessary. This is a wrapper convenience method which wraps the provided Map of vars in a{@link MapVariableResolverFactory}
*
* @param expression A string containing the expression to be evaluated.
* @param vars A map of vars to be injected
* @param toType The target type the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value
* @see #eval(String, org.mvel2.integration.VariableResolverFactory)
*/
public static T eval(String expression, Map vars, Class toType) {
CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars);
try {
return convert(new MVELInterpretedRuntime(expression, null, factory).parse(), toType);
}
finally {
factory.externalize();
}
}
/**
* Evaluates an expression against a context object and externally injected variables. If necessary, the resultant
* value is coerced to the specified type.
*
* @param expression A string containing the expression to be evaluated.
* @param ctx The context object to evaluate against
* @param vars The vars to be injected
* @param toType The target type that the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value.
* @see #eval(String, Object, VariableResolverFactory)
* @see #eval(String, Class)
*/
public static T eval(String expression, Object ctx, VariableResolverFactory vars, Class toType) {
return convert(new MVELInterpretedRuntime(expression, ctx, vars).parse(), toType);
}
/**
* Evaluates an expression against a context object and externally injected variables. If necessary, the resultant
* value is coerced to the specified type.
*
* @param expression A string containing the expression to be evaluated.
* @param ctx The context object to evaluate against
* @param vars A Map of variables to be injected.
* @param toType The target type that the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value.
* @see #eval(String, Object, VariableResolverFactory)
* @see #eval(String, Class)
*/
public static T eval(String expression, Object ctx, Map vars, Class toType) {
CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars);
try {
return convert(new MVELInterpretedRuntime(expression, ctx, factory).parse(), toType);
}
finally {
factory.externalize();
}
}
/**
* Evaluates an expression and returns the resultant value as a String.
*
* @param expression A string containing the expressino to be evaluated.
* @return The resultant value
*/
public static String evalToString(String expression) {
return valueOf(eval(expression));
}
/**
* Evaluates an expression and returns the resultant value as a String.
*
* @param expression A string containing the expressino to be evaluated.
* @param ctx The context object to evaluate against
* @return The resultant value
* @see #eval(String, Object)
*/
public static String evalToString(String expression, Object ctx) {
return valueOf(eval(expression, ctx));
}
/**
* Evaluates an expression and returns the resultant value as a String.
*
* @param expression A string containing the expressino to be evaluated.
* @param vars The variables to be injected
* @return The resultant value
* @see #eval(String, VariableResolverFactory)
*/
public static String evalToString(String expression, VariableResolverFactory vars) {
return valueOf(eval(expression, vars));
}
/**
* Evaluates an expression and returns the resultant value as a String.
*
* @param expression A string containing the expressino to be evaluated.
* @param vars A Map of variables to be injected
* @return The resultant value
* @see #eval(String, Map)
*/
public static String evalToString(String expression, Map vars) {
return valueOf(eval(expression, vars));
}
/**
* Evaluates an expression and returns the resultant value as a String.
*
* @param expression A string containing the expressino to be evaluated.
* @param ctx The context object to evaluate against.
* @param vars The variables to be injected
* @return The resultant value
* @see #eval(String, Map)
*/
public static String evalToString(String expression, Object ctx, VariableResolverFactory vars) {
return valueOf(eval(expression, ctx, vars));
}
/**
* Evaluates an expression and returns the resultant value as a String.
*
* @param expression A string containing the expressino to be evaluated.
* @param ctx The context object to evaluate against.
* @param vars A Map of variables to be injected
* @return The resultant value
* @see #eval(String, Map)
*/
public static String evalToString(String expression, Object ctx, Map vars) {
return valueOf(eval(expression, ctx, vars));
}
/**
* Evaluate an expression and return the value.
*
* @param expression A char[] containing the expression to be evaluated.
* @return The resultant value
* @see #eval(String)
*/
public static Object eval(char[] expression) {
return new MVELInterpretedRuntime(expression, new ImmutableDefaultFactory()).parse();
}
/**
* Evaluate an expression against a context object and return the value
*
* @param expression A char[] containing the expression to be evaluated.
* @param ctx The context object to evaluate against
* @return The resultant value
* @see #eval(String, Object)
*/
public static Object eval(char[] expression, Object ctx) {
return new MVELInterpretedRuntime(expression, ctx).parse();
}
public static T eval(char[] expression, Class type) {
return convert(new MVELInterpretedRuntime(expression).parse(), type);
}
/**
* Evaluate an expression against a context object and return the value
*
* @param expression A char[] containing the expression to be evaluated.
* @param ctx The context object to evaluate against
* @param vars The variables to be injected
* @return The resultant value
* @see #eval(String, Object, VariableResolverFactory)
*/
public static Object eval(char[] expression, Object ctx, VariableResolverFactory vars) {
return new MVELInterpretedRuntime(expression, ctx, vars).parse();
}
public static Object eval(char[] expression, int start, int offset, Object ctx, VariableResolverFactory vars) {
return new MVELInterpretedRuntime(expression, start, offset, ctx, vars).parse();
}
public static T eval(char[] expression, int start, int offset, Object ctx, VariableResolverFactory vars, Class toType) {
return convert(new MVELInterpretedRuntime(expression, start, offset, ctx, vars).parse(), toType);
}
/**
* Evaluate an expression against a context object and return the value
*
* @param expression A char[] containing the expression to be evaluated.
* @param ctx The context object to evaluate against
* @param vars A Map of variables to be injected
* @return The resultant value
* @see #eval(String, Object, Map)
*/
public static Object eval(char[] expression, Object ctx, Map vars) {
return new MVELInterpretedRuntime(expression, ctx, vars).parse();
}
/**
* Evaluate an expression with a context object and injected variables and return the value. If necessary convert
* the resultant value to the specified type.
*
* @param expression A char[] containing the expression to be evaluated.
* @param ctx The context object to evaluate against
* @param vars A Map of variables to be injected
* @param toType The target type the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value
* @see #eval(String, Object, Map, Class)
*/
public static T eval(char[] expression, Object ctx, Map vars, Class toType) {
return convert(new MVELInterpretedRuntime(expression, ctx, vars).parse(), toType);
}
/**
* Evaluate an expression with a context object and return the value. If necessary convert
* the resultant value to the specified type.
*
* @param expression A char[] containing the expression to be evaluated.
* @param ctx The context object to evaluate against
* @param toType The target type the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value
* @see #eval(String, Object, Class)
*/
public static T eval(char[] expression, Object ctx, Class toType) {
return convert(new MVELInterpretedRuntime(expression, ctx).parse(), toType);
}
/**
* Evaluate an expression with a context object and injected variables and return the value. If necessary convert
* the resultant value to the specified type.
*
* @param expression A char[] containing the expression to be evaluated.
* @param ctx The context object to evaluate against
* @param vars The variables to be injected
* @param toType The target type the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value
* @see #eval(String, Object, VariableResolverFactory, Class)
*/
public static T eval(char[] expression, Object ctx, VariableResolverFactory vars, Class toType) {
return convert(new MVELInterpretedRuntime(expression, ctx, vars).parse(), toType);
}
/**
* Evaluate an expression with injected variables and return the value. If necessary convert
* the resultant value to the specified type.
*
* @param expression A char[] containing the expression to be evaluated.
* @param vars The variables to be injected
* @param toType The target type the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value
* @see #eval(String, VariableResolverFactory, Class)
*/
public static T eval(char[] expression, VariableResolverFactory vars, Class toType) {
return convert(new MVELInterpretedRuntime(expression, null, vars).parse(), toType);
}
/**
* Evaluate an expression with injected variables and return the resultant value. If necessary convert
* the resultant value to the specified type.
*
* @param expression A char[] containing the expression to be evaluated.
* @param vars The variables to be injected
* @param toType The target type the resultant value will be converted to, if necessary.
* @param type
* @return The resultant value
* @see #eval(String, Map, Class)
*/
public static T eval(char[] expression, Map vars, Class toType) {
return convert(new MVELInterpretedRuntime(expression, null, vars).parse(), toType);
}
/**
* Evaluate a script from a file and return the resultant value.
*
* @param file The file to process
* @return The resultant value
* @throws IOException Exception thrown if there is an IO problem accessing the file.
*/
public static Object evalFile(File file) throws IOException {
return _evalFile(file, null, new CachedMapVariableResolverFactory(new HashMap()));
}
public static Object evalFile(File file, String encoding) throws IOException {
return _evalFile(file, encoding, null, new CachedMapVariableResolverFactory(new HashMap()));
}
/**
* Evaluate a script from a file, against a context object and return the resultant value.
*
* @param file The file to process
* @param ctx The context to evaluate the script against.
* @return The resultant value
* @throws IOException Exception thrown if there is an IO problem accessing the file.
*/
public static Object evalFile(File file, Object ctx) throws IOException {
return _evalFile(file, ctx, new CachedMapVariableResolverFactory(new HashMap()));
}
public static Object evalFile(File file, String encoding, Object ctx) throws IOException {
return _evalFile(file, encoding, ctx, new CachedMapVariableResolverFactory(new HashMap()));
}
/**
* Evaluate a script from a file with injected variables and return the resultant value.
*
* @param file The file to process
* @param vars Variables to be injected
* @return The resultant value
* @throws IOException Exception thrown if there is an IO problem accessing the file.
*/
public static Object evalFile(File file, Map vars) throws IOException {
CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars);
try {
return _evalFile(file, null, factory);
}
finally {
factory.externalize();
}
}
/**
* Evaluate a script from a file with injected variables and a context object, then return the resultant value.
*
* @param file The file to process
* @param ctx The context to evaluate the script against.
* @param vars Variables to be injected
* @return The resultant value
* @throws IOException Exception thrown if there is an IO problem accessing the file.
*/
public static Object evalFile(File file, Object ctx, Map vars) throws IOException {
CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars);
try {
return _evalFile(file, ctx, factory);
}
finally {
factory.externalize();
}
}
public static Object evalFile(File file, String encoding, Object ctx, Map vars) throws IOException {
CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars);
try {
return _evalFile(file, encoding, ctx, factory);
}
finally {
factory.externalize();
}
}
/**
* Evaluate a script from a file with injected variables and a context object, then return the resultant value.
*
* @param file The file to process
* @param ctx The context to evaluate the script against.
* @param vars Variables to be injected
* @return The resultant value
* @throws IOException Exception thrown if there is an IO problem accessing the file.
*/
public static Object evalFile(File file, Object ctx, VariableResolverFactory vars) throws IOException {
return _evalFile(file, ctx, vars);
}
public static Object evalFile(File file, String encoding, Object ctx, VariableResolverFactory vars) throws IOException {
return _evalFile(file, encoding, ctx, vars);
}
private static Object _evalFile(File file, Object ctx, VariableResolverFactory factory) throws IOException {
return _evalFile(file, null, ctx, factory);
}
private static Object _evalFile(File file, String encoding, Object ctx, VariableResolverFactory factory) throws IOException {
return eval(loadFromFile(file, encoding), ctx, factory);
}
/**
* Evaluate an expression in Boolean-only mode against a root context object and injected variables.
*
* @param expression A string containing the expression to be evaluated.
* @param ctx The context against which to evaluate the expression
* @param vars The variables to be injected
* @return The resultant value as a Boolean
*/
public static Boolean evalToBoolean(String expression, Object ctx, Map vars) {
return eval(expression, ctx, vars, Boolean.class);
}
/**
* Evaluate an expression in Boolean-only mode against a root context object.
*
* @param expression A string containing the expression to be evaluated.
* @param ctx The context against which to evaluate the expression
* @return The resultant value as a Boolean
*/
public static Boolean evalToBoolean(String expression, Object ctx) {
return eval(expression, ctx, new ImmutableDefaultFactory(), Boolean.class);
}
/**
* Evaluate an expression in Boolean-only mode against a root context object and injected variables.
*
* @param expression A string containing the expression to be evaluated.
* @param ctx The context against which to evaluate the expression
* @param vars The variables to be injected
* @return The resultant value as a Boolean
*/
public static Boolean evalToBoolean(String expression, Object ctx, VariableResolverFactory vars) {
return eval(expression, ctx, vars, Boolean.class);
}
/**
* Evaluate an expression in Boolean-only with injected variables.
*
* @param expression A string containing the expression to be evaluated.
* @param vars The variables to be injected
* @return The resultant value as a Boolean
*/
public static Boolean evalToBoolean(String expression, VariableResolverFactory vars) {
return eval(expression, vars, Boolean.class);
}
/**
* Evaluate an expression in Boolean-only with injected variables.
*
* @param expression A string containing the expression to be evaluated.
* @param vars The variables to be injected
* @return The resultant value as a Boolean
*/
public static Boolean evalToBoolean(String expression, Map vars) {
return evalToBoolean(expression, null, vars);
}
/**
* Performs an analysis compileShared, which will populate the ParserContext with type, input and variable information,
* but will not produce a payload.
*
* @param expression - the expression to analyze
* @param ctx - the parser context
*/
public static void analysisCompile(char[] expression, ParserContext ctx) {
ExpressionCompiler compiler = new ExpressionCompiler(expression, ctx);
compiler.setVerifyOnly(true);
compiler.compile();
}
public static void analysisCompile(String expression, ParserContext ctx) {
analysisCompile(expression.toCharArray(), ctx);
}
public static Class analyze(char[] expression, ParserContext ctx) {
ExpressionCompiler compiler = new ExpressionCompiler(expression, ctx);
compiler.setVerifyOnly(true);
compiler.compile();
return compiler.getReturnType();
}
public static Class analyze(String expression, ParserContext ctx) {
return analyze(expression.toCharArray(), ctx);
}
/**
* Compiles an expression and returns a Serializable object containing the compiled expression. The returned value
* can be reused for higher-performance evaluation of the expression. It is used in a straight forward way:
*
*
* // Compile the expression
* Serializable compiled = MVEL.compileExpression("x * 10");
*
* // Create a Map to hold the variables.
* Map vars = new HashMap();
*
* // Create a factory to envelop the variable map
* VariableResolverFactory factory = new MapVariableResolverFactory(vars);
*
* int total = 0;
* for (int i = 0; i < 100; i++) {
* // Update the 'x' variable.
* vars.put("x", i);
*
* // Execute the expression against the compiled payload and factory, and add the result to the total variable.
* total += (Integer) MVEL.executeExpression(compiled, factory);
* }
*
* // Total should be 49500
* assert total == 49500;
*
*
* The above example demonstrates a compiled expression being reused ina tight, closed, loop. Doing this greatly
* improves performance as re-parsing of the expression is not required, and the runtime can dynamically compileShared
* the expression to bytecode of necessary.
*
* @param expression A String contaiing the expression to be compiled.
* @return The cacheable compiled payload.
*/
public static Serializable compileExpression(String expression) {
return compileExpression(expression, null, null, null);
}
/**
* Compiles an expression and returns a Serializable object containing the compiled expression. This method
* also accept a Map of imports. The Map's keys are String's representing the imported, short-form name of the
* Classes or Methods imported. An import of a Method is essentially a static import. This is a substitute for
* needing to declare import statements within the actual script.
*
*
* Map imports = new HashMap();
* imports.put("HashMap", java.util.HashMap.class); // import a class
* imports.put("time", MVEL.getStaticMethod(System.class, "currentTimeMillis", new Class[0])); // import a static method
*
* // Compile the expression
* Serializable compiled = MVEL.compileExpression("map = new HashMap(); map.put('time', time()); map.time");
*
* // Execute with a blank Map to allow vars to be declared.
* Long val = (Long) MVEL.executeExpression(compiled, new HashMap());
*
* assert val > 0;
*
*
* @param expression A String contaiing the expression to be compiled.
* @param imports A String-Class/String-Method pair Map containing imports for the compiler.
* @return The cacheable compiled payload.
*/
public static Serializable compileExpression(String expression, Map imports) {
return compileExpression(expression, imports, null, null);
}
/**
* Compiles an expression and returns a Serializable object containing the compiled expression. This method
* accepts a Map of imports and Interceptors. See {@link #compileExpression(String, Map)} for information on
* imports. The imports parameter in this method is optional and it is safe to pass a null
* value. {@link org.mvel2.integration.Interceptor Interceptors} are markers within an expression that allow external hooks
* to be tied into the expression.
*
*
* // Create a Map to hold the interceptors.
* Map interceptors = new HashMap();
*
* // Create a simple interceptor.
* Interceptor logInterceptor = new Interceptor() {
* public int doBefore(ASTNode node, VariableResolverFactory factory) {
* System.out.println("Interceptor called before!");
* }
*
* public int doAfter(Object exitValue, ASTNode node, VariableResolverFactory factory) {
* System.out.println("Interceptor called after!");
* }
* };
*
* // Add the interceptor to the Map.
* interceptors.put("log", logInterceptor);
*
* // Create an expression
* String expr = "list = [1,2,3,4,5]; @log for (item : list) { System.out.println(item); };
*
* Serializable compiled = MVEL.compileExpression(expr, null, interceptors);
*
* // Execute expression with a blank Map to allow vars to be declared.
* MVEL.executeExpression(compiled, new HashMap());
*
*
* The above example demonstrates inserting an interceptor into a piece of code. The @log interceptor
* wraps the subsequent statement. In this case, the interceptor is fired before the for loop and
* after the for loop finishes.
*
* @param expression A String containing the expression to be evaluated.
* @param imports A String-Class/String-Method pair Map containing imports for the compiler.
* @param interceptors A Map of registered interceptors.
* @return A cacheable compiled payload.
*/
public static Serializable compileExpression(String expression, Map imports, Map interceptors) {
return compileExpression(expression, imports, interceptors, null);
}
/**
* Compiles an expression, and accepts a {@link ParserContext} instance. The ParserContext object is the
* fine-grained configuration object for the MVEL parser and compiler.
*
* @param expression A string containing the expression to be compiled.
* @param ctx The parser context
* @return A cacheable compiled payload.
*/
public static Serializable compileExpression(String expression, ParserContext ctx) {
return optimizeTree(new ExpressionCompiler(expression, ctx).compile());
}
public static Serializable compileExpression(char[] expression, int start, int offset, ParserContext ctx) {
ExpressionCompiler c = new ExpressionCompiler(expression, start, offset, ctx);
return optimizeTree(c._compile());
}
public static Serializable compileExpression(String expression, Map imports, Map interceptors, String sourceName) {
return compileExpression(expression, new ParserContext(imports, interceptors, sourceName));
}
public static Serializable compileExpression(char[] expression, ParserContext ctx) {
return optimizeTree(new ExpressionCompiler(expression, ctx).compile());
}
/**
* Compiles an expression and returns a Serializable object containing the compiled
* expression.
*
* @param expression The expression to be compiled
* @param imports Imported classes
* @param interceptors Map of named interceptos
* @param sourceName The name of the source file being evaluated (optional)
* @return The cacheable compiled payload
*/
public static Serializable compileExpression(char[] expression, Map imports, Map interceptors, String sourceName) {
return compileExpression(expression, new ParserContext(imports, interceptors, sourceName));
}
public static Serializable compileExpression(char[] expression) {
return compileExpression(expression, null, null, null);
}
public static Serializable compileExpression(char[] expression, Map imports) {
return compileExpression(expression, imports, null, null);
}
public static Serializable compileExpression(char[] expression, Map imports, Map interceptors) {
return compileExpression(expression, imports, interceptors, null);
}
public static Serializable compileGetExpression(String expression) {
return new CompiledAccExpression(expression.toCharArray(), Object.class, new ParserContext());
}
public static Serializable compileGetExpression(String expression, ParserContext ctx) {
return new CompiledAccExpression(expression.toCharArray(), Object.class, ctx);
}
public static Serializable compileGetExpression(char[] expression) {
return new CompiledAccExpression(expression, Object.class, new ParserContext());
}
public static Serializable compileGetExpression(char[] expression, ParserContext ctx) {
return new CompiledAccExpression(expression, Object.class, ctx);
}
public static Serializable compileSetExpression(String expression) {
return new CompiledAccExpression(expression.toCharArray(), Object.class, new ParserContext());
}
public static Serializable compileSetExpression(String expression, ParserContext ctx) {
return new CompiledAccExpression(expression.toCharArray(), Object.class, ctx);
}
public static Serializable compileSetExpression(String expression, Class ingressType, ParserContext ctx) {
return new CompiledAccExpression(expression.toCharArray(), ingressType, ctx);
}
public static Serializable compileSetExpression(char[] expression) {
return new CompiledAccExpression(expression, Object.class, new ParserContext());
}
public static Serializable compileSetExpression(char[] expression, ParserContext ctx) {
return new CompiledAccExpression(expression, Object.class, ctx);
}
public static Serializable compileSetExpression(char[] expression, int start, int offset, ParserContext ctx) {
return new CompiledAccExpression(expression, start, offset, Object.class, ctx);
}
public static Serializable compileSetExpression(char[] expression, Class ingressType, ParserContext ctx) {
return new CompiledAccExpression(expression, ingressType, ctx);
}
public static void executeSetExpression(Serializable compiledSet, Object ctx, Object value) {
((CompiledAccExpression) compiledSet).setValue(ctx, ctx, new ImmutableDefaultFactory(), value);
}
public static void executeSetExpression(Serializable compiledSet, Object ctx, VariableResolverFactory vrf, Object value) {
((CompiledAccExpression) compiledSet).setValue(ctx, ctx, vrf, value);
}
public static Object executeExpression(Object compiledExpression) {
return ((ExecutableStatement) compiledExpression).getValue(null, new ImmutableDefaultFactory());
}
/**
* Executes a compiled expression.
*
* @param compiledExpression -
* @param ctx -
* @param vars -
* @return -
* @see #compileExpression(String)
*/
@SuppressWarnings({"unchecked"})
public static Object executeExpression(final Object compiledExpression, final Object ctx, final Map vars) {
CachingMapVariableResolverFactory factory = vars != null ? new CachingMapVariableResolverFactory(vars) : null;
try {
return ((ExecutableStatement) compiledExpression).getValue(ctx, factory);
}
finally {
if (factory != null) factory.externalize();
}
}
public static Object executeTbExpression(final Object compiledExpression, final ExecutionContext ctx, Map vars) {
if(vars != null) {
Map newVars = new HashMap();
vars.forEach((k,v) -> newVars.put(k , ArgsRepackUtil.repack(ctx, v)));
vars = newVars;
}
return ArgsRepackUtil.unpack(executeExpression(compiledExpression, ctx, vars));
}
public static Object executeExpression(final Object compiledExpression, final Object ctx, final VariableResolverFactory resolverFactory) {
return ((ExecutableStatement) compiledExpression).getValue(ctx, resolverFactory);
}
/**
* Executes a compiled expression.
*
* @param compiledExpression -
* @param factory -
* @return -
* @see #compileExpression(String)
*/
public static Object executeExpression(final Object compiledExpression, final VariableResolverFactory factory) {
return ((ExecutableStatement) compiledExpression).getValue(null, factory);
}
/**
* Executes a compiled expression.
*
* @param compiledExpression -
* @param ctx -
* @return -
* @see #compileExpression(String)
*/
public static Object executeExpression(final Object compiledExpression, final Object ctx) {
return ((ExecutableStatement) compiledExpression).getValue(ctx, new ImmutableDefaultFactory());
}
/**
* Executes a compiled expression.
*
* @param compiledExpression -
* @param vars -
* @return -
* @see #compileExpression(String)
*/
@SuppressWarnings({"unchecked"})
public static Object executeExpression(final Object compiledExpression, final Map vars) {
CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars);
try {
return ((ExecutableStatement) compiledExpression).getValue(null, factory);
}
finally {
factory.externalize();
}
}
/**
* Execute a compiled expression and convert the result to a type
*
* @param compiledExpression -
* @param ctx -
* @param vars -
* @param toType -
* @param type
* @return -
*/
@SuppressWarnings({"unchecked"})
public static T executeExpression(final Object compiledExpression, final Object ctx, final Map vars, Class toType) {
return convert(executeExpression(compiledExpression, ctx, vars), toType);
}
public static T executeExpression(final Object compiledExpression, final Object ctx, final VariableResolverFactory vars, Class toType) {
return convert(executeExpression(compiledExpression, ctx, vars), toType);
}
/**
* Execute a compiled expression and convert the result to a type
*
* @param compiledExpression -
* @param vars -
* @param toType -
* @param type
* @return -
*/
@SuppressWarnings({"unchecked"})
public static T executeExpression(final Object compiledExpression, Map vars, Class toType) {
return convert(executeExpression(compiledExpression, vars), toType);
}
/**
* Execute a compiled expression and convert the result to a type.
*
* @param compiledExpression -
* @param ctx -
* @param toType -
* @param type
* @return -
*/
public static T executeExpression(final Object compiledExpression, final Object ctx, Class toType) {
return convert(executeExpression(compiledExpression, ctx), toType);
}
public static void executeExpression(Iterable compiledExpression) {
for (CompiledExpression ce : compiledExpression) {
ce.getValue(null, null);
}
}
public static void executeExpression(Iterable compiledExpression, Object ctx) {
for (CompiledExpression ce : compiledExpression) {
ce.getValue(ctx, null);
}
}
public static void executeExpression(Iterable compiledExpression, Map vars) {
CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars);
executeExpression(compiledExpression, null, factory);
factory.externalize();
}
public static void executeExpression(Iterable compiledExpression, Object ctx, Map vars) {
CachingMapVariableResolverFactory factory = new CachingMapVariableResolverFactory(vars);
executeExpression(compiledExpression, ctx, factory);
factory.externalize();
}
public static void executeExpression(Iterable compiledExpression, Object ctx, VariableResolverFactory vars) {
for (CompiledExpression ce : compiledExpression) {
ce.getValue(ctx, vars);
}
}
public static Object[] executeAllExpression(Serializable[] compiledExpressions, Object ctx, VariableResolverFactory vars) {
if (compiledExpressions == null) return GetterAccessor.EMPTY;
Object[] o = new Object[compiledExpressions.length];
for (int i = 0; i < compiledExpressions.length; i++) {
o[i] = executeExpression(compiledExpressions[i], ctx, vars);
}
return o;
}
public static Object executeDebugger(CompiledExpression expression, Object ctx, VariableResolverFactory vars) {
if (expression.isImportInjectionRequired()) {
return execute(true, expression, ctx, new ClassImportResolverFactory(expression.getParserConfiguration(), vars, false));
}
else {
return execute(true, expression, ctx, vars);
}
}
public static String parseMacros(String input, Map macros) {
return new MacroProcessor(macros).parse(input);
}
public static String preprocess(char[] input, PreProcessor[] preprocessors) {
char[] ex = input;
for (PreProcessor proc : preprocessors) {
ex = proc.parse(ex);
}
return new String(ex);
}
public static String preprocess(String input, PreProcessor[] preprocessors) {
return preprocess(input.toCharArray(), preprocessors);
}
public static Object getProperty(String property, Object ctx) {
return PropertyAccessor.get(property, ctx);
}
public static void setProperty(Object ctx, String property, Object value) {
PropertyAccessor.set(ctx, property, value);
}
/**
* A simple utility method to get a static method from a class with no checked exception. With throw a
* RuntimeException if the method is not found or is not a static method.
*
* @param cls The class containing the static method
* @param methodName The method name
* @param signature The signature of the method
* @return An instance of the Method
*/
public static Method getStaticMethod(Class cls, String methodName, Class[] signature) {
try {
Method m = cls.getMethod(methodName, signature);
if ((m.getModifiers() & Modifier.STATIC) == 0)
throw new RuntimeException("method not a static method: " + methodName);
return m;
}
catch (NoSuchMethodException e) {
throw new RuntimeException("no such method: " + methodName);
}
}
}