This is an automated email from the ASF dual-hosted git repository.

henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git


The following commit(s) were added to refs/heads/master by this push:
     new 41d69998 JEXL-410, JEXL-409, JEXL-408: added new methods to 
instantiate JexlFeatures with no/default/scripting features set; - fixed 
lexical/lexicalShade missing relationship; - updated doc;
41d69998 is described below

commit 41d6999840bc54ad4b044924060406738337ffeb
Author: Henri Biestro <hbies...@cloudera.com>
AuthorDate: Wed Oct 18 15:28:24 2023 +0200

    JEXL-410, JEXL-409, JEXL-408: added new methods to instantiate JexlFeatures 
with no/default/scripting features set;
    - fixed lexical/lexicalShade missing relationship;
    - updated doc;
---
 .../org/apache/commons/jexl3/JexlFeatures.java     | 135 ++++++++++++++++-----
 .../org/apache/commons/jexl3/FeaturesTest.java     |  50 +++++++-
 2 files changed, 155 insertions(+), 30 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/JexlFeatures.java 
b/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
index c5a23926..4ed1f8d7 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlFeatures.java
@@ -80,7 +80,7 @@ public final class JexlFeatures {
     public static final int LOCAL_VAR = 2;
     /** Side effects feature ordinal. */
     public static final int SIDE_EFFECT = 3;
-    /** Global side-effects feature ordinal. */
+    /** Global side effects feature ordinal. */
     public static final int SIDE_EFFECT_GLOBAL = 4;
     /** Array get is allowed on expr. */
     public static final int ARRAY_REF_EXPR = 5;
@@ -104,7 +104,7 @@ public final class JexlFeatures {
     public static final int LEXICAL = 14;
     /** Lexical shade feature ordinal. */
     public static final int LEXICAL_SHADE = 15;
-    /** Fat-arrow lambda syntax. */
+    /** Thin-arrow lambda syntax. */
     public static final int THIN_ARROW = 16;
     /** Fat-arrow lambda syntax. */
     public static final int FAT_ARROW = 17;
@@ -117,36 +117,99 @@ public final class JexlFeatures {
     /** The pragma anywhere feature ordinal. */
     public static final int PRAGMA_ANYWHERE = 21;
     /** Captured variables are const. */
-    public static final  int CONST_CAPTURE = 22;
+    public static final int CONST_CAPTURE = 22;
+
     /**
      * The default features flag mask.
+     * <p>Meant for compatibility with scripts written before 3.3.1</p>
      */
     private static final long DEFAULT_FEATURES =
-            1L << LOCAL_VAR
-            | 1L << SIDE_EFFECT
-            | 1L << SIDE_EFFECT_GLOBAL
-            | 1L << ARRAY_REF_EXPR
-            | 1L << NEW_INSTANCE
-            | 1L << LOOP
-            | 1L << LAMBDA
-            | 1L << METHOD_CALL
-            | 1L << STRUCTURED_LITERAL
-            | 1L << PRAGMA
-            | 1L << ANNOTATION
-            | 1L << SCRIPT
-            | 1L << THIN_ARROW
-            | 1L << NS_PRAGMA
-            | 1L << IMPORT_PRAGMA
-            | 1L << COMPARATOR_NAMES
-            | 1L << PRAGMA_ANYWHERE;
-
-    /**
-     * Creates an all-features-enabled instance.
+        1L << LOCAL_VAR
+        | 1L << SIDE_EFFECT
+        | 1L << SIDE_EFFECT_GLOBAL
+        | 1L << ARRAY_REF_EXPR
+        | 1L << NEW_INSTANCE
+        | 1L << LOOP
+        | 1L << LAMBDA
+        | 1L << METHOD_CALL
+        | 1L << STRUCTURED_LITERAL
+        | 1L << PRAGMA
+        | 1L << ANNOTATION
+        | 1L << SCRIPT
+        | 1L << THIN_ARROW
+        | 1L << NS_PRAGMA
+        | 1L << IMPORT_PRAGMA
+        | 1L << COMPARATOR_NAMES
+        | 1L << PRAGMA_ANYWHERE;
+
+    /**
+     * The canonical scripting (since 3.3.1) features flag mask based on the 
original default.
+     * <p>Adds lexical, lexical-shade and const-capture but removes 
comparator-names and pragma-anywhere</p>
+     */
+    private static final long SCRIPT_FEATURES =
+        DEFAULT_FEATURES
+        | 1L << LEXICAL
+        | 1L << LEXICAL_SHADE
+        | 1L << CONST_CAPTURE
+        & ~(1L << COMPARATOR_NAMES)
+        & ~(1L << PRAGMA_ANYWHERE);
+
+    /**
+     * Creates an empty feature set.
+     * <p>This is the strictest base-set since no feature is allowed, suitable 
as-is only
+     * for the simplest expressions.</p>
+     * @return a new instance of an empty features set
+     * @since 3.3.1
+     */
+    public static JexlFeatures create() {
+        return new JexlFeatures(0L, null, null);
+    }
+
+    /**
+     * Creates a default features set suitable for basic scripting needs.
+     * <p>Meant for legacy (before 3.3) scripting checks.</p>
+     * <p>The following scripting features are enabled:</p>
+     * <lu>
+     *   <li>local variable {@link JexlFeatures#supportsLocalVar()}</li>
+     *   <li>side effect {@link JexlFeatures#supportsSideEffect()}</li>
+     *   <li>global side effect {@link 
JexlFeatures#supportsSideEffectGlobal()}</li>
+     *   <li>array reference expression {@link 
JexlFeatures#supportsStructuredLiteral()}</li>
+     *   <li>new instance  {@link JexlFeatures#supportsNewInstance()} </li>
+     *   <li>loop {@link JexlFeatures#supportsLoops()} </li>
+     *   <li>lambda {@link JexlFeatures#supportsLambda()}</li>
+     *   <li>method call {@link JexlFeatures#supportsMethodCall()}</li>
+     *   <li>structured literal {@link 
JexlFeatures#supportsStructuredLiteral()}</li>
+     *   <li>pragma {@link JexlFeatures#supportsPragma()}</li>
+     *   <li>annotation {@link JexlFeatures#supportsAnnotation()}</li>
+     *   <li>script {@link JexlFeatures#supportsScript()}</li>
+     *   <li>comparator names  {@link 
JexlFeatures#supportsComparatorNames()}</li>
+     *   <li>namespace pragma  {@link 
JexlFeatures#supportsNamespacePragma()}</li>
+     *   <li>import pragma {@link JexlFeatures#supportsImportPragma()}</li>
+     *   <li>pragma anywhere {@link JexlFeatures#supportsPragmaAnywhere()} 
</li>
+     * </lu>
+     * @return a new instance of a default scripting features set
+     * @since 3.3.1
+     */
+    public static JexlFeatures createDefault() {
+        return new JexlFeatures(DEFAULT_FEATURES, null, null);
+    }
+
+    /**
+     * The modern scripting features set.
+     * <p>All scripting features are set including lexical, lexical-shade and 
const-capture.</p>
+     * @return a new instance of a modern scripting features set
+     * @since 3.3.1
+     */
+    public static JexlFeatures createScript() {
+        return new JexlFeatures(SCRIPT_FEATURES, null, null);
+    }
+
+    /**
+     * Creates default instance, equivalent to the result of calling the 
preferred alternative
+     * {@link JexlFeatures#createDefault()}
      */
     public JexlFeatures() {
-        flags = DEFAULT_FEATURES;
-        reservedNames = Collections.emptySet();
-        nameSpaces = TEST_STR_FALSE;
+        this(DEFAULT_FEATURES, null, null);
     }
 
     /**
@@ -154,9 +217,20 @@ public final class JexlFeatures {
      * @param features the feature to copy from
      */
     public JexlFeatures(final JexlFeatures features) {
-        this.flags = features.flags;
-        this.reservedNames = features.reservedNames;
-        this.nameSpaces = features.nameSpaces;
+        this(features.flags, features.reservedNames, features.nameSpaces);
+    }
+
+    /**
+     * An all member constructor.
+     * @param f flag
+     * @param r reserved variable names
+     * @param n namespace predicate
+     */
+    protected JexlFeatures(final long f, final Set<String> r, final 
Predicate<String> n) {
+        this.flags = f;
+        this.reservedNames = r == null? Collections.emptySet() : r;
+        this.nameSpaces = n == null? TEST_STR_FALSE : n;
+        setFeature(RESERVED, !reservedNames.isEmpty());
     }
 
     @Override
@@ -718,6 +792,9 @@ public final class JexlFeatures {
      */
     public JexlFeatures lexical(final boolean flag) {
         setFeature(LEXICAL, flag);
+        if (!flag) {
+            setFeature(LEXICAL_SHADE, false);
+        }
         return this;
     }
 
diff --git a/src/test/java/org/apache/commons/jexl3/FeaturesTest.java 
b/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
index 3b8e5d02..bb2ae330 100644
--- a/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
+++ b/src/test/java/org/apache/commons/jexl3/FeaturesTest.java
@@ -32,7 +32,7 @@ public class FeaturesTest extends JexlTestCase {
      * Create the test
      */
     public FeaturesTest() {
-        super("BlockTest");
+        super("FeaturesTest");
     }
 
     /**
@@ -324,4 +324,52 @@ public class FeaturesTest extends JexlTestCase {
         assertOk(nof, scripts);
     }
 
+    @Test
+    public void testIssue409() {
+        final JexlFeatures baseFeatures = JexlFeatures.createDefault();
+        Assert.assertFalse(baseFeatures.isLexical());
+        Assert.assertFalse(baseFeatures.isLexicalShade());
+        Assert.assertFalse(baseFeatures.supportsConstCapture());
+
+        final JexlFeatures scriptFeatures = JexlFeatures.createScript();
+        Assert.assertTrue(scriptFeatures.isLexical());
+        Assert.assertTrue(scriptFeatures.isLexicalShade());
+        scriptFeatures.lexical(false);
+        Assert.assertFalse(scriptFeatures.isLexical());
+        Assert.assertFalse(scriptFeatures.isLexicalShade());
+
+        scriptFeatures.constCapture(false);
+        Assert.assertEquals(baseFeatures, scriptFeatures);
+    }
+
+    @Test
+    public void testCreate() {
+        final JexlFeatures f = JexlFeatures.create();
+        Assert.assertTrue(f.supportsExpression());
+
+        Assert.assertFalse(f.supportsAnnotation());
+        Assert.assertFalse(f.supportsArrayReferenceExpr());
+        Assert.assertFalse(f.supportsComparatorNames());
+        Assert.assertFalse(f.supportsFatArrow());
+        Assert.assertFalse(f.supportsImportPragma());
+        Assert.assertFalse(f.supportsLambda());
+        Assert.assertFalse(f.supportsLocalVar());
+        Assert.assertFalse(f.supportsLoops());
+        Assert.assertFalse(f.supportsMethodCall());
+        Assert.assertFalse(f.supportsNamespacePragma());
+        Assert.assertFalse(f.supportsNewInstance());
+        Assert.assertFalse(f.supportsPragma());
+        Assert.assertFalse(f.supportsPragmaAnywhere());
+        Assert.assertFalse(f.supportsScript());
+        Assert.assertFalse(f.supportsStructuredLiteral());
+
+        Assert.assertFalse(f.isLexical());
+        Assert.assertFalse(f.isLexicalShade());
+        Assert.assertFalse(f.supportsConstCapture());
+
+        JexlEngine jnof = new JexlBuilder().features(f).create();
+        Assert.assertThrows(JexlException.Feature.class, 
()->jnof.createScript("{ 3 + 4 }"));
+        Assert.assertNotNull(jnof.createExpression("3 + 4"));
+    }
+
 }

Reply via email to