Search in sources :

Example 21 with CompileException

use of org.mvel2.CompileException in project mvel by mikebrock.

the class ASMAccessorOptimizer method getBeanProperty.

private Object getBeanProperty(Object ctx, String property) throws IllegalAccessException, InvocationTargetException {
    assert debug("\n  **  ENTER -> {bean: " + property + "; ctx=" + ctx + "}");
    if ((pCtx == null ? currType : pCtx.getVarOrInputTypeOrNull(property)) == Object.class && !pCtx.isStrongTyping()) {
        currType = null;
    }
    if (returnType != null && returnType.isPrimitive()) {
        // noinspection unchecked
        wrapPrimitive(returnType);
    }
    boolean classRef = false;
    Class<?> cls;
    if (ctx instanceof Class) {
        if (MVEL.COMPILER_OPT_SUPPORT_JAVA_STYLE_CLASS_LITERALS && "class".equals(property)) {
            ldcClassConstant((Class<?>) ctx);
            return ctx;
        }
        cls = (Class<?>) ctx;
        classRef = true;
    } else if (ctx != null) {
        cls = ctx.getClass();
    } else {
        cls = null;
    }
    if (hasPropertyHandler(cls)) {
        PropertyHandler prop = getPropertyHandler(cls);
        if (prop instanceof ProducesBytecode) {
            ((ProducesBytecode) prop).produceBytecodeGet(mv, property, variableFactory);
            return prop.getProperty(property, ctx, variableFactory);
        } else {
            throw new RuntimeException("unable to compileShared: custom accessor does not support producing bytecode: " + prop.getClass().getName());
        }
    }
    Member member = cls != null ? getFieldOrAccessor(cls, property) : null;
    if (member != null && classRef && (member.getModifiers() & Modifier.STATIC) == 0) {
        member = null;
    }
    if (member != null && hasGetListeners()) {
        mv.visitVarInsn(ALOAD, 1);
        mv.visitLdcInsn(member.getName());
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKESTATIC, NAMESPACE + "integration/GlobalListenerFactory", "notifyGetListeners", "(Ljava/lang/Object;Ljava/lang/String;L" + NAMESPACE + "integration/VariableResolverFactory;)V");
        notifyGetListeners(ctx, member.getName(), variableFactory);
    }
    if (first) {
        if ("this".equals(property)) {
            assert debug("ALOAD 2");
            mv.visitVarInsn(ALOAD, 2);
            return thisRef;
        } else if (variableFactory != null && variableFactory.isResolveable(property)) {
            if (variableFactory.isIndexedFactory() && variableFactory.isTarget(property)) {
                int idx;
                try {
                    loadVariableByIndex(idx = variableFactory.variableIndexOf(property));
                } catch (Exception e) {
                    throw new OptimizationFailure(property);
                }
                return variableFactory.getIndexedVariableResolver(idx).getValue();
            } else {
                try {
                    loadVariableByName(property);
                } catch (Exception e) {
                    throw new OptimizationFailure("critical error in JIT", e);
                }
                return variableFactory.getVariableResolver(property).getValue();
            }
        } else {
            assert debug("ALOAD 1");
            mv.visitVarInsn(ALOAD, 1);
        }
    }
    if (member instanceof Field) {
        Object o = ((Field) member).get(ctx);
        if (((member.getModifiers() & STATIC) != 0)) {
            // Check if the static field reference is a constant and a primitive.
            if ((member.getModifiers() & FINAL) != 0 && (o instanceof String || ((Field) member).getType().isPrimitive())) {
                o = ((Field) member).get(null);
                assert debug("LDC " + valueOf(o));
                mv.visitLdcInsn(o);
                wrapPrimitive(o.getClass());
                if (hasNullPropertyHandler()) {
                    if (o == null) {
                        o = getNullPropertyHandler().getProperty(member.getName(), ctx, variableFactory);
                    }
                    writeOutNullHandler(member, 0);
                }
                return o;
            } else {
                assert debug("GETSTATIC " + getDescriptor(member.getDeclaringClass()) + "." + member.getName() + "::" + getDescriptor(((Field) member).getType()));
                mv.visitFieldInsn(GETSTATIC, getInternalName(member.getDeclaringClass()), member.getName(), getDescriptor(returnType = ((Field) member).getType()));
            }
        } else {
            assert debug("CHECKCAST " + getInternalName(cls));
            mv.visitTypeInsn(CHECKCAST, getInternalName(cls));
            assert debug("GETFIELD " + property + ":" + getDescriptor(((Field) member).getType()));
            mv.visitFieldInsn(GETFIELD, getInternalName(cls), property, getDescriptor(returnType = ((Field) member).getType()));
        }
        returnType = ((Field) member).getType();
        if (hasNullPropertyHandler()) {
            if (o == null) {
                o = getNullPropertyHandler().getProperty(member.getName(), ctx, variableFactory);
            }
            writeOutNullHandler(member, 0);
        }
        return o;
    } else if (member != null) {
        Object o;
        if (first) {
            assert debug("ALOAD 1 (B)");
            mv.visitVarInsn(ALOAD, 1);
        }
        try {
            o = ((Method) member).invoke(ctx, EMPTYARG);
            if (returnType != member.getDeclaringClass()) {
                assert debug("CHECKCAST " + getInternalName(member.getDeclaringClass()));
                mv.visitTypeInsn(CHECKCAST, getInternalName(member.getDeclaringClass()));
            }
            returnType = ((Method) member).getReturnType();
            assert debug("INVOKEVIRTUAL " + member.getName() + ":" + returnType);
            mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(member.getDeclaringClass()), member.getName(), getMethodDescriptor((Method) member));
        } catch (IllegalAccessException e) {
            Method iFaceMeth = determineActualTargetMethod((Method) member);
            if (iFaceMeth == null)
                throw new PropertyAccessException("could not access field: " + cls.getName() + "." + property, expr, st, e);
            assert debug("CHECKCAST " + getInternalName(iFaceMeth.getDeclaringClass()));
            mv.visitTypeInsn(CHECKCAST, getInternalName(iFaceMeth.getDeclaringClass()));
            returnType = iFaceMeth.getReturnType();
            assert debug("INVOKEINTERFACE " + member.getName() + ":" + returnType);
            mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(iFaceMeth.getDeclaringClass()), member.getName(), getMethodDescriptor((Method) member));
            o = iFaceMeth.invoke(ctx, EMPTYARG);
        } catch (IllegalArgumentException e) {
            if (member.getDeclaringClass().equals(ctx)) {
                try {
                    Class c = Class.forName(member.getDeclaringClass().getName() + "$" + property);
                    throw new CompileException("name collision between innerclass: " + c.getCanonicalName() + "; and bean accessor: " + property + " (" + member.toString() + ")", expr, tkStart);
                } catch (ClassNotFoundException e2) {
                // fallthru
                }
            }
            throw e;
        }
        if (hasNullPropertyHandler()) {
            if (o == null)
                o = getNullPropertyHandler().getProperty(member.getName(), ctx, variableFactory);
            writeOutNullHandler(member, 0);
        }
        return o;
    } else if (ctx instanceof Map && (((Map) ctx).containsKey(property) || nullSafe)) {
        assert debug("CHECKCAST java/util/Map");
        mv.visitTypeInsn(CHECKCAST, "java/util/Map");
        assert debug("LDC: \"" + property + "\"");
        mv.visitLdcInsn(property);
        assert debug("INVOKEINTERFACE: get");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
        return ((Map) ctx).get(property);
    } else if (first && "this".equals(property)) {
        assert debug("ALOAD 2");
        // load the thisRef value.
        mv.visitVarInsn(ALOAD, 2);
        return this.thisRef;
    } else if ("length".equals(property) && ctx.getClass().isArray()) {
        anyArrayCheck(ctx.getClass());
        assert debug("ARRAYLENGTH");
        mv.visitInsn(ARRAYLENGTH);
        wrapPrimitive(int.class);
        return getLength(ctx);
    } else if (LITERALS.containsKey(property)) {
        Object lit = LITERALS.get(property);
        if (lit instanceof Class) {
            ldcClassConstant((Class) lit);
        }
        return lit;
    } else {
        Object ts = tryStaticAccess();
        if (ts != null) {
            if (ts instanceof Class) {
                ldcClassConstant((Class) ts);
                return ts;
            } else if (ts instanceof Method) {
                writeFunctionPointerStub(((Method) ts).getDeclaringClass(), (Method) ts);
                return ts;
            } else {
                Field f = (Field) ts;
                if ((f.getModifiers() & FINAL) != 0) {
                    Object finalVal = f.get(null);
                    assert debug("LDC " + valueOf(finalVal));
                    mv.visitLdcInsn(finalVal);
                    wrapPrimitive(finalVal.getClass());
                    return finalVal;
                } else {
                    assert debug("GETSTATIC " + getInternalName(f.getDeclaringClass()) + "." + ((Field) ts).getName() + "::" + getDescriptor(f.getType()));
                    mv.visitFieldInsn(GETSTATIC, getInternalName(f.getDeclaringClass()), f.getName(), getDescriptor(returnType = f.getType()));
                    return f.get(null);
                }
            }
        } else if (ctx instanceof Class) {
            /**
             * This is our ugly support for function pointers.  This works but needs to be re-thought out at some
             * point.
             */
            Class c = (Class) ctx;
            for (Method m : c.getMethods()) {
                if (property.equals(m.getName())) {
                    if (MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL) {
                        assert debug("POP");
                        mv.visitInsn(POP);
                        assert debug("INVOKESTATIC " + m.getName());
                        mv.visitMethodInsn(INVOKESTATIC, getInternalName(m.getDeclaringClass()), m.getName(), getMethodDescriptor(m));
                        returnType = m.getReturnType();
                        return m.invoke(null, EMPTY_OBJ_ARR);
                    } else {
                        writeFunctionPointerStub(c, m);
                        return m;
                    }
                }
            }
            try {
                Class subClass = findClass(variableFactory, c.getName() + "$" + property, pCtx);
                ldcClassConstant(subClass);
                return subClass;
            } catch (ClassNotFoundException cnfe) {
            // fall through.
            }
        } else if (MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL) {
            return getMethod(ctx, property);
        }
        if (ctx == null) {
            throw new PropertyAccessException("unresolvable property or identifier: " + property, expr, st);
        } else {
            throw new PropertyAccessException("could not access: " + property + "; in class: " + ctx.getClass().getName(), expr, st);
        }
    }
}
Also used : IOException(java.io.IOException) PropertyHandler(org.mvel2.integration.PropertyHandler) Map(java.util.Map)

