All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.testifyproject.jexl3.JexlBuilder Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.testifyproject.jexl3;

import org.testifyproject.jexl3.internal.Engine;
import org.testifyproject.jexl3.introspection.JexlSandbox;
import org.testifyproject.jexl3.introspection.JexlUberspect;
import org.apache.commons.logging.Log;

import java.util.Map;
import java.nio.charset.Charset;

/**
 * Configure and builds a JexlEngine.
 *
 * 

The setSilent and setStrict methods allow to fine-tune an engine instance behavior * according to various error control needs. The strict flag tells the engine when and if null as operand is * considered an error, the silent flag tells the engine what to do with the error * (log as warning or throw exception).

* *
    *
  • When "silent" & "not-strict": *

    0 & null should be indicators of "default" values so that even in an case of error, * something meaningful can still be inferred; may be convenient for configurations. *

    *
  • *
  • When "silent" & "strict": *

    One should probably consider using null as an error case - ie, every object * manipulated by JEXL should be valued; the ternary operator, especially the '?:' form * can be used to workaround exceptional cases. * Use case could be configuration with no implicit values or defaults. *

    *
  • *
  • When "not-silent" & "not-strict": *

    The error control grain is roughly on par with JEXL 1.0

    *
  • *
  • When "not-silent" & "strict": *

    The finest error control grain is obtained; it is the closest to Java code - * still augmented by "script" capabilities regarding automated conversions and type matching. *

    *
  • *
*/ public class JexlBuilder { /** The default maximum expression length to hit the expression cache. */ protected static final int CACHE_THRESHOLD = 64; /** The JexlUberspect instance. */ private JexlUberspect uberspect = null; /** The strategy strategy. */ private JexlUberspect.ResolverStrategy strategy = null; /** The sandbox. */ private JexlSandbox sandbox = null; /** The Log to which all JexlEngine messages will be logged. */ private Log logger = null; /** * Whether expressions evaluated by this engine will throw exceptions (false) or * return null (true) on errors. Default is false. */ private Boolean silent = null; /** Whether this engine is in lenient or strict mode; if unspecified, use the arithmetic lenient property. */ private Boolean strict = null; /** Whether error messages will carry debugging information. */ private Boolean debug = null; /** Whether interrupt throws JexlException.Cancel. */ private Boolean cancellable = null; /** The map of 'prefix:function' to object implementing the namespaces. */ private Map namespaces = null; /** The {@link JexlArithmetic} instance. */ private JexlArithmetic arithmetic = null; /** The cache size. */ private int cache = -1; /** The maximum expression length to hit the expression cache. */ private int cacheThreshold = CACHE_THRESHOLD; /** The charset. */ private Charset charset = Charset.defaultCharset(); /** The class loader. */ private ClassLoader loader = null; /** * Sets the JexlUberspect instance the engine will use. * * @param u the uberspect * @return this builder */ public JexlBuilder uberspect(JexlUberspect u) { this.uberspect = u; return this; } /** @return the uberspect */ public JexlUberspect uberspect() { return this.uberspect; } /** * Sets the JexlUberspect strategy strategy the engine will use. *

This is ignored if the uberspect has been set. * * @param rs the strategy * @return this builder */ public JexlBuilder strategy(JexlUberspect.ResolverStrategy rs) { this.strategy = rs; return this; } /** @return the strategy strategy */ public JexlUberspect.ResolverStrategy strategy() { return this.strategy; } /** * Sets the JexlArithmetic instance the engine will use. * * @param a the arithmetic * @return this builder */ public JexlBuilder arithmetic(JexlArithmetic a) { this.arithmetic = a; return this; } /** @return the arithmetic */ public JexlArithmetic arithmetic() { return this.arithmetic; } /** * Sets the sandbox the engine will use. * * @param box the sandbox * @return this builder */ public JexlBuilder sandbox(JexlSandbox box) { this.sandbox = box; return this; } /** @return the sandbox */ public JexlSandbox sandbox() { return this.sandbox; } /** * Sets the o.a.c.Log instance to use. * * @param l the logger * @return this builder */ public JexlBuilder logger(Log l) { this.logger = l; return this; } /** @return the logger */ public Log logger() { return this.logger; } /** * Sets the class loader to use. * * @param l the class loader * @return this builder */ public JexlBuilder loader(ClassLoader l) { this.loader = l; return this; } /** @return the class loader */ public ClassLoader loader() { return loader; } /** * Sets the charset to use. * * @param arg the charset * @return this builder * @deprecated since 3.1 use {@link #charset(Charset)} instead */ @Deprecated public JexlBuilder loader(Charset arg) { return charset(arg); } /** * Sets the charset to use. * * @param arg the charset * @return this builder * @since 3.1 */ public JexlBuilder charset(Charset arg) { this.charset = arg; return this; } /** @return the charset */ public Charset charset() { return charset; } /** * Sets whether the engine will throw JexlException during evaluation when an error is triggered. * * @param flag true means no JexlException will occur, false allows them * @return this builder */ public JexlBuilder silent(boolean flag) { this.silent = flag; return this; } /** @return the silent error handling flag */ public Boolean silent() { return this.silent; } /** * Sets whether the engine considers unknown variables, methods, functions and constructors as errors or * evaluates them as null. * * @param flag true means strict error reporting, false allows them to be evaluated as null * @return this builder */ public JexlBuilder strict(boolean flag) { this.strict = flag; return this; } /** @return true if strict, false otherwise */ public Boolean strict() { return this.strict; } /** * Sets whether the engine will report debugging information when error occurs. * * @param flag true implies debug is on, false implies debug is off. * @return this builder */ public JexlBuilder debug(boolean flag) { this.debug = flag; return this; } /** @return the debugging information flag */ public Boolean debug() { return this.debug; } /** * Sets the engine behavior upon interruption: throw an JexlException.Cancel or terminates the current evaluation * and return null. * * @param flag true implies the engine throws the exception, false makes the engine return null. * @return this builder * @since 3.1 */ public JexlBuilder cancellable(boolean flag) { this.cancellable = flag; return this; } /** * @return the cancellable information flag * @since 3.1 */ public Boolean cancellable() { return this.cancellable; } /** * Sets the default namespaces map the engine will use. *

* Each entry key is used as a prefix, each entry value used as a bean implementing * methods; an expression like 'nsx:method(123)' will thus be solved by looking at * a registered bean named 'nsx' that implements method 'method' in that map. * If all methods are static, you may use the bean class instead of an instance as value. *

*

* If the entry value is a class that has one contructor taking a JexlContext as argument, an instance * of the namespace will be created at evaluation time. It might be a good idea to derive a JexlContext * to carry the information used by the namespace to avoid variable space pollution and strongly type * the constructor with this specialized JexlContext. *

*

* The key or prefix allows to retrieve the bean that plays the role of the namespace. * If the prefix is null, the namespace is the top-level namespace allowing to define * top-level user defined namespaces ( ie: myfunc(...) ) *

*

Note that the JexlContext is also used to try to solve top-level namespaces. This allows ObjectContext * derived instances to call methods on the wrapped object.

* * @param ns the map of namespaces * @return this builder */ public JexlBuilder namespaces(Map ns) { this.namespaces = ns; return this; } /** * @return the map of namespaces. */ public Map namespaces() { return this.namespaces; } /** * Sets the expression cache size the engine will use. *

The cache will contain at most size expressions of at most cacheThreshold length. * Note that all JEXL caches are held through SoftReferences and may be garbage-collected.

* * @param size if not strictly positive, no cache is used. * @return this builder */ public JexlBuilder cache(int size) { this.cache = size; return this; } /** * @return the cache size */ public int cache() { return cache; } /** * Sets the maximum length for an expression to be cached. *

Expression whose length is greater than this expression cache length threshold will * bypass the cache.

*

It is expected that a "long" script will be parsed once and its reference kept * around in user-space structures; the jexl expression cache has no added-value in this case.

* * @param length if not strictly positive, the value is silently replaced by the default value (64). * @return this builder */ public JexlBuilder cacheThreshold(int length) { this.cacheThreshold = length > 0? length : CACHE_THRESHOLD; return this; } /** * @return the cache threshold */ public int cacheThreshold() { return cacheThreshold; } /** * @return a {@link JexlEngine} instance */ public JexlEngine create() { return new Engine(this); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy