Class JexlConfigLoader

java.lang.Object
org.apache.commons.jexl3.JexlConfigLoader

public final class JexlConfigLoader extends Object
Loads a YAML configuration file and applies it to a JexlBuilder.

Quick start:

try (InputStream in = getClass().getResourceAsStream("/jexl.yaml")) {
    JexlEngine engine = JexlConfigLoader.load(in).create();
}

The loader understands a simple YAML subset: top-level scalars, one level of section nesting, and list items. No external YAML library is required. Inline comments (# after whitespace), empty lines, and single/double-quoted string values are supported.

Top-level scalar keys

These map directly to the matching JexlBuilder setter. Boolean values accept true/false, yes/no, or on/off. Example:

strict: true         # JexlBuilder.strict(true)
silent: false        # JexlBuilder.silent(false)
safe: true           # JexlBuilder.safe(true)   — enable safe-navigation ?.
cancellable: false   # JexlBuilder.cancellable(false)
antish: true         # JexlBuilder.antish(true) — resolve ant-style dotted names
lexical: true        # JexlBuilder.lexical(true)
lexicalShade: false  # JexlBuilder.lexicalShade(false)
strictInterpolation: false
booleanLogical: false
debug: true          # include source location in exceptions
cache: 512           # expression cache size (entries)
cacheThreshold: 64   # max expression length cached
stackOverflow: 512   # max recursion depth
collectMode: 1       # variable collection mode (0=off, 1=on)
charset: UTF-8       # source charset for script text
strategy: JEXL_STRATEGY   # property-resolver order: JEXL_STRATEGY or MAP_STRATEGY

permissions: section

Controls which classes and members are visible to scripts.

permissions:
  base: SECURE           # NONE (default) | SECURE | RESTRICTED | UNRESTRICTED
  rules:                 # list of JexlPermissions DSL strings composed on top of base
    - "com.example.api +{}"           # allow whole package
    - "com.example.api +{ Foo{} }"    # allow specific class
    - "java.util +{ -Formatter { Formatter(); } }"  # deny one constructor
  classes:               # explicit fully-qualified class names to allow (ClassPermissions)
    - com.example.api.Foo
    - com.example.api.Bar
  logging: my.logger     # optional: wrap in LoggingPermissions; value = logger name
                         # bare "logging:" with no value uses the default logger

See JexlPermissions.parse(String...) for the DSL syntax, JexlPermissions.SECURE, JexlPermissions.RESTRICTED, JexlPermissions.logging() for the logging wrapper.

features: section

Controls which syntactic constructs are available at parse time. Each key is the name of a JexlFeatures boolean setter method; unknown keys are silently ignored.

features:
  # Script structure
  script: true             # multi-statement scripts (vs. single-expression mode)
  localVar: true           # local variable declarations (var x = ...)
  lambda: true             # lambda / named-function definitions
  loops: true              # for / while / do-while loops
  newInstance: true        # new(...) constructor calls

  # Side-effects
  sideEffect: true         # any assignment or modification (=, +=, ...)
  sideEffectGlobal: true   # assignment to context / global variables

  # Literals and operators
  structuredLiteral: true  # array [], map {}, set {} literals; ranges a..b
  arrayReferenceExpr: true # non-constant array index expressions (x[f()])
  methodCall: true         # method calls on objects (obj.method())
  annotation: true         # @annotation statements
  pragma: true             # #pragma directives
  pragmaAnywhere: true     # allow #pragma anywhere (not just at the top)
  namespacePragma: true    # #pragma jexl.namespace.ns ... syntax
  namespaceIdentifier: true# ns:fun(...) compact namespace call syntax
  importPragma: true       # #pragma jexl.import ... syntax

  # Lambda arrow styles
  thinArrow: true          # thin-arrow lambdas  x -> x + 1
  fatArrow: true           # fat-arrow lambdas   x => x + 1

  # Variable capture semantics
  constCapture: true       # captured variables are read-only (Java-style)
  referenceCapture: false  # captured variables are pass-by-reference (ECMAScript-style)

  # Lexical scoping (also settable at top level via 'lexical:' / 'lexicalShade:')
  lexical: true
  lexicalShade: false

  # Misc
  comparatorNames: true    # allow 'gt', 'lt', 'ge', 'le', 'eq', 'ne' as operator aliases
  ambiguousStatement: true # allow statements that are syntactically ambiguous
  ignoreTemplatePrefix: false

  # Reserved names (list — cannot be used as local variable or parameter names)
  reservedNames:
    - try
    - catch
    - class

arithmetic: section

Selects and configures the JexlArithmetic implementation.

arithmetic:
  clazz: org.apache.commons.jexl3.JexlArithmetic  # fully-qualified class (default)
  strict: true       # strict arithmetic (true = default); passed to the constructor
  mathContext: DECIMAL64   # java.math.MathContext field: DECIMAL32 | DECIMAL64 | DECIMAL128 | UNLIMITED
  mathScale: 10      # BigDecimal scale; requires mathContext; -1 = use context default

When mathContext is present the constructor (boolean, MathContext, int) is used; otherwise (boolean) is used. The class must be on the classpath.

namespaces: section

Maps namespace prefixes to fully-qualified class names. The class is loaded and passed to JexlBuilder.namespaces(java.util.Map). Its static (or instance) methods become callable as prefix:methodName(args) from scripts.

namespaces:
  math: java.lang.Math          # math:abs(-1) etc.
  str:  com.example.StringUtils # str:trim(x) etc.

imports: section

A list of package or class names passed to JexlBuilder.imports(java.util.Collection). Imported packages allow unqualified class names in new(...) and type references.

imports:
  - java.lang
  - java.util
  - com.example.api

pragmas: section

A list of allowed pragma key patterns, turned into the predicate passed to JexlFeatures.pragmaTest(java.util.function.Predicate). A pattern ending with * matches any key starting with what precedes it; any other pattern must match the key exactly. Scripts declaring a pragma whose key matches no pattern fail to parse with a JexlException.Feature. The section is an allow-list: when present with no items, no pragma is allowed; when absent, all pragmas are allowed (subject to the pragma, importPragma and namespacePragma features). The list applies to JEXL's own pragmas too: jexl.options, jexl.import, jexl.namespace.* and jexl.module.* must be listed to be allowed. A single pattern may also be written inline (pragmas: dlm.*); entries that are not - pattern items, or flow-style lists, are rejected with an IllegalArgumentException.

pragmas:
  - dlm.*              # any pragma key starting with 'dlm.'
  - jexl.import        # exactly 'jexl.import'
  - jexl.namespace.*

Complete annotated example

Every flag is listed explicitly so the configuration does not depend on any library default (which may change between releases). The features: block below reproduces the pre-3.7 feature set (JexlFeatures.createDefault()).

# Production engine — explicit permissions + legacy feature set
strict: true
safe: false
cache: 512

permissions:
  base: RESTRICTED
  rules:
    - "com.example.api +{}"
  logging: com.example.jexl.permissions  # log allow/deny at INFO once per element

features:
  script: true
  localVar: true
  lambda: true
  loops: true
  newInstance: true
  sideEffect: true
  sideEffectGlobal: true
  structuredLiteral: true
  arrayReferenceExpr: true
  methodCall: true
  annotation: true
  pragma: true
  pragmaAnywhere: true
  namespacePragma: true
  importPragma: true
  namespaceIdentifier: false
  thinArrow: true
  fatArrow: false
  constCapture: false
  referenceCapture: false
  lexical: false
  lexicalShade: false
  comparatorNames: true
  ambiguousStatement: false
  ignoreTemplatePrefix: false

namespaces:
  math: java.lang.Math

imports:
  - java.lang
  - java.util
Since:
3.7.0
  • Method Details

    • load

      public static JexlBuilder load(InputStream in) throws IOException
      Loads configuration from a YAML InputStream (UTF-8) into a JexlBuilder.
      Parameters:
      in - YAML input; the caller is responsible for closing it
      Returns:
      A configured JexlBuilder
      Throws:
      IOException - Thrown if the stream cannot be read
    • load

      public static JexlBuilder load(Reader reader) throws IOException
      Loads configuration from a YAML Reader into a JexlBuilder.
      Parameters:
      reader - YAML input; the caller is responsible for closing it
      Returns:
      A configured JexlBuilder
      Throws:
      IOException - Thrown if the reader cannot be read
    • engine

      public static JexlEngine engine(InputStream in) throws IOException
      Convenience: loads YAML from in and creates the engine in one call.
      Parameters:
      in - YAML input; the caller is responsible for closing it
      Returns:
      A new JexlEngine configured from the YAML
      Throws:
      IOException - Thrown if the stream cannot be read