Search in sources :

Example 1 with ExecutableLiteral

use of org.mvel2.compiler.ExecutableLiteral in project drools by kiegroup.

the class ConditionAnalyzer method analyzeCondition.

private Condition analyzeCondition(ASTNode node) {
    boolean isNegated = false;
    if (node instanceof Negation) {
        isNegated = true;
        ExecutableStatement statement = ((Negation) node).getStatement();
        if (statement instanceof ExecutableLiteral) {
            return new FixedValueCondition(!(Boolean) ((ExecutableLiteral) statement).getLiteral());
        }
        node = ((ExecutableAccessor) statement).getNode();
    }
    node = analyzeSubstatement(node);
    if (node instanceof LiteralNode && node.getEgressType() == Boolean.class) {
        boolean literalValue = (Boolean) node.getLiteralValue();
        return new FixedValueCondition(isNegated ? !literalValue : literalValue);
    }
    if (node instanceof Negation) {
        isNegated = !isNegated;
        node = ((ExecutableAccessor) ((Negation) node).getStatement()).getNode();
        node = analyzeSubstatement(node);
    }
    if (node instanceof And || node instanceof Or) {
        return analyzeCombinedCondition((BooleanNode) node, isNegated);
    }
    return analyzeSingleCondition(node, isNegated);
}
Also used : LiteralNode(org.mvel2.ast.LiteralNode) ExecutableStatement(org.mvel2.compiler.ExecutableStatement) Or(org.mvel2.ast.Or) Negation(org.mvel2.ast.Negation) And(org.mvel2.ast.And) ExecutableLiteral(org.mvel2.compiler.ExecutableLiteral)

Example 2 with ExecutableLiteral

use of org.mvel2.compiler.ExecutableLiteral in project drools by kiegroup.

the class ConditionAnalyzer method analyzeNode.