Example 22 with CompileException

use of org.mvel2.CompileException in project mvel by mikebrock.

the class ASMAccessorOptimizer method getCollectionProperty.

private Object getCollectionProperty(Object ctx, String prop) throws IllegalAccessException, InvocationTargetException {
    if (prop.trim().length() > 0) {
        ctx = getBeanProperty(ctx, prop);
        first = false;
    }
    if (ctx == null)
        return null;
    assert debug("\n  **  ENTER -> {collection:<<" + prop + ">>; ctx=" + ctx + "}");
    if (first) {
        assert debug("ALOAD 1");
        mv.visitVarInsn(ALOAD, 1);
    }
    int start = ++cursor;
    skipWhitespace();
    if (cursor == end)
        throw new CompileException("unterminated '['", expr, st);
    if (scanTo(']'))
        throw new CompileException("unterminated '['", expr, st);
    String tk = new String(expr, start, cursor - start);
    assert debug("{collection token: [" + tk + "]}");
    ExecutableStatement compiled = (ExecutableStatement) subCompileExpression(tk.toCharArray(), pCtx);
    Object item = compiled.getValue(ctx, variableFactory);
    ++cursor;
    if (ctx instanceof Map) {
        assert debug("CHECKCAST java/util/Map");
        mv.visitTypeInsn(CHECKCAST, "java/util/Map");
        Class c = writeLiteralOrSubexpression(compiled);
        if (c != null && c.isPrimitive()) {
            wrapPrimitive(c);
        }
        assert debug("INVOKEINTERFACE: get");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
        return ((Map) ctx).get(item);
    } else if (ctx instanceof List) {
        assert debug("CHECKCAST java/util/List");
        mv.visitTypeInsn(CHECKCAST, "java/util/List");
        writeLiteralOrSubexpression(compiled, int.class);
        assert debug("INVOKEINTERFACE: java/util/List.get");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;");
        return ((List) ctx).get(convert(item, Integer.class));
    } else if (ctx.getClass().isArray()) {
        assert debug("CHECKCAST " + getDescriptor(ctx.getClass()));
        mv.visitTypeInsn(CHECKCAST, getDescriptor(ctx.getClass()));
        writeLiteralOrSubexpression(compiled, int.class, item.getClass());
        Class cls = getBaseComponentType(ctx.getClass());
        if (cls.isPrimitive()) {
            if (cls == int.class) {
                assert debug("IALOAD");
                mv.visitInsn(IALOAD);
            } else if (cls == char.class) {
                assert debug("CALOAD");
                mv.visitInsn(CALOAD);
            } else if (cls == boolean.class) {
                assert debug("BALOAD");
                mv.visitInsn(BALOAD);
            } else if (cls == double.class) {
                assert debug("DALOAD");
                mv.visitInsn(DALOAD);
            } else if (cls == float.class) {
                assert debug("FALOAD");
                mv.visitInsn(FALOAD);
            } else if (cls == short.class) {
                assert debug("SALOAD");
                mv.visitInsn(SALOAD);
            } else if (cls == long.class) {
                assert debug("LALOAD");
                mv.visitInsn(LALOAD);
            } else if (cls == byte.class) {
                assert debug("BALOAD");
                mv.visitInsn(BALOAD);
            }
            wrapPrimitive(cls);
        } else {
            assert debug("AALOAD");
            mv.visitInsn(AALOAD);
        }
        return Array.get(ctx, convert(item, Integer.class));
    } else if (ctx instanceof CharSequence) {
        assert debug("CHECKCAST java/lang/CharSequence");
        mv.visitTypeInsn(CHECKCAST, "java/lang/CharSequence");
        if (item instanceof Integer) {
            intPush((Integer) item);
            assert debug("INVOKEINTERFACE java/lang/CharSequence.charAt");
            mv.visitMethodInsn(INVOKEINTERFACE, "java/lang/CharSequence", "charAt", "(I)C");
            wrapPrimitive(char.class);
            return ((CharSequence) ctx).charAt((Integer) item);
        } else {
            writeLiteralOrSubexpression(compiled, Integer.class);
            unwrapPrimitive(int.class);
            assert debug("INVOKEINTERFACE java/lang/CharSequence.charAt");
            mv.visitMethodInsn(INVOKEINTERFACE, "java/lang/CharSequence", "charAt", "(I)C");
            wrapPrimitive(char.class);
            return ((CharSequence) ctx).charAt(convert(item, Integer.class));
        }
    } else {
        TypeDescriptor tDescr = new TypeDescriptor(expr, this.start, length, 0);
        if (tDescr.isArray()) {
            try {
                Class cls = getClassReference((Class) ctx, tDescr, variableFactory, pCtx);
                // rootNode = new StaticReferenceAccessor(cls);
                ldcClassConstant(cls);
                return cls;
            } catch (Exception e) {
            // fall through
            }
        }
        throw new CompileException("illegal use of []: unknown type: " + (ctx == null ? null : ctx.getClass().getName()), expr, st);
    }
}
Also used : TypeDescriptor(org.mvel2.ast.TypeDescriptor) ArrayList(java.util.ArrayList) List(java.util.List) Map(java.util.Map) IOException(java.io.IOException)

Example 23 with CompileException

use of org.mvel2.CompileException in project mvel by mikebrock.

the class ReflectiveAccessorOptimizer method optimizeSetAccessor.

public Accessor optimizeSetAccessor(ParserContext pCtx, char[] property, int start, int offset, Object ctx, Object thisRef, VariableResolverFactory factory, boolean rootThisRef, Object value, Class ingressType) {
    this.rootNode = this.currNode = null;
    this.expr = property;
    this.start = start;
    this.first = true;
    this.length = start + offset;
    this.ctx = ctx;
    this.thisRef = thisRef;
    this.variableFactory = factory;
    this.ingressType = ingressType;
    char[] root = null;
    int split = findLastUnion();
    PropertyVerifier verifier = new PropertyVerifier(property, this.pCtx = pCtx);
    if (split != -1) {
        root = subset(property, 0, split++);
        // todo: must use the property verifier.
        property = subset(property, split, property.length - split);
    }
    if (root != null) {
        this.length = end = (this.expr = root).length;
        compileGetChain();
        ctx = this.val;
    }
    if (ctx == null) {
        throw new PropertyAccessException("could not access property: " + new String(property, this.start, length) + "; parent is null: " + new String(expr), expr, this.start);
    }
    try {
        this.length = end = (this.expr = property).length;
        int st;
        this.cursor = st = 0;
        skipWhitespace();
        if (collection) {
            st = cursor;
            if (cursor == end)
                throw new PropertyAccessException("unterminated '['", expr, this.start);
            if (scanTo(']'))
                throw new PropertyAccessException("unterminated '['", expr, this.start);
            String ex = new String(property, st, cursor - st);
            if (ctx instanceof Map) {
                if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(Map.class)) {
                    propHandlerSet(ex, ctx, Map.class, value);
                } else {
                    // noinspection unchecked
                    ((Map) ctx).put(eval(ex, ctx, variableFactory), convert(value, returnType = verifier.analyze()));
                    addAccessorNode(new MapAccessorNest(ex, returnType));
                }
                return rootNode;
            } else if (ctx instanceof List) {
                if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(List.class)) {
                    propHandlerSet(ex, ctx, List.class, value);
                } else {
                    // noinspection unchecked
                    ((List) ctx).set(eval(ex, ctx, variableFactory, Integer.class), convert(value, returnType = verifier.analyze()));
                    addAccessorNode(new ListAccessorNest(ex, returnType));
                }
                return rootNode;
            } else if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(ctx.getClass())) {
                propHandlerSet(ex, ctx, ctx.getClass(), value);
                return rootNode;
            } else if (ctx.getClass().isArray()) {
                if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(Array.class)) {
                    propHandlerSet(ex, ctx, Array.class, value);
                } else {
                    // noinspection unchecked
                    Array.set(ctx, eval(ex, ctx, variableFactory, Integer.class), convert(value, getBaseComponentType(ctx.getClass())));
                    addAccessorNode(new ArrayAccessorNest(ex));
                }
                return rootNode;
            } else {
                throw new PropertyAccessException("cannot bind to collection property: " + new String(property) + ": not a recognized collection type: " + ctx.getClass(), expr, this.st);
            }
        } else if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(ctx.getClass())) {
            propHandlerSet(new String(property), ctx, ctx.getClass(), value);
            return rootNode;
        }
        String tk = new String(property, 0, length);
        if (hasSetListeners()) {
            notifySetListeners(ctx, tk, variableFactory, value);
            addAccessorNode(new Notify(tk));
        }
        Member member = getFieldOrWriteAccessor(ctx.getClass(), tk, value == null ? null : ingressType);
        if (member instanceof Field) {
            Field fld = (Field) member;
            if (value != null && !fld.getType().isAssignableFrom(value.getClass())) {
                if (!canConvert(fld.getType(), value.getClass())) {
                    throw new CompileException("cannot convert type: " + value.getClass() + ": to " + fld.getType(), this.expr, this.start);
                }
                fld.set(ctx, convert(value, fld.getType()));
                addAccessorNode(new DynamicFieldAccessor(fld));
            } else if (value == null && fld.getType().isPrimitive()) {
                fld.set(ctx, PropertyTools.getPrimitiveInitialValue(fld.getType()));
                addAccessorNode(new FieldAccessor(fld));
            } else {
                fld.set(ctx, value);
                addAccessorNode(new FieldAccessor(fld));
            }
        } else if (member != null) {
            Method meth = (Method) member;
            if (value != null && !meth.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
                if (!canConvert(meth.getParameterTypes()[0], value.getClass())) {
                    throw new CompileException("cannot convert type: " + value.getClass() + ": to " + meth.getParameterTypes()[0], this.expr, this.start);
                }
                meth.invoke(ctx, convert(value, meth.getParameterTypes()[0]));
            } else if (value == null && meth.getParameterTypes()[0].isPrimitive()) {
                meth.invoke(ctx, PropertyTools.getPrimitiveInitialValue(meth.getParameterTypes()[0]));
            } else {
                meth.invoke(ctx, value);
            }
            addAccessorNode(new SetterAccessor(meth));
        } else if (ctx instanceof Map) {
            // noinspection unchecked
            ((Map) ctx).put(tk, value);
            addAccessorNode(new MapAccessor(tk));
        } else {
            throw new PropertyAccessException("could not access property (" + tk + ") in: " + ingressType.getName(), this.expr, this.start);
        }
    } catch (InvocationTargetException e) {
        throw new PropertyAccessException("could not access property: " + new String(property), this.expr, st, e);
    } catch (IllegalAccessException e) {
        throw new PropertyAccessException("could not access property: " + new String(property), this.expr, st, e);
    } catch (IllegalArgumentException e) {
        throw new PropertyAccessException("error binding property: " + new String(property) + " (value <<" + value + ">>::" + (value == null ? "null" : value.getClass().getCanonicalName()) + ")", this.expr, st, e);
    }
    return rootNode;
}
Also used : PropertyVerifier(org.mvel2.compiler.PropertyVerifier) List(java.util.List) Map(java.util.Map) WeakHashMap(java.util.WeakHashMap)

Example 24 with CompileException

use of org.mvel2.CompileException in project mvel by mikebrock.

the class ReflectiveAccessorOptimizer method getMethod.

/**
 * Find an appropriate method, execute it, and return it's response.
 *
 * @param ctx  -
 * @param name -
 * @return -
 * @throws Exception -
 */
@SuppressWarnings({ "unchecked" })
private Object getMethod(Object ctx, String name) throws Exception {
    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[] args;
    Class[] argTypes;
    ExecutableStatement[] es;
    if (tk.length() == 0) {
        args = ParseTools.EMPTY_OBJ_ARR;
        argTypes = ParseTools.EMPTY_CLS_ARR;
        es = null;
    } else {
        List<char[]> subtokens = parseParameterList(tk.toCharArray(), 0, -1);
        es = new ExecutableStatement[subtokens.size()];
        args = new Object[subtokens.size()];
        argTypes = new Class[subtokens.size()];
        for (int i = 0; i < subtokens.size(); i++) {
            try {
                args[i] = (es[i] = (ExecutableStatement) subCompileExpression(subtokens.get(i), pCtx)).getValue(this.thisRef, thisRef, variableFactory);
            } catch (CompileException e) {
                throw ErrorUtil.rewriteIfNeeded(e, this.expr, this.start);
            }
            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 Function) {
            Function func = (Function) ptr;
            if (!name.equals(func.getName())) {
                getBeanProperty(ctx, name);
                addAccessorNode(new DynamicFunctionAccessor(es));
            } else {
                addAccessorNode(new FunctionAccessor((Function) ptr, es));
            }
            return ((Function) 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;
    }
    if (ctx == null) {
        throw new PropertyAccessException("null pointer or function not found: " + name, this.expr, this.start);
    }
    boolean classTarget = false;
    Class<?> cls = currType != null ? currType : ((classTarget = ctx instanceof Class) ? (Class<?>) ctx : ctx.getClass());
    currType = null;
    Method m;
    Class[] parameterTypes = null;
    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 (m == null) {
        StringAppender errorBuild = new StringAppender();
        if ("size".equals(name) && args.length == 0 && cls.isArray()) {
            addAccessorNode(new ArrayLength());
            return getLength(ctx);
        }
        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(", ");
        }
        throw new PropertyAccessException("unable to resolve method: " + cls.getName() + "." + name + "(" + errorBuild.toString() + ") [arglength=" + args.length + "]", this.expr, this.st);
    } else {
        if (es != null) {
            ExecutableStatement cExpr;
            for (int i = 0; i < es.length; i++) {
                cExpr = (ExecutableStatement) es[i];
                if (cExpr.getKnownIngressType() == null) {
                    cExpr.setKnownIngressType(parameterTypes[i]);
                    cExpr.computeTypeConversionRule();
                }
                if (!cExpr.isConvertableIngressEgress()) {
                    args[i] = convert(args[i], parameterTypes[i]);
                }
            }
        } else {
            /**
             * Coerce any types if required.
             */
            for (int i = 0; i < args.length; i++) args[i] = convert(args[i], parameterTypes[i]);
        }
        Object o = getWidenedTarget(m).invoke(ctx, args);
        if (hasNullMethodHandler()) {
            addAccessorNode(new MethodAccessorNH(getWidenedTarget(m), (ExecutableStatement[]) es, getNullMethodHandler()));
            if (o == null)
                o = getNullMethodHandler().getProperty(m.getName(), ctx, variableFactory);
        } else {
            addAccessorNode(new MethodAccessor(getWidenedTarget(m), (ExecutableStatement[]) es));
        }
        /**
         * return the response.
         */
        return o;
    }
}
Also used : ExecutableStatement(org.mvel2.compiler.ExecutableStatement) Function(org.mvel2.ast.Function)

Example 25 with CompileException

use of org.mvel2.CompileException in project mvel by mikebrock.

the class TemplateCompiler method compileFrom.

public Node compileFrom(Node root, ExecutionStack stack) {
    line = 1;
    Node n = root;
    if (root == null) {
        n = root = new TextNode(0, 0);
    }
    IfNode last;
    Integer opcode;
    String name;
    int x;
    try {
        while (cursor < length) {
            switch(template[cursor]) {
                case '\n':
                    line++;
                    colStart = cursor + 1;
                    break;
                case '@':
                case '$':
                    if (isNext(template[cursor])) {
                        start = ++cursor;
                        (n = markTextNode(n)).setEnd(n.getEnd() + 1);
                        start = lastTextRangeEnding = ++cursor;
                        continue;
                    }
                    if ((x = captureOrbToken()) != -1) {
                        start = x;
                        switch((opcode = OPCODES.get(name = new String(capture()))) == null ? 0 : opcode) {
                            case Opcodes.IF:
                                /**
                                 * Capture any residual text node, and push the if statement on the nesting stack.
                                 */
                                stack.push(n = markTextNode(n).next = codeCache ? new CompiledIfNode(start, name, template, captureOrbInternal(), start, parserContext) : new IfNode(start, name, template, captureOrbInternal(), start));
                                n.setTerminus(new TerminalNode());
                                break;
                            case Opcodes.ELSE:
                                if (!stack.isEmpty() && stack.peek() instanceof IfNode) {
                                    markTextNode(n).next = (last = (IfNode) stack.pop()).getTerminus();
                                    last.demarcate(last.getTerminus(), template);
                                    last.next = n = codeCache ? new CompiledIfNode(start, name, template, captureOrbInternal(), start, parserContext) : new IfNode(start, name, template, captureOrbInternal(), start);
                                    n.setTerminus(last.getTerminus());
                                    stack.push(n);
                                }
                                break;
                            case Opcodes.FOREACH:
                                stack.push(n = markTextNode(n).next = codeCache ? new CompiledForEachNode(start, name, template, captureOrbInternal(), start, parserContext) : new ForEachNode(start, name, template, captureOrbInternal(), start));
                                n.setTerminus(new TerminalNode());
                                break;
                            case Opcodes.INCLUDE_FILE:
                                n = markTextNode(n).next = codeCache ? new CompiledIncludeNode(start, name, template, captureOrbInternal(), start = cursor + 1, parserContext) : new IncludeNode(start, name, template, captureOrbInternal(), start = cursor + 1);
                                break;
                            case Opcodes.INCLUDE_NAMED:
                                n = markTextNode(n).next = codeCache ? new CompiledNamedIncludeNode(start, name, template, captureOrbInternal(), start = cursor + 1, parserContext) : new NamedIncludeNode(start, name, template, captureOrbInternal(), start = cursor + 1);
                                break;
                            case Opcodes.CODE:
                                n = markTextNode(n).next = codeCache ? new CompiledCodeNode(start, name, template, captureOrbInternal(), start = cursor + 1, parserContext) : new CodeNode(start, name, template, captureOrbInternal(), start = cursor + 1);
                                break;
                            case Opcodes.EVAL:
                                n = markTextNode(n).next = codeCache ? new CompiledEvalNode(start, name, template, captureOrbInternal(), start = cursor + 1, parserContext) : new EvalNode(start, name, template, captureOrbInternal(), start = cursor + 1);
                                break;
                            case Opcodes.COMMENT:
                                n = markTextNode(n).next = new CommentNode(start, name, template, captureOrbInternal(), start = cursor + 1);
                                break;
                            case Opcodes.DECLARE:
                                stack.push(n = markTextNode(n).next = codeCache ? new CompiledDeclareNode(start, name, template, captureOrbInternal(), start = cursor + 1, parserContext) : new DeclareNode(start, name, template, captureOrbInternal(), start = cursor + 1));
                                n.setTerminus(new TerminalNode());
                                break;
                            case Opcodes.END:
                                n = markTextNode(n);
                                Node end = (Node) stack.pop();
                                Node terminal = end.getTerminus();
                                terminal.setCStart(captureOrbInternal());
                                terminal.setEnd((lastTextRangeEnding = start) - 1);
                                terminal.calculateContents(template);
                                if (end.demarcate(terminal, template))
                                    n = n.next = terminal;
                                else
                                    n = terminal;
                                break;
                            default:
                                if (name.length() == 0) {
                                    n = markTextNode(n).next = codeCache ? new CompiledExpressionNode(start, name, template, captureOrbInternal(), start = cursor + 1, parserContext) : new ExpressionNode(start, name, template, captureOrbInternal(), start = cursor + 1);
                                } else if (customNodes != null && customNodes.containsKey(name)) {
                                    Class<? extends Node> customNode = customNodes.get(name);
                                    try {
                                        (n = markTextNode(n).next = (customNode.newInstance())).setBegin(start);
                                        n.setName(name);
                                        n.setCStart(captureOrbInternal());
                                        n.setCEnd(start = cursor + 1);
                                        n.setEnd(n.getCEnd());
                                        n.setContents(subset(template, n.getCStart(), n.getCEnd() - n.getCStart() - 1));
                                        if (n.isOpenNode()) {
                                            stack.push(n);
                                        }
                                    } catch (InstantiationException e) {
                                        throw new RuntimeException("unable to instantiate custom node class: " + customNode.getName());
                                    } catch (IllegalAccessException e) {
                                        throw new RuntimeException("unable to instantiate custom node class: " + customNode.getName());
                                    }
                                } else {
                                    throw new RuntimeException("unknown token type: " + name);
                                }
                        }
                    }
                    break;
            }
            cursor++;
        }
    } catch (RuntimeException e) {
        CompileException ce = new CompileException(e.getMessage(), template, cursor, e);
        ce.setExpr(template);
        if (e instanceof CompileException) {
            CompileException ce2 = (CompileException) e;
            if (ce2.getCursor() != -1) {
                ce.setCursor(ce2.getCursor());
                if (ce2.getColumn() == -1)
                    ce.setColumn(ce.getCursor() - colStart);
                else
                    ce.setColumn(ce2.getColumn());
            }
        }
        ce.setLineNumber(line);
        throw ce;
    }
    if (!stack.isEmpty()) {
        CompileException ce = new CompileException("unclosed @" + ((Node) stack.peek()).getName() + "{} block. expected @end{}", template, cursor);
        ce.setColumn(cursor - colStart);
        ce.setLineNumber(line);
        throw ce;
    }
    if (start < template.length) {
        n = n.next = new TextNode(start, template.length);
    }
    n.next = new EndNode();
    n = root;
    do {
        if (n.getLength() != 0) {
            break;
        }
    } while ((n = n.getNext()) != null);
    if (n != null && n.getLength() == template.length - 1) {
        if (n instanceof ExpressionNode) {
            return codeCache ? new CompiledTerminalExpressionNode(n, parserContext) : new TerminalExpressionNode(n);
        } else {
            return n;
        }
    }
    return root;
}
Also used : CompileException(org.mvel2.CompileException)

Aggregations

CompileException (org.mvel2.CompileException)25 Map (java.util.Map)9 List (java.util.List)8 IOException (java.io.IOException)7 ExecutableStatement (org.mvel2.compiler.ExecutableStatement)7 ArrayList (java.util.ArrayList)6 ParserContext (org.mvel2.ParserContext)4 Function (org.mvel2.ast.Function)4 TypeDescriptor (org.mvel2.ast.TypeDescriptor)4 WeakHashMap (java.util.WeakHashMap)3 Proto (org.mvel2.ast.Proto)3 ExpressionCompiler (org.mvel2.compiler.ExpressionCompiler)3 StringAppender (org.mvel2.util.StringAppender)3 HashMap (java.util.HashMap)2 Label (org.mvel2.asm.Label)2 ASTNode (org.mvel2.ast.ASTNode)2 EndOfStatement (org.mvel2.ast.EndOfStatement)2 CompiledExpression (org.mvel2.compiler.CompiledExpression)2 DefaultLocalVariableResolverFactory (org.mvel2.integration.impl.DefaultLocalVariableResolverFactory)2 ItemResolverFactory (org.mvel2.integration.impl.ItemResolverFactory)2