Author: henrib Date: Mon Jan 8 15:04:04 2018 New Revision: 1820568 URL: http://svn.apache.org/viewvc?rev=1820568&view=rev Log: JEXL-246: Better error handling or operator overload error, added specific test, changes & release notes updated
Modified: commons/proper/jexl/trunk/RELEASE-NOTES.txt commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Operators.java commons/proper/jexl/trunk/src/site/xdoc/changes.xml commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest200.java Modified: commons/proper/jexl/trunk/RELEASE-NOTES.txt URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/RELEASE-NOTES.txt?rev=1820568&r1=1820567&r2=1820568&view=diff ============================================================================== --- commons/proper/jexl/trunk/RELEASE-NOTES.txt (original) +++ commons/proper/jexl/trunk/RELEASE-NOTES.txt Mon Jan 8 15:04:04 2018 @@ -40,6 +40,7 @@ New Features in 3.2: Bugs Fixed in 3.2: ================== +* JEXL-246: Intermittent ambiguous method invocation when processing assignOverload * JEXL-245: Engine in strict mode fails to fail on unsolvable variables or properties * JEXL-244: Webapp classloader memory leaks * JEXL-241: NPE when script containing string interpolation executed in multiple threads Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Operators.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Operators.java?rev=1820568&r1=1820567&r2=1820568&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Operators.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Operators.java Mon Jan 8 15:04:04 2018 @@ -139,26 +139,32 @@ public class Operators { } } // base eval - switch (operator) { - case SELF_ADD: - return arithmetic.add(args[0], args[1]); - case SELF_SUBTRACT: - return arithmetic.subtract(args[0], args[1]); - case SELF_MULTIPLY: - return arithmetic.multiply(args[0], args[1]); - case SELF_DIVIDE: - return arithmetic.divide(args[0], args[1]); - case SELF_MOD: - return arithmetic.mod(args[0], args[1]); - case SELF_AND: - return arithmetic.and(args[0], args[1]); - case SELF_OR: - return arithmetic.or(args[0], args[1]); - case SELF_XOR: - return arithmetic.xor(args[0], args[1]); - default: - throw new JexlException.Operator(node, operator.getOperatorSymbol(), null); + try { + switch (operator) { + case SELF_ADD: + return arithmetic.add(args[0], args[1]); + case SELF_SUBTRACT: + return arithmetic.subtract(args[0], args[1]); + case SELF_MULTIPLY: + return arithmetic.multiply(args[0], args[1]); + case SELF_DIVIDE: + return arithmetic.divide(args[0], args[1]); + case SELF_MOD: + return arithmetic.mod(args[0], args[1]); + case SELF_AND: + return arithmetic.and(args[0], args[1]); + case SELF_OR: + return arithmetic.or(args[0], args[1]); + case SELF_XOR: + return arithmetic.xor(args[0], args[1]); + default: + // unexpected, new operator added? + throw new UnsupportedOperationException(operator.getOperatorSymbol()); + } + } catch (Exception xany) { + interpreter.operatorError(node, base, xany); } + return JexlEngine.TRY_FAILED; } /** 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=1820568&r1=1820567&r2=1820568&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/site/xdoc/changes.xml (original) +++ commons/proper/jexl/trunk/src/site/xdoc/changes.xml Mon Jan 8 15:04:04 2018 @@ -26,6 +26,9 @@ </properties> <body> <release version="3.2" date="unreleased"> + <action dev="henrib" type="fix" issue="JEXL-246" due-to="Dmitri Blinov"> + Intermittent ambiguous method invocation when processing assignOverload + </action> <action dev="henrib" type="fix" issue="JEXL-245" due-to="Ate Douma"> Engine in strict mode fails to fail on unsolvable variables or properties </action> Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest200.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest200.java?rev=1820568&r1=1820567&r2=1820568&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest200.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest200.java Mon Jan 8 15:04:04 2018 @@ -16,7 +16,8 @@ */ package org.apache.commons.jexl3; -import java.text.NumberFormat; +import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -27,6 +28,10 @@ import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.logging.Level; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -264,8 +269,7 @@ public class IssuesTest200 extends JexlT m2.put("item", "B"); handle(pool, script, m1); - System.out.println(script.execute(new MapContext(m2))); - System.out.println("Reached the end"); + script.execute(new MapContext(m2)); pool.shutdown(); } @@ -343,4 +347,71 @@ public class IssuesTest200 extends JexlT } } } + + /** + * An arithmetic that implements 2 selfAdd methods. + */ + public static class Arithmetic246 extends JexlArithmetic { + public Arithmetic246(boolean astrict) { + super(astrict); + } + + public Collection<String> selfAdd(Collection<String> c, String item) { + c.add(item); + return c; + } + + public Appendable selfAdd(Appendable c, String item) throws IOException { + c.append(item); + return c; + } + } + + @Test + public void test246() throws Exception { + Log log246 = LogFactory.getLog(IssuesTest200.class); + // quiesce the logger + java.util.logging.Logger ll246 = java.util.logging.LogManager.getLogManager().getLogger(IssuesTest200.class.getName()); + ll246.setLevel(Level.SEVERE); + JexlEngine jexl = new JexlBuilder().arithmetic(new Arithmetic246(true)).debug(true).logger(log246).create(); + JexlScript script = jexl.createScript("z += x", "x"); + MapContext ctx = new MapContext(); + List<String> z = new ArrayList<String>(1); + Object zz; + + // no ambiguous, std case + ctx.set("z", z); + zz = script.execute(ctx, "42"); + Assert.assertTrue(zz == z); + Assert.assertEquals(1, z.size()); + z.clear(); + ctx.clear(); + + // method discovery will fail due to ambiguity: first arg is null, no type, 2 potential methods + // create a cache-miss entry in method resolution + String expectNullOperand = null; + try { + script.execute(ctx, "42"); + Assert.fail("null z evaluating 'z += x'"); + } catch(JexlException xae) { + expectNullOperand = xae.toString(); + } + Assert.assertNotNull(expectNullOperand); + + // second call will not provoque ambiguity (since cache-miss is recalled) but operator will fail nevertheless + try { + // discovery will fail for null arg + script.execute(ctx, "42"); + Assert.fail("null z evaluating 'z += x'"); + } catch(JexlException xae) { + expectNullOperand = xae.toString(); + } + Assert.assertNotNull(expectNullOperand); + + // a non ambiguous call still succeeds + ctx.set("z", z); + zz = script.execute(ctx, "42"); + Assert.assertTrue(zz == z); + Assert.assertEquals(1, z.size()); + } }