Search in sources :

Example 1 with JexlMethod

use of org.apache.commons.jexl3.introspection.JexlMethod in project commons-jexl by apache.

the class Interpreter method visit.

@Override
protected Object visit(final ASTConstructorNode node, final Object data) {
    if (isCancelled()) {
        throw new JexlException.Cancel(node);
    }
    // first child is class or class name
    final Object target = node.jjtGetChild(0).jjtAccept(this, data);
    // get the ctor args
    final int argc = node.jjtGetNumChildren() - 1;
    Object[] argv = new Object[argc];
    for (int i = 0; i < argc; i++) {
        argv[i] = node.jjtGetChild(i + 1).jjtAccept(this, data);
    }
    try {
        final boolean cacheable = cache;
        // attempt to reuse last funcall cached in volatile JexlNode.value
        if (cacheable) {
            final Object cached = node.jjtGetValue();
            if (cached instanceof Funcall) {
                final Object eval = ((Funcall) cached).tryInvoke(this, null, target, argv);
                if (JexlEngine.TRY_FAILED != eval) {
                    return eval;
                }
            }
        }
        boolean narrow = false;
        JexlMethod ctor = null;
        Funcall funcall = null;
        while (true) {
            // try as stated
            ctor = uberspect.getConstructor(target, argv);
            if (ctor != null) {
                if (cacheable && ctor.isCacheable()) {
                    funcall = new Funcall(ctor, narrow);
                }
                break;
            }
            // try with prepending context as first argument
            final Object[] nargv = callArguments(context, narrow, argv);
            ctor = uberspect.getConstructor(target, nargv);
            if (ctor != null) {
                if (cacheable && ctor.isCacheable()) {
                    funcall = new ContextualCtor(ctor, narrow);
                }
                argv = nargv;
                break;
            }
            // attempt to narrow the parameters and if this succeeds, try again in next loop
            if (!narrow && arithmetic.narrowArguments(argv)) {
                narrow = true;
                continue;
            }
            // we are done trying
            break;
        }
        // we have either evaluated and returned or might have found a ctor
        if (ctor != null) {
            final Object eval = ctor.invoke(target, argv);
            // cache executor in volatile JexlNode.value
            if (funcall != null) {
                node.jjtSetValue(funcall);
            }
            return eval;
        }
        final String tstr = target != null ? target.toString() : "?";
        return unsolvableMethod(node, tstr, argv);
    } catch (final JexlException.Method xmethod) {
        throw xmethod;
    } catch (final Exception xany) {
        final String tstr = target != null ? target.toString() : "?";
        throw invocationException(node, tstr, xany);
    }
}
Also used : JexlMethod(org.apache.commons.jexl3.introspection.JexlMethod) JexlException(org.apache.commons.jexl3.JexlException) JexlException(org.apache.commons.jexl3.JexlException)

Example 2 with JexlMethod

use of org.apache.commons.jexl3.introspection.JexlMethod in project commons-jexl by apache.

the class Engine method doCreateInstance.

/**
 * Creates a new instance of an object using the most appropriate constructor
 * based on the arguments.
 * @param clazz the class to instantiate
 * @param args  the constructor arguments
 * @return the created object instance or null on failure when silent
 */
protected Object doCreateInstance(final Object clazz, final Object... args) {
    JexlException xjexl = null;
    Object result = null;
    final JexlInfo info = debug ? createInfo() : null;
    try {
        JexlMethod ctor = uberspect.getConstructor(clazz, args);
        if (ctor == null && arithmetic.narrowArguments(args)) {
            ctor = uberspect.getConstructor(clazz, args);
        }
        if (ctor != null) {
            result = ctor.invoke(clazz, args);
        } else {
            xjexl = new JexlException.Method(info, clazz.toString(), args);
        }
    } catch (final JexlException xany) {
        xjexl = xany;
    } catch (final Exception xany) {
        xjexl = new JexlException.Method(info, clazz.toString(), args, xany);
    }
    if (xjexl != null) {
        if (silent) {
            if (logger.isWarnEnabled()) {
                logger.warn(xjexl.getMessage(), xjexl.getCause());
            }
            return null;
        }
        throw xjexl.clean();
    }
    return result;
}
Also used : JexlMethod(org.apache.commons.jexl3.introspection.JexlMethod) JexlException(org.apache.commons.jexl3.JexlException) JexlInfo(org.apache.commons.jexl3.JexlInfo) JexlMethod(org.apache.commons.jexl3.introspection.JexlMethod) JexlException(org.apache.commons.jexl3.JexlException)

Example 3 with JexlMethod

use of org.apache.commons.jexl3.introspection.JexlMethod in project commons-jexl by apache.

the class Engine method invokeMethod.

@Override
public Object invokeMethod(final Object obj, final String meth, final Object... args) {
    JexlException xjexl = null;
    Object result = null;
    final JexlInfo info = debug ? createInfo() : null;
    try {
        JexlMethod method = uberspect.getMethod(obj, meth, args);
        if (method == null && arithmetic.narrowArguments(args)) {
            method = uberspect.getMethod(obj, meth, args);
        }
        if (method != null) {
            result = method.invoke(obj, args);
        } else {
            xjexl = new JexlException.Method(info, meth, args);
        }
    } catch (final JexlException xany) {
        xjexl = xany;
    } catch (final Exception xany) {
        xjexl = new JexlException.Method(info, meth, args, xany);
    }
    if (xjexl != null) {
        if (!silent) {
            throw xjexl.clean();
        }
        if (logger.isWarnEnabled()) {
            logger.warn(xjexl.getMessage(), xjexl.getCause());
        }
    }
    return result;
}
Also used : JexlMethod(org.apache.commons.jexl3.introspection.JexlMethod) JexlException(org.apache.commons.jexl3.JexlException) JexlInfo(org.apache.commons.jexl3.JexlInfo) JexlMethod(org.apache.commons.jexl3.introspection.JexlMethod) JexlException(org.apache.commons.jexl3.JexlException)

