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 2020/01/17 15:48:37 UTC

[commons-jexl] branch master updated (12146f6 -> de8eb7d)

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

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


    from 12146f6  JEXL-318: release notes and changes Task #JEXL-318 - Annotation processing may fail in lexical mode
     new a70b3d8  JEXL-321: do/while with empty statement contributed fix Task #JEXL-321 - Empty do-while loop is broken
     new de8eb7d  JEXL-320: remove dependency on Unsafe in test Task #JEXL-320 - "mvn test" fails with COMPILATION ERROR in SynchronizedArithmetic.java on Java 11

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 RELEASE-NOTES.txt                                  |  1 +
 .../apache/commons/jexl3/internal/Debugger.java    | 13 ++--
 .../apache/commons/jexl3/internal/Interpreter.java | 32 ++++----
 src/site/xdoc/changes.xml                          |  3 +
 .../java/org/apache/commons/jexl3/DoWhileTest.java | 32 ++++++++
 .../commons/jexl3/SynchronizedArithmetic.java      | 88 ++++++++++++++++------
 .../commons/jexl3/SynchronizedOverloadsTest.java   |  2 +-
 7 files changed, 125 insertions(+), 46 deletions(-)


[commons-jexl] 01/02: JEXL-321: do/while with empty statement contributed fix Task #JEXL-321 - Empty do-while loop is broken

Posted by he...@apache.org.
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

commit a70b3d8a75d5805a6daeedcf80ff44bf8b8cb276
Author: henrib <he...@apache.org>
AuthorDate: Fri Jan 17 16:43:00 2020 +0100

    JEXL-321: do/while with empty statement contributed fix
    Task #JEXL-321 - Empty do-while loop is broken
---
 RELEASE-NOTES.txt                                  |  1 +
 .../apache/commons/jexl3/internal/Debugger.java    | 13 +++++----
 .../apache/commons/jexl3/internal/Interpreter.java | 32 +++++++++++-----------
 src/site/xdoc/changes.xml                          |  3 ++
 .../java/org/apache/commons/jexl3/DoWhileTest.java | 32 ++++++++++++++++++++++
 5 files changed, 59 insertions(+), 22 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 7950413..f2aab63 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -74,6 +74,7 @@ New Features in 3.2:
 
 Bugs Fixed in 3.2:
 ==================
+* JEXL-321:      Empty do-while loop is broken
 * JEXL-318:      Annotation processing may fail in lexical mode
 * JEXL-315:      JxltEngine literal string strings ending in \ $ or # throw JxltEngine$Exception
 * JEXL-314:      Comparison NULL values of variables NAME1.NAME2
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
index 43339f9..0312c50 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
@@ -1003,13 +1003,14 @@ public class Debugger extends ParserVisitor implements JexlInfo.Detail {
     @Override
     protected Object visit(ASTDoWhileStatement node, Object data) {
         builder.append("do ");
-
-        acceptStatement(node.jjtGetChild(0), data);
-
+        int nc = node.jjtGetNumChildren();
+        if (nc > 1) {
+            acceptStatement(node.jjtGetChild(0), data);
+        } else {
+            builder.append(";");
+        }
         builder.append(" while (");
-
-        accept(node.jjtGetChild(1), data);
-
+        accept(node.jjtGetChild(nc - 1), data);
         builder.append(")");
         return data;
     }
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
index 563877f..8b116b0 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -747,9 +747,9 @@ public class Interpreter extends InterpreterBase {
     @Override
     protected Object visit(ASTWhileStatement node, Object data) {
         Object result = null;
-        /* first objectNode is the expression */
-        Node expressionNode = node.jjtGetChild(0);
-        while (arithmetic.toBoolean(expressionNode.jjtAccept(this, data))) {
+        /* first objectNode is the condition */
+        Node condition = node.jjtGetChild(0);
+        while (arithmetic.toBoolean(condition.jjtAccept(this, data))) {
             cancelCheck(node);
             if (node.jjtGetNumChildren() > 1) {
                 try {
@@ -768,22 +768,22 @@ public class Interpreter extends InterpreterBase {
     @Override
     protected Object visit(ASTDoWhileStatement node, Object data) {
         Object result = null;
-        /* last objectNode is the expression */
-        Node expressionNode = node.jjtGetChild(1);
+        int nc = node.jjtGetNumChildren();
+        /* last objectNode is the condition */
+        Node condition = node.jjtGetChild(nc - 1);
         do {
             cancelCheck(node);
-
-            try {
-                // execute statement
-                result = node.jjtGetChild(0).jjtAccept(this, data);
-            } catch (JexlException.Break stmtBreak) {
-                break;
-            } catch (JexlException.Continue stmtContinue) {
-                //continue;
+            if (nc > 1) {
+                try {
+                    // execute statement
+                    result = node.jjtGetChild(0).jjtAccept(this, data);
+                } catch (JexlException.Break stmtBreak) {
+                    break;
+                } catch (JexlException.Continue stmtContinue) {
+                    //continue;
+                }
             }
-
-        } while (arithmetic.toBoolean(expressionNode.jjtAccept(this, data)));
-
+        } while (arithmetic.toBoolean(condition.jjtAccept(this, data)));
         return result;
     }
 
diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml
index 20480fd..db4d582 100644
--- a/src/site/xdoc/changes.xml
+++ b/src/site/xdoc/changes.xml
@@ -26,6 +26,9 @@
     </properties>
     <body>
         <release version="3.2" date="unreleased">
+            <action dev="henrib" type="fix" issue="JEXL-321" due-to="Dmitri Blinov">
+                Empty do-while loop is broken
+            </action>
             <action dev="henrib" type="fix" issue="JEXL-318" due-to="Dmitri Blinov">
                 Annotation processing may fail in lexical mode
             </action>
diff --git a/src/test/java/org/apache/commons/jexl3/DoWhileTest.java b/src/test/java/org/apache/commons/jexl3/DoWhileTest.java
index c29b853..9c017f5 100644
--- a/src/test/java/org/apache/commons/jexl3/DoWhileTest.java
+++ b/src/test/java/org/apache/commons/jexl3/DoWhileTest.java
@@ -105,4 +105,36 @@ public class DoWhileTest extends JexlTestCase {
         JexlScript e = JEXL.createScript("(x)->{ for (i : 1..2) {  continue; var y = function() { 42; } break; } }");
         Assert.assertNotNull(e);
     }
+    
+    @Test
+    public void testEmptyBody() throws Exception {
+        JexlScript e = JEXL.createScript("var i = 0; do ; while((i+=1) < 10); i");
+        JexlContext jc = new MapContext();
+        Object o = e.execute(jc);
+        Assert.assertEquals(10, o);       
+    }
+    
+    @Test
+    public void testEmptyStmtBody() throws Exception {
+        JexlScript e = JEXL.createScript("var i = 0; do {} while((i+=1) < 10); i");
+        JexlContext jc = new MapContext();
+        Object o = e.execute(jc);
+        Assert.assertEquals(10, o);       
+    } 
+        
+    @Test
+    public void testWhileEmptyBody() throws Exception {
+        JexlScript e = JEXL.createScript("var i = 0; while((i+=1) < 10); i");
+        JexlContext jc = new MapContext();
+        Object o = e.execute(jc);
+        Assert.assertEquals(10, o);       
+    }
+    
+    @Test
+    public void testWhileEmptyStmtBody() throws Exception {
+        JexlScript e = JEXL.createScript("var i = 0; while((i+=1) < 10) {}; i");
+        JexlContext jc = new MapContext();
+        Object o = e.execute(jc);
+        Assert.assertEquals(10, o);       
+    }
 }


[commons-jexl] 02/02: JEXL-320: remove dependency on Unsafe in test Task #JEXL-320 - "mvn test" fails with COMPILATION ERROR in SynchronizedArithmetic.java on Java 11

Posted by he...@apache.org.
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

commit de8eb7d2897ebcbfa7d4ff61ed5fce5fa42e20f7
Author: henrib <he...@apache.org>
AuthorDate: Fri Jan 17 16:45:01 2020 +0100

    JEXL-320: remove dependency on Unsafe in test
    Task #JEXL-320 - "mvn test" fails with COMPILATION ERROR in SynchronizedArithmetic.java on Java 11
---
 .../commons/jexl3/SynchronizedArithmetic.java      | 88 ++++++++++++++++------
 .../commons/jexl3/SynchronizedOverloadsTest.java   |  2 +-
 2 files changed, 66 insertions(+), 24 deletions(-)

diff --git a/src/test/java/org/apache/commons/jexl3/SynchronizedArithmetic.java b/src/test/java/org/apache/commons/jexl3/SynchronizedArithmetic.java
index 9938b2b..7c897c0 100644
--- a/src/test/java/org/apache/commons/jexl3/SynchronizedArithmetic.java
+++ b/src/test/java/org/apache/commons/jexl3/SynchronizedArithmetic.java
@@ -16,12 +16,13 @@
  */
 package org.apache.commons.jexl3;
 
-import java.lang.reflect.Field;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.concurrent.atomic.AtomicInteger;
-import sun.misc.Unsafe;
+//import java.lang.reflect.Field;
+//import sun.misc.Unsafe;
 
 /**
  *
@@ -60,7 +61,6 @@ public class SynchronizedArithmetic extends JexlArithmetic {
          * @param o the monitored object
          */
         protected void monitorEnter(Object o) {
-            UNSAFE.monitorEnter(o);
             enters.incrementAndGet();
         }
 
@@ -69,7 +69,6 @@ public class SynchronizedArithmetic extends JexlArithmetic {
          * @param o the monitored object
          */
         protected void monitorExit(Object o) {
-            UNSAFE.monitorExit(o);
             exits.incrementAndGet();
         }
 
@@ -94,32 +93,75 @@ public class SynchronizedArithmetic extends JexlArithmetic {
     /**
      * You should know better than to use this...
      */
-    private static Unsafe UNSAFE;
-    static {
-        try {
-            Field f = Unsafe.class.getDeclaredField("theUnsafe");
-            f.setAccessible(true);
-            UNSAFE = (Unsafe) f.get(null);
-        } catch (Exception e) {
-            UNSAFE = null;
-        }
-    }
-
+//    private static Unsafe UNSAFE;
+//    static {
+//        try {
+//            Field f = Unsafe.class.getDeclaredField("theUnsafe");
+//            f.setAccessible(true);
+//            UNSAFE = (Unsafe) f.get(null);
+//        } catch (Exception e) {
+//            UNSAFE = null;
+//        }
+//    }
+//
+//    /**
+//     * Using the unsafe to enter & exit object intrinsic monitors.
+//     */
+//    static class UnsafeMonitor extends Monitor {
+//        @Override protected void monitorEnter(Object o) {
+//            UNSAFE.monitorEnter(o);
+//            super.monitorEnter(o);
+//        }
+//
+//        @Override protected void monitorExit(Object o) {
+//            UNSAFE.monitorExit(o);
+//            super.monitorExit(o);
+//        }
+//    }
+    
     /**
-     * Using the unsafe to enter & exit object intrinsic monitors.
+     * Crude monitor replacement...
      */
-    static class UnsafeMonitor extends Monitor {
-        @Override protected void monitorEnter(Object o) {
-            UNSAFE.monitorEnter(o);
-            super.monitorEnter(o);
+    static class SafeMonitor extends Monitor {
+         private final Map<Object, Object> monitored = new IdentityHashMap<Object, Object>();
+
+        @Override
+        protected void monitorEnter(Object o) {
+            Object guard;
+            try {
+                while (true) {
+                    synchronized (monitored) {
+                        guard = monitored.get(o);
+                        if (guard == null) {
+                            guard = new Object();
+                            monitored.put(o, guard);
+                            super.monitorEnter(o);
+                            break;
+                        }
+                    }
+                    synchronized (guard) {
+                        guard.wait();
+                    }
+                }
+            } catch (InterruptedException xint) {
+                // oops
+            }
         }
 
         @Override protected void monitorExit(Object o) {
-            UNSAFE.monitorExit(o);
-            super.monitorExit(o);
+            final Object guard;
+            synchronized(monitored) {
+                guard = monitored.remove(o);
+            }
+            if (guard != null) {
+                synchronized(guard) {
+                    guard.notifyAll();
+                }
+                super.monitorExit(o);
+            }
         }
     }
-
+    
     /**
      * An iterator that implements Closeable (at least implements a close method)
      * and uses monitors to protect iteration.
diff --git a/src/test/java/org/apache/commons/jexl3/SynchronizedOverloadsTest.java b/src/test/java/org/apache/commons/jexl3/SynchronizedOverloadsTest.java
index cf98bce..769da63 100644
--- a/src/test/java/org/apache/commons/jexl3/SynchronizedOverloadsTest.java
+++ b/src/test/java/org/apache/commons/jexl3/SynchronizedOverloadsTest.java
@@ -64,7 +64,7 @@ public class SynchronizedOverloadsTest extends JexlTestCase {
 
     @Test
     public void testUnsafeMonitor() throws Exception {
-        SynchronizedArithmetic.Monitor monitor = new SynchronizedArithmetic.UnsafeMonitor();
+        SynchronizedArithmetic.Monitor monitor = new SynchronizedArithmetic.SafeMonitor();
         Map<String, Object> foo = new TreeMap<String, Object>();
         foo.put("one", 1);
         foo.put("two", 2);