Author: henrib
Date: Thu May 26 21:13:48 2016
New Revision: 1745646

URL: http://svn.apache.org/viewvc?rev=1745646&view=rev
Log:
JEXL-196: break out of method resolution loop when already failed to resolve 
through context method

Modified:
    commons/proper/jexl/trunk/RELEASE-NOTES.txt
    
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
    commons/proper/jexl/trunk/src/site/xdoc/changes.xml
    
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java

Modified: commons/proper/jexl/trunk/RELEASE-NOTES.txt
URL: 
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/RELEASE-NOTES.txt?rev=1745646&r1=1745645&r2=1745646&view=diff
==============================================================================
--- commons/proper/jexl/trunk/RELEASE-NOTES.txt (original)
+++ commons/proper/jexl/trunk/RELEASE-NOTES.txt Thu May 26 21:13:48 2016
@@ -28,6 +28,7 @@ Version 3.0.1 is a micro release to fix
 Bugs Fixed in 3.0.1:
 ====================
 
+* JEXL-196:     Script execution hangs while calling method with one argument 
without parameter
 * JEXL-195:     Support for AtomicBoolean in logical expressions
 * JEXL-193:     InterruptedException is swallowed in function call in silent 
and non-strict mode
 * JEXL-192:     Invalid return type when expected result is null

Modified: 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
URL: 
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java?rev=1745646&r1=1745645&r2=1745646&view=diff
==============================================================================
--- 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
 (original)
+++ 
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
 Thu May 26 21:13:48 2016
@@ -219,13 +219,7 @@ public class Interpreter extends ParserV
         } finally {
             if (functors != null && AUTOCLOSEABLE != null) {
                 for (Object functor : functors.values()) {
-                    if (functor != null && 
AUTOCLOSEABLE.isAssignableFrom(functor.getClass())) {
-                        try {
-                            jexl.invokeMethod(functor, "close", EMPTY_PARAMS);
-                        } catch (Exception xclose) {
-                            logger.warn(xclose.getMessage(), 
xclose.getCause());
-                        }
-                    }
+                    closeIfSupported(functor);
                 }
             }
             functors = null;
@@ -249,6 +243,26 @@ public class Interpreter extends ParserV
     }
 
     /**
+     * Attempt to call close() if supported.
+     * <p>This is used when dealing with auto-closeable (duck-like) objects
+     * @param closeable the object we'd like to close
+     */
+    protected void closeIfSupported(Object closeable) {
+        if (closeable != null) {
+            if (AUTOCLOSEABLE == null || 
AUTOCLOSEABLE.isAssignableFrom(closeable.getClass())) {
+                JexlMethod mclose = uberspect.getMethod(closeable, "close", 
EMPTY_PARAMS);
+                if (mclose != null) {
+                    try {
+                        mclose.invoke(closeable, EMPTY_PARAMS);
+                    } catch (Exception xignore) {
+                        logger.warn(xignore);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
      * Finds the node causing a NPE for diadic operators.
      * @param xrt   the RuntimeException
      * @param node  the parent node
@@ -810,9 +824,13 @@ public class Interpreter extends ParserV
         if (iterableValue != null && node.jjtGetNumChildren() >= 3) {
             /* third objectNode is the statement to execute */
             JexlNode statement = node.jjtGetChild(2);
-            // get an iterator for the collection/array etc via the
-            // introspector.
-            Iterator<?> itemsIterator = uberspect.getIterator(iterableValue);
+            // get an iterator for the collection/array etc via the 
introspector.
+            Object forEach = null;
+            try {
+                forEach = null;//operators.tryForeachOverload(node, 
iterableValue);
+                Iterator<?> itemsIterator = forEach instanceof Iterator
+                                ? (Iterator<?>) forEach
+                                : uberspect.getIterator(iterableValue);
                 if (itemsIterator != null) {
                     while (itemsIterator.hasNext()) {
                         if (isCancelled()) {
@@ -835,7 +853,11 @@ public class Interpreter extends ParserV
                         }
                     }
                 }
-                        }
+            } finally {
+                //  closeable iterator handling
+                closeIfSupported(forEach);
+            }
+        }
         return result;
     }
 
@@ -1708,7 +1730,11 @@ public class Interpreter extends ParserV
                     // solve 'null' namespace
                     if (target == context) {
                         Object namespace = resolveNamespace(null, node);
-                        if (namespace != null) {
+                        if (namespace == context) {
+                            // we can not solve it
+                            break;
+                        }
+                        else if (namespace != null) {
                             target = namespace;
                             caller = null;
                             continue;

Modified: commons/proper/jexl/trunk/src/site/xdoc/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/site/xdoc/changes.xml?rev=1745646&r1=1745645&r2=1745646&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/site/xdoc/changes.xml (original)
+++ commons/proper/jexl/trunk/src/site/xdoc/changes.xml Thu May 26 21:13:48 2016
@@ -26,6 +26,9 @@
     </properties>
     <body>
         <release version="3.0.1" date="unreleased">
+            <action dev="henrib" type="fix" issue="JEXL-196" due-to="Dmitri 
Blinov">
+                Script execution hangs while calling method with one argument 
without parameter
+            </action>
             <action dev="henrib" type="fix" issue="JEXL-195" due-to="Dmitri 
Blinov">
                 Support for AtomicBoolean in logical expressions
             </action>

Modified: 
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java?rev=1745646&r1=1745645&r2=1745646&view=diff
==============================================================================
--- 
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java
 (original)
+++ 
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java
 Thu May 26 21:13:48 2016
@@ -146,6 +146,10 @@ public class ScriptCallableTest extends
                 throw xint;
             }
         }
+
+        public int hangs(Object t) {
+            return 1;
+        }
     }
 
     @Test
@@ -409,4 +413,21 @@ public class ScriptCallableTest extends
             exec.shutdown();
         }
     }
+
+    @Test
+    public void testHangs() throws Exception {
+        JexlScript e = JEXL.createScript("hangs()");
+        Callable<Object> c = e.callable(new TestContext());
+
+        ExecutorService executor = Executors.newFixedThreadPool(1);
+        try {
+            Future<?> future = executor.submit(c);
+            Object t = future.get(1, TimeUnit.SECONDS);
+            Assert.fail("hangs should not be solved");
+        } catch(ExecutionException xexec) {
+            Assert.assertTrue(xexec.getCause() instanceof 
JexlException.Method);
+        } finally {
+            executor.shutdown();
+        }
+    }
 }


Reply via email to