private Expression analyzeNode(ASTNode node) {
    node = analyzeRegEx(analyzeSubstatement(node));
    if (node instanceof LiteralNode) {
        LiteralNode literalNode = (LiteralNode) node;
        return new FixedExpression(literalNode.getEgressType(), literalNode.getLiteralValue());
    }
    if (node instanceof BinaryOperation) {
        BinaryOperation op = (BinaryOperation) node;
        return new AritmeticExpression(analyzeNode(op.getLeft()), AritmeticOperator.fromMvelOpCode(op.getOperation()), analyzeNode(op.getRight()));
    }
    if (node instanceof TypeCast) {
        ExecutableStatement statement = ((TypeCast) node).getStatement();
        if (statement instanceof ExecutableAccessor) {
            ExecutableAccessor accessor = (ExecutableAccessor) statement;
            return new CastExpression(node.getEgressType(), analyzeNode(accessor.getNode()));
        } else {
            ExecutableLiteral literal = (ExecutableLiteral) statement;
            return new CastExpression(node.getEgressType(), new FixedExpression(literal.getLiteral()));
        }
    }
    if (node instanceof Union) {
        ASTNode main = ((Union) node).getMain();
        Accessor accessor = node.getAccessor();
        EvaluatedExpression expression = new EvaluatedExpression();
        expression.firstExpression = analyzeNode(main);
        if (accessor instanceof DynamicGetAccessor) {
            AccessorNode accessorNode = (AccessorNode) ((DynamicGetAccessor) accessor).getSafeAccessor();
            expression.addInvocation(analyzeAccessorInvocation(accessorNode, node, null, null));
        } else if (accessor instanceof AccessorNode) {
            AccessorNode accessorNode = (AccessorNode) accessor;
            while (accessorNode != null) {
                expression.addInvocation(analyzeAccessorInvocation(accessorNode, node, null, null));
                accessorNode = accessorNode.getNextNode();
            }
        } else {
            throw new RuntimeException("Unexpected accessor: " + accessor);
        }
        return expression;
    }
    if (node instanceof Sign) {
        ExecutableStatement statement = getFieldValue(Sign.class, "stmt", (Sign) node);
        if (statement instanceof ExecutableAccessor) {
            ExecutableAccessor accessor = (ExecutableAccessor) statement;
            return new AritmeticExpression(new FixedExpression(0), AritmeticOperator.SUB, analyzeNode(accessor.getNode()));
        } else {
            ExecutableLiteral literal = (ExecutableLiteral) statement;
            return new AritmeticExpression(new FixedExpression(0), AritmeticOperator.SUB, new FixedExpression(literal.getLiteral()));
        }
    }
    Accessor accessor = node.getAccessor();
    if (accessor instanceof IndexedVariableAccessor) {
        String variableName = node.getName();
        int dot = variableName.indexOf('.');
        if (dot > 0) {
            variableName = variableName.substring(0, dot);
        }
        Class<?> variableType = getVariableType(variableName);
        return new VariableExpression(variableName, analyzeExpressionNode(((AccessorNode) accessor).getNextNode(), node, variableType), variableType != null ? variableType : node.getEgressType());
    }
    if (accessor == null && node instanceof NewObjectNode) {
        accessor = ((NewObjectNode) node).getNewObjectOptimizer();
    }
    if (accessor instanceof VariableAccessor) {
        VariableAccessor variableAccessor = (VariableAccessor) accessor;
        AccessorNode accessorNode = variableAccessor.getNextNode();
        if (accessorNode == null || !isStaticAccessor(accessorNode)) {
            String variableName = (String) (variableAccessor.getProperty());
            Class<?> variableType = getVariableType(variableName);
            if (variableType != null) {
                return new VariableExpression(variableName, analyzeExpressionNode(accessorNode, node, variableType), variableType);
            } else {
                if (node.getLiteralValue() instanceof ParserContext) {
                    ParserContext pCtx = (ParserContext) node.getLiteralValue();
                    // it's not a variable but a method invocation on this
                    Class<?> thisClass = pCtx.getInputs().get("this");
                    try {
                        return new EvaluatedExpression(new MethodInvocation(thisClass.getMethod(variableName)));
                    } catch (NoSuchMethodException e) {
                        if (node.getEgressType() == Class.class) {
                            // there's no method on this with the given name, check if it is a class literal
                            Class<?> classLiteral = pCtx.getParserConfiguration().getImport(variableName);
                            if (classLiteral != null) {
                                return new FixedExpression(Class.class, classLiteral);
                            }
                        }
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
    if (accessor == null) {
        throw new RuntimeException("Null accessor on node: " + node);
    }
    return analyzeNodeAccessor(accessor, node);
}
Also used : BinaryOperation(org.mvel2.ast.BinaryOperation) ExecutableAccessor(org.mvel2.compiler.ExecutableAccessor) FieldAccessor(org.mvel2.optimizers.impl.refl.nodes.FieldAccessor) StaticVarAccessor(org.mvel2.optimizers.impl.refl.nodes.StaticVarAccessor) ListAccessor(org.mvel2.optimizers.impl.refl.nodes.ListAccessor) ExecutableAccessor(org.mvel2.compiler.ExecutableAccessor) GetterAccessor(org.mvel2.optimizers.impl.refl.nodes.GetterAccessor) DynamicGetAccessor(org.mvel2.optimizers.dynamic.DynamicGetAccessor) ExprValueAccessor(org.mvel2.optimizers.impl.refl.collection.ExprValueAccessor) MapAccessor(org.mvel2.optimizers.impl.refl.nodes.MapAccessor) ThisValueAccessor(org.mvel2.optimizers.impl.refl.nodes.ThisValueAccessor) Accessor(org.mvel2.compiler.Accessor) IndexedVariableAccessor(org.mvel2.optimizers.impl.refl.nodes.IndexedVariableAccessor) MethodAccessor(org.mvel2.optimizers.impl.refl.nodes.MethodAccessor) VariableAccessor(org.mvel2.optimizers.impl.refl.nodes.VariableAccessor) ConstructorAccessor(org.mvel2.optimizers.impl.refl.nodes.ConstructorAccessor) StaticReferenceAccessor(org.mvel2.optimizers.impl.refl.nodes.StaticReferenceAccessor) ArrayAccessor(org.mvel2.optimizers.impl.refl.nodes.ArrayAccessor) Union(org.mvel2.ast.Union) AccessorNode(org.mvel2.compiler.AccessorNode) DynamicGetAccessor(org.mvel2.optimizers.dynamic.DynamicGetAccessor) ExecutableLiteral(org.mvel2.compiler.ExecutableLiteral) ASTNode(org.mvel2.ast.ASTNode) ExecutableStatement(org.mvel2.compiler.ExecutableStatement) IndexedVariableAccessor(org.mvel2.optimizers.impl.refl.nodes.IndexedVariableAccessor) VariableAccessor(org.mvel2.optimizers.impl.refl.nodes.VariableAccessor) LiteralNode(org.mvel2.ast.LiteralNode) IndexedVariableAccessor(org.mvel2.optimizers.impl.refl.nodes.IndexedVariableAccessor) NewObjectNode(org.mvel2.ast.NewObjectNode) Sign(org.mvel2.ast.Sign) TypeCast(org.mvel2.ast.TypeCast) ParserContext(org.mvel2.ParserContext)

Example 3 with ExecutableLiteral

use of org.mvel2.compiler.ExecutableLiteral in project mvel by mvel.

the class ExpressionCompiler method verify.

protected ASTNode verify(ParserContext pCtx, ASTNode tk) {
    if (tk.isOperator() && (tk.getOperator().equals(Operator.AND) || tk.getOperator().equals(Operator.OR))) {
        secondPassOptimization = true;
    }
    if (tk.isDiscard() || tk.isOperator()) {
        return tk;
    } else if (tk.isLiteral()) {
        /**
         * Convert literal values from the default ASTNode to the more-efficient LiteralNode.
         */
        if ((fields & COMPILE_IMMEDIATE) != 0 && tk.getClass() == ASTNode.class) {
            return new LiteralNode(tk.getLiteralValue(), pCtx);
        } else {
            return tk;
        }
    }
    if (verifying) {
        if (tk.isIdentifier()) {
            PropertyVerifier propVerifier = new PropertyVerifier(expr, tk.getStart(), tk.getOffset(), pCtx);
            if (tk instanceof Union) {
                propVerifier.setCtx(((Union) tk).getLeftEgressType());
                tk.setEgressType(returnType = propVerifier.analyze());
            } else {
                tk.setEgressType(returnType = propVerifier.analyze());
                if (propVerifier.isFqcn()) {
                    tk.setAsFQCNReference();
                }
                if (propVerifier.isClassLiteral()) {
                    return new LiteralNode(returnType, pCtx);
                }
                if (propVerifier.isInput()) {
                    pCtx.addInput(tk.getAbsoluteName(), propVerifier.isDeepProperty() ? Object.class : returnType);
                }
                if (!propVerifier.isMethodCall() && !returnType.isEnum() && !pCtx.isOptimizerNotified() && pCtx.isStrongTyping() && !pCtx.isVariableVisible(tk.getAbsoluteName()) && !tk.isFQCN()) {
                    throw new CompileException("no such identifier: " + tk.getAbsoluteName(), expr, tk.getStart());
                }
            }
        } else if (tk.isAssignment()) {
            Assignment a = (Assignment) tk;
            if (a.getAssignmentVar() != null) {
                // pCtx.makeVisible(a.getAssignmentVar());
                PropertyVerifier propVerifier = new PropertyVerifier(a.getAssignmentVar(), pCtx);
                tk.setEgressType(returnType = propVerifier.analyze());
                if (!a.isNewDeclaration() && propVerifier.isResolvedExternally()) {
                    pCtx.addInput(tk.getAbsoluteName(), returnType);
                }
                ExecutableStatement c = (ExecutableStatement) subCompileExpression(expr, tk.getStart(), tk.getOffset(), pCtx);
                if (pCtx.isStrictTypeEnforcement()) {
                    /**
                     * If we're using strict type enforcement, we need to see if this coercion can be done now,
                     * or fail epicly.
                     */
                    if (!returnType.isAssignableFrom(c.getKnownEgressType()) && c.isLiteralOnly()) {
                        if (canConvert(c.getKnownEgressType(), returnType)) {
                            /**
                             * We convert the literal to the proper type.
                             */
                            try {
                                a.setValueStatement(new ExecutableLiteral(convert(c.getValue(null, null), returnType)));
                                return tk;
                            } catch (Exception e) {
                            // fall through.
                            }
                        } else if (returnType.isPrimitive() && unboxPrimitive(c.getKnownEgressType()).equals(returnType)) {
                            /**
                             * We ignore boxed primitive cases, since MVEL does not recognize primitives.
                             */
                            return tk;
                        }
                        throw new CompileException("cannot assign type " + c.getKnownEgressType().getName() + " to " + returnType.getName(), expr, st);
                    }
                }
            }
        } else if (tk instanceof NewObjectNode) {
            // this is a bit of a hack for now.
            NewObjectNode n = (NewObjectNode) tk;
            List<char[]> parms = ParseTools.parseMethodOrConstructor(tk.getNameAsArray());
            if (parms != null) {
                for (char[] p : parms) {
                    MVEL.analyze(p, pCtx);
                }
            }
        }
        returnType = tk.getEgressType();
    }
    if (!tk.isLiteral() && tk.getClass() == ASTNode.class && (tk.getFields() & ASTNode.ARRAY_TYPE_LITERAL) == 0) {
        if (pCtx.isStrongTyping())
            tk.strongTyping();
        tk.storePctx();
        tk.storeInLiteralRegister(pCtx);
    }
    return tk;
}
Also used : Assignment(org.mvel2.ast.Assignment) LiteralNode(org.mvel2.ast.LiteralNode) NewObjectNode(org.mvel2.ast.NewObjectNode) CompileException(org.mvel2.CompileException) Union(org.mvel2.ast.Union) CompileException(org.mvel2.CompileException)

Example 4 with ExecutableLiteral

use of org.mvel2.compiler.ExecutableLiteral in project mvel by mvel.

the class ASMAccessorOptimizer method writeLiteralOrSubexpression.

private Class writeLiteralOrSubexpression(Object stmt, Class desiredTarget, Class knownIngressType) {
    if (stmt instanceof ExecutableLiteral) {
        Object literalValue = ((ExecutableLiteral) stmt).getLiteral();
        // Handle the case when the literal is null MVEL-312
        if (literalValue == null) {
            mv.visitInsn(ACONST_NULL);
            return null;
        }
        Class type = literalValue == null ? desiredTarget : literalValue.getClass();
        assert debug("*** type:" + type + ";desired:" + desiredTarget);
        if (type == Integer.class && desiredTarget == int.class) {
            intPush(((ExecutableLiteral) stmt).getInteger32());
            type = int.class;
        } else if (desiredTarget != null && desiredTarget != type) {
            assert debug("*** Converting because desiredType(" + desiredTarget.getClass() + ") is not: " + type);
            if (!DataConversion.canConvert(type, desiredTarget)) {
                throw new CompileException("was expecting type: " + desiredTarget.getName() + "; but found type: " + type.getName(), expr, st);
            }
            writeOutLiteralWrapped(convert(literalValue, desiredTarget));
        } else {
            writeOutLiteralWrapped(literalValue);
        }
        return type;
    } else {
        literal = false;
        addSubstatement((ExecutableStatement) stmt);
        Class type;
        if (knownIngressType == null) {
            type = ((ExecutableStatement) stmt).getKnownEgressType();
        } else {
            type = knownIngressType;
        }
        if (desiredTarget != null && type != desiredTarget) {
            if (desiredTarget.isPrimitive()) {
                if (type == null)
                    throw new OptimizationFailure("cannot optimize expression: " + new String(expr) + ": cannot determine ingress type for primitive output");
                checkcast(type);
                unwrapPrimitive(desiredTarget);
            }
        }
        return type;
    }
}
Also used : ExecutableLiteral(org.mvel2.compiler.ExecutableLiteral) OptimizationFailure(org.mvel2.OptimizationFailure) CompileException(org.mvel2.CompileException)

Example 5 with ExecutableLiteral

use of org.mvel2.compiler.ExecutableLiteral in project mvel by mvel.

the class ASMAccessorOptimizer method getMethod.

@SuppressWarnings({ "unchecked" })
private Object getMethod(Object ctx, String name) throws IllegalAccessException, InvocationTargetException {
    assert debug("\n  **  {method: " + name + "}");
    int st = cursor;
    String tk = cursor != end && expr[cursor] == '(' && ((cursor = balancedCapture(expr, cursor, '(')) - st) > 1 ? new String(expr, st + 1, cursor - st - 1) : "";
    cursor++;
    Object[] preConvArgs;
    Object[] args;
    Class[] argTypes;
    ExecutableStatement[] es;
    List<char[]> subtokens;
    if (tk.length() == 0) {
        args = preConvArgs = ParseTools.EMPTY_OBJ_ARR;
        argTypes = ParseTools.EMPTY_CLS_ARR;
        es = null;
        subtokens = null;
    } else {
        subtokens = parseParameterList(tk.toCharArray(), 0, -1);
        es = new ExecutableStatement[subtokens.size()];
        args = new Object[subtokens.size()];
        argTypes = new Class[subtokens.size()];
        preConvArgs = new Object[es.length];
        for (int i = 0; i < subtokens.size(); i++) {
            assert debug("subtoken[" + i + "] { " + new String(subtokens.get(i)) + " }");
            preConvArgs[i] = args[i] = (es[i] = (ExecutableStatement) subCompileExpression(subtokens.get(i), pCtx)).getValue(this.thisRef, this.thisRef, variableFactory);
            if (es[i].isExplicitCast())
                argTypes[i] = es[i].getKnownEgressType();
        }
        if (pCtx.isStrictTypeEnforcement()) {
            for (int i = 0; i < args.length; i++) {
                argTypes[i] = es[i].getKnownEgressType();
            }
        } else {
            for (int i = 0; i < args.length; i++) {
                if (argTypes[i] != null)
                    continue;
                if (es[i].getKnownEgressType() == Object.class) {
                    argTypes[i] = args[i] == null ? null : args[i].getClass();
                } else {
                    argTypes[i] = es[i].getKnownEgressType();
                }
            }
        }
    }
    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) {
            if (es != null && es.length != 0) {
                compiledInputs.addAll(Arrays.asList(es));
                intPush(es.length);
                assert debug("ANEWARRAY [" + es.length + "]");
                mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
                assert debug("ASTORE 4");
                mv.visitVarInsn(ASTORE, 4);
                for (int i = 0; i < es.length; i++) {
                    assert debug("ALOAD 4");
                    mv.visitVarInsn(ALOAD, 4);
                    intPush(i);
                    loadField(i);
                    assert debug("ALOAD 1");
                    mv.visitVarInsn(ALOAD, 1);
                    assert debug("ALOAD 3");
                    mv.visitIntInsn(ALOAD, 3);
                    assert debug("INVOKEINTERFACE ExecutableStatement.getValue");
                    mv.visitMethodInsn(INVOKEINTERFACE, NAMESPACE + "compiler/ExecutableStatement", "getValue", "(Ljava/lang/Object;L" + NAMESPACE + "integration/VariableResolverFactory;)Ljava/lang/Object;");
                    assert debug("AASTORE");
                    mv.visitInsn(AASTORE);
                }
            } else {
                assert debug("ACONST_NULL");
                mv.visitInsn(ACONST_NULL);
                assert debug("CHECKCAST java/lang/Object");
                mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/Object;");
                assert debug("ASTORE 4");
                mv.visitVarInsn(ASTORE, 4);
            }
            if (variableFactory.isIndexedFactory() && variableFactory.isTarget(name)) {
                loadVariableByIndex(variableFactory.variableIndexOf(name));
            } else {
                loadVariableByName(name);
            }
            checkcast(FunctionInstance.class);
            assert debug("ALOAD 1");
            mv.visitVarInsn(ALOAD, 1);
            assert debug("ALOAD 2");
            mv.visitVarInsn(ALOAD, 2);
            assert debug("ALOAD 3");
            mv.visitVarInsn(ALOAD, 3);
            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);
            assert debug("INVOKEVIRTUAL Function.call");
            mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(FunctionInstance.class), "call", "(Ljava/lang/Object;Ljava/lang/Object;L" + NAMESPACE + "integration/VariableResolverFactory;[Ljava/lang/Object;)Ljava/lang/Object;");
            return ((FunctionInstance) ptr).call(ctx, thisRef, 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;
    } else if (returnType != null && returnType.isPrimitive()) {
        // noinspection unchecked
        wrapPrimitive(returnType);
    }
    /**
     * If the target object is an instance of java.lang.Class itself then do not
     * adjust the Class scope target.
     */
    boolean classTarget = false;
    Class<?> cls = currType != null ? currType : ((classTarget = ctx instanceof Class) ? (Class<?>) ctx : ctx.getClass());
    currType = null;
    Method m;
    Class[] parameterTypes = null;
    /**
     * Try to find an instance method from the class target.
     */
    if ((m = getBestCandidate(argTypes, name, cls, cls.getMethods(), false, classTarget)) != null) {
        parameterTypes = m.getParameterTypes();
    }
    if (m == null && classTarget) {
        /**
         * If we didn't find anything, maybe we're looking for the actual java.lang.Class methods.
         */
        if ((m = getBestCandidate(argTypes, name, cls, Class.class.getMethods(), false)) != null) {
            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(argTypes, name, cls, cls.getMethods(), false, classTarget)) != null) {
            parameterTypes = m.getParameterTypes();
        }
    }
    if (es != null && m != null && m.isVarArgs() && (es.length != parameterTypes.length || !(es[es.length - 1] instanceof ExecutableAccessor))) {
        // normalize ExecutableStatement for varargs
        ExecutableStatement[] varArgEs = new ExecutableStatement[parameterTypes.length];
        int varArgStart = parameterTypes.length - 1;
        for (int i = 0; i < varArgStart; i++) varArgEs[i] = es[i];
        String varargsTypeName = parameterTypes[parameterTypes.length - 1].getComponentType().getName();
        String varArgExpr;
        if ("null".equals(tk)) {
            // if null is the token no need for wrapping
            varArgExpr = tk;
        } else {
            StringBuilder sb = new StringBuilder("new ").append(varargsTypeName).append("[] {");
            for (int i = varArgStart; i < subtokens.size(); i++) {
                sb.append(subtokens.get(i));
                if (i < subtokens.size() - 1)
                    sb.append(",");
            }
            varArgExpr = sb.append("}").toString();
        }
        char[] token = varArgExpr.toCharArray();
        varArgEs[varArgStart] = ((ExecutableStatement) subCompileExpression(token, pCtx));
        es = varArgEs;
        if (preConvArgs.length == parameterTypes.length - 1) {
            // empty vararg
            Object[] preConvArgsForVarArg = new Object[parameterTypes.length];
            for (int i = 0; i < preConvArgs.length; i++) preConvArgsForVarArg[i] = preConvArgs[i];
            preConvArgsForVarArg[parameterTypes.length - 1] = Array.newInstance(parameterTypes[parameterTypes.length - 1].getComponentType(), 0);
            preConvArgs = preConvArgsForVarArg;
        }
    }
    int inputsOffset = compiledInputs.size();
    if (es != null) {
        for (ExecutableStatement e : es) {
            if (e instanceof ExecutableLiteral) {
                continue;
            }
            compiledInputs.add(e);
        }
    }
    if (first) {
        assert debug("ALOAD 1 (D) ");
        mv.visitVarInsn(ALOAD, 1);
    }
    if (m == null) {
        StringAppender errorBuild = new StringAppender();
        if (parameterTypes != null) {
            for (int i = 0; i < args.length; i++) {
                errorBuild.append(parameterTypes[i] != null ? parameterTypes[i].getClass().getName() : null);
                if (i < args.length - 1)
                    errorBuild.append(", ");
            }
        }
        if ("size".equals(name) && args.length == 0 && cls.isArray()) {
            anyArrayCheck(cls);
            assert debug("ARRAYLENGTH");
            mv.visitInsn(ARRAYLENGTH);
            wrapPrimitive(int.class);
            return getLength(ctx);
        }
        throw new CompileException("unable to resolve method: " + cls.getName() + "." + name + "(" + errorBuild.toString() + ") [arglength=" + args.length + "]", expr, st);
    } else {
        m = getWidenedTarget(m);
        if (es != null) {
            ExecutableStatement cExpr;
            for (int i = 0; i < es.length; i++) {
                if ((cExpr = es[i]).getKnownIngressType() == null) {
                    cExpr.setKnownIngressType(parameterTypes[i]);
                    cExpr.computeTypeConversionRule();
                }
                if (!cExpr.isConvertableIngressEgress() && i < args.length) {
                    args[i] = convert(args[i], paramTypeVarArgsSafe(parameterTypes, i, m.isVarArgs()));
                }
            }
        } else {
            /**
             * Coerce any types if required.
             */
            for (int i = 0; i < args.length; i++) {
                args[i] = convert(args[i], paramTypeVarArgsSafe(parameterTypes, i, m.isVarArgs()));
            }
        }
        if (m.getParameterTypes().length == 0) {
            if ((m.getModifiers() & STATIC) != 0) {
                assert debug("INVOKESTATIC " + m.getName());
                mv.visitMethodInsn(INVOKESTATIC, getInternalName(m.getDeclaringClass()), m.getName(), getMethodDescriptor(m));
            } else {
                assert debug("CHECKCAST " + getInternalName(m.getDeclaringClass()));
                mv.visitTypeInsn(CHECKCAST, getInternalName(m.getDeclaringClass()));
                if (m.getDeclaringClass().isInterface()) {
                    assert debug("INVOKEINTERFACE " + m.getName());
                    mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(m.getDeclaringClass()), m.getName(), getMethodDescriptor(m));
                } else {
                    assert debug("INVOKEVIRTUAL " + m.getName());
                    mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(m.getDeclaringClass()), m.getName(), getMethodDescriptor(m));
                }
            }
            returnType = m.getReturnType();
            stacksize++;
        } else {
            if ((m.getModifiers() & STATIC) == 0) {
                assert debug("CHECKCAST " + getInternalName(cls));
                mv.visitTypeInsn(CHECKCAST, getInternalName(cls));
            }
            Class<?> aClass = m.getParameterTypes()[m.getParameterTypes().length - 1];
            if (m.isVarArgs()) {
                if (es == null || es.length == (m.getParameterTypes().length - 1)) {
                    ExecutableStatement[] executableStatements = new ExecutableStatement[m.getParameterTypes().length];
                    if (es != null) {
                        System.arraycopy(es, 0, executableStatements, 0, es.length);
                    }
                    executableStatements[executableStatements.length - 1] = new ExecutableLiteral(Array.newInstance(aClass, 0));
                    es = executableStatements;
                }
            }
            for (int i = 0; es != null && i < es.length; i++) {
                if (es[i] instanceof ExecutableLiteral) {
                    ExecutableLiteral literal = (ExecutableLiteral) es[i];
                    if (literal.getLiteral() == null) {
                        assert debug("ICONST_NULL");
                        mv.visitInsn(ACONST_NULL);
                        continue;
                    } else if (parameterTypes[i] == int.class && literal.intOptimized()) {
                        intPush(literal.getInteger32());
                        continue;
                    } else if (parameterTypes[i] == int.class && preConvArgs[i] instanceof Integer) {
                        intPush((Integer) preConvArgs[i]);
                        continue;
                    } else if (parameterTypes[i] == boolean.class) {
                        boolean bool = DataConversion.convert(literal.getLiteral(), Boolean.class);
                        assert debug(bool ? "ICONST_1" : "ICONST_0");
                        mv.visitInsn(bool ? ICONST_1 : ICONST_0);
                        continue;
                    } else {
                        Object lit = literal.getLiteral();
                        if (parameterTypes[i] == Object.class) {
                            if (isPrimitiveWrapper(lit.getClass())) {
                                if (lit.getClass() == Integer.class) {
                                    intPush((Integer) lit);
                                } else {
                                    assert debug("LDC " + lit);
                                    mv.visitLdcInsn(lit);
                                }
                                wrapPrimitive(lit.getClass());
                            } else if (lit instanceof String) {
                                mv.visitLdcInsn(lit);
                                checkcast(Object.class);
                            }
                            continue;
                        } else if (canConvert(parameterTypes[i], lit.getClass())) {
                            Object c = convert(lit, parameterTypes[i]);
                            if (c instanceof Class) {
                                ldcClassConstant((Class) c);
                            } else {
                                assert debug("LDC " + lit + " (" + lit.getClass().getName() + ")");
                                mv.visitLdcInsn(convert(lit, parameterTypes[i]));
                                if (isPrimitiveWrapper(parameterTypes[i])) {
                                    wrapPrimitive(lit.getClass());
                                }
                            }
                            continue;
                        } else {
                            throw new OptimizationNotSupported();
                        }
                    }
                }
                assert debug("ALOAD 0");
                mv.visitVarInsn(ALOAD, 0);
                assert debug("GETFIELD p" + inputsOffset);
                mv.visitFieldInsn(GETFIELD, className, "p" + inputsOffset, "L" + NAMESPACE + "compiler/ExecutableStatement;");
                inputsOffset++;
                assert debug("ALOAD 2");
                mv.visitVarInsn(ALOAD, 2);
                assert debug("ALOAD 3");
                mv.visitVarInsn(ALOAD, 3);
                assert debug("INVOKEINTERFACE ExecutableStatement.getValue");
                mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(ExecutableStatement.class), "getValue", "(Ljava/lang/Object;L" + NAMESPACE + "integration/VariableResolverFactory;)Ljava/lang/Object;");
                if (parameterTypes[i].isPrimitive()) {
                    if (preConvArgs[i] == null || (parameterTypes[i] != String.class && !parameterTypes[i].isAssignableFrom(preConvArgs[i].getClass()))) {
                        ldcClassConstant(getWrapperClass(parameterTypes[i]));
                        assert debug("INVOKESTATIC DataConversion.convert");
                        mv.visitMethodInsn(INVOKESTATIC, NAMESPACE + "DataConversion", "convert", "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
                    }
                    unwrapPrimitive(parameterTypes[i]);
                } else if (preConvArgs[i] == null || (parameterTypes[i] != String.class && !parameterTypes[i].isAssignableFrom(preConvArgs[i].getClass()))) {
                    ldcClassConstant(parameterTypes[i]);
                    assert debug("INVOKESTATIC DataConversion.convert");
                    mv.visitMethodInsn(INVOKESTATIC, NAMESPACE + "DataConversion", "convert", "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
                    assert debug("CHECKCAST " + getInternalName(parameterTypes[i]));
                    mv.visitTypeInsn(CHECKCAST, getInternalName(parameterTypes[i]));
                } else if (parameterTypes[i] == String.class) {
                    assert debug("<<<DYNAMIC TYPE OPTIMIZATION STRING>>");
                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;");
                } else {
                    assert debug("<<<DYNAMIC TYPING BYPASS>>>");
                    assert debug("<<<OPT. JUSTIFICATION " + parameterTypes[i] + "=" + preConvArgs[i].getClass() + ">>>");
                    assert debug("CHECKCAST " + getInternalName(parameterTypes[i]));
                    mv.visitTypeInsn(CHECKCAST, getInternalName(parameterTypes[i]));
                }
            }
            if ((m.getModifiers() & STATIC) != 0) {
                assert debug("INVOKESTATIC: " + m.getName());
                mv.visitMethodInsn(INVOKESTATIC, getInternalName(m.getDeclaringClass()), m.getName(), getMethodDescriptor(m));
            } else {
                if (m.getDeclaringClass().isInterface() && (m.getDeclaringClass() != cls || (ctx != null && ctx.getClass() != m.getDeclaringClass()))) {
                    assert debug("INVOKEINTERFACE: " + getInternalName(m.getDeclaringClass()) + "." + m.getName());
                    mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(m.getDeclaringClass()), m.getName(), getMethodDescriptor(m));
                } else {
                    assert debug("INVOKEVIRTUAL: " + getInternalName(cls) + "." + m.getName());
                    mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(cls), m.getName(), getMethodDescriptor(m));
                }
            }
            returnType = m.getReturnType();
            stacksize++;
        }
        Object o = m.invoke(ctx, normalizeArgsForVarArgs(parameterTypes, args, m.isVarArgs()));
        if (hasNullMethodHandler()) {
            writeOutNullHandler(m, 1);
            if (o == null)
                o = getNullMethodHandler().getProperty(m.getName(), ctx, variableFactory);
        }
        currType = toNonPrimitiveType(m.getReturnType());
        return o;
    }
}
Also used : ExecutableStatement(org.mvel2.compiler.ExecutableStatement) OptimizationFailure(org.mvel2.OptimizationFailure) ExecutableAccessor(org.mvel2.compiler.ExecutableAccessor) Method(java.lang.reflect.Method) FunctionInstance(org.mvel2.ast.FunctionInstance) MethodStub(org.mvel2.util.MethodStub) ExecutableLiteral(org.mvel2.compiler.ExecutableLiteral) StringAppender(org.mvel2.util.StringAppender) CompileException(org.mvel2.CompileException) OptimizationNotSupported(org.mvel2.optimizers.OptimizationNotSupported)

