All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.codehaus.janino.ExpressionEvaluator Maven / Gradle / Ivy

There is a newer version: 5.4.0
Show newest version

/*
 * Janino - An embedded Java[TM] com.hazelcast.com.iler
 *
 * Copyright (c) 2001-2010 Arno Unkrig. All rights reserved.
 * Copyright (c) 2015-2016 TIBCO Software Inc. 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. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
 *       products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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 com.hazelcast.org.codehaus.janino;

import java.io.IOException;
import java.io.Reader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.CompileException;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.Cookable;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.IClassBodyEvaluator;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.ICookable;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.IExpressionEvaluator;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.IScriptEvaluator;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.com.hazelcast.com.iler.ISimpleCompiler;
import com.hazelcast.org.codehaus.com.hazelcast.com.ons.nullanalysis.Nullable;
import com.hazelcast.org.codehaus.janino.Java.AmbiguousName;
import com.hazelcast.org.codehaus.janino.Java.BlockStatement;
import com.hazelcast.org.codehaus.janino.Java.MethodDeclarator;
import com.hazelcast.org.codehaus.janino.Java.Rvalue;
import com.hazelcast.org.codehaus.janino.util.AbstractTraverser;

/**
 * This {@link IExpressionEvaluator} is implemented by creating and com.hazelcast.com.iling a temporary com.hazelcast.com.ilation unit defining one
 * class with one static method with one RETURN statement.
 * 

* A number of "convenience constructors" exist that execute the set-up steps described for {@link * IExpressionEvaluator} instantly. *

*

* If the parameter and return types of the expression are known at com.hazelcast.com.ile time, then a "fast" expression evaluator * can be instantiated through {@link #createFastExpressionEvaluator(String, Class, String[], ClassLoader)}. * 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);
 *     }
 *     ...
 *     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 {@code interfaceToImplement} must either be declared {@code 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?) *

*/ public class ExpressionEvaluator extends ScriptEvaluator implements IExpressionEvaluator { /** * Equivalent to *
     *     ExpressionEvaluator ee = new ExpressionEvaluator();
     *     ee.setExpressionType(expressionType);
     *     ee.setParameters(parameterNames, parameterTypes);
     *     ee.cook(expression);
     * 
* * @see #ExpressionEvaluator() * @see ExpressionEvaluator#setExpressionType(Class) * @see ScriptEvaluator#setParameters(String[], Class[]) * @see Cookable#cook(String) */ public ExpressionEvaluator(String expression, Class expressionType, String[] parameterNames, Class[] parameterTypes) throws CompileException { this.setExpressionType(expressionType); this.setParameters(parameterNames, parameterTypes); this.cook(expression); } /** * Equivalent to *
     *     ExpressionEvaluator ee = new ExpressionEvaluator();
     *     ee.setExpressionType(expressionType);
     *     ee.setParameters(parameterNames, parameterTypes);
     *     ee.setThrownExceptions(thrownExceptions);
     *     ee.setParentClassLoader(optionalParentClassLoader);
     *     ee.cook(expression);
     * 
* * @see #ExpressionEvaluator() * @see ExpressionEvaluator#setExpressionType(Class) * @see ScriptEvaluator#setParameters(String[], Class[]) * @see ScriptEvaluator#setThrownExceptions(Class[]) * @see SimpleCompiler#setParentClassLoader(ClassLoader) * @see Cookable#cook(String) */ public ExpressionEvaluator( String expression, Class expressionType, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, @Nullable ClassLoader optionalParentClassLoader ) throws CompileException { this.setExpressionType(expressionType); this.setParameters(parameterNames, parameterTypes); this.setThrownExceptions(thrownExceptions); this.setParentClassLoader(optionalParentClassLoader); this.cook(expression); } /** * Equivalent to *
     *     ExpressionEvaluator ee = new ExpressionEvaluator();
     *     ee.setExpressionType(expressionType);
     *     ee.setParameters(parameterNames, parameterTypes);
     *     ee.setThrownExceptions(thrownExceptions);
     *     ee.setExtendedType(optionalExtendedType);
     *     ee.setImplementedTypes(implementedTypes);
     *     ee.setParentClassLoader(optionalParentClassLoader);
     *     ee.cook(expression);
     * 
* * @see #ExpressionEvaluator() * @see ExpressionEvaluator#setExpressionType(Class) * @see ScriptEvaluator#setParameters(String[], Class[]) * @see ScriptEvaluator#setThrownExceptions(Class[]) * @see ClassBodyEvaluator#setExtendedClass(Class) * @see ClassBodyEvaluator#setImplementedInterfaces(Class[]) * @see SimpleCompiler#setParentClassLoader(ClassLoader) * @see Cookable#cook(String) */ public ExpressionEvaluator( String expression, Class expressionType, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, @Nullable Class optionalExtendedType, Class[] implementedTypes, @Nullable ClassLoader optionalParentClassLoader ) throws CompileException { this.setExpressionType(expressionType); this.setParameters(parameterNames, parameterTypes); this.setThrownExceptions(thrownExceptions); this.setExtendedClass(optionalExtendedType); this.setImplementedInterfaces(implementedTypes); this.setParentClassLoader(optionalParentClassLoader); this.cook(expression); } /** * Creates an expression evaluator with the full configurability. *

* Equivalent to: *

*
     *     ExpressionEvaluator ee = new ExpressionEvaluator();
     *     ee.setClassName(className);
     *     ee.setExtendedType(optionalExtendedType);
     *     ee.setImplementedTypes(implementedTypes);
     *     ee.setStaticMethod(staticMethod);
     *     ee.setExpressionType(expressionType);
     *     ee.setMethodName(methodName);
     *     ee.setParameters(parameterNames, parameterTypes);
     *     ee.setThrownExceptions(thrownExceptions);
     *     ee.setParentClassLoader(optionalParentClassLoader);
     *     ee.cook(scanner);
     * 
* * @see IExpressionEvaluator * @see IClassBodyEvaluator#setClassName(String) * @see IClassBodyEvaluator#setExtendedClass(Class) * @see IClassBodyEvaluator#setImplementedInterfaces(Class[]) * @see IScriptEvaluator#setStaticMethod(boolean) * @see IExpressionEvaluator#setExpressionType(Class) * @see IScriptEvaluator#setMethodName(String) * @see IScriptEvaluator#setParameters(String[], Class[]) * @see IScriptEvaluator#setThrownExceptions(Class[]) * @see ISimpleCompiler#setParentClassLoader(ClassLoader) * @see ICookable#cook(Reader) */ public ExpressionEvaluator( Scanner scanner, String className, @Nullable Class optionalExtendedType, Class[] implementedTypes, boolean staticMethod, Class expressionType, String methodName, String[] parameterNames, Class[] parameterTypes, Class[] thrownExceptions, @Nullable ClassLoader optionalParentClassLoader ) throws CompileException, IOException { this.setClassName(className); this.setExtendedClass(optionalExtendedType); this.setImplementedInterfaces(implementedTypes); this.setStaticMethod(staticMethod); this.setExpressionType(expressionType); this.setMethodName(methodName); this.setParameters(parameterNames, parameterTypes); this.setThrownExceptions(thrownExceptions); this.setParentClassLoader(optionalParentClassLoader); this.cook(scanner); } public ExpressionEvaluator() {} /** * @deprecated Must not be used on an {@link IExpressionEvaluator}; use {@link #setExpressionType(Class)} instead */ @Deprecated @Override public void setReturnType(Class expressionType) { super.setReturnType(expressionType); } /** * @deprecated Must not be used on an {@link IExpressionEvaluator}; use {@link #setExpressionTypes(Class[])} * instead */ @Deprecated @Override public void setReturnTypes(Class[] expressionTypes) { super.setReturnTypes(expressionTypes); } @Override public void setExpressionType(Class expressionType) { super.setReturnType(expressionType); } @Override public void setExpressionTypes(Class[] expressionTypes) { super.setReturnTypes(expressionTypes); } @Override protected Class getDefaultReturnType() { return Object.class; } @Override protected void makeStatements( int idx, Parser parser, List resultStatements, List resultMethods ) throws CompileException, IOException { // Parse the expression. Rvalue value = parser.parseExpression().toRvalueOrCompileException(); Class et = this.getReturnType(idx); if (et == void.class) { resultStatements.add(new Java.ExpressionStatement(value)); } else { resultStatements.add(new Java.ReturnStatement(parser.location(), value)); } if (!parser.peek(TokenType.END_OF_INPUT)) { throw new CompileException("Unexpected token \"" + parser.peek() + "\"", parser.location()); } } /** * @deprecated Use {@link #createFastEvaluator(String, Class, String[])} instead: */ @Deprecated public static Object createFastExpressionEvaluator( String expression, Class interfaceToImplement, String[] parameterNames, @Nullable ClassLoader optionalParentClassLoader ) throws CompileException { IExpressionEvaluator ee = new ExpressionEvaluator(); ee.setParentClassLoader(optionalParentClassLoader); return ee.createFastEvaluator(expression, interfaceToImplement, parameterNames); } /** * @deprecated Use {@link #createFastEvaluator(Reader, Class, String[])} instead */ @Deprecated public static Object createFastExpressionEvaluator( Scanner scanner, String className, @Nullable Class optionalExtendedType, Class interfaceToImplement, String[] parameterNames, @Nullable ClassLoader optionalParentClassLoader ) throws CompileException, IOException { ExpressionEvaluator ee = new ExpressionEvaluator(); ee.setClassName(className); ee.setExtendedClass(optionalExtendedType); ee.setParentClassLoader(optionalParentClassLoader); return ee.createFastEvaluator(scanner, interfaceToImplement, parameterNames); } /** * @deprecated Use {@link #createFastEvaluator(Reader, Class, String[])} instead */ @Deprecated public static Object createFastExpressionEvaluator( Scanner scanner, @Nullable String[] optionalDefaultImports, String className, @Nullable Class optionalExtendedType, Class interfaceToImplement, String[] parameterNames, @Nullable ClassLoader optionalParentClassLoader ) throws CompileException, IOException { ExpressionEvaluator ee = new ExpressionEvaluator(); ee.setClassName(className); ee.setExtendedClass(optionalExtendedType); ee.setDefaultImports(optionalDefaultImports); ee.setParentClassLoader(optionalParentClassLoader); return ee.createFastEvaluator(scanner, interfaceToImplement, parameterNames); } /** * Guess the names of the parameters used in the given expression. The strategy is to look * at all "ambiguous names" in the expression (e.g. in "a.b.c.d()", the ambiguous name * is "a.b.c"), and then at the first com.hazelcast.com.onents of the ambiguous name. *
    *
  • If any com.hazelcast.com.onent starts with an upper-case letter, then ambiguous name is assumed to be a type name.
  • *
  • Otherwise, it is assumed to be a parameter name.
  • *
* * @see Scanner#Scanner(String, Reader) */ public static String[] guessParameterNames(Scanner scanner) throws CompileException, IOException { Parser parser = new Parser(scanner); // Eat optional leading import declarations. while (parser.peek("import")) parser.parseImportDeclaration(); // Parse the expression. Rvalue rvalue = parser.parseExpression().toRvalueOrCompileException(); if (!parser.peek(TokenType.END_OF_INPUT)) { throw new CompileException("Unexpected token \"" + parser.peek() + "\"", scanner.location()); } // Traverse the expression for ambiguous names and guess which of them are parameter names. final Set parameterNames = new HashSet(); new AbstractTraverser() { @Override public void traverseAmbiguousName(AmbiguousName an) { // If any of the com.hazelcast.com.onents starts with an upper-case letter, then the ambiguous // name is most probably a type name, e.g. "System.out" or "java.lang.System.out". for (String identifier : an.identifiers) { if (Character.isUpperCase(identifier.charAt(0))) return; } // It's most probably a parameter name (although it could be a field name as well). parameterNames.add(an.identifiers[0]); } }.visitAtom(rvalue); return (String[]) parameterNames.toArray(new String[parameterNames.size()]); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy