Search in sources :

Example 6 with PropertyAccessException

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

the class ASMAccessorOptimizer 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.expr = property;
    this.start = this.cursor = start;
    this.end = start + offset;
    this.length = start + offset;
    this.first = true;
    this.ingressType = ingressType;
    compiledInputs = new ArrayList<ExecutableStatement>();
    this.pCtx = pCtx;
    this.ctx = ctx;
    this.thisRef = thisRef;
    this.variableFactory = factory;
    char[] root = null;
    PropertyVerifier verifier = new PropertyVerifier(property, this.pCtx = pCtx);
    int split = findLastUnion();
    if (split != -1) {
        root = subset(property, 0, split);
    }
    AccessorNode rootAccessor = null;
    _initJIT2();
    if (root != null) {
        int _length = this.length;
        int _end = this.end;
        char[] _expr = this.expr;
        this.length = end = (this.expr = root).length;
        // run the compiler but don't finish building.
        deferFinish = true;
        noinit = true;
        compileAccessor();
        ctx = this.val;
        this.expr = _expr;
        this.cursor = start + root.length + 1;
        this.length = _length - root.length - 1;
        this.end = this.cursor + this.length;
    } else {
        assert debug("ALOAD 1");
        mv.visitVarInsn(ALOAD, 1);
    }
    try {
        skipWhitespace();
        if (collection) {
            int st = cursor;
            whiteSpaceSkip();
            if (st == end)
                throw new PropertyAccessException("unterminated '['", expr, start);
            if (scanTo(']'))
                throw new PropertyAccessException("unterminated '['", expr, start);
            String ex = new String(expr, st, cursor - st);
            assert debug("CHECKCAST " + ctx.getClass().getName());
            mv.visitTypeInsn(CHECKCAST, getInternalName(ctx.getClass()));
            if (ctx instanceof Map) {
                if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(Map.class)) {
                    propHandlerByteCodePut(ex, ctx, Map.class, value);
                } else {
                    // noinspection unchecked
                    ((Map) ctx).put(eval(ex, ctx, variableFactory), convert(value, returnType = verifier.analyze()));
                    writeLiteralOrSubexpression(subCompileExpression(ex.toCharArray(), pCtx));
                    assert debug("ALOAD 4");
                    mv.visitVarInsn(ALOAD, 4);
                    if (value != null & returnType != value.getClass()) {
                        dataConversion(returnType);
                        checkcast(returnType);
                    }
                    assert debug("INVOKEINTERFACE Map.put");
                    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
                    assert debug("POP");
                    mv.visitInsn(POP);
                    assert debug("ALOAD 4");
                    mv.visitVarInsn(ALOAD, 4);
                }
            } else if (ctx instanceof List) {
                if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(List.class)) {
                    propHandlerByteCodePut(ex, ctx, List.class, value);
                } else {
                    // noinspection unchecked
                    ((List) ctx).set(eval(ex, ctx, variableFactory, Integer.class), convert(value, returnType = verifier.analyze()));
                    writeLiteralOrSubexpression(subCompileExpression(ex.toCharArray(), pCtx));
                    unwrapPrimitive(int.class);
                    assert debug("ALOAD 4");
                    mv.visitVarInsn(ALOAD, 4);
                    if (value != null & !value.getClass().isAssignableFrom(returnType)) {
                        dataConversion(returnType);
                        checkcast(returnType);
                    }
                    assert debug("INVOKEINTERFACE List.set");
                    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "set", "(ILjava/lang/Object;)Ljava/lang/Object;");
                    assert debug("ALOAD 4");
                    mv.visitVarInsn(ALOAD, 4);
                }
            } else if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(ctx.getClass())) {
                propHandlerByteCodePut(ex, ctx, ctx.getClass(), value);
            } else if (ctx.getClass().isArray()) {
                if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(Array.class)) {
                    propHandlerByteCodePut(ex, ctx, Array.class, value);
                } else {
                    Class type = getBaseComponentType(ctx.getClass());
                    Object idx = eval(ex, ctx, variableFactory);
                    writeLiteralOrSubexpression(subCompileExpression(ex.toCharArray(), pCtx), int.class);
                    if (!(idx instanceof Integer)) {
                        dataConversion(Integer.class);
                        idx = DataConversion.convert(idx, Integer.class);
                        unwrapPrimitive(int.class);
                    }
                    assert debug("ALOAD 4");
                    mv.visitVarInsn(ALOAD, 4);
                    if (type.isPrimitive())
                        unwrapPrimitive(type);
                    else if (!type.equals(value.getClass())) {
                        dataConversion(type);
                    }
                    arrayStore(type);
                    // noinspection unchecked
                    Array.set(ctx, (Integer) idx, convert(value, type));
                    assert debug("ALOAD 4");
                    mv.visitVarInsn(ALOAD, 4);
                }
            } else {
                throw new PropertyAccessException("cannot bind to collection property: " + new String(expr) + ": not a recognized collection type: " + ctx.getClass(), expr, start);
            }
            deferFinish = false;
            noinit = false;
            _finishJIT();
            try {
                deferFinish = false;
                return _initializeAccessor();
            } catch (Exception e) {
                throw new CompileException("could not generate accessor", expr, start, e);
            }
        }
        String tk = new String(expr, this.cursor, this.length);
        Member member = getFieldOrWriteAccessor(ctx.getClass(), tk, value == null ? null : ingressType);
        if (GlobalListenerFactory.hasSetListeners()) {
            mv.visitVarInsn(ALOAD, 1);
            mv.visitLdcInsn(tk);
            mv.visitVarInsn(ALOAD, 3);
            mv.visitVarInsn(ALOAD, 4);
            mv.visitMethodInsn(INVOKESTATIC, NAMESPACE + "integration/GlobalListenerFactory", "notifySetListeners", "(Ljava/lang/Object;Ljava/lang/String;L" + NAMESPACE + "integration/VariableResolverFactory;Ljava/lang/Object;)V");
            GlobalListenerFactory.notifySetListeners(ctx, tk, variableFactory, value);
        }
        if (member instanceof Field) {
            checkcast(ctx.getClass());
            Field fld = (Field) member;
            Label jmp = null;
            Label jmp2 = new Label();
            if (fld.getType().isPrimitive()) {
                assert debug("ASTORE 5");
                mv.visitVarInsn(ASTORE, 5);
                assert debug("ALOAD 4");
                mv.visitVarInsn(ALOAD, 4);
                if (value == null)
                    value = PropertyTools.getPrimitiveInitialValue(fld.getType());
                jmp = new Label();
                assert debug("IFNOTNULL jmp");
                mv.visitJumpInsn(IFNONNULL, jmp);
                assert debug("ALOAD 5");
                mv.visitVarInsn(ALOAD, 5);
                assert debug("ICONST_0");
                mv.visitInsn(ICONST_0);
                assert debug("PUTFIELD " + getInternalName(fld.getDeclaringClass()) + "." + tk);
                mv.visitFieldInsn(PUTFIELD, getInternalName(fld.getDeclaringClass()), tk, getDescriptor(fld.getType()));
                assert debug("GOTO jmp2");
                mv.visitJumpInsn(GOTO, jmp2);
                assert debug("jmp:");
                mv.visitLabel(jmp);
                assert debug("ALOAD 5");
                mv.visitVarInsn(ALOAD, 5);
                assert debug("ALOAD 4");
                mv.visitVarInsn(ALOAD, 4);
                unwrapPrimitive(fld.getType());
            } else {
                assert debug("ALOAD 4");
                mv.visitVarInsn(ALOAD, 4);
                checkcast(fld.getType());
            }
            if (jmp == null && value != null && !fld.getType().isAssignableFrom(value.getClass())) {
                if (!canConvert(fld.getType(), value.getClass())) {
                    throw new CompileException("cannot convert type: " + value.getClass() + ": to " + fld.getType(), expr, start);
                }
                dataConversion(fld.getType());
                fld.set(ctx, convert(value, fld.getType()));
            } else {
                fld.set(ctx, value);
            }
            assert debug("PUTFIELD " + getInternalName(fld.getDeclaringClass()) + "." + tk);
            mv.visitFieldInsn(PUTFIELD, getInternalName(fld.getDeclaringClass()), tk, getDescriptor(fld.getType()));
            assert debug("jmp2:");
            mv.visitLabel(jmp2);
            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);
        } else if (member != null) {
            assert debug("CHECKCAST " + getInternalName(ctx.getClass()));
            mv.visitTypeInsn(CHECKCAST, getInternalName(ctx.getClass()));
            Method meth = (Method) member;
            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);
            Class targetType = meth.getParameterTypes()[0];
            Label jmp = null;
            Label jmp2 = new Label();
            if (value != null && !targetType.isAssignableFrom(value.getClass())) {
                if (!canConvert(targetType, value.getClass())) {
                    throw new CompileException("cannot convert type: " + value.getClass() + ": to " + meth.getParameterTypes()[0], expr, start);
                }
                dataConversion(getWrapperClass(targetType));
                if (targetType.isPrimitive()) {
                    unwrapPrimitive(targetType);
                } else
                    checkcast(targetType);
                meth.invoke(ctx, convert(value, meth.getParameterTypes()[0]));
            } else {
                if (targetType.isPrimitive()) {
                    if (value == null)
                        value = PropertyTools.getPrimitiveInitialValue(targetType);
                    jmp = new Label();
                    assert debug("IFNOTNULL jmp");
                    mv.visitJumpInsn(IFNONNULL, jmp);
                    assert debug("ICONST_0");
                    mv.visitInsn(ICONST_0);
                    assert debug("INVOKEVIRTUAL " + getInternalName(meth.getDeclaringClass()) + "." + meth.getName());
                    mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(meth.getDeclaringClass()), meth.getName(), getMethodDescriptor(meth));
                    assert debug("GOTO jmp2");
                    mv.visitJumpInsn(GOTO, jmp2);
                    assert debug("jmp:");
                    mv.visitLabel(jmp);
                    assert debug("ALOAD 4");
                    mv.visitVarInsn(ALOAD, 4);
                    unwrapPrimitive(targetType);
                } else {
                    checkcast(targetType);
                }
                meth.invoke(ctx, value);
            }
            assert debug("INVOKEVIRTUAL " + getInternalName(meth.getDeclaringClass()) + "." + meth.getName());
            mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(meth.getDeclaringClass()), meth.getName(), getMethodDescriptor(meth));
            assert debug("jmp2:");
            mv.visitLabel(jmp2);
            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);
        } else if (ctx instanceof Map) {
            assert debug("CHECKCAST " + getInternalName(ctx.getClass()));
            mv.visitTypeInsn(CHECKCAST, getInternalName(ctx.getClass()));
            assert debug("LDC '" + tk + "'");
            mv.visitLdcInsn(tk);
            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);
            assert debug("INVOKEVIRTUAL java/util/HashMap.put");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/HashMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);
            // noinspection unchecked
            ((Map) ctx).put(tk, value);
        } else {
            throw new PropertyAccessException("could not access property (" + tk + ") in: " + ingressType.getName(), expr, start);
        }
    } catch (InvocationTargetException e) {
        throw new PropertyAccessException("could not access property", expr, start, e);
    } catch (IllegalAccessException e) {
        throw new PropertyAccessException("could not access property", expr, start, e);
    }
    try {
        deferFinish = false;
        noinit = false;
        _finishJIT();
        return _initializeAccessor();
    } catch (Exception e) {
        throw new CompileException("could not generate accessor", expr, start, e);
    }
}
Also used : Label(org.mvel2.asm.Label) IOException(java.io.IOException) ArrayList(java.util.ArrayList) List(java.util.List) Map(java.util.Map)

Example 7 with PropertyAccessException

use of org.mvel2.PropertyAccessException 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 8 with PropertyAccessException

use of org.mvel2.PropertyAccessException 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 9 with PropertyAccessException

use of org.mvel2.PropertyAccessException 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 10 with PropertyAccessException

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

the class ASMAccessorOptimizer method compileAccessor.

private Accessor compileAccessor() {
    assert debug("<<INITIATE COMPILE>>");
    Object curr = ctx;
    try {
        if (!MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING) {
            while (cursor < end) {
                switch(nextSubToken()) {
                    case BEAN:
                        curr = getBeanProperty(curr, capture());
                        break;
                    case METH:
                        curr = getMethod(curr, capture());
                        break;
                    case COL:
                        curr = getCollectionProperty(curr, capture());
                        break;
                    case WITH:
                        curr = getWithProperty(curr);
                        break;
                }
                // check to see if a null safety is enabled on this property.
                if (fields == -1) {
                    if (curr == null) {
                        if (nullSafe) {
                            throw new OptimizationNotSupported();
                        }
                        break;
                    } else {
                        fields = 0;
                    }
                }
                first = false;
                if (nullSafe && cursor < end) {
                    assert debug("DUP");
                    mv.visitInsn(DUP);
                    Label j = new Label();
                    assert debug("IFNONNULL : jump");
                    mv.visitJumpInsn(IFNONNULL, j);
                    assert debug("ARETURN");
                    mv.visitInsn(ARETURN);
                    assert debug("LABEL:jump");
                    mv.visitLabel(j);
                }
            }
        } else {
            while (cursor < end) {
                switch(nextSubToken()) {
                    case BEAN:
                        curr = getBeanPropertyAO(curr, capture());
                        break;
                    case METH:
                        curr = getMethod(curr, capture());
                        break;
                    case COL:
                        curr = getCollectionPropertyAO(curr, capture());
                        break;
                    case WITH:
                        curr = getWithProperty(curr);
                        break;
                }
                // check to see if a null safety is enabled on this property.
                if (fields == -1) {
                    if (curr == null) {
                        if (nullSafe) {
                            throw new OptimizationNotSupported();
                        }
                        break;
                    } else {
                        fields = 0;
                    }
                }
                first = false;
                if (nullSafe && cursor < end) {
                    assert debug("DUP");
                    mv.visitInsn(DUP);
                    Label j = new Label();
                    assert debug("IFNONNULL : jump");
                    mv.visitJumpInsn(IFNONNULL, j);
                    assert debug("ARETURN");
                    mv.visitInsn(ARETURN);
                    assert debug("LABEL:jump");
                    mv.visitLabel(j);
                }
            }
        }
        val = curr;
        _finishJIT();
        return _initializeAccessor();
    } catch (InvocationTargetException e) {
        throw new PropertyAccessException(new String(expr), expr, st, e);
    } catch (IllegalAccessException e) {
        throw new PropertyAccessException(new String(expr), expr, st, e);
    } catch (IndexOutOfBoundsException e) {
        throw new PropertyAccessException(new String(expr), expr, st, e);
    } catch (PropertyAccessException e) {
        throw new CompileException(e.getMessage(), expr, st, e);
    } catch (CompileException e) {
        throw e;
    } catch (NullPointerException e) {
        throw new PropertyAccessException(new String(expr), expr, st, e);
    } catch (OptimizationNotSupported e) {
        throw e;
    } catch (Exception e) {
        throw new CompileException(e.getMessage(), expr, st, e);
    }
}
Also used : Label(org.mvel2.asm.Label) OptimizationNotSupported(org.mvel2.optimizers.OptimizationNotSupported) IOException(java.io.IOException)

Aggregations

Test (org.junit.Test)5 KieServices (org.kie.api.KieServices)5 KieFileSystem (org.kie.api.builder.KieFileSystem)5 ReleaseId (org.kie.api.builder.ReleaseId)5 KieContainer (org.kie.api.runtime.KieContainer)5 KieSession (org.kie.api.runtime.KieSession)5 PropertyAccessException (org.mvel2.PropertyAccessException)5 IOException (java.io.IOException)3 Map (java.util.Map)3 ConsequenceException (org.kie.api.runtime.rule.ConsequenceException)3 List (java.util.List)2 Label (org.mvel2.asm.Label)2 Function (org.mvel2.ast.Function)2 TypeDescriptor (org.mvel2.ast.TypeDescriptor)2 ArrayList (java.util.ArrayList)1 WeakHashMap (java.util.WeakHashMap)1 Proto (org.mvel2.ast.Proto)1 ExecutableStatement (org.mvel2.compiler.ExecutableStatement)1 PropertyVerifier (org.mvel2.compiler.PropertyVerifier)1 PropertyHandler (org.mvel2.integration.PropertyHandler)1