Aggregations

ExecutableLiteral (org.mvel2.compiler.ExecutableLiteral)5 ExecutableStatement (org.mvel2.compiler.ExecutableStatement)4 CompileException (org.mvel2.CompileException)3 LiteralNode (org.mvel2.ast.LiteralNode)3 ExecutableAccessor (org.mvel2.compiler.ExecutableAccessor)3 Method (java.lang.reflect.Method)2 AccessorNode (org.mule.mvel2.compiler.AccessorNode)2 ExecutableLiteral (org.mule.mvel2.compiler.ExecutableLiteral)2 MapAccessor (org.mule.mvel2.optimizers.impl.refl.nodes.MapAccessor)2 MapAccessorNest (org.mule.mvel2.optimizers.impl.refl.nodes.MapAccessorNest)2 VariableAccessor (org.mule.mvel2.optimizers.impl.refl.nodes.VariableAccessor)2 OptimizationFailure (org.mvel2.OptimizationFailure)2 NewObjectNode (org.mvel2.ast.NewObjectNode)2 Union (org.mvel2.ast.Union)2 ArrayAccessor (org.mvel2.optimizers.impl.refl.nodes.ArrayAccessor)2 ConstructorAccessor (org.mvel2.optimizers.impl.refl.nodes.ConstructorAccessor)2 FieldAccessor (org.mvel2.optimizers.impl.refl.nodes.FieldAccessor)2 GetterAccessor (org.mvel2.optimizers.impl.refl.nodes.GetterAccessor)2 ListAccessor (org.mvel2.optimizers.impl.refl.nodes.ListAccessor)2 MapAccessor (org.mvel2.optimizers.impl.refl.nodes.MapAccessor)2