Example 4 with JexlMethod

use of org.apache.commons.jexl3.introspection.JexlMethod in project commons-jexl by apache.

the class Operators method tryOverload.

/**
 * Attempts to call an operator.
 * <p>
 * This takes care of finding and caching the operator method when appropriate
 * @param node     the syntactic node
 * @param operator the operator
 * @param args     the arguments
 * @return the result of the operator evaluation or TRY_FAILED
 */
protected Object tryOverload(final JexlNode node, final JexlOperator operator, final Object... args) {
    if (operators != null && operators.overloads(operator)) {
        final JexlArithmetic arithmetic = interpreter.arithmetic;
        final boolean cache = interpreter.cache;
        try {
            if (cache) {
                final Object cached = node.jjtGetValue();
                if (cached instanceof JexlMethod) {
                    final JexlMethod me = (JexlMethod) cached;
                    final Object eval = me.tryInvoke(operator.getMethodName(), arithmetic, args);
                    if (!me.tryFailed(eval)) {
                        return eval;
                    }
                }
            }
            final JexlMethod vm = operators.getOperator(operator, args);
            if (vm != null && !isArithmetic(vm)) {
                final Object result = vm.invoke(arithmetic, args);
                if (cache) {
                    node.jjtSetValue(vm);
                }
                return result;
            }
        } catch (final Exception xany) {
            return interpreter.operatorError(node, operator, xany);
        }
    }
    return JexlEngine.TRY_FAILED;
}
Also used : JexlMethod(org.apache.commons.jexl3.introspection.JexlMethod) JexlArithmetic(org.apache.commons.jexl3.JexlArithmetic) JexlException(org.apache.commons.jexl3.JexlException)

Example 5 with JexlMethod

use of org.apache.commons.jexl3.introspection.JexlMethod in project commons-jexl by apache.

the class Operators method contains.

/**
 * The 'match'/'in' operator implementation.
 * <p>
 * Note that 'x in y' or 'x matches y' means 'y contains x' ;
 * the JEXL operator arguments order syntax is the reverse of this method call.
 * </p>
 * @param node  the node
 * @param op    the calling operator, =~ or !~
 * @param right the left operand
 * @param left  the right operand
 * @return true if left matches right, false otherwise
 */
protected boolean contains(final JexlNode node, final String op, final Object left, final Object right) {
    final JexlArithmetic arithmetic = interpreter.arithmetic;
    final JexlUberspect uberspect = interpreter.uberspect;
    try {
        // try operator overload
        final Object result = tryOverload(node, JexlOperator.CONTAINS, left, right);
        if (result instanceof Boolean) {
            return (Boolean) result;
        }
        // use arithmetic / pattern matching ?
        final Boolean matched = arithmetic.contains(left, right);
        if (matched != null) {
            return matched;
        }
        // try a contains method (duck type set)
        try {
            final Object[] argv = { right };
            JexlMethod vm = uberspect.getMethod(left, "contains", argv);
            if (returnsBoolean(vm)) {
                return (Boolean) vm.invoke(left, argv);
            }
            if (arithmetic.narrowArguments(argv)) {
                vm = uberspect.getMethod(left, "contains", argv);
                if (returnsBoolean(vm)) {
                    return (Boolean) vm.invoke(left, argv);
                }
            }
        } catch (final Exception e) {
            throw new JexlException(node, op + " error", e);
        }
        // defaults to equal
        return arithmetic.equals(left, right);
    } catch (final ArithmeticException xrt) {
        throw new JexlException(node, op + " error", xrt);
    }
}
Also used : JexlMethod(org.apache.commons.jexl3.introspection.JexlMethod) JexlException(org.apache.commons.jexl3.JexlException) JexlUberspect(org.apache.commons.jexl3.introspection.JexlUberspect) JexlArithmetic(org.apache.commons.jexl3.JexlArithmetic) JexlException(org.apache.commons.jexl3.JexlException)

Aggregations

JexlMethod (org.apache.commons.jexl3.introspection.JexlMethod)18 JexlException (org.apache.commons.jexl3.JexlException)14 JexlArithmetic (org.apache.commons.jexl3.JexlArithmetic)7 JexlUberspect (org.apache.commons.jexl3.introspection.JexlUberspect)7 Test (org.junit.Test)4 JexlPropertyGet (org.apache.commons.jexl3.introspection.JexlPropertyGet)3 JexlInfo (org.apache.commons.jexl3.JexlInfo)2 ASTNumberLiteral (org.apache.commons.jexl3.parser.ASTNumberLiteral)2 JexlNode (org.apache.commons.jexl3.parser.JexlNode)2 HashMap (java.util.HashMap)1 Map (java.util.Map)1 Optional (java.util.Optional)1 JexlOperator (org.apache.commons.jexl3.JexlOperator)1 JexlScript (org.apache.commons.jexl3.JexlScript)1 JexlPropertySet (org.apache.commons.jexl3.introspection.JexlPropertySet)1 ASTIdentifier (org.apache.commons.jexl3.parser.ASTIdentifier)1 ASTIdentifierAccess (org.apache.commons.jexl3.parser.ASTIdentifierAccess)1 ASTJexlScript (org.apache.commons.jexl3.parser.ASTJexlScript)1