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 2015/07/11 22:41:10 UTC
svn commit: r1690404 - in /commons/proper/jexl/trunk/src:
main/java/org/apache/commons/jexl3/
main/java/org/apache/commons/jexl3/internal/
main/java/org/apache/commons/jexl3/parser/ site/xdoc/ site/xdoc/reference/
test/java/org/apache/commons/jexl3/
Author: henrib
Date: Sat Jul 11 20:41:09 2015
New Revision: 1690404
URL: http://svn.apache.org/r1690404
Log:
JEXL:
JEXL-162 fixed, specific exception for operator error, behavior as lenient as 2.x, added test, clarified doc and updated changes
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
commons/proper/jexl/trunk/src/site/xdoc/changes.xml
commons/proper/jexl/trunk/src/site/xdoc/reference/syntax.xml
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java?rev=1690404&r1=1690403&r2=1690404&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java Sat Jul 11 20:41:09 2015
@@ -484,6 +484,48 @@ public class JexlException extends Runti
}
/**
+ * Thrown when an operator fails.
+ * @since 3.0
+ */
+ public static class Operator extends JexlException {
+ /**
+ * Creates a new Operator exception instance.
+ * @param node the location information
+ * @param symbol the operator name
+ * @param cause the exception causing the error
+ */
+ public Operator(JexlNode node, String symbol, Throwable cause) {
+ super(node, symbol, cause);
+ }
+
+ /**
+ * @return the method name
+ */
+ public String getSymbol() {
+ return super.detailedMessage();
+ }
+
+ @Override
+ protected String detailedMessage() {
+ return "error calling operator '" + getSymbol() + "'";
+ }
+ }
+
+ /**
+ * Generates a message for an operator error.
+ * @param node the node where the error occurred
+ * @param symbol the operator name
+ * @return the error message
+ */
+ public static String operatorError(JexlNode node, String symbol) {
+ StringBuilder msg = errorAt(node);
+ msg.append("error calling operator '");
+ msg.append(symbol);
+ msg.append('\'');
+ return msg.toString();
+ }
+
+ /**
* Thrown to return a value.
* @since 3.0
*/
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=1690404&r1=1690403&r2=1690404&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 Sat Jul 11 20:41:09 2015
@@ -303,6 +303,24 @@ public class Interpreter extends ParserV
}
/**
+ * Triggered when an operator fails.
+ * @param node the node where the error originated from
+ * @param operator the method name
+ * @param cause the cause of error (if any)
+ * @throws JexlException if isStrict
+ */
+ protected void operatorError(JexlNode node, JexlArithmetic.Operator operator, Throwable cause) {
+ if (cause != null) {
+ if (strictEngine) {
+ throw new JexlException.Operator(node, operator.getOperatorSymbol(), cause);
+ }
+ if (!silent) {
+ logger.warn(JexlException.operatorError(node, operator.getOperatorSymbol()));
+ }
+ }
+ }
+
+ /**
* Triggered when method, function or constructor invocation fails.
* @param xjexl the JexlException wrapping the original error
* @return throws JexlException if isStrict, null otherwise
@@ -412,7 +430,7 @@ public class Interpreter extends ParserV
return result;
}
} catch (Exception xany) {
- return invocationFailed(new JexlException(node, operator.getMethodName(), xany));
+ operatorError(node, operator, xany);
}
}
return JexlEngine.TRY_FAILED;
@@ -450,7 +468,7 @@ public class Interpreter extends ParserV
return result;
}
} catch (Exception xany) {
- return invocationFailed(new JexlException(node, operator.getMethodName(), xany));
+ operatorError(node, operator, xany);
}
}
return JexlEngine.TRY_FAILED;
@@ -1237,15 +1255,13 @@ public class Interpreter extends ParserV
// boolean and if so, just use it
JexlMethod vm = uberspect.getMethod(object, "isEmpty", EMPTY_PARAMS);
if (vm != null && vm.getReturnType() == Boolean.TYPE) {
- Boolean result;
try {
- result = (Boolean) vm.invoke(object, EMPTY_PARAMS);
- } catch (Exception e) {
- throw new JexlException(node, "empty() : error executing", e);
+ return (Boolean) vm.invoke(object, EMPTY_PARAMS);
+ } catch (Exception xany) {
+ operatorError(node, Operator.EMPTY, xany);
}
- return result;
}
- throw new JexlException(node, "empty() : unsupported type : " + object.getClass(), null);
+ return Boolean.FALSE;
}
/**
@@ -1280,15 +1296,13 @@ public class Interpreter extends ParserV
// integer and if so, just use it
JexlMethod vm = uberspect.getMethod(object, "size", EMPTY_PARAMS);
if (vm != null && vm.getReturnType() == Integer.TYPE) {
- Integer result;
try {
- result = (Integer) vm.invoke(object, EMPTY_PARAMS);
- } catch (Exception e) {
- throw new JexlException(node, "size() : error executing", e);
+ return (Integer) vm.invoke(object, EMPTY_PARAMS);
+ } catch (Exception xany) {
+ operatorError(node, Operator.SIZE, xany);
}
- return result;
}
- throw new JexlException(node, "size() : unsupported type : " + object.getClass(), null);
+ return 0;
}
@Override
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt?rev=1690404&r1=1690403&r2=1690404&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt Sat Jul 11 20:41:09 2015
@@ -747,7 +747,7 @@ void MethodCall() #void : {}
{
LOOKAHEAD(<DOT> <SIZE>) (<DOT> <SIZE> <LPAREN> <RPAREN>) #SizeMethod(1)
|
- LOOKAHEAD(<DOT> <EMPTY>) ( <DOT> <SIZE> <LPAREN> <RPAREN>) #EmptyMethod(1)
+ LOOKAHEAD(<DOT> <EMPTY>) (<DOT> <EMPTY> <LPAREN> <RPAREN>) #EmptyMethod(1)
|
(MemberAccess() (LOOKAHEAD(<LPAREN>) Arguments())+) #MethodNode(>1)
}
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=1690404&r1=1690403&r2=1690404&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/site/xdoc/changes.xml (original)
+++ commons/proper/jexl/trunk/src/site/xdoc/changes.xml Sat Jul 11 20:41:09 2015
@@ -26,6 +26,9 @@
</properties>
<body>
<release version="3.0" date="unreleased">
+ <action dev="henrib" type="fix" issue="JEXL-162" due-to="Dmitri Blinov">
+ empty() function throws an exception : unsupported type
+ </action>
<action dev="henrib" type="add" >
Added a method to get parameters from a template
</action>
Modified: commons/proper/jexl/trunk/src/site/xdoc/reference/syntax.xml
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/site/xdoc/reference/syntax.xml?rev=1690404&r1=1690403&r2=1690404&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/site/xdoc/reference/syntax.xml (original)
+++ commons/proper/jexl/trunk/src/site/xdoc/reference/syntax.xml Sat Jul 11 20:41:09 2015
@@ -290,28 +290,39 @@
<tr>
<td>empty</td>
<td>
- Returns true if the expression following is either:
+ Evaluates whether an expression if 'empty'.
+ This is true when the argument is:
<ol>
<li><code>null</code></li>
+ <li>An instance of class C and the derived JexlArithmetic overloads a method 'public boolean empty(C arg)'
+ that returns true when the argument is considered empty</li>
<li>An empty string</li>
<li>An array of length zero</li>
<li>A collection of size zero</li>
<li>An empty map</li>
+ <li>Defining a method 'public boolean isEmpty()'
+ that returns true when the instance is considered empty</li>
</ol>
- <source>empty(var1)</source>
+ This is false in other cases (besides errors).
+ <source>empty(arg)</source>
</td>
</tr>
<tr>
<td>size</td>
<td>
- Returns the information about the expression:
+ Evaluates the 'size' of an expression.
+ This returns:
<ol>
+ <li>0 if the argument is null</li>
+ <li>The result of calling a method from a derived JexlArithmetic overload 'public int size(C arg)',
+ C being the class of the argument</li>
<li>Length of an array</li>
- <li>Size of a List</li>
- <li>Size of a Map</li>
- <li>Size of a Set</li>
<li>Length of a string</li>
+ <li>Size of a Collection</li>
+ <li>Size of a Map</li>
+ <li>The result of calling a method 'public int size()' defined by the argument class</li>
</ol>
+ This returns 0 in other cases (besides errors).
<source>size("Hello")</source> returns 5.
</td>
</tr>
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java?rev=1690404&r1=1690403&r2=1690404&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java Sat Jul 11 20:41:09 2015
@@ -18,14 +18,19 @@ package org.apache.commons.jexl3;
import org.apache.commons.jexl3.junit.Asserter;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
-
import java.math.BigDecimal;
import java.math.BigInteger;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
@SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
public class ArithmeticTest extends JexlTestCase {
@@ -767,4 +772,65 @@ public class ArithmeticTest extends Jexl
evaluate = jexl.createExpression("math:abs(-42)").evaluate(null);
Assert.assertEquals(42, evaluate);
}
+
+ private static Document getDocument(String xml) throws Exception {
+ DocumentBuilder xmlBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ InputStream stringInputStream = new ByteArrayInputStream(xml.getBytes("UTF-8"));
+ return xmlBuilder.parse(stringInputStream);
+ }
+
+ public static class XmlArithmetic extends JexlArithmetic {
+ public XmlArithmetic(boolean lenient) {
+ super(lenient);
+ }
+ public boolean empty(org.w3c.dom.Element elt) {
+ return !elt.hasAttributes() && !elt.hasChildNodes();
+ }
+ public int size(org.w3c.dom.Element elt) {
+ return elt.getChildNodes().getLength();
+ }
+ }
+
+ @Test
+ public void testXmlArithmetic() throws Exception {
+ JexlEngine jexl = new JexlBuilder().arithmetic(new XmlArithmetic(false)).create();
+ JexlScript e0 = jexl.createScript("x.empty()", "x");
+ JexlScript e1 = jexl.createScript("empty(x)", "x");
+ JexlScript s0 = jexl.createScript("x.size()", "x");
+ JexlScript s1 = jexl.createScript("size(x)", "x");
+ Document xml;
+ Node x;
+ Boolean empty;
+ int size;
+ xml = getDocument("<node info='123'/>");
+ x = xml.getLastChild();
+ empty = (Boolean) e0.execute(null, x);
+ Assert.assertFalse(empty);
+ empty = (Boolean) e1.execute(null, x);
+ Assert.assertFalse(empty);
+ size = (Integer) s0.execute(null, x);
+ Assert.assertEquals(0, size);
+ size = (Integer) s1.execute(null, x);
+ Assert.assertEquals(0, size);
+ xml = getDocument("<node><a/><b/></node>");
+ x = xml.getLastChild();
+ empty = (Boolean) e0.execute(null, x);
+ Assert.assertFalse(empty);
+ empty = (Boolean) e1.execute(null, x);
+ Assert.assertFalse(empty);
+ size = (Integer) s0.execute(null, x);
+ Assert.assertEquals(2, size);
+ size = (Integer) s1.execute(null, x);
+ Assert.assertEquals(2, size);
+ xml = getDocument("<node/>");
+ x = xml.getLastChild();
+ empty = (Boolean) e0.execute(null, x);
+ Assert.assertTrue(empty);
+ empty = (Boolean) e1.execute(null, x);
+ Assert.assertTrue(empty);
+ size = (Integer) s0.execute(null, x);
+ Assert.assertEquals(0, size);
+ size = (Integer) s1.execute(null, x);
+ Assert.assertEquals(0, size);
+ }
}