You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2019/12/18 15:59:57 UTC

[commons-jexl] branch master updated: JEXL-307: nitpicking on options handling Task #JEXL-307 - Variable redeclaration option

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 676448c  JEXL-307: nitpicking on options handling Task #JEXL-307 - Variable redeclaration option
676448c is described below

commit 676448c88b58ed49a97f7284d5dcee57258da08f
Author: henrib <he...@apache.org>
AuthorDate: Wed Dec 18 16:59:25 2019 +0100

    JEXL-307: nitpicking on options handling
    Task #JEXL-307 - Variable redeclaration option
---
 .../java/org/apache/commons/jexl3/JexlContext.java |  2 +
 .../org/apache/commons/jexl3/internal/Engine.java  | 76 +++++++---------------
 .../org/apache/commons/jexl3/internal/Script.java  | 33 ++++++++--
 .../java/org/apache/commons/jexl3/LexicalTest.java | 60 +++++++++++++++++
 4 files changed, 113 insertions(+), 58 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/JexlContext.java b/src/main/java/org/apache/commons/jexl3/JexlContext.java
index 7a9c828..2f8371b 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlContext.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlContext.java
@@ -147,6 +147,7 @@ public interface JexlContext {
     
     /**
      * A marker interface of the JexlContext that exposes runtime evaluation options.
+     * @since 3.2
      */
     interface OptionsHandle {
         /**
@@ -183,6 +184,7 @@ public interface JexlContext {
      * of its cancellation through the context. It uses the same interpreter logic
      * that reacts to cancellation and is an alternative to using callable() and/or
      * interrupting script interpreter threads.
+     * @since 3.2
      */
     interface CancellationHandle {
         /**
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Engine.java b/src/main/java/org/apache/commons/jexl3/internal/Engine.java
index 2b96b98..d3ac4c3 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Engine.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Engine.java
@@ -301,14 +301,25 @@ public class Engine extends JexlEngine {
     }
  
     /**
+     * Solves an optional option.
+     * @param conf the option as configured, may be null
+     * @param def the default value if null, shall not be null
+     * @param <T> the option type
+     * @return conf or def
+     */
+    private static <T> T option(T conf, T def) {
+        return conf == null? def : conf;
+    }
+    
+    /**
      * Extracts the engine evaluation options from context if available, the engine
      * options otherwise.
-     * <p>This creates a copy of the options so they are immutable during
-     * execution.
+     * <p>If the context is a options handle and the handled options shared instance flag
+     * is false, this method creates a copy of the options making them immutable during execution.
      * @param context the context
      * @return the options if any
      */
-    JexlOptions options(JexlContext context) {
+    protected JexlOptions options(JexlContext context) {
         // Make a copy of the handled options if any
         if (context instanceof JexlContext.OptionsHandle) {
             JexlOptions jexlo = ((JexlContext.OptionsHandle) context).getEngineOptions();
@@ -333,14 +344,15 @@ public class Engine extends JexlEngine {
     }
 
     /**
-     * Solves an optional option.
-     * @param conf the option as configured, may be null
-     * @param def the default value if null, shall not be null
-     * @param <T> the option type
-     * @return conf or def
+     * Sets options from this engine options.
+     * @param opts the options to set
+     * @return the options
      */
-    private static <T> T option(T conf, T def) {
-        return conf == null? def : conf;
+    public JexlOptions optionsSet(JexlOptions opts) {
+        if (opts != null) {
+            opts.set(options);
+    }
+        return opts;
     }
     
     @Override
@@ -356,50 +368,6 @@ public class Engine extends JexlEngine {
     }
        
     /**
-     * Sets options from this engine options.
-     * @param opts the options to set
-     * @return the options
-     */
-    public JexlOptions optionsSet(JexlOptions opts) {
-        if (opts != null) {
-            opts.set(options);
-        }
-        return opts;
-    }
-    
-    /**
-     * Creates a script evaluation options.
-     * <p>This also calls the pragma processor if any
-     * @param script the script
-     * @param context the context
-     * @return the options
-     */
-    protected JexlOptions createOptions(Script script, JexlContext context) {
-        JexlOptions opts = options(context);
-        Map<String, Object> pragmas = script.getPragmas();
-        if (pragmas != null) {
-            JexlContext.PragmaProcessor processor =
-                    context instanceof JexlContext.PragmaProcessor
-                    ? (JexlContext.PragmaProcessor) context
-                    : null;
-            for(Map.Entry<String, Object> pragma : pragmas.entrySet()) {
-                String key = pragma.getKey();
-                Object value = pragma.getValue();
-                if (PRAGMA_OPTIONS.equals(key)) {
-                    if (value instanceof String) {
-                        String[] vs = ((String) value).split(" ");
-                        opts.setFlags(vs);
-                    }
-                }
-                if (processor != null) {
-                    processor.processPragma(key, value);
-                }
-            }
-        }
-        return opts;
-    }
-    
-    /**
      * Creates an interpreter.
      * @param context a JexlContext; if null, the empty context is used instead.
      * @param frame   the interpreter frame
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Script.java b/src/main/java/org/apache/commons/jexl3/internal/Script.java
index 5b1f53d..2baa25c 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Script.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Script.java
@@ -50,6 +50,10 @@ public class Script implements JexlScript, JexlExpression {
      * The engine version (as class loader change count) that last evaluated this script.
      */
     protected int version;
+    /**
+     * The name of the options pragma.
+     */
+    protected static final String PRAGMA_OPTIONS = "jexl.options";
 
     /**
      * @return the script AST
@@ -101,13 +105,13 @@ public class Script implements JexlScript, JexlExpression {
     }
     
     /**
-     * Creates this script options for evaluation.
+     * Compute this script options for evaluation.
      * <p>This also calls the pragma processor 
      * @param context the context
      * @return the options
      */
-    protected JexlOptions createOptions(JexlContext context) {
-        JexlOptions opts = jexl.createOptions(this, context);
+    protected JexlOptions options(JexlContext context) {
+        JexlOptions opts = jexl.options(context);
         // when parsing lexical, try hard to run lexical
         JexlFeatures features = script.getFeatures();
         if (features != null) {
@@ -118,6 +122,27 @@ public class Script implements JexlScript, JexlExpression {
                 opts.setLexicalShade(true);
             }
         }
+        // process script pragmas if any
+        Map<String, Object> pragmas = script.getPragmas();
+        if (pragmas != null) {
+            JexlContext.PragmaProcessor processor =
+                    context instanceof JexlContext.PragmaProcessor
+                    ? (JexlContext.PragmaProcessor) context
+                    : null;
+            for(Map.Entry<String, Object> pragma : pragmas.entrySet()) {
+                String key = pragma.getKey();
+                Object value = pragma.getValue();
+                if (PRAGMA_OPTIONS.equals(key)) {
+                    if (value instanceof String) {
+                        String[] vs = ((String) value).split(" ");
+                        opts.setFlags(vs);
+                    }
+                }
+                if (processor != null) {
+                    processor.processPragma(key, value);
+                }
+            }
+        }
         return opts;
     }
     
@@ -128,7 +153,7 @@ public class Script implements JexlScript, JexlExpression {
      * @return  the interpreter
      */
     protected Interpreter createInterpreter(JexlContext context, Frame frame) {
-        return jexl.createInterpreter(context, frame, createOptions(context));
+        return jexl.createInterpreter(context, frame, options(context));
     }
 
     /**
diff --git a/src/test/java/org/apache/commons/jexl3/LexicalTest.java b/src/test/java/org/apache/commons/jexl3/LexicalTest.java
index cbdde4f..eac41eb 100644
--- a/src/test/java/org/apache/commons/jexl3/LexicalTest.java
+++ b/src/test/java/org/apache/commons/jexl3/LexicalTest.java
@@ -554,4 +554,64 @@ public class LexicalTest {
         Object o = e.execute(ctxt);
         Assert.assertEquals(0, o);
     }
+    
+    public static class VarContext extends MapContext implements JexlContext.PragmaProcessor, JexlContext.OptionsHandle {
+        private JexlOptions options = new JexlOptions();
+        
+        JexlOptions snatchOptions() {
+            JexlOptions o = options;
+            options = new JexlOptions();
+            return o;
+}
+
+        @Override
+        public void processPragma(String key, Object value) {
+            if ("jexl.options".equals(key) && "canonical".equals(value)) {
+                options.setStrict(true);
+                options.setLexical(true);
+                options.setLexicalShade(true);
+                options.setSafe(false);
+            }
+        }
+
+        @Override
+        public JexlOptions getEngineOptions() {
+            return options;
+        }
+    }
+
+        
+    @Test
+    public void testOptionsPragma() throws Exception {
+        try {
+            JexlOptions.setDefaultFlags("+safe", "-lexical", "-lexicalShade");
+            VarContext vars = new VarContext();
+            JexlEngine jexl = new JexlBuilder().create();
+            int n42;
+            JexlOptions o;
+
+            n42 = (Integer) jexl.createScript("#pragma jexl.options none\n-42").execute(vars);
+            Assert.assertEquals(-42, n42);
+            o = vars.snatchOptions();
+            Assert.assertNotNull(o);
+            Assert.assertTrue(o.isStrict());
+            Assert.assertTrue(o.isSafe());
+            Assert.assertTrue(o.isCancellable());
+            Assert.assertFalse(o.isLexical());
+            Assert.assertFalse(o.isLexicalShade());
+
+            n42 = (Integer) jexl.createScript("#pragma jexl.options canonical\n42").execute(vars);
+            Assert.assertEquals(42, n42);
+            o = vars.snatchOptions();
+            Assert.assertNotNull(o);
+            Assert.assertTrue(o.isStrict());
+            Assert.assertFalse(o.isSafe());
+            Assert.assertTrue(o.isCancellable());
+            Assert.assertTrue(o.isLexical());
+            Assert.assertTrue(o.isLexicalShade());
+            Assert.assertFalse(o.isSharedInstance());
+        } finally {
+            JexlOptions.setDefaultFlags("-safe", "+lexical");
+        }
+    }
 }