Search in sources :

Example 6 with And

use of org.mvel2.ast.And in project drools by kiegroup.

the class MVELDialectRuntimeData method getParserConfiguration.

public ParserConfiguration getParserConfiguration() {
    if (parserConfiguration == null) {
        ClassLoader packageClassLoader = getPackageClassLoader();
        String key = null;
        Object value = null;
        try {
            // First replace fields and method tokens with actual instances
            for (Entry<String, Object> entry : this.imports.entrySet()) {
                key = entry.getKey();
                value = entry.getValue();
                if (entry.getValue() instanceof String) {
                    String str = (String) value;
                    // @TODO MVEL doesn't yet support importing of fields
                    if (str.startsWith("m:")) {
                        Class cls = packageClassLoader.loadClass(str.substring(2));
                        for (Method method : cls.getDeclaredMethods()) {
                            if (method.getName().equals(key)) {
                                entry.setValue(method);
                                break;
                            }
                        }
                    } else {
                        Class cls = packageClassLoader.loadClass(str);
                        entry.setValue(cls);
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("Unable to resolve method of field: " + key + " - " + value, e);
        }
        final ParserConfiguration conf = new ParserConfiguration();
        conf.setImports(this.imports);
        conf.setPackageImports(this.packageImports);
        conf.setClassLoader(packageClassLoader);
        this.parserConfiguration = conf;
    }
    return this.parserConfiguration;
}
Also used : Method(java.lang.reflect.Method) ParserConfiguration(org.mvel2.ParserConfiguration)

Example 7 with And

use of org.mvel2.ast.And in project drools by kiegroup.

the class MethodComparator method getMethodBytecode.

/**
 * This will return a series of bytecode instructions which can be used to compare one method with another.
 * debug info like local var declarations and line numbers are ignored, so the focus is on the content.
 */
public static List getMethodBytecode(final String methodName, final byte[] bytes) {
    final Tracer visit = new Tracer(methodName);
    final ClassReader classReader = new ClassReader(bytes);
    classReader.accept(visit, ClassReader.SKIP_DEBUG);
    return visit.getText();
}
Also used : ClassReader(org.mvel2.asm.ClassReader)

Example 8 with And

use of org.mvel2.ast.And in project mvel by mvel.

the class Analyzer method analyze.

/**
 * Analyzes the given method.
 *
 * @param owner
 *            the internal name of the class to which the method belongs.
 * @param m
 *            the method to be analyzed.
 * @return the symbolic state of the execution stack frame at each bytecode
 *         instruction of the method. The size of the returned array is
 *         equal to the number of instructions (and labels) of the method. A
 *         given frame is <tt>null</tt> if and only if the corresponding
 *         instruction cannot be reached (dead code).
 * @throws AnalyzerException
 *             if a problem occurs during the analysis.
 */
@SuppressWarnings("unchecked")
public Frame<V>[] analyze(final String owner, final MethodNode m) throws AnalyzerException {
    if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
        frames = (Frame<V>[]) new Frame<?>[0];
        return frames;
    }
    n = m.instructions.size();
    insns = m.instructions;
    handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
    frames = (Frame<V>[]) new Frame<?>[n];
    subroutines = new Subroutine[n];
    queued = new boolean[n];
    queue = new int[n];
    top = 0;
    // computes exception handlers for each instruction
    for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
        TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
        int begin = insns.indexOf(tcb.start);
        int end = insns.indexOf(tcb.end);
        for (int j = begin; j < end; ++j) {
            List<TryCatchBlockNode> insnHandlers = handlers[j];
            if (insnHandlers == null) {
                insnHandlers = new ArrayList<TryCatchBlockNode>();
                handlers[j] = insnHandlers;
            }
            insnHandlers.add(tcb);
        }
    }
    // computes the subroutine for each instruction:
    Subroutine main = new Subroutine(null, m.maxLocals, null);
    List<AbstractInsnNode> subroutineCalls = new ArrayList<AbstractInsnNode>();
    Map<LabelNode, Subroutine> subroutineHeads = new HashMap<LabelNode, Subroutine>();
    findSubroutine(0, main, subroutineCalls);
    while (!subroutineCalls.isEmpty()) {
        JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
        Subroutine sub = subroutineHeads.get(jsr.label);
        if (sub == null) {
            sub = new Subroutine(jsr.label, m.maxLocals, jsr);
            subroutineHeads.put(jsr.label, sub);
            findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
        } else {
            sub.callers.add(jsr);
        }
    }
    for (int i = 0; i < n; ++i) {
        if (subroutines[i] != null && subroutines[i].start == null) {
            subroutines[i] = null;
        }
    }
    // initializes the data structures for the control flow analysis
    Frame<V> current = newFrame(m.maxLocals, m.maxStack);
    Frame<V> handler = newFrame(m.maxLocals, m.maxStack);
    current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
    Type[] args = Type.getArgumentTypes(m.desc);
    int local = 0;
    if ((m.access & ACC_STATIC) == 0) {
        Type ctype = Type.getObjectType(owner);
        current.setLocal(local++, interpreter.newValue(ctype));
    }
    for (int i = 0; i < args.length; ++i) {
        current.setLocal(local++, interpreter.newValue(args[i]));
        if (args[i].getSize() == 2) {
            current.setLocal(local++, interpreter.newValue(null));
        }
    }
    while (local < m.maxLocals) {
        current.setLocal(local++, interpreter.newValue(null));
    }
    merge(0, current, null);
    init(owner, m);
    // control flow analysis
    while (top > 0) {
        int insn = queue[--top];
        Frame<V> f = frames[insn];
        Subroutine subroutine = subroutines[insn];
        queued[insn] = false;
        AbstractInsnNode insnNode = null;
        try {
            insnNode = m.instructions.get(insn);
            int insnOpcode = insnNode.getOpcode();
            int insnType = insnNode.getType();
            if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
                merge(insn + 1, f, subroutine);
                newControlFlowEdge(insn, insn + 1);
            } else {
                current.init(f).execute(insnNode, interpreter);
                subroutine = subroutine == null ? null : subroutine.copy();
                if (insnNode instanceof JumpInsnNode) {
                    JumpInsnNode j = (JumpInsnNode) insnNode;
                    if (insnOpcode != GOTO && insnOpcode != JSR) {
                        merge(insn + 1, current, subroutine);
                        newControlFlowEdge(insn, insn + 1);
                    }
                    int jump = insns.indexOf(j.label);
                    if (insnOpcode == JSR) {
                        merge(jump, current, new Subroutine(j.label, m.maxLocals, j));
                    } else {
                        merge(jump, current, subroutine);
                    }
                    newControlFlowEdge(insn, jump);
                } else if (insnNode instanceof LookupSwitchInsnNode) {
                    LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
                    int jump = insns.indexOf(lsi.dflt);
                    merge(jump, current, subroutine);
                    newControlFlowEdge(insn, jump);
                    for (int j = 0; j < lsi.labels.size(); ++j) {
                        LabelNode label = lsi.labels.get(j);
                        jump = insns.indexOf(label);
                        merge(jump, current, subroutine);
                        newControlFlowEdge(insn, jump);
                    }
                } else if (insnNode instanceof TableSwitchInsnNode) {
                    TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
                    int jump = insns.indexOf(tsi.dflt);
                    merge(jump, current, subroutine);
                    newControlFlowEdge(insn, jump);
                    for (int j = 0; j < tsi.labels.size(); ++j) {
                        LabelNode label = tsi.labels.get(j);
                        jump = insns.indexOf(label);
                        merge(jump, current, subroutine);
                        newControlFlowEdge(insn, jump);
                    }
                } else if (insnOpcode == RET) {
                    if (subroutine == null) {
                        throw new AnalyzerException(insnNode, "RET instruction outside of a sub routine");
                    }
                    for (int i = 0; i < subroutine.callers.size(); ++i) {
                        JumpInsnNode caller = subroutine.callers.get(i);
                        int call = insns.indexOf(caller);
                        if (frames[call] != null) {
                            merge(call + 1, frames[call], current, subroutines[call], subroutine.access);
                            newControlFlowEdge(insn, call + 1);
                        }
                    }
                } else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
                    if (subroutine != null) {
                        if (insnNode instanceof VarInsnNode) {
                            int var = ((VarInsnNode) insnNode).var;
                            subroutine.access[var] = true;
                            if (insnOpcode == LLOAD || insnOpcode == DLOAD || insnOpcode == LSTORE || insnOpcode == DSTORE) {
                                subroutine.access[var + 1] = true;
                            }
                        } else if (insnNode instanceof IincInsnNode) {
                            int var = ((IincInsnNode) insnNode).var;
                            subroutine.access[var] = true;
                        }
                    }
                    merge(insn + 1, current, subroutine);
                    newControlFlowEdge(insn, insn + 1);
                }
            }
            List<TryCatchBlockNode> insnHandlers = handlers[insn];
            if (insnHandlers != null) {
                for (int i = 0; i < insnHandlers.size(); ++i) {
                    TryCatchBlockNode tcb = insnHandlers.get(i);
                    Type type;
                    if (tcb.type == null) {
                        type = Type.getObjectType("java/lang/Throwable");
                    } else {
                        type = Type.getObjectType(tcb.type);
                    }
                    int jump = insns.indexOf(tcb.handler);
                    if (newControlFlowExceptionEdge(insn, tcb)) {
                        handler.init(f);
                        handler.clearStack();
                        handler.push(interpreter.newValue(type));
                        merge(jump, handler, subroutine);
                    }
                }
            }
        } catch (AnalyzerException e) {
            throw new AnalyzerException(e.node, "Error at instruction " + insn + ": " + e.getMessage(), e);
        } catch (Exception e) {
            throw new AnalyzerException(insnNode, "Error at instruction " + insn + ": " + e.getMessage(), e);
        }
    }
    return frames;
}
Also used : LabelNode(org.mvel2.asm.tree.LabelNode) TryCatchBlockNode(org.mvel2.asm.tree.TryCatchBlockNode) TableSwitchInsnNode(org.mvel2.asm.tree.TableSwitchInsnNode) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) AbstractInsnNode(org.mvel2.asm.tree.AbstractInsnNode) Type(org.mvel2.asm.Type) JumpInsnNode(org.mvel2.asm.tree.JumpInsnNode) IincInsnNode(org.mvel2.asm.tree.IincInsnNode) ArrayList(java.util.ArrayList) List(java.util.List) InsnList(org.mvel2.asm.tree.InsnList) LookupSwitchInsnNode(org.mvel2.asm.tree.LookupSwitchInsnNode) VarInsnNode(org.mvel2.asm.tree.VarInsnNode)

Example 9 with And

use of org.mvel2.ast.And in project mvel by mvel.

the class MVELRuntime method execute.

/**
 * Main interpreter.
 *
 * @param debugger        Run in debug mode
 * @param expression      The compiled expression object
 * @param ctx             The root context object
 * @param variableFactory The variable factory to be injected
 * @return The resultant value
 * @see org.mvel2.MVEL
 */
public static Object execute(boolean debugger, final CompiledExpression expression, final Object ctx, VariableResolverFactory variableFactory) {
    Object v1, v2;
    ExecutionStack stk = new ExecutionStack();
    ASTNode tk = expression.getFirstNode();
    Integer operator;
    if (tk == null)
        return null;
    try {
        do {
            if (tk.fields == -1) {
                /**
                 * This may seem silly and redundant, however, when an MVEL script recurses into a block
                 * or substatement, a new runtime loop is entered.   Since the debugger state is not
                 * passed through the AST, it is not possible to forward the state directly.  So when we
                 * encounter a debugging symbol, we check the thread local to see if there is are registered
                 * breakpoints.  If we find them, we assume that we are debugging.
                 *
                 * The consequence of this of course, is that it's not ideal to compileShared expressions with
                 * debugging symbols which you plan to use in a production enviroment.
                 */
                if (debugger || (debugger = hasDebuggerContext())) {
                    try {
                        debuggerContext.get().checkBreak((LineLabel) tk, variableFactory, expression);
                    } catch (NullPointerException e) {
                    // do nothing for now.  this isn't as calus as it seems.
                    }
                }
                continue;
            } else if (stk.isEmpty()) {
                stk.push(tk.getReducedValueAccelerated(ctx, ctx, variableFactory));
            }
            if (variableFactory.tiltFlag()) {
                return stk.pop();
            }
            switch(operator = tk.getOperator()) {
                case RETURN:
                    variableFactory.setTiltFlag(true);
                    return stk.pop();
                case NOOP:
                    continue;
                case TERNARY:
                    if (!stk.popBoolean()) {
                        // noinspection StatementWithEmptyBody
                        while (tk.nextASTNode != null && !(tk = tk.nextASTNode).isOperator(TERNARY_ELSE)) ;
                    }
                    stk.clear();
                    continue;
                case TERNARY_ELSE:
                    return stk.pop();
                case END_OF_STMT:
                    /**
                     * If the program doesn't end here then we wipe anything off the stack that remains.
                     * Althought it may seem like intuitive stack optimizations could be leveraged by
                     * leaving hanging values on the stack,  trust me it's not a good idea.
                     */
                    if (tk.nextASTNode != null) {
                        stk.clear();
                    }
                    continue;
            }
            stk.push(tk.nextASTNode.getReducedValueAccelerated(ctx, ctx, variableFactory), operator);
            try {
                while (stk.isReduceable()) {
                    if ((Integer) stk.peek() == CHOR) {
                        stk.pop();
                        v1 = stk.pop();
                        v2 = stk.pop();
                        if (!isEmpty(v2) || !isEmpty(v1)) {
                            stk.clear();
                            stk.push(!isEmpty(v2) ? v2 : v1);
                        } else
                            stk.push(null);
                    } else {
                        stk.op();
                    }
                }
            } catch (ClassCastException e) {
                throw new CompileException("syntax error or incomptable types", new char[0], 0, e);
            } catch (CompileException e) {
                throw e;
            } catch (Exception e) {
                throw new CompileException("failed to compileShared sub expression", new char[0], 0, e);
            }
        } while ((tk = tk.nextASTNode) != null);
        return stk.peek();
    } catch (NullPointerException e) {
        if (tk != null && tk.isOperator() && tk.nextASTNode != null) {
            throw new CompileException("incomplete statement: " + tk.getName() + " (possible use of reserved keyword as identifier: " + tk.getName() + ")", tk.getExpr(), tk.getStart());
        } else {
            throw e;
        }
    } finally {
        OptimizerFactory.clearThreadAccessorOptimizer();
    }
}
Also used : ExecutionStack(org.mvel2.util.ExecutionStack) ASTNode(org.mvel2.ast.ASTNode)

Example 10 with And

use of org.mvel2.ast.And in project mvel by mvel.

the class PropertyAccessor method getMethod.

/**
 * Find an appropriate method, execute it, and return it's response.
 *
 * @param ctx  -
 * @param name -
 * @return -
 */
@SuppressWarnings({ "unchecked" })
private Object getMethod(Object ctx, String name) {
    int _start = cursor;
    String tk = cursor != end && property[cursor] == '(' && ((cursor = balancedCapture(property, cursor, '(')) - _start) > 1 ? new String(property, _start + 1, cursor - _start - 1) : "";
    cursor++;
    Object[] args;
    if (tk.length() == 0) {
        args = ParseTools.EMPTY_OBJ_ARR;
    } else {
        List<char[]> subtokens = parseParameterList(tk.toCharArray(), 0, -1);
        args = new Object[subtokens.size()];
        for (int i = 0; i < subtokens.size(); i++) {
            args[i] = eval(subtokens.get(i), thisReference, variableFactory);
        }
    }
    if (first && variableFactory != null && variableFactory.isResolveable(name)) {
        Object ptr = variableFactory.getVariableResolver(name).getValue();
        if (ptr instanceof Method) {
            ctx = ((Method) ptr).getDeclaringClass();
            name = ((Method) ptr).getName();
        } else if (ptr instanceof MethodStub) {
            ctx = ((MethodStub) ptr).getClassReference();
            name = ((MethodStub) ptr).getMethodName();
        } else if (ptr instanceof FunctionInstance) {
            ((FunctionInstance) ptr).getFunction().checkArgumentCount(args.length);
            return ((FunctionInstance) ptr).call(null, thisReference, variableFactory, args);
        } else {
            throw new OptimizationFailure("attempt to optimize a method call for a reference that does not point to a method: " + name + " (reference is type: " + (ctx != null ? ctx.getClass().getName() : null) + ")");
        }
        first = false;
    }
    if (ctx == null)
        throw new CompileException("no such method or function: " + name, property, cursor);
    /**
     * If the target object is an instance of java.lang.Class itself then do not
     * adjust the Class scope target.
     */
    Class cls = currType != null ? currType : ((ctx instanceof Class ? (Class) ctx : ctx.getClass()));
    currType = null;
    if (cls == Proto.ProtoInstance.class) {
        return ((Proto.ProtoInstance) ctx).get(name).call(null, thisReference, variableFactory, args);
    }
    /**
     * Check to see if we have already cached this method;
     */
    Object[] cache = checkMethodCache(cls, createSignature(name, tk));
    Method m;
    Class[] parameterTypes;
    if (cache != null) {
        m = (Method) cache[0];
        parameterTypes = (Class[]) cache[1];
    } else {
        m = null;
        parameterTypes = null;
    }
    /**
     * If we have not cached the method then we need to go ahead and try to resolve it.
     */
    if (m == null) {
        /**
         * Try to find an instance method from the class target.
         */
        if ((m = getBestCandidate(args, name, cls, cls.getMethods(), false)) != null) {
            addMethodCache(cls, createSignature(name, tk), m);
            parameterTypes = m.getParameterTypes();
        }
        if (m == null) {
            /**
             * If we didn't find anything, maybe we're looking for the actual java.lang.Class methods.
             */
            if ((m = getBestCandidate(args, name, cls, cls.getDeclaredMethods(), false)) != null) {
                addMethodCache(cls, createSignature(name, tk), m);
                parameterTypes = m.getParameterTypes();
            }
        }
    }
    // If we didn't find anything and the declared class is different from the actual one try also with the actual one
    if (m == null && cls != ctx.getClass() && !(ctx instanceof Class)) {
        cls = ctx.getClass();
        if ((m = getBestCandidate(args, name, cls, cls.getDeclaredMethods(), false)) != null) {
            addMethodCache(cls, createSignature(name, tk), m);
            parameterTypes = m.getParameterTypes();
        }
    }
    if (ctx instanceof PrototypalFunctionInstance) {
        final VariableResolverFactory funcCtx = ((PrototypalFunctionInstance) ctx).getResolverFactory();
        Object prop = funcCtx.getVariableResolver(name).getValue();
        if (prop instanceof PrototypalFunctionInstance) {
            return ((PrototypalFunctionInstance) prop).call(ctx, thisReference, new InvokationContextFactory(variableFactory, funcCtx), args);
        }
    }
    if (m == null) {
        StringAppender errorBuild = new StringAppender();
        for (int i = 0; i < args.length; i++) {
            errorBuild.append(args[i] != null ? args[i].getClass().getName() : null);
            if (i < args.length - 1)
                errorBuild.append(", ");
        }
        if ("size".equals(name) && args.length == 0 && cls.isArray()) {
            return getLength(ctx);
        }
        throw new PropertyAccessException("unable to resolve method: " + cls.getName() + "." + name + "(" + errorBuild.toString() + ") [arglength=" + args.length + "]", property, st, pCtx);
    } else {
        for (int i = 0; i < args.length; i++) {
            args[i] = convert(args[i], paramTypeVarArgsSafe(parameterTypes, i, m.isVarArgs()));
        }
        /**
         * Invoke the target method and return the response.
         */
        currType = toNonPrimitiveType(m.getReturnType());
        try {
            return m.invoke(ctx, normalizeArgsForVarArgs(parameterTypes, args, m.isVarArgs()));
        } catch (IllegalAccessException e) {
            try {
                addMethodCache(cls, createSignature(name, tk), (m = getWidenedTarget(m)));
                return m.invoke(ctx, args);
            } catch (Exception e2) {
                throw new PropertyAccessException("unable to invoke method: " + name, property, cursor, e2, pCtx);
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new PropertyAccessException("unable to invoke method: " + name, property, cursor, e, pCtx);
        }
    }
}
Also used : VariableResolverFactory(org.mvel2.integration.VariableResolverFactory) MethodStub(org.mvel2.util.MethodStub) StringAppender(org.mvel2.util.StringAppender)

Aggregations

CompileException (org.mvel2.CompileException)22 HashMap (java.util.HashMap)13 Map (java.util.Map)12 ParserContext (org.mvel2.ParserContext)12 ASTNode (org.mvel2.ast.ASTNode)9 Type (org.mvel2.asm.Type)8 Serializable (java.io.Serializable)7 Method (java.lang.reflect.Method)7 ExecutableStatement (org.mvel2.compiler.ExecutableStatement)7 ExpressionCompiler (org.mvel2.compiler.ExpressionCompiler)7 StringAppender (org.mvel2.util.StringAppender)6 EndOfStatement (org.mvel2.ast.EndOfStatement)5 IOException (java.io.IOException)4 BitSet (java.util.BitSet)4 List (java.util.List)4 LabelNode (org.mvel2.asm.tree.LabelNode)4 LiteralNode (org.mvel2.ast.LiteralNode)4 Proto (org.mvel2.ast.Proto)4 ArrayList (java.util.ArrayList)3 Money (org.broadleafcommerce.common.money.Money)3