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 757dcb9  JEXL-253: Added public API to allow creation of inheritable 
permissions in sandbox; added tests Task #JEXL-253 - Permissions by super type 
in JexlSandbox
757dcb9 is described below

commit 757dcb90f2ca2ba92fd9ec43291deb4305eee02c
Author: henrib <[email protected]>
AuthorDate: Mon Jun 17 16:36:39 2019 +0200

    JEXL-253: Added public API to allow creation of inheritable permissions in 
sandbox; added tests
    Task #JEXL-253 - Permissions by super type in JexlSandbox
---
 RELEASE-NOTES.txt                                  |  1 +
 .../commons/jexl3/introspection/JexlSandbox.java   | 39 ++++++++---
 .../commons/jexl3/scripting/JexlScriptEngine.java  |  2 +-
 src/site/xdoc/changes.xml                          |  7 +-
 .../commons/jexl3/introspection/SandboxTest.java   | 80 ++++++++++++++++------
 5 files changed, 97 insertions(+), 32 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 9d01ebe..44dba2a 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -56,6 +56,7 @@ New Features in 3.2:
 * JEXL-273:      Add do...while(...) loops
 * JEXL-264:      Allow space, quote & double-quote in identifiers
 * JEXL-260:      Automatically inject JexlContext in constructor call when 
possible
+* JEXL-253:      Permissions by super type in JexlSandbox
 * JEXL-252:      Allow for interpolated strings to be used in property access 
operators
 * JEXL-250:      Safe navigation operator (?.)
 * JEXL-248:      Allow range subexpression as an array property assignment 
identifier
diff --git 
a/src/main/java/org/apache/commons/jexl3/introspection/JexlSandbox.java 
b/src/main/java/org/apache/commons/jexl3/introspection/JexlSandbox.java
index fecacb7..178e95b 100644
--- a/src/main/java/org/apache/commons/jexl3/introspection/JexlSandbox.java
+++ b/src/main/java/org/apache/commons/jexl3/introspection/JexlSandbox.java
@@ -24,8 +24,8 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * A sandbox describes permissions on a class by explicitly allowing or 
forbidding access to methods and properties
- * through "whitelists" and "blacklists".
+ * A sandbox describes permissions on a class by explicitly allowing or 
forbidding
+ * access to methods and properties through "whitelists" and "blacklists".
  *
  * <p>A <b>whitelist</b> explicitly allows methods/properties for a class;</p>
  *
@@ -43,16 +43,25 @@ import java.util.concurrent.ConcurrentHashMap;
  *   <li>If it is not empty, the only forbidden properties/methods are the 
ones contained.</li>
  * </ul>
  *
- * <p>Permissions are composed of three lists, read, write, execute, each 
being "white" or "black":</p>
+ * <p>Permissions are composed of three lists, read, write, execute, each being
+ * "white" or "black":</p>
  *
  * <ul>
  *   <li><b>read</b> controls readable properties </li>
  *   <li><b>write</b> controls writable properties</li>
  *   <li><b>execute</b> controls executable methods and constructor</li>
  * </ul>
+ * 
+ * <p>When specified, permissions - white or black lists - can be created 
inheritable
+ * on interfaces or classes and thus applicable to their implementations or 
derived
+ * classes; the sandbox must be created with the 'inheritable' flag for this 
behavior
+ * to be triggered. Note that even in this configuration, it is still possible 
to
+ * add non-inheritable permissions.
+ * Adding inheritable lists to a non inheritable sandbox has no added effect;
+ * permissions only apply to their specified class.</p>
  *
- * <p>Note that a JexlUberspect always uses a copy of the JexlSandbox used to 
built it to avoid synchronization and/or
- * concurrent modifications at runtime.</p>
+ * <p>Note that a JexlUberspect always uses a <em>copy</em> of the JexlSandbox
+ * used to built it preventing permission changes after its instantiation.</p>
  *
  * @since 3.0
  */
@@ -76,7 +85,7 @@ public final class JexlSandbox {
      * sandbox is a white-box, white-listing that class for all permissions 
(read, write and execute).
      */
     public JexlSandbox() {
-        this(true, new HashMap<String, Permissions>());
+        this(true, false, null);
     }
 
     /**
@@ -88,15 +97,26 @@ public final class JexlSandbox {
      * @since 3.1
      */
     public JexlSandbox(boolean wb) {
-        this(wb, new HashMap<String, Permissions>());
+        this(wb, false, null);
+    }
+    
+    /**
+     * Creates a sandbox.
+     * @param wb whether this sandbox is white (true) or black (false)
+     * @param inh whether permissions on interfaces and classes are inherited 
(true) or not (false)
+     * @since 3.2
+     */
+    public JexlSandbox(boolean wb, boolean inh) {
+        this(wb, inh, null);
     }
 
     /**
      * Creates a sandbox based on an existing permissions map.
      * @param map the permissions map
      */
+    @Deprecated
     protected JexlSandbox(Map<String, Permissions> map) {
-        this(true, map);
+        this(true, false, map);
     }
 
     /**
@@ -105,6 +125,7 @@ public final class JexlSandbox {
      * @param map the permissions map
      * @since 3.1
      */
+    @Deprecated
     protected JexlSandbox(boolean wb, Map<String, Permissions> map) {
         this(wb, false, map);
     }
@@ -119,7 +140,7 @@ public final class JexlSandbox {
     protected JexlSandbox(boolean wb, boolean inh, Map<String, Permissions> 
map) {
         white = wb;
         inherit = inh;
-        sandbox = map;
+        sandbox = map != null? map : new HashMap<String, Permissions>();
     }
 
     /**
diff --git 
a/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java 
b/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
index 73cf14c..fdf11e2 100644
--- a/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
+++ b/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
@@ -96,7 +96,7 @@ public class JexlScriptEngine extends AbstractScriptEngine 
implements Compilable
 
     /**
      * Implements engine and engine context properties for use by JEXL scripts.
-     * Those properties are allways bound to the default engine scope context.
+     * Those properties are always bound to the default engine scope context.
      *
      * <p>The following properties are defined:</p>
      * 
diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml
index 709b5ac..800064e 100644
--- a/src/site/xdoc/changes.xml
+++ b/src/site/xdoc/changes.xml
@@ -119,11 +119,14 @@
             <action dev="henrib" type="add" issue="JEXL-261">
                 JexlEngine.setClassLoader(...) should reload namespaces that 
are classes
             </action>
+            <action dev="henrib" type="add" issue="JEXL-260" due-to="Dmitri 
Blinov">
+                Automatically inject JexlContext in constructor call when 
possible
+            </action>
             <action dev="henrib" type="fix" issue="JEXL-257" due-to="Dmitri 
Blinov">
                 Function throwing IllegalArgumentException may be called twice
             </action>
-            <action dev="henrib" type="add" issue="JEXL-260" due-to="Dmitri 
Blinov">
-                Automatically inject JexlContext in constructor call when 
possible
+            <action dev="henrib" type="add" issue="JEXL-253" due-to="Woonsan 
Ko">
+                Permissions by super type in JexlSandbox
             </action>
             <action dev="henrib" type="add" issue="JEXL-252" due-to="Dmitri 
Blinov">
                 Allow for interpolated strings to be used in property access 
operators
diff --git 
a/src/test/java/org/apache/commons/jexl3/introspection/SandboxTest.java 
b/src/test/java/org/apache/commons/jexl3/introspection/SandboxTest.java
index 2f5f063..4e718c2 100644
--- a/src/test/java/org/apache/commons/jexl3/introspection/SandboxTest.java
+++ b/src/test/java/org/apache/commons/jexl3/introspection/SandboxTest.java
@@ -17,9 +17,7 @@
 package org.apache.commons.jexl3.introspection;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import org.apache.commons.jexl3.JexlBuilder;
 import org.apache.commons.jexl3.JexlContext;
 import org.apache.commons.jexl3.JexlEngine;
@@ -384,36 +382,78 @@ public class SandboxTest extends JexlTestCase {
     }
 
     @Test
-    public void testSandboxInherit() throws Exception {
+       public void testSandboxInherit0() throws Exception {
         Object result;
         JexlContext ctxt = null;
-        Map<String, JexlSandbox.Permissions> perms = new HashMap<String, 
JexlSandbox.Permissions>();
         List<String> foo = new ArrayList<String>();
-        JexlSandbox sandbox = new JexlSandbox(false, true, perms);
+        JexlSandbox sandbox = new JexlSandbox(false, true);
         sandbox.white(java.util.List.class.getName());
-        //sandbox.black(Foo.class.getName()).execute();
+        
         JexlEngine sjexl = new 
JexlBuilder().sandbox(sandbox).strict(true).create();
         JexlScript method = sjexl.createScript("foo.add(y)", "foo", "y");
         JexlScript set = sjexl.createScript("foo[x] = y", "foo", "x", "y");
         JexlScript get = sjexl.createScript("foo[x]", "foo", "x");
+
+        result = method.execute(ctxt, foo, "nothing");
+        Assert.assertEquals(true, result);
+        result = null;
+        result = get.execute(null, foo, 0);
+        Assert.assertEquals("nothing", result);
+        result = null;
+        result = set.execute(null, foo, 0, "42");
+        Assert.assertEquals("42", result);
+
+        result = null;
+        result = get.execute(null, foo, 0);
+        Assert.assertEquals("42", result);
+    }
+    
+    public abstract static class Operation {
+        protected final int base;
+        public Operation(int sz) {
+         base = sz;
+        }
+        
+        public abstract int someOp(int x);
+        public abstract int nonCallable(int y);
+    }
+
+    public static class Operation2 extends Operation {
+        public Operation2(int sz) {
+            super(sz);
+        }
+
+        @Override
+        public int someOp(int x) {
+            return base + x;
+        }
+
+        @Override
+        public int nonCallable(int y) {
+            throw new UnsupportedOperationException("do NOT call");
+        }
+    }
+
+    @Test
+    public void testSandboxInherit1() throws Exception {
+        Object result;
+        JexlContext ctxt = null;
+        Operation2 foo = new Operation2(12);
+        JexlSandbox sandbox = new JexlSandbox(false, true);
+        sandbox.white(Operation.class.getName());
+        sandbox.black(Operation.class.getName()).execute("nonCallable");
+        //sandbox.black(Foo.class.getName()).execute();
+        JexlEngine sjexl = new 
JexlBuilder().sandbox(sandbox).strict(true).create();
+        JexlScript someOp = sjexl.createScript("foo.someOp(y)", "foo", "y");
+        result = someOp.execute(ctxt, foo, 30);
+        Assert.assertEquals(42, result);
+        JexlScript nonCallable = sjexl.createScript("foo.nonCallable(y)", 
"foo", "y");
         try {
-            result = method.execute(ctxt, foo, "nothing");
-            Assert.assertEquals(true, result);
-            result = null;
-            result = get.execute(null, foo, 0);
-            Assert.assertEquals("nothing", result);
-            result = null;
-            result = set.execute(null, foo, 0, "42");
-            Assert.assertEquals("42", result);
-
-            result = null;
-            result = get.execute(null, foo, 0);
-            Assert.assertEquals("42", result);
-            //Assert.fail("should have not been possible");
+            result = nonCallable.execute(null, foo, 0);
+            Assert.fail("should not be possible");
         } catch (JexlException xjm) {
             // ok
             LOGGER.info(xjm.toString());
         }
-
     }
 }

Reply via email to