Search in sources :

Example 11 with MVEL

use of org.mvel2.MVEL in project drools by kiegroup.

the class PatternBuilder method getFieldValue.

private FieldValue getFieldValue(RuleBuildContext context, ValueType vtype, String value) {
    try {
        MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL = true;
        MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING = true;
        MVEL.COMPILER_OPT_ALLOW_RESOLVE_INNERCLASSES_WITH_DOTNOTATION = true;
        MVEL.COMPILER_OPT_SUPPORT_JAVA_STYLE_CLASS_LITERALS = true;
        MVELDialectRuntimeData data = (MVELDialectRuntimeData) context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel");
        ParserConfiguration pconf = data.getParserConfiguration();
        ParserContext pctx = new ParserContext(pconf);
        Object o = MVELSafeHelper.getEvaluator().executeExpression(MVEL.compileExpression(value, pctx));
        if (o != null && vtype == null) {
            // was a compilation problem else where, so guess valuetype so we can continue
            vtype = ValueType.determineValueType(o.getClass());
        }
        return context.getCompilerFactory().getFieldFactory().getFieldValue(o, vtype);
    } catch (final Exception e) {
    // we will fallback to regular preducates, so don't raise an error
    }
    return null;
}
Also used : MVELDialectRuntimeData(org.drools.core.rule.MVELDialectRuntimeData) ParserContext(org.mvel2.ParserContext) DroolsParserException(org.drools.compiler.compiler.DroolsParserException) ParserConfiguration(org.mvel2.ParserConfiguration)

Example 12 with MVEL

use of org.mvel2.MVEL in project drools by kiegroup.

the class MVELDialectRuntimeData method getParserConfiguration.

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

Example 13 with MVEL

use of org.mvel2.MVEL in project camel by apache.

the class MvelEndpoint method onExchange.

@Override
protected void onExchange(Exchange exchange) throws Exception {
    String path = getResourceUri();
    ObjectHelper.notNull(path, "resourceUri");
    String newResourceUri = exchange.getIn().getHeader(MvelConstants.MVEL_RESOURCE_URI, String.class);
    if (newResourceUri != null) {
        exchange.getIn().removeHeader(MvelConstants.MVEL_RESOURCE_URI);
        log.debug("{} set to {} creating new endpoint to handle exchange", MvelConstants.MVEL_RESOURCE_URI, newResourceUri);
        MvelEndpoint newEndpoint = findOrCreateEndpoint(getEndpointUri(), newResourceUri);
        newEndpoint.onExchange(exchange);
        return;
    }
    CompiledTemplate compiled;
    ParserContext mvelContext = ParserContext.create();
    Map<String, Object> variableMap = ExchangeHelper.createVariableMap(exchange);
    String content = exchange.getIn().getHeader(MvelConstants.MVEL_TEMPLATE, String.class);
    if (content != null) {
        // use content from header
        if (log.isDebugEnabled()) {
            log.debug("Mvel content read from header {} for endpoint {}", MvelConstants.MVEL_TEMPLATE, getEndpointUri());
        }
        // remove the header to avoid it being propagated in the routing
        exchange.getIn().removeHeader(MvelConstants.MVEL_TEMPLATE);
        compiled = TemplateCompiler.compileTemplate(content, mvelContext);
    } else {
        if (log.isDebugEnabled()) {
            log.debug("Mvel content read from resource {} with resourceUri: {} for endpoint {}", new Object[] { getResourceUri(), path, getEndpointUri() });
        }
        // getResourceAsInputStream also considers the content cache
        Reader reader = getEncoding() != null ? new InputStreamReader(getResourceAsInputStream(), getEncoding()) : new InputStreamReader(getResourceAsInputStream());
        String template = IOConverter.toString(reader);
        if (!template.equals(this.template)) {
            this.template = template;
            this.compiled = TemplateCompiler.compileTemplate(template, mvelContext);
        }
        compiled = this.compiled;
    }
    // let mvel parse and execute the template
    log.debug("Mvel is evaluating using mvel context: {}", variableMap);
    Object result = TemplateRuntime.execute(compiled, mvelContext, variableMap);
    // now lets output the results to the exchange
    Message out = exchange.getOut();
    out.setBody(result.toString());
    out.setHeaders(exchange.getIn().getHeaders());
    out.setAttachments(exchange.getIn().getAttachments());
}
Also used : InputStreamReader(java.io.InputStreamReader) Message(org.apache.camel.Message) Reader(java.io.Reader) InputStreamReader(java.io.InputStreamReader) ParserContext(org.mvel2.ParserContext) CompiledTemplate(org.mvel2.templates.CompiledTemplate)

Example 14 with MVEL

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

the class MVELRuntime method execute.

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

Example 15 with MVEL

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

the class PropertyVerifier method getMethod.

/**
 * Process method
 *
 * @param ctx  - the ingress type
 * @param name - the property component
 * @return known egress type.
 */
private Class getMethod(Class ctx, String name) {
    int st = cursor;
    /**
     * Check to see if this is the first element in the statement.
     */
    if (first) {
        first = false;
        methodCall = true;
        /**
         * It's the first element in the statement, therefore we check to see if there is a static import of a
         * native Java method or an MVEL function.
         */
        if (pCtx.hasImport(name)) {
            Method m = pCtx.getStaticImport(name).getMethod();
            /**
             * Replace the method parameters.
             */
            ctx = m.getDeclaringClass();
            name = m.getName();
        } else if (pCtx.hasFunction(name)) {
            resolvedExternally = false;
            Function f = pCtx.getFunction(name);
            f.checkArgumentCount(parseParameterList((((cursor = balancedCapture(expr, cursor, end, '(')) - st) > 1 ? ParseTools.subset(expr, st + 1, cursor - st - 1) : new char[0]), 0, -1).size());
            return f.getEgressType();
        } else if (pCtx.hasVarOrInput("this")) {
            if (pCtx.isStrictTypeEnforcement()) {
                recordTypeParmsForProperty("this");
            }
            ctx = pCtx.getVarOrInputType("this");
            resolvedExternally = false;
        }
    }
    /**
     * Get the arguments for the method.
     */
    String tk;
    if (cursor < end && expr[cursor] == '(' && ((cursor = balancedCapture(expr, cursor, end, '(')) - st) > 1) {
        tk = new String(expr, st + 1, cursor - st - 1);
    } else {
        tk = "";
    }
    cursor++;
    /**
     * Parse out the arguments list.
     */
    Class[] args;
    List<char[]> subtokens = parseParameterList(tk.toCharArray(), 0, -1);
    if (subtokens.size() == 0) {
        args = new Class[0];
        subtokens = Collections.emptyList();
    } else {
        // ParserContext subCtx = pCtx.createSubcontext();
        args = new Class[subtokens.size()];
        /**
         *  Subcompile all the arguments to determine their known types.
         */
        // ExpressionCompiler compiler;
        List<ErrorDetail> errors = pCtx.getErrorList().isEmpty() ? pCtx.getErrorList() : new ArrayList<ErrorDetail>(pCtx.getErrorList());
        CompileException rethrow = null;
        for (int i = 0; i < subtokens.size(); i++) {
            try {
                args[i] = MVEL.analyze(subtokens.get(i), pCtx);
                if ("null".equals(String.valueOf(subtokens.get(i)))) {
                    args[i] = NullType.class;
                }
            } catch (CompileException e) {
                rethrow = ErrorUtil.rewriteIfNeeded(e, expr, this.st);
            }
            if (errors.size() < pCtx.getErrorList().size()) {
                for (ErrorDetail detail : pCtx.getErrorList()) {
                    if (!errors.contains(detail)) {
                        detail.setExpr(expr);
                        detail.setCursor(new String(expr).substring(this.st).indexOf(new String(subtokens.get(i))) + this.st);
                        detail.setColumn(0);
                        detail.setLineNumber(0);
                        detail.calcRowAndColumn();
                    }
                }
            }
            if (rethrow != null) {
                throw rethrow;
            }
        }
    }
    /**
     * If the target object is an instance of java.lang.Class itself then do not
     * adjust the Class scope target.
     */
    Method m;
    if ((m = getBestCandidate(args, name, ctx, ctx.getMethods(), pCtx.isStrongTyping())) == null) {
        if ((m = getBestCandidate(args, name, ctx, ctx.getDeclaredMethods(), pCtx.isStrongTyping())) == null) {
            StringAppender errorBuild = new StringAppender();
            for (int i = 0; i < args.length; i++) {
                errorBuild.append(args[i] != null ? args[i].getName() : null);
                if (i < args.length - 1)
                    errorBuild.append(", ");
            }
            if (("size".equals(name) || "length".equals(name)) && args.length == 0 && ctx.isArray()) {
                return Integer.class;
            }
            if (pCtx.isStrictTypeEnforcement()) {
                throw new CompileException("unable to resolve method using strict-mode: " + ctx.getName() + "." + name + "(" + errorBuild.toString() + ")", expr, tkStart);
            }
            return Object.class;
        }
    }
    /**
     * If we're in strict mode, we look for generic type information.
     */
    if (pCtx.isStrictTypeEnforcement() && m.getGenericReturnType() != null) {
        Map<String, Class> typeArgs = new HashMap<String, Class>();
        Type[] gpt = m.getGenericParameterTypes();
        Class z;
        ParameterizedType pt;
        for (int i = 0; i < gpt.length; i++) {
            if (gpt[i] instanceof ParameterizedType) {
                pt = (ParameterizedType) gpt[i];
                if ((z = pCtx.getImport(new String(subtokens.get(i)))) != null) {
                    /**
                     * We record the value of the type parameter to our typeArgs Map.
                     */
                    if (pt.getRawType().equals(Class.class)) {
                        /**
                         * If this is an instance of Class, we deal with the special parameterization case.
                         */
                        typeArgs.put(pt.getActualTypeArguments()[0].toString(), z);
                    } else {
                        typeArgs.put(gpt[i].toString(), z);
                    }
                }
            }
        }
        if (pCtx.isStrictTypeEnforcement() && ctx.getTypeParameters().length != 0 && pCtx.getLastTypeParameters() != null && pCtx.getLastTypeParameters().length == ctx.getTypeParameters().length) {
            TypeVariable[] typeVariables = ctx.getTypeParameters();
            for (int i = 0; i < typeVariables.length; i++) {
                typeArgs.put(typeVariables[i].getName(), (Class) pCtx.getLastTypeParameters()[i]);
            }
        }
        /**
         * Get the return type argument
         */
        Type parametricReturnType = m.getGenericReturnType();
        String returnTypeArg = parametricReturnType.toString();
        // push return type parameters onto parser context, only if this is a parametric type
        if (parametricReturnType instanceof ParameterizedType) {
            pCtx.setLastTypeParameters(((ParameterizedType) parametricReturnType).getActualTypeArguments());
        }
        if (paramTypes != null && paramTypes.containsKey(returnTypeArg)) {
            /**
             * If the paramTypes Map contains the known type, return that type.
             */
            return (Class) paramTypes.get(returnTypeArg);
        } else if (typeArgs.containsKey(returnTypeArg)) {
            /**
             * If the generic type was declared as part of the method, it will be in this
             * Map.
             */
            return typeArgs.get(returnTypeArg);
        }
    }
    if (!Modifier.isPublic(m.getModifiers())) {
        StringAppender errorBuild = new StringAppender();
        for (int i = 0; i < args.length; i++) {
            errorBuild.append(args[i] != null ? args[i].getName() : null);
            if (i < args.length - 1)
                errorBuild.append(", ");
        }
        String scope = Modifier.toString(m.getModifiers());
        if (scope.trim().equals(""))
            scope = "<package local>";
        addFatalError("the referenced method is not accessible: " + ctx.getName() + "." + name + "(" + errorBuild.toString() + ")" + " (scope: " + scope + "; required: public", this.tkStart);
    }
    return m.getReturnType();
}
Also used : Function(org.mvel2.ast.Function) NullType(org.mvel2.util.NullType) StringAppender(org.mvel2.util.StringAppender)

Aggregations

ParserContext (org.mvel2.ParserContext)7 MVELDialectRuntimeData (org.drools.core.rule.MVELDialectRuntimeData)6 Test (org.junit.Test)6 ParserConfiguration (org.mvel2.ParserConfiguration)6 HashMap (java.util.HashMap)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 PropertyAccessException (org.mvel2.PropertyAccessException)5 Map (java.util.Map)4 KieSession (org.kie.api.runtime.KieSession)4 CompileException (org.mvel2.CompileException)4 Declaration (org.drools.core.rule.Declaration)3 Serializable (java.io.Serializable)2 HashSet (java.util.HashSet)2 List (java.util.List)2 Entry (java.util.Map.Entry)2 RecognitionException (org.antlr.runtime.RecognitionException)2 DroolsParserException (org.drools.compiler.compiler.DroolsParserException)2