Search in sources :

Example 1 with OptimizationFailure

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

the class ASMAccessorOptimizer method optimizeCollection.

public Accessor optimizeCollection(ParserContext pCtx, Object o, Class type, char[] property, int start, int offset, Object ctx, Object thisRef, VariableResolverFactory factory) {
    this.expr = property;
    this.cursor = this.start = start;
    this.end = start + offset;
    this.length = offset;
    this.returnType = type;
    this.compiledInputs = new ArrayList<ExecutableStatement>();
    this.ctx = ctx;
    this.thisRef = thisRef;
    this.variableFactory = factory;
    _initJIT();
    literal = true;
    _getAccessor(o, type);
    _finishJIT();
    try {
        Accessor compiledAccessor = _initializeAccessor();
        if (property != null && length > start) {
            return new Union(compiledAccessor, property, start, length);
        } else {
            return compiledAccessor;
        }
    } catch (Exception e) {
        throw new OptimizationFailure("could not optimize collection", e);
    }
}
Also used : PropertyTools.getFieldOrWriteAccessor(org.mvel2.util.PropertyTools.getFieldOrWriteAccessor) PropertyTools.getFieldOrAccessor(org.mvel2.util.PropertyTools.getFieldOrAccessor) Union(org.mvel2.optimizers.impl.refl.nodes.Union) IOException(java.io.IOException)

Example 2 with OptimizationFailure

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

the class ASMAccessorOptimizer method optimizeObjectCreation.

public Accessor optimizeObjectCreation(ParserContext pCtx, char[] property, int start, int offset, Object ctx, Object thisRef, VariableResolverFactory factory) {
    _initJIT();
    compiledInputs = new ArrayList<ExecutableStatement>();
    this.start = cursor = start;
    this.end = start + offset;
    this.length = this.end - this.start;
    this.ctx = ctx;
    this.thisRef = thisRef;
    this.variableFactory = factory;
    this.pCtx = pCtx;
    String[] cnsRes = captureContructorAndResidual(property, start, offset);
    List<char[]> constructorParms = parseMethodOrConstructor(cnsRes[0].toCharArray());
    try {
        if (constructorParms != null) {
            for (char[] constructorParm : constructorParms) {
                compiledInputs.add((ExecutableStatement) subCompileExpression(constructorParm, pCtx));
            }
            Class cls = findClass(factory, new String(subset(property, 0, findFirst('(', start, length, property))), pCtx);
            assert debug("NEW " + getInternalName(cls));
            mv.visitTypeInsn(NEW, getInternalName(cls));
            assert debug("DUP");
            mv.visitInsn(DUP);
            Object[] parms = new Object[constructorParms.size()];
            int i = 0;
            for (ExecutableStatement es : compiledInputs) {
                parms[i++] = es.getValue(ctx, factory);
            }
            Constructor cns = getBestConstructorCandidate(parms, cls, pCtx.isStrongTyping());
            if (cns == null) {
                StringBuilder error = new StringBuilder();
                for (int x = 0; x < parms.length; x++) {
                    error.append(parms[x].getClass().getName());
                    if (x + 1 < parms.length)
                        error.append(", ");
                }
                throw new CompileException("unable to find constructor: " + cls.getName() + "(" + error.toString() + ")", expr, st);
            }
            this.returnType = cns.getDeclaringClass();
            Class tg;
            for (i = 0; i < constructorParms.size(); i++) {
                assert debug("ALOAD 0");
                mv.visitVarInsn(ALOAD, 0);
                assert debug("GETFIELD p" + i);
                mv.visitFieldInsn(GETFIELD, className, "p" + i, "L" + NAMESPACE + "compiler/ExecutableStatement;");
                assert debug("ALOAD 2");
                mv.visitVarInsn(ALOAD, 2);
                assert debug("ALOAD 3");
                mv.visitVarInsn(ALOAD, 3);
                assert debug("INVOKEINTERFACE " + NAMESPACE + "compiler/ExecutableStatement.getValue");
                mv.visitMethodInsn(INVOKEINTERFACE, "" + NAMESPACE + "compiler/ExecutableStatement", "getValue", "(Ljava/lang/Object;L" + NAMESPACE + "integration/VariableResolverFactory;)Ljava/lang/Object;");
                tg = cns.getParameterTypes()[i].isPrimitive() ? getWrapperClass(cns.getParameterTypes()[i]) : cns.getParameterTypes()[i];
                if (parms[i] != null && !parms[i].getClass().isAssignableFrom(cns.getParameterTypes()[i])) {
                    ldcClassConstant(tg);
                    assert debug("INVOKESTATIC " + NAMESPACE + "DataConversion.convert");
                    mv.visitMethodInsn(INVOKESTATIC, "" + NAMESPACE + "DataConversion", "convert", "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
                    if (cns.getParameterTypes()[i].isPrimitive()) {
                        unwrapPrimitive(cns.getParameterTypes()[i]);
                    } else {
                        assert debug("CHECKCAST " + getInternalName(tg));
                        mv.visitTypeInsn(CHECKCAST, getInternalName(tg));
                    }
                } else {
                    assert debug("CHECKCAST " + getInternalName(cns.getParameterTypes()[i]));
                    mv.visitTypeInsn(CHECKCAST, getInternalName(cns.getParameterTypes()[i]));
                }
            }
            assert debug("INVOKESPECIAL " + getInternalName(cls) + ".<init> : " + getConstructorDescriptor(cns));
            mv.visitMethodInsn(INVOKESPECIAL, getInternalName(cls), "<init>", getConstructorDescriptor(cns));
            _finishJIT();
            Accessor acc = _initializeAccessor();
            if (cnsRes.length > 1 && cnsRes[1] != null && !cnsRes[1].trim().equals("")) {
                return new Union(acc, cnsRes[1].toCharArray(), 0, cnsRes[1].length());
            }
            return acc;
        } else {
            Class cls = findClass(factory, new String(property), pCtx);
            assert debug("NEW " + getInternalName(cls));
            mv.visitTypeInsn(NEW, getInternalName(cls));
            assert debug("DUP");
            mv.visitInsn(DUP);
            Constructor cns = cls.getConstructor(EMPTYCLS);
            assert debug("INVOKESPECIAL <init>");
            mv.visitMethodInsn(INVOKESPECIAL, getInternalName(cls), "<init>", getConstructorDescriptor(cns));
            _finishJIT();
            Accessor acc = _initializeAccessor();
            if (cnsRes.length > 1 && cnsRes[1] != null && !cnsRes[1].trim().equals("")) {
                return new Union(acc, cnsRes[1].toCharArray(), 0, cnsRes[1].length());
            }
            return acc;
        }
    } catch (ClassNotFoundException e) {
        throw new CompileException("class or class reference not found: " + new String(property), property, st);
    } catch (Exception e) {
        throw new OptimizationFailure("could not optimize construtor: " + new String(property), e);
    }
}
Also used : PropertyTools.getFieldOrWriteAccessor(org.mvel2.util.PropertyTools.getFieldOrWriteAccessor) PropertyTools.getFieldOrAccessor(org.mvel2.util.PropertyTools.getFieldOrAccessor) Union(org.mvel2.optimizers.impl.refl.nodes.Union) IOException(java.io.IOException)

Example 3 with OptimizationFailure

use of org.mvel2.OptimizationFailure in project mvel by mvel.

the class PropertyAccessor method getMethod.

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

Example 4 with OptimizationFailure

use of org.mvel2.OptimizationFailure in project mvel by mvel.

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) {
        return optimizeFieldMethodProperty(ctx, property, cls, member);
    } 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();
            if (member.getDeclaringClass().isInterface()) {
                assert debug("INVOKEINTERFACE " + member.getName() + ":" + returnType);
                mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(member.getDeclaringClass()), member.getName(), getMethodDescriptor((Method) member));
            } else {
                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, pCtx);
            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);
        }
        currType = toNonPrimitiveType(returnType);
        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;
                return optimizeFieldMethodProperty(ctx, property, cls, f);
            }
        } 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 (pCtx != null && pCtx.getParserConfiguration() != null ? pCtx.getParserConfiguration().isAllowNakedMethCall() : 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 (pCtx != null && pCtx.getParserConfiguration() != null ? pCtx.getParserConfiguration().isAllowNakedMethCall() : MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL) {
            return getMethod(ctx, property);
        }
        if (ctx == null) {
            throw new PropertyAccessException("unresolvable property or identifier: " + property, expr, st, pCtx);
        } else {
            throw new PropertyAccessException("could not access: " + property + "; in class: " + ctx.getClass().getName(), expr, st, pCtx);
        }
    }
}
Also used : OptimizationFailure(org.mvel2.OptimizationFailure) PropertyAccessException(org.mvel2.PropertyAccessException) ParseTools.determineActualTargetMethod(org.mvel2.util.ParseTools.determineActualTargetMethod) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) PropertyAccessException(org.mvel2.PropertyAccessException) IOException(java.io.IOException) CompileException(org.mvel2.CompileException) Field(java.lang.reflect.Field) PropertyHandlerFactory.hasNullPropertyHandler(org.mvel2.integration.PropertyHandlerFactory.hasNullPropertyHandler) PropertyHandlerFactory.getNullPropertyHandler(org.mvel2.integration.PropertyHandlerFactory.getNullPropertyHandler) PropertyHandlerFactory.hasPropertyHandler(org.mvel2.integration.PropertyHandlerFactory.hasPropertyHandler) PropertyHandlerFactory.getPropertyHandler(org.mvel2.integration.PropertyHandlerFactory.getPropertyHandler) PropertyHandler(org.mvel2.integration.PropertyHandler) CompileException(org.mvel2.CompileException) ParseTools.findClass(org.mvel2.util.ParseTools.findClass) Member(java.lang.reflect.Member) Map(java.util.Map)

Example 5 with OptimizationFailure

use of org.mvel2.OptimizationFailure in project mvel by mvel.

the class ASMAccessorOptimizer method optimizeObjectCreation.

public Accessor optimizeObjectCreation(ParserContext pCtx, char[] property, int start, int offset, Object ctx, Object thisRef, VariableResolverFactory factory) {
    _initJIT();
    compiledInputs = new ArrayList<ExecutableStatement>();
    this.start = cursor = start;
    this.end = start + offset;
    this.length = this.end - this.start;
    this.ctx = ctx;
    this.thisRef = thisRef;
    this.variableFactory = factory;
    this.pCtx = pCtx;
    String[] cnsRes = captureContructorAndResidual(property, start, offset);
    List<char[]> constructorParms = parseMethodOrConstructor(cnsRes[0].toCharArray());
    try {
        if (constructorParms != null) {
            for (char[] constructorParm : constructorParms) {
                compiledInputs.add((ExecutableStatement) subCompileExpression(constructorParm, pCtx));
            }
            Class cls = findClass(factory, new String(subset(property, 0, findFirst('(', start, length, property))), pCtx);
            assert debug("NEW " + getInternalName(cls));
            mv.visitTypeInsn(NEW, getInternalName(cls));
            assert debug("DUP");
            mv.visitInsn(DUP);
            Object[] parms = new Object[constructorParms.size()];
            int i = 0;
            for (ExecutableStatement es : compiledInputs) {
                parms[i++] = es.getValue(ctx, factory);
            }
            Constructor cns = getBestConstructorCandidate(parms, cls, pCtx.isStrongTyping());
            if (cns == null) {
                StringBuilder error = new StringBuilder();
                for (int x = 0; x < parms.length; x++) {
                    error.append(parms[x].getClass().getName());
                    if (x + 1 < parms.length)
                        error.append(", ");
                }
                throw new CompileException("unable to find constructor: " + cls.getName() + "(" + error.toString() + ")", expr, st);
            }
            this.returnType = cns.getDeclaringClass();
            Class[] parameterTypes = cns.getParameterTypes();
            Class tg;
            Class<?> paramType = null;
            int vaStart = -1;
            for (i = 0; i < constructorParms.size(); i++) {
                if (i < parameterTypes.length) {
                    paramType = parameterTypes[i];
                    if (cns.isVarArgs() && i == parameterTypes.length - 1) {
                        paramType = getBaseComponentType(paramType);
                        vaStart = i;
                        createArray(paramType, constructorParms.size() - vaStart);
                    }
                } else {
                    if (vaStart < 0 || paramType == null) {
                        throw new IllegalStateException("Incorrect argument count " + i);
                    }
                }
                if (vaStart >= 0) {
                    assert debug("DUP");
                    mv.visitInsn(DUP);
                    intPush(i - vaStart);
                }
                assert debug("ALOAD 0");
                mv.visitVarInsn(ALOAD, 0);
                assert debug("GETFIELD p" + i);
                mv.visitFieldInsn(GETFIELD, className, "p" + i, "L" + NAMESPACE + "compiler/ExecutableStatement;");
                assert debug("ALOAD 2");
                mv.visitVarInsn(ALOAD, 2);
                assert debug("ALOAD 3");
                mv.visitVarInsn(ALOAD, 3);
                assert debug("INVOKEINTERFACE " + NAMESPACE + "compiler/ExecutableStatement.getValue");
                mv.visitMethodInsn(INVOKEINTERFACE, "" + NAMESPACE + "compiler/ExecutableStatement", "getValue", "(Ljava/lang/Object;L" + NAMESPACE + "integration/VariableResolverFactory;)Ljava/lang/Object;");
                tg = paramType.isPrimitive() ? getWrapperClass(paramType) : paramType;
                if (parms[i] != null && !parms[i].getClass().isAssignableFrom(paramType)) {
                    ldcClassConstant(tg);
                    assert debug("INVOKESTATIC " + NAMESPACE + "DataConversion.convert");
                    mv.visitMethodInsn(INVOKESTATIC, "" + NAMESPACE + "DataConversion", "convert", "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
                    if (paramType.isPrimitive()) {
                        unwrapPrimitive(paramType);
                    } else {
                        assert debug("CHECKCAST " + getInternalName(tg));
                        mv.visitTypeInsn(CHECKCAST, getInternalName(tg));
                    }
                } else {
                    assert debug("CHECKCAST " + getInternalName(paramType));
                    mv.visitTypeInsn(CHECKCAST, getInternalName(paramType));
                }
                if (vaStart >= 0) {
                    arrayStore(paramType);
                }
            }
            if (i < parameterTypes.length && cns.isVarArgs()) {
                // The last parameter is a vararg and there is no value, create an empty array array
                createArray(getBaseComponentType(parameterTypes[i]), 0);
            }
            assert debug("INVOKESPECIAL " + getInternalName(cls) + ".<init> : " + getConstructorDescriptor(cns));
            mv.visitMethodInsn(INVOKESPECIAL, getInternalName(cls), "<init>", getConstructorDescriptor(cns));
            _finishJIT();
            Accessor acc = _initializeAccessor();
            if (cnsRes.length > 1 && cnsRes[1] != null && !cnsRes[1].trim().equals("")) {
                return new Union(pCtx, acc, cnsRes[1].toCharArray(), 0, cnsRes[1].length());
            }
            return acc;
        } else {
            Class cls = findClass(factory, new String(property), pCtx);
            assert debug("NEW " + getInternalName(cls));
            mv.visitTypeInsn(NEW, getInternalName(cls));
            assert debug("DUP");
            mv.visitInsn(DUP);
            Constructor cns = cls.getConstructor(EMPTYCLS);
            assert debug("INVOKESPECIAL <init>");
            mv.visitMethodInsn(INVOKESPECIAL, getInternalName(cls), "<init>", getConstructorDescriptor(cns));
            _finishJIT();
            Accessor acc = _initializeAccessor();
            if (cnsRes.length > 1 && cnsRes[1] != null && !cnsRes[1].trim().equals("")) {
                return new Union(pCtx, acc, cnsRes[1].toCharArray(), 0, cnsRes[1].length());
            }
            return acc;
        }
    } catch (ClassNotFoundException e) {
        throw new CompileException("class or class reference not found: " + new String(property), property, st);
    } catch (Exception e) {
        throw new OptimizationFailure("could not optimize construtor: " + new String(property), e);
    }
}
Also used : ExecutableStatement(org.mvel2.compiler.ExecutableStatement) Constructor(java.lang.reflect.Constructor) ParseTools.parseMethodOrConstructor(org.mvel2.util.ParseTools.parseMethodOrConstructor) OptimizationFailure(org.mvel2.OptimizationFailure) ExecutableAccessor(org.mvel2.compiler.ExecutableAccessor) PropertyTools.getFieldOrWriteAccessor(org.mvel2.util.PropertyTools.getFieldOrWriteAccessor) PropertyTools.getFieldOrAccessor(org.mvel2.util.PropertyTools.getFieldOrAccessor) Accessor(org.mvel2.compiler.Accessor) Union(org.mvel2.optimizers.impl.refl.nodes.Union) InvocationTargetException(java.lang.reflect.InvocationTargetException) PropertyAccessException(org.mvel2.PropertyAccessException) IOException(java.io.IOException) CompileException(org.mvel2.CompileException) CompileException(org.mvel2.CompileException) ParseTools.findClass(org.mvel2.util.ParseTools.findClass)

Aggregations

IOException (java.io.IOException)6 OptimizationFailure (org.mvel2.OptimizationFailure)6 CompileException (org.mvel2.CompileException)5 ExecutableStatement (org.mvel2.compiler.ExecutableStatement)5 PropertyAccessException (org.mvel2.PropertyAccessException)4 Union (org.mvel2.optimizers.impl.refl.nodes.Union)4 MethodStub (org.mvel2.util.MethodStub)4 ParseTools.findClass (org.mvel2.util.ParseTools.findClass)4 PropertyTools.getFieldOrAccessor (org.mvel2.util.PropertyTools.getFieldOrAccessor)4 PropertyTools.getFieldOrWriteAccessor (org.mvel2.util.PropertyTools.getFieldOrWriteAccessor)4 StringAppender (org.mvel2.util.StringAppender)4 InvocationTargetException (java.lang.reflect.InvocationTargetException)3 Method (java.lang.reflect.Method)3 ExecutableAccessor (org.mvel2.compiler.ExecutableAccessor)3 Map (java.util.Map)2 Function (org.mvel2.ast.Function)2 FunctionInstance (org.mvel2.ast.FunctionInstance)2 Accessor (org.mvel2.compiler.Accessor)2 ExecutableLiteral (org.mvel2.compiler.ExecutableLiteral)2 PropertyHandler (org.mvel2.integration.PropertyHandler)2