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 2012/05/12 08:52:23 UTC
svn commit: r1337453 [1/3] - in /commons/proper/jexl/trunk: ./
src/main/java/org/apache/commons/jexl3/
src/main/java/org/apache/commons/jexl3/internal/
src/main/java/org/apache/commons/jexl3/internal/introspection/
src/main/java/org/apache/commons/jexl...
Author: henrib
Date: Sat May 12 06:52:21 2012
New Revision: 1337453
URL: http://svn.apache.org/viewvc?rev=1337453&view=rev
Log:
JEXL-123:
Reworked classloader change handling so that script ASTs purge references to cached methods & ctors;
Lots of nitpicking names, Javadoc, etc
Modified:
commons/proper/jexl/trunk/RELEASE-NOTES.txt
commons/proper/jexl/trunk/pom.xml
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlExpression.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlInfo.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Main.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.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/internal/Script.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Introspector.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/SandboxUberspect.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/JexlSandbox.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/JexlUberspect.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/package.html
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngineFactory.java
commons/proper/jexl/trunk/src/site/site.xml
commons/proper/jexl/trunk/src/site/xdoc/changes.xml
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JexlTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PropertyAccessTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/examples/MethodPropertyTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/Util.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/parser/ParserTest.java
commons/proper/jexl/trunk/src/test/scripts/test1.jexl
Modified: commons/proper/jexl/trunk/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/RELEASE-NOTES.txt?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/RELEASE-NOTES.txt (original)
+++ commons/proper/jexl/trunk/RELEASE-NOTES.txt Sat May 12 06:52:21 2012
@@ -36,35 +36,69 @@ Its goal is to expose scripting features
http://commons.apache.org/jexl/
-Due to binary and source incompatibilities and the scope of modifications, JEXL has moved to the org.apache.commons.jexl3
-package.
-Also note that JEXL now requires Java 6.
+========================================================================================================================
+Release 3.0
+========================================================================================================================
+
+Version 3.0 is a major release changing the public JEXL API.
+
+Due to binary and source incompatibilities and the scope of modifications, JEXL has moved to the
+org.apache.commons.jexl3 package.
However, this is a drop-in replacement through JSR-223 and casual code usage should find easy equivalence between
jexl-2.x and 3.x (besides the package name).
+Also note that JEXL 3.0 now requires Java 6.
-3.0
-==================
-
What's new in 3.0:
==================
* A redesigned API that properly segregates the "public" part and the "internal" parts of JEXL.
* The ability to create JEXL functions in script, closure/variables hoisting included.
New features in 3.0:
-====================
+====================
* JEXL-128: ObjectContext<> should implement NamespaceResolver
* JEXL-127: Allow the creation of functions
-* JEXL-126: Decimal numbers literals should be 'double' by default (instead of 'float')
* JEXL-123: Redesign API for stability
* JEXL-122: Move JEXL from org.apache.comms.jexl2 to org.apache.commons.jexl3
-Previous Releases:
-==================
+========================================================================================================================
+Release 2.1.2:
+========================================================================================================================
-2.1
-==================
+Version 2.1.2 is a micro release to fix few issues detected in 2.1.1:
+
+* JEXL-131: UnifiedJexl parsing may fail with NPE
+* JEXL-130: Ternary Conditional fails for Object values
+* JEXL-126: Decimal numbers literals should be 'double' by default (instead of 'float')
+
+There are no other changes.
+
+
+========================================================================================================================
+Release 2.1.1
+========================================================================================================================
+
+Version 2.1.2 is a micro release to fix a regression detected in 2.1:
+
+* JEXL-124: Array parameters to methods don't work anymore (Jexl 2.1.1)
+
+There are no other changes.
+
+
+========================================================================================================================
+Release 2.1
+========================================================================================================================
+
+Version 2.1 is a minor release adding new features and fixing known issues detected in 2.0.
+
+Compatibility with previous releases
+====================================
+Version 2.1 is binary compatible with 2.0.1.
+
+However it is not source compatible.
+New methods have been added to the org.apache.commons.jexl2.Script and org.apache.commons.jexl2.JexlInfo interfaces.
+Any source code that implements these interfaces will need to be updated.
What's new in 2.1:
==================
@@ -77,7 +111,7 @@ What's new in 2.1:
* Extensions to UnifiedJEXL that allow the creation of templates.
New features in 2.1:
-====================
+====================
* JEXL-114: Allow scripts to create local variables // Add return keyword
* JEXL-113: Add functions to extract which variables, parameters and local variables are used to evaluate a script
* JEXL-118: Provide an IN operator
@@ -97,7 +131,7 @@ Bugs Fixed in 2.1:
* JEXL-101: Vararg methods where the first argument is no vararg can not be called with only the fixed parameters given
* JEXL-105: Array literals are considered constant even when they are not
* JEXL-104: NPE in JexlArithmetic when an Array-Expression containing a null is used.
-* JEXL-112: Cannot parse Integer.MIN_VALUE
+* JEXL-112: Cannot parse Integer.MIN_VALUE
* JEXL-111: expression execute error
Bugs fixed in 2.0.1:
@@ -181,7 +215,7 @@ Other Changes:
o Add @since 2.0 tags to code so we can track API additions via Javadoc
-Upgrading from JEXL 1.x
+Upgrading from JEXL 1.x
=======================
JEXL now requires Java 1.5 or later.
Modified: commons/proper/jexl/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/pom.xml?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/pom.xml (original)
+++ commons/proper/jexl/trunk/pom.xml Sat May 12 06:52:21 2012
@@ -110,15 +110,6 @@
<version>4.10</version>
<scope>test</scope>
</dependency>
- <!-- For JSR-223 API -->
- <!--
- <dependency>
- <groupId>org.apache.bsf</groupId>
- <artifactId>bsf-api</artifactId>
- <version>3.1</version>
- <scope>provided</scope>
- </dependency>
- -->
</dependencies>
<properties>
@@ -128,6 +119,8 @@
<commons.release.version>3.0</commons.release.version>
<!-- The RC version used in the staging repository URL. -->
<commons.rc.version>RC1</commons.rc.version>
+ <commons.release.3.version>2.1</commons.release.3.version>
+ <commons.release.3.binary.suffix>2.1.1</commons.release.3.binary.suffix>
<commons.release.2.version>1.1</commons.release.2.version>
<commons.release.2.binary.suffix />
<commons.jira.id>JEXL</commons.jira.id>
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java Sat May 12 06:52:21 2012
@@ -28,7 +28,7 @@ import java.math.MathContext;
* The 5 arithmetic operators (+, - , *, /, %) follow the same evaluation rules regarding their arguments.
* <ol>
* <li>If both are null, result is 0</li>
- * <li>If either is a BigDecimal, coerce both to BigDecimal and perform operation</li>
+ * <li>If either is a BigDecimal, coerce both to BigDecimal and perform operation</li>
* <li>If either is a floating point number, coerce both to Double and perform operation</li>
* <li>Else treat as BigInteger, perform operation and attempt to narrow result:
* <ol>
@@ -43,6 +43,9 @@ import java.math.MathContext;
* @since 2.0
*/
public class JexlArithmetic {
+ /** Maker class for null operand exceptions. */
+ public static class NullOperand extends ArithmeticException {
+ }
/** Double.MAX_VALUE as BigDecimal. */
protected static final BigDecimal BIGD_DOUBLE_MAX_VALUE = BigDecimal.valueOf(Double.MAX_VALUE);
/** Double.MIN_VALUE as BigDecimal. */
@@ -70,14 +73,14 @@ public class JexlArithmetic {
/**
* Creates a JexlArithmetic.
- * @param astrict whether this arithmetic is lenient or strict
+ * @param astrict whether this arithmetic is lenient or strict
* @param bigdContext the math context instance to use for +,-,/,*,% operations on big decimals.
- * @param bigdScale the scale used for big decimals.
+ * @param bigdScale the scale used for big decimals.
*/
public JexlArithmetic(boolean astrict, MathContext bigdContext, int bigdScale) {
this.strict = astrict;
- this.mathContext = bigdContext == null? MathContext.DECIMAL128 : bigdContext;
- this.mathScale = bigdScale == Integer.MIN_VALUE? BIGD_SCALE : bigdScale;
+ this.mathContext = bigdContext == null ? MathContext.DECIMAL128 : bigdContext;
+ this.mathScale = bigdScale == Integer.MIN_VALUE ? BIGD_SCALE : bigdScale;
}
/**
@@ -98,8 +101,8 @@ public class JexlArithmetic {
bigdScale = mathScale;
}
if ((ostrict != this.strict)
- || bigdScale != this.mathScale
- || bigdContext != this.mathContext) {
+ || bigdScale != this.mathScale
+ || bigdContext != this.mathContext) {
return new JexlArithmetic(ostrict, bigdContext, bigdScale);
} else {
return this;
@@ -152,7 +155,7 @@ public class JexlArithmetic {
*/
protected Object controlNullNullOperands() {
if (isStrict()) {
- throw new ArithmeticException(JexlException.NULL_OPERAND);
+ throw new NullOperand();
}
return Integer.valueOf(0);
}
@@ -163,7 +166,7 @@ public class JexlArithmetic {
*/
protected void controlNullOperand() {
if (isStrict()) {
- throw new ArithmeticException(JexlException.NULL_OPERAND);
+ throw new NullOperand();
}
}
@@ -210,6 +213,21 @@ public class JexlArithmetic {
}
/**
+ * Given a Number, return back the value using the smallest type the result
+ * will fit into.
+ * <p>This works hand in hand with parameter 'widening' in java
+ * method calls, e.g. a call to substring(int,int) with an int and a long
+ * will fail, but a call to substring(int,int) with an int and a short will
+ * succeed.</p>
+ *
+ * @param original the original number.
+ * @return a value of the smallest type the original number will fit into.
+ */
+ public Number narrow(Number original) {
+ return narrowNumber(original, null);
+ }
+
+ /**
* Whether we consider the narrow class as a potential candidate for narrowing the source.
* @param narrow the target narrow class
* @param source the orginal source class
@@ -222,8 +240,8 @@ public class JexlArithmetic {
/**
* Given a Number, return back the value attempting to narrow it to a target class.
* @param original the original number
- * @param narrow the attempted target class
- * @return the narrowed number or the source if no narrowing was possible
+ * @param narrow the attempted target class
+ * @return the narrowed number or the source if no narrowing was possible
*/
public Number narrowNumber(Number original, Class<?> narrow) {
if (original == null) {
@@ -233,7 +251,8 @@ public class JexlArithmetic {
if (original instanceof BigDecimal) {
BigDecimal bigd = (BigDecimal) original;
// if it's bigger than a double it can't be narrowed
- if (bigd.compareTo(BIGD_DOUBLE_MAX_VALUE) > 0) {
+ if (bigd.compareTo(BIGD_DOUBLE_MAX_VALUE) > 0
+ || bigd.compareTo(BIGD_DOUBLE_MIN_VALUE) < 0) {
return original;
} else {
try {
@@ -251,7 +270,7 @@ public class JexlArithmetic {
}
}
}
- if (original instanceof Double || original instanceof Float || original instanceof BigDecimal) {
+ if (original instanceof Double || original instanceof Float) {
double value = original.doubleValue();
if (narrowAccept(narrow, Float.class)
&& value <= Float.MAX_VALUE
@@ -296,8 +315,8 @@ public class JexlArithmetic {
* if either arguments is a BigInteger, no narrowing will occur
* if either arguments is a Long, no narrowing to Integer will occur
* </p>
- * @param lhs the left hand side operand that lead to the bigi result
- * @param rhs the right hand side operand that lead to the bigi result
+ * @param lhs the left hand side operand that lead to the bigi result
+ * @param rhs the right hand side operand that lead to the bigi result
* @param bigi the BigInteger to narrow
* @return an Integer or Long if narrowing is possible, the original BigInteger otherwise
*/
@@ -323,8 +342,8 @@ public class JexlArithmetic {
* Given a BigDecimal, attempt to narrow it to an Integer or Long if it fits if
* one of the arguments is a numberable.
*
- * @param lhs the left hand side operand that lead to the bigd result
- * @param rhs the right hand side operand that lead to the bigd result
+ * @param lhs the left hand side operand that lead to the bigd result
+ * @param rhs the right hand side operand that lead to the bigd result
* @param bigd the BigDecimal to narrow
* @return an Integer or Long if narrowing is possible, the original BigInteger otherwise
*/
@@ -414,7 +433,7 @@ public class JexlArithmetic {
* Replace all numbers in an arguments array with the smallest type that will fit.
* @param args the argument array
* @return true if some arguments were narrowed and args array is modified,
- * false if no narrowing occured and args array has not been modified
+ * false if no narrowing occured and args array has not been modified
*/
public boolean narrowArguments(Object[] args) {
boolean narrowed = false;
@@ -437,45 +456,45 @@ public class JexlArithmetic {
* If any numeric add fails on coercion to the appropriate type,
* treat as Strings and do concatenation.
* </p>
- * @param left first value
+ * @param left first value
* @param right second value
* @return left + right.
*/
- public Object add(Object left, Object right) {
- if (left == null && right == null) {
- return controlNullNullOperands();
+ public Object add(Object left, Object right) {
+ if (left == null && right == null) {
+ return controlNullNullOperands();
+ }
+ try {
+ // if either are bigdecimal use that type
+ if (left instanceof BigDecimal || right instanceof BigDecimal) {
+ BigDecimal l = toBigDecimal(left);
+ BigDecimal r = toBigDecimal(right);
+ BigDecimal result = l.add(r, getMathContext());
+ return narrowBigDecimal(left, right, result);
}
- try {
- // if either are bigdecimal use that type
- if (left instanceof BigDecimal || right instanceof BigDecimal) {
- BigDecimal l = toBigDecimal(left);
- BigDecimal r = toBigDecimal(right);
- BigDecimal result = l.add(r, getMathContext());
- return narrowBigDecimal(left, right, result);
- }
- // if either are floating point (double or float) use double
- if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) {
- double l = toDouble(left);
- double r = toDouble(right);
- return new Double(l + r);
- }
- // otherwise treat as integers
- BigInteger l = toBigInteger(left);
- BigInteger r = toBigInteger(right);
- BigInteger result = l.add(r);
- return narrowBigInteger(left, right, result);
- } catch (java.lang.NumberFormatException nfe) {
- // Well, use strings!
- if (left == null || right == null) {
- controlNullOperand();
- }
- return toString(left).concat(toString(right));
+ // if either are floating point (double or float) use double
+ if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) {
+ double l = toDouble(left);
+ double r = toDouble(right);
+ return new Double(l + r);
+ }
+ // otherwise treat as integers
+ BigInteger l = toBigInteger(left);
+ BigInteger r = toBigInteger(right);
+ BigInteger result = l.add(r);
+ return narrowBigInteger(left, right, result);
+ } catch (java.lang.NumberFormatException nfe) {
+ // Well, use strings!
+ if (left == null || right == null) {
+ controlNullOperand();
}
+ return toString(left).concat(toString(right));
}
+ }
/**
* Divide the left value by the right.
- * @param left first value
+ * @param left first value
* @param right second value
* @return left / right
* @throws ArithmeticException if right == 0
@@ -490,7 +509,7 @@ public class JexlArithmetic {
BigDecimal r = toBigDecimal(right);
if (BigDecimal.ZERO.equals(r)) {
throw new ArithmeticException("/");
- }
+ }
BigDecimal result = l.divide(r, getMathContext());
return narrowBigDecimal(left, right, result);
}
@@ -508,14 +527,14 @@ public class JexlArithmetic {
BigInteger r = toBigInteger(right);
if (BigInteger.ZERO.equals(r)) {
throw new ArithmeticException("/");
- }
+ }
BigInteger result = l.divide(r);
return narrowBigInteger(left, right, result);
}
/**
* left value mod right.
- * @param left first value
+ * @param left first value
* @param right second value
* @return left mod right
* @throws ArithmeticException if right == 0.0
@@ -530,7 +549,7 @@ public class JexlArithmetic {
BigDecimal r = toBigDecimal(right);
if (BigDecimal.ZERO.equals(r)) {
throw new ArithmeticException("%");
- }
+ }
BigDecimal remainder = l.remainder(r, getMathContext());
return narrowBigDecimal(left, right, remainder);
}
@@ -549,13 +568,13 @@ public class JexlArithmetic {
BigInteger result = l.mod(r);
if (BigInteger.ZERO.equals(r)) {
throw new ArithmeticException("%");
- }
+ }
return narrowBigInteger(left, right, result);
}
/**
* Multiply the left value by the right.
- * @param left first value
+ * @param left first value
* @param right second value
* @return left * right.
*/
@@ -585,7 +604,7 @@ public class JexlArithmetic {
/**
* Subtract the right value from the left.
- * @param left first value
+ * @param left first value
* @param right second value
* @return left - right.
*/
@@ -652,7 +671,7 @@ public class JexlArithmetic {
/**
* Test if left regexp matches right.
*
- * @param left first value
+ * @param left first value
* @param right second value
* @return test result.
*/
@@ -675,7 +694,7 @@ public class JexlArithmetic {
/**
* Performs a bitwise and.
- * @param left the left operand
+ * @param left the left operand
* @param right the right operator
* @return left & right
*/
@@ -687,7 +706,7 @@ public class JexlArithmetic {
/**
* Performs a bitwise or.
- * @param left the left operand
+ * @param left the left operand
* @param right the right operator
* @return left | right
*/
@@ -699,9 +718,9 @@ public class JexlArithmetic {
/**
* Performs a bitwise xor.
- * @param left the left operand
+ * @param left the left operand
* @param right the right operator
- * @return left right
+ * @return left right
*/
public Object bitwiseXor(Object left, Object right) {
long l = toLong(left);
@@ -721,10 +740,10 @@ public class JexlArithmetic {
/**
* Performs a comparison.
- * @param left the left operand
- * @param right the right operator
+ * @param left the left operand
+ * @param right the right operator
* @param operator the operator
- * @return -1 if left < right; +1 if left > > right; 0 if left == right
+ * @return -1 if left < right; +1 if left > > right; 0 if left == right
* @throws ArithmeticException if either left or right is null
*/
protected int compare(Object left, Object right, String operator) {
@@ -786,7 +805,7 @@ public class JexlArithmetic {
/**
* Test if left and right are equal.
*
- * @param left first value
+ * @param left first value
* @param right second value
* @return test result.
*/
@@ -803,9 +822,9 @@ public class JexlArithmetic {
}
/**
- * Test if left < right.
+ * Test if left < right.
*
- * @param left first value
+ * @param left first value
* @param right second value
* @return test result.
*/
@@ -819,9 +838,9 @@ public class JexlArithmetic {
}
/**
- * Test if left > right.
+ * Test if left > right.
*
- * @param left first value
+ * @param left first value
* @param right second value
* @return test result.
*/
@@ -834,9 +853,9 @@ public class JexlArithmetic {
}
/**
- * Test if left <= right.
+ * Test if left <= right.
*
- * @param left first value
+ * @param left first value
* @param right second value
* @return test result.
*/
@@ -851,9 +870,9 @@ public class JexlArithmetic {
}
/**
- * Test if left >= right.
+ * Test if left >= right.
*
- * @param left first value
+ * @param left first value
* @param right second value
* @return test result.
*/
@@ -868,7 +887,8 @@ public class JexlArithmetic {
}
/**
- * Coerce to a boolean (not a java.lang.Boolean).
+ * Coerce to a primitive boolean.
+ * <p>Double.NaN, null, "false" and empty string coerce to false.</p>
*
* @param val Object to be coerced.
* @return the boolean value if coercion is possible, true if value was not null.
@@ -892,20 +912,24 @@ public class JexlArithmetic {
}
/**
- * Coerce to a int.
+ * Coerce to a primitive int.
+ * <p>Double.NaN, null and empty string coerce to zero.</p>
+ * <p>Boolean false is 0, true is 1.</p>
*
* @param val Object to be coerced.
* @return The int coerced value.
+ * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
*/
public int toInteger(Object val) {
if (val == null) {
controlNullOperand();
return 0;
} else if (val instanceof Double) {
- if (!Double.isNaN(((Double) val).doubleValue())) {
+ Double dval = (Double) val;
+ if (Double.isNaN(dval.doubleValue())) {
return 0;
} else {
- return ((Double) val).intValue();
+ return dval.intValue();
}
} else if (val instanceof Number) {
return ((Number) val).intValue();
@@ -925,26 +949,30 @@ public class JexlArithmetic {
}
/**
- * Coerce to a long (not a java.lang.Long).
+ * Coerce to a primitive long.
+ * <p>Double.NaN, null and empty string coerce to zero.</p>
+ * <p>Boolean false is 0, true is 1.</p>
*
* @param val Object to be coerced.
* @return The long coerced value.
+ * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
*/
public long toLong(Object val) {
if (val == null) {
controlNullOperand();
return 0L;
} else if (val instanceof Double) {
- if (!Double.isNaN(((Double) val).doubleValue())) {
- return 0;
+ Double dval = (Double) val;
+ if (Double.isNaN(dval.doubleValue())) {
+ return 0L;
} else {
- return ((Double) val).longValue();
+ return dval.longValue();
}
} else if (val instanceof Number) {
return ((Number) val).longValue();
} else if (val instanceof String) {
if ("".equals(val)) {
- return 0;
+ return 0L;
} else {
return Long.parseLong((String) val);
}
@@ -959,11 +987,13 @@ public class JexlArithmetic {
}
/**
- * Get a BigInteger from the object passed.
- * Null and empty string maps to zero.
+ * Coerce to a BigInteger.
+ * <p>Double.NaN, null and empty string coerce to zero.</p>
+ * <p>Boolean false is 0, true is 1.</p>
+ *
* @param val the object to be coerced.
* @return a BigDecimal.
- * @throws NullPointerException if val is null and mode is strict.
+ * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
*/
public BigInteger toBigInteger(Object val) {
if (val == null) {
@@ -972,10 +1002,11 @@ public class JexlArithmetic {
} else if (val instanceof BigInteger) {
return (BigInteger) val;
} else if (val instanceof Double) {
- if (!Double.isNaN(((Double) val).doubleValue())) {
- return new BigInteger(val.toString());
- } else {
+ Double dval = (Double) val;
+ if (Double.isNaN(dval.doubleValue())) {
return BigInteger.ZERO;
+ } else {
+ return new BigInteger(dval.toString());
}
} else if (val instanceof Number) {
return new BigInteger(val.toString());
@@ -996,11 +1027,13 @@ public class JexlArithmetic {
}
/**
- * Get a BigDecimal from the object passed.
- * Null and empty string maps to zero.
+ * Coerce to a BigDecimal.
+ * <p>Double.NaN, null and empty string coerce to zero.</p>
+ * <p>Boolean false is 0, true is 1.</p>
+ *
* @param val the object to be coerced.
* @return a BigDecimal.
- * @throws NullPointerException if val is null and mode is strict.
+ * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
*/
public BigDecimal toBigDecimal(Object val) {
if (val instanceof BigDecimal) {
@@ -1015,10 +1048,10 @@ public class JexlArithmetic {
}
return roundBigDecimal(new BigDecimal(string, getMathContext()));
} else if (val instanceof Double) {
- if (!Double.isNaN(((Double) val).doubleValue())) {
- return roundBigDecimal(new BigDecimal(val.toString(), getMathContext()));
- } else {
+ if (Double.isNaN(((Double) val).doubleValue())) {
return BigDecimal.ZERO;
+ } else {
+ return roundBigDecimal(new BigDecimal(val.toString(), getMathContext()));
}
} else if (val instanceof Number) {
return roundBigDecimal(new BigDecimal(val.toString(), getMathContext()));
@@ -1026,17 +1059,17 @@ public class JexlArithmetic {
int i = ((Character) val).charValue();
return new BigDecimal(i);
}
-
throw new ArithmeticException("BigDecimal coercion: "
+ val.getClass().getName() + ":(" + val + ")");
}
/**
- * Coerce to a double.
- *
+ * Coerce to a primitive double.
+ * <p>Double.NaN, null and empty string coerce to zero.</p>
+ * <p>Boolean false is 0, true is 1.</p>
* @param val Object to be coerced.
* @return The double coerced value.
- * @throws NullPointerException if val is null and mode is strict.
+ * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
*/
public double toDouble(Object val) {
if (val == null) {
@@ -1062,17 +1095,17 @@ public class JexlArithmetic {
int i = ((Character) val).charValue();
return i;
}
-
throw new ArithmeticException("Double coercion: "
+ val.getClass().getName() + ":(" + val + ")");
}
/**
* Coerce to a string.
+ * <p>Double.NaN coerce to the empty string.</p>
*
* @param val Object to be coerced.
* @return The String coerced value.
- * @throws NullPointerException if val is null and mode is strict.
+ * @throws ArithmeticException if val is null and mode is strict or if coercion is not possible.
*/
public String toString(Object val) {
if (val == null) {
@@ -1089,18 +1122,4 @@ public class JexlArithmetic {
return val.toString();
}
}
-
- /**
- * Given a Number, return back the value using the smallest type the result
- * will fit into. This works hand in hand with parameter 'widening' in java
- * method calls, e.g. a call to substring(int,int) with an int and a long
- * will fail, but a call to substring(int,int) with an int and a short will
- * succeed.
- *
- * @param original the original number.
- * @return a value of the smallest type the original number will fit into.
- */
- public Number narrow(Number original) {
- return narrowNumber(original, null);
- }
}
\ No newline at end of file
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java Sat May 12 06:52:21 2012
@@ -54,6 +54,10 @@ import org.apache.commons.logging.Log;
*/
public class JexlBuilder {
/**
+ * The default maximum expression length to hit the expression cache.
+ */
+ protected static final int CACHE_THRESHOLD = 64;
+ /**
* The JexlUberspect instance.
*/
protected JexlUberspect uberspect = null;
@@ -91,6 +95,10 @@ public class JexlBuilder {
*/
protected int cache = -1;
/**
+ * The maximum expression length to hit the expression cache.
+ */
+ protected int cacheThreshold = CACHE_THRESHOLD;
+ /**
* The class loader.
*/
protected ClassLoader loader = null;
@@ -124,7 +132,7 @@ public class JexlBuilder {
public JexlArithmetic arithmetic() {
return this.arithmetic;
}
-
+
/**
* Sets the sandbox the engine will use.
* @param box the sandbox
@@ -134,7 +142,7 @@ public class JexlBuilder {
this.sandbox = box;
return this;
}
-
+
/** @return the sandbox */
public JexlSandbox sandbox() {
return this.sandbox;
@@ -154,7 +162,7 @@ public class JexlBuilder {
public Log logger() {
return this.logger;
}
-
+
/**
* Sets the class loader to use.
* @param l the class loader
@@ -164,7 +172,7 @@ public class JexlBuilder {
this.loader = l;
return this;
}
-
+
/** @return the class loader */
public ClassLoader loader() {
return loader;
@@ -254,8 +262,8 @@ public class JexlBuilder {
/**
* Sets the expression cache size the engine will use.
- * <p>The cache will contain at most <code>size</code> expressions. Note that
- * all JEXL caches are held through SoftReferences and may be garbage-collected.</p>
+ * <p>The cache will contain at most <code>size</code> expressions of at most <code>cacheThreshold</code> length.
+ * Note that all JEXL caches are held through SoftReferences and may be garbage-collected.</p>
* @param size if not strictly positive, no cache is used.
* @return this builder
*/
@@ -270,6 +278,25 @@ public class JexlBuilder {
}
/**
+ * Sets the maximum length for an expression to be cached.
+ * <p>Expression whose length is greater than this expression cache length threshold will
+ * bypass the cache.</p>
+ * <p>It is expected that a "long" script will be parsed once and its reference kept
+ * around in user-space structures; the jexl expression cache has no added-value in this case.</p>
+ * @param length if not strictly positive, the value is silently replaced by the default value (64).
+ * @return this builder
+ */
+ public JexlBuilder cacheThreshold(int length) {
+ this.cacheThreshold = length > 0? length : CACHE_THRESHOLD;
+ return this;
+ }
+
+ /**@return the cache threshold */
+ public int cacheThreshold() {
+ return cacheThreshold;
+ }
+
+ /**
* @return a {@link JexlEngine} instance
*/
public JexlEngine create() {
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java Sat May 12 06:52:21 2012
@@ -16,22 +16,24 @@
*/
package org.apache.commons.jexl3;
+import org.apache.commons.jexl3.introspection.JexlUberspect;
+
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileReader;
import java.io.IOException;
-import java.io.Reader;
-import java.net.URL;
+import java.io.InputStreamReader;
import java.math.MathContext;
-import org.apache.commons.jexl3.introspection.JexlUberspect;
+import java.net.URL;
/**
* Creates and evaluates JexlExpression and JexlScript objects.
* Determines the behavior of expressions & scripts during their evaluation with respect to:
* <ul>
- * <li>Introspection, see {@link JexlUberspect}</li>
- * <li>Arithmetic & comparison, see {@link JexlArithmetic}</li>
- * <li>Error reporting</li>
- * <li>Logging</li>
+ * <li>Introspection, see {@link JexlUberspect}</li>
+ * <li>Arithmetic & comparison, see {@link JexlArithmetic}</li>
+ * <li>Error reporting</li>
+ * <li>Logging</li>
* </ul>
* <p>
* Note that methods that evaluate expressions may throw <em>unchecked</em> exceptions;
@@ -131,83 +133,145 @@ public abstract class JexlEngine {
* Creates an JexlExpression from a String containing valid JEXL syntax.
* This method parses the expression which must contain either a reference or an expression.
*
+ * @param info An info structure to carry debugging information if needed
* @param expression A String containing valid JEXL syntax
* @return An {@link JexlExpression} which can be evaluated using a {@link JexlContext}
- * @throws JexlException An exception can be thrown if there is a problem parsing this expression, or if the
- * expression is neither an expression nor a reference.
+ * @throws JexlException if there is a problem parsing the script
*/
- public abstract JexlExpression createExpression(String expression);
+ public abstract JexlExpression createExpression(JexlInfo info, String expression);
/**
- * Creates an JexlExpression from a String containing valid JEXL syntax.
- * This method parses the expression which must contain either a reference or an expression.
+ * Creates a JexlScript from a String containing valid JEXL syntax.
+ * This method parses the script and validates the syntax.
+ *
+ * @param info An info structure to carry debugging information if needed
+ * @param source A string containing valid JEXL syntax
+ * @param names The script parameter names used during parsing; a corresponding array of arguments containing
+ * values should be used during evaluation
+ * @return A {@link JexlScript} which can be executed using a {@link JexlContext}
+ * @throws JexlException if there is a problem parsing the script
+ */
+ public abstract JexlScript createScript(JexlInfo info, String source, String[] names);
+
+ /**
+ * Creates a JexlExpression from a String containing valid JEXL syntax.
+ * This method parses the expression which must contain either a reference or an expression.
*
* @param expression A String containing valid JEXL syntax
- * @param info An info structure to carry debugging information if needed
* @return An {@link JexlExpression} which can be evaluated using a {@link JexlContext}
- * @throws JexlException An exception can be thrown if there is a problem parsing this expression, or if the
- * expression is neither an expression or a reference.
+ * @throws JexlException if there is a problem parsing the script
*/
- public abstract JexlExpression createExpression(String expression, JexlInfo info);
+ public final JexlExpression createExpression(String expression) {
+ return createExpression(null, expression);
+ }
/**
* Creates a Script from a String containing valid JEXL syntax.
- * This method parses the script which validates the syntax.
+ * This method parses the script and validates the syntax.
*
* @param scriptText A String containing valid JEXL syntax
* @return A {@link JexlScript} which can be executed using a {@link JexlContext}
* @throws JexlException if there is a problem parsing the script.
*/
- public abstract JexlScript createScript(String scriptText);
+ public final JexlScript createScript(String scriptText) {
+ return createScript(null, scriptText, null);
+ }
/**
* Creates a Script from a String containing valid JEXL syntax.
- * This method parses the script which validates the syntax.
+ * This method parses the script and validates the syntax.
*
* @param scriptText A String containing valid JEXL syntax
- * @param names the script parameter names
+ * @param names The script parameter names used during parsing; a corresponding array of arguments containing
+ * values should be used during evaluation
* @return A {@link JexlScript} which can be executed using a {@link JexlContext}
- * @throws JexlException if there is a problem parsing the script.
+ * @throws JexlException if there is a problem parsing the script
*/
- public abstract JexlScript createScript(String scriptText, String... names);
+ public final JexlScript createScript(String scriptText, String... names) {
+ return createScript(null, scriptText, names);
+ }
/**
- * Creates a Script from a String containing valid JEXL syntax.
- * This method parses the script which validates the syntax.
- * It uses an array of parameter names that will be resolved during parsing;
- * a corresponding array of arguments containing values should be used during evaluation.
+ * Creates a Script from a {@link File} containing valid JEXL syntax.
+ * This method parses the script and validates the syntax.
*
- * @param scriptText A String containing valid JEXL syntax
- * @param info An info structure to carry debugging information if needed
- * @param names the script parameter names
- * @return A {@link JexlScript} which can be executed using a {@link JexlContext}
- * @throws JexlException if there is a problem parsing the script.
+ * @param scriptFile A {@link File} containing valid JEXL syntax. Must not be null. Must be a readable file.
+ * @return A {@link JexlScript} which can be executed with a {@link JexlContext}.
+ * @throws JexlException if there is a problem reading or parsing the script.
*/
- public abstract JexlScript createScript(String scriptText, JexlInfo info, String[] names);
+ public final JexlScript createScript(File scriptFile) {
+ return createScript(null, readSource(scriptFile), null);
+ }
/**
* Creates a Script from a {@link File} containing valid JEXL syntax.
* This method parses the script and validates the syntax.
*
* @param scriptFile A {@link File} containing valid JEXL syntax. Must not be null. Must be a readable file.
- * @return A {@link JexlScript} which can be executed with a
- * {@link JexlContext}.
- * @throws IOException if there is a problem reading the script.
- * @throws JexlException if there is a problem parsing the script.
+ * @param names The script parameter names used during parsing; a corresponding array of arguments containing
+ * values should be used during evaluation.
+ * @return A {@link JexlScript} which can be executed with a {@link JexlContext}.
+ * @throws JexlException if there is a problem reading or parsing the script.
*/
- public abstract JexlScript createScript(File scriptFile) throws IOException;
+ public final JexlScript createScript(File scriptFile, String... names) {
+ return createScript(null, readSource(scriptFile), names);
+ }
+
+ /**
+ * Creates a Script from a {@link File} containing valid JEXL syntax.
+ * This method parses the script and validates the syntax.
+ *
+ * @param info An info structure to carry debugging information if needed
+ * @param scriptFile A {@link File} containing valid JEXL syntax. Must not be null. Must be a readable file.
+ * @param names The script parameter names used during parsing; a corresponding array of arguments containing
+ * values should be used during evaluation.
+ * @return A {@link JexlScript} which can be executed with a {@link JexlContext}.
+ * @throws JexlException if there is a problem reading or parsing the script.
+ */
+ public final JexlScript createScript(JexlInfo info, File scriptFile, String[] names) {
+ return createScript(info, readSource(scriptFile), names);
+ }
/**
* Creates a Script from a {@link URL} containing valid JEXL syntax.
* This method parses the script and validates the syntax.
*
- * @param scriptUrl A {@link URL} containing valid JEXL syntax. Must not be null. Must be a readable file.
- * @return A {@link JexlScript} which can be executed with a
- * {@link JexlContext}.
- * @throws IOException if there is a problem reading the script.
- * @throws JexlException if there is a problem parsing the script.
+ * @param scriptUrl A {@link URL} containing valid JEXL syntax. Must not be null.
+ * @return A {@link JexlScript} which can be executed with a {@link JexlContext}.
+ * @throws JexlException if there is a problem reading or parsing the script.
+ */
+ public final JexlScript createScript(URL scriptUrl) {
+ return createScript(null, readSource(scriptUrl), null);
+ }
+
+ /**
+ * Creates a Script from a {@link URL} containing valid JEXL syntax.
+ * This method parses the script and validates the syntax.
+ *
+ * @param scriptUrl A {@link URL} containing valid JEXL syntax. Must not be null.
+ * @param names The script parameter names used during parsing; a corresponding array of arguments containing
+ * values should be used during evaluation.
+ * @return A {@link JexlScript} which can be executed with a {@link JexlContext}.
+ * @throws JexlException if there is a problem reading or parsing the script.
+ */
+ public final JexlScript createScript(URL scriptUrl, String[] names) {
+ return createScript(null, readSource(scriptUrl), names);
+ }
+
+ /**
+ * Creates a Script from a {@link URL} containing valid JEXL syntax.
+ * This method parses the script and validates the syntax.
+ *
+ * @param info An info structure to carry debugging information if needed
+ * @param scriptUrl A {@link URL} containing valid JEXL syntax. Must not be null.
+ * @param names The script parameter names used during parsing; a corresponding array of arguments containing
+ * values should be used during evaluation.
+ * @return A {@link JexlScript} which can be executed with a {@link JexlContext}.
+ * @throws JexlException if there is a problem reading or parsing the script.
*/
- public abstract JexlScript createScript(URL scriptUrl) throws IOException;
+ public final JexlScript createScript(JexlInfo info, URL scriptUrl, String[] names) {
+ return createScript(info, readSource(scriptUrl), names);
+ }
/**
* Accesses properties of a bean using an expression.
@@ -233,8 +297,8 @@ public abstract class JexlEngine {
* </p>
*
* @param context the evaluation context
- * @param bean the bean to get properties from
- * @param expr the property expression
+ * @param bean the bean to get properties from
+ * @param expr the property expression
* @return the value of the property
* @throws JexlException if there is an error parsing the expression or during evaluation
*/
@@ -250,8 +314,8 @@ public abstract class JexlEngine {
* If the JEXL engine is silent, errors will be logged through its logger as warning.
* </p>
*
- * @param bean the bean to set properties in
- * @param expr the property expression
+ * @param bean the bean to set properties in
+ * @param expr the property expression
* @param value the value of the property
* @throws JexlException if there is an error parsing the expression or during evaluation
*/
@@ -262,16 +326,16 @@ public abstract class JexlEngine {
* its logger as warning. </p>
*
* @param context the evaluation context
- * @param bean the bean to set properties in
- * @param expr the property expression
- * @param value the value of the property
+ * @param bean the bean to set properties in
+ * @param expr the property expression
+ * @param value the value of the property
* @throws JexlException if there is an error parsing the expression or during evaluation
*/
public abstract void setProperty(JexlContext context, Object bean, String expr, Object value);
/**
* Invokes an object's method by name and arguments.
- * @param obj the method's invoker object
+ * @param obj the method's invoker object
* @param meth the method's name
* @param args the method's arguments
* @return the method returned value or null if it failed and engine is silent
@@ -281,9 +345,9 @@ public abstract class JexlEngine {
/**
* Creates a new instance of an object using the most appropriate constructor based on the arguments.
- * @param <T> the type of object
+ * @param <T> the type of object
* @param clazz the class to instantiate
- * @param args the constructor arguments
+ * @param args the constructor arguments
* @return the created object instance or null on failure when silent
*/
public abstract <T> T newInstance(Class<? extends T> clazz, Object... args);
@@ -291,63 +355,118 @@ public abstract class JexlEngine {
/**
* Creates a new instance of an object using the most appropriate constructor based on the arguments.
* @param clazz the name of the class to instantiate resolved through this engine's class loader
- * @param args the constructor arguments
+ * @param args the constructor arguments
* @return the created object instance or null on failure when silent
*/
public abstract Object newInstance(String clazz, Object... args);
/**
- * Trims the expression from front & ending spaces.
- * @param str expression to clean
- * @return trimmed expression ending in a semi-colon
- */
- public static String cleanExpression(CharSequence str) {
- if (str != null) {
- int start = 0;
- int end = str.length();
- if (end > 0) {
- // trim front spaces
- while (start < end && str.charAt(start) == ' ') {
- ++start;
- }
- // trim ending spaces
- while (end > 0 && str.charAt(end - 1) == ' ') {
- --end;
+ * Creates a JexlInfo instance.
+ * @param fn url/file/template/script user given name
+ * @param l line number
+ * @param c column number
+ * @return a JexlInfo instance
+ */
+ protected JexlInfo createInfo(String fn, int l, int c) {
+ return new JexlInfo(fn, l, c);
+ }
+
+ /**
+ * Create an information structure for dynamic set/get/invoke/new.
+ * <p>This gathers the class, method and line number of the first calling method
+ * outside of o.a.c.jexl3.</p>
+ * @return a JexlInfo instance
+ */
+ protected JexlInfo createInfo() {
+ JexlInfo info = null;
+ Throwable xinfo = new Throwable();
+ xinfo.fillInStackTrace();
+ StackTraceElement[] stack = xinfo.getStackTrace();
+ StackTraceElement se = null;
+ String name = getClass().getName();
+ for (int s = 1; s < stack.length; ++s) {
+ se = stack[s];
+ String className = se.getClassName();
+ if (!className.equals(name)) {
+ // go deeper if called from jexl3 implementation classes
+ if (className.startsWith("org.apache.commons.jexl3.internal.")
+ || className.startsWith("org.apache.commons.jexl3.J")) {
+ name = className;
+ } else {
+ break;
}
- return str.subSequence(start, end).toString();
}
- return "";
}
- return null;
+ if (se != null) {
+ info = createInfo(se.getClassName() + "." + se.getMethodName(), se.getLineNumber(), 0);
+ }
+ return info;
}
/**
- * Read from a reader into a local buffer and return a String with the contents of the reader.
- * @param scriptReader to be read.
+ * Creates a string from a reader.
+ * @param reader to be read.
* @return the contents of the reader as a String.
* @throws IOException on any error reading the reader.
*/
- public static String readerToString(Reader scriptReader) throws IOException {
+ protected static String toString(BufferedReader reader) throws IOException {
StringBuilder buffer = new StringBuilder();
- BufferedReader reader;
- if (scriptReader instanceof BufferedReader) {
- reader = (BufferedReader) scriptReader;
- } else {
- reader = new BufferedReader(scriptReader);
+ String line;
+ while ((line = reader.readLine()) != null) {
+ buffer.append(line).append('\n');
}
+ return buffer.toString();
+ }
+
+ /**
+ * Reads a Jexl source from a File.
+ * @param file the script file
+ * @return the source
+ */
+ protected String readSource(final File file) {
+ if (file == null) {
+ throw new NullPointerException("source file is null");
+ }
+ BufferedReader reader = null;
try {
- String line;
- while ((line = reader.readLine()) != null) {
- buffer.append(line).append('\n');
- }
- return buffer.toString();
+ reader = new BufferedReader(new FileReader(file));
+ return toString(reader);
+ } catch (IOException xio) {
+ throw new JexlException(createInfo(file.toString(), 1, 1), "could not read source File", xio);
} finally {
- try {
- reader.close();
- } catch (IOException xio) {
- // ignore
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException xignore) {
+ // cant to much
+ }
}
}
+ }
+ /**
+ * Reads a Jexl source from an URL.
+ * @param url the script url
+ * @return the source
+ */
+ protected String readSource(final URL url) {
+ if (url == null) {
+ throw new NullPointerException("source URL is null");
+ }
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(url.openStream()));
+ return toString(reader);
+ } catch (IOException xio) {
+ throw new JexlException(createInfo(url.toString(), 1, 1), "could not read source URL", xio);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException xignore) {
+ // cant to much
+ }
+ }
+ }
}
}
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=1337453&r1=1337452&r2=1337453&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 May 12 06:52:21 2012
@@ -35,17 +35,13 @@ public class JexlException extends Runti
private final transient JexlNode mark;
/** The debug info. */
private final transient JexlInfo info;
- /** A marker to use in NPEs stating a null operand error. */
- public static final String NULL_OPERAND = "jexl.null";
- /** Minimum number of characters around exception location. */
- private static final int MIN_EXCHARLOC = 10;
/** Maximum number of characters around exception location. */
- private static final int MAX_EXCHARLOC = 15;
+ private static final int MAX_EXCHARLOC = 32;
/**
* Creates a new JexlException.
* @param node the node causing the error
- * @param msg the error message
+ * @param msg the error message
*/
public JexlException(JexlNode node, String msg) {
this(node, msg, null);
@@ -53,28 +49,28 @@ public class JexlException extends Runti
/**
* Creates a new JexlException.
- * @param node the node causing the error
- * @param msg the error message
+ * @param node the node causing the error
+ * @param msg the error message
* @param cause the exception causing the error
*/
public JexlException(JexlNode node, String msg, Throwable cause) {
- this(node != null ? node.jexlInfo() : null, msg, cause);
+ this(node != null ? node.jexlInfo() : null, msg != null ? msg : "", cause);
}
/**
* Creates a new JexlException.
* @param jinfo the debugging information associated
- * @param msg the error message
+ * @param msg the error message
* @param cause the exception causing the error
*/
public JexlException(JexlInfo jinfo, String msg, Throwable cause) {
- super(msg, clean(unwrap(cause)));
+ super(msg, unwrap(cause));
mark = null;
info = jinfo;
}
/**
- * Cleans a JexlException from any org.apache.commons.jexl3 stack trace element.
+ * Cleans a JexlException from any org.apache.commons.jexl3.internal stack trace element.
* @return this exception
*/
public JexlException clean() {
@@ -82,8 +78,8 @@ public class JexlException extends Runti
}
/**
- * Cleans a Throwable from any org.apache.commons.jexl3 stack trace element.
- * @param <X> the throwable type
+ * Cleans a Throwable from any org.apache.commons.jexl3.internal stack trace element.
+ * @param <X> the throwable type
* @param xthrow the thowable
* @return the throwable
*/
@@ -91,11 +87,11 @@ public class JexlException extends Runti
if (xthrow != null) {
StackTraceElement[] stack = xthrow.getStackTrace();
List<StackTraceElement> stackJexl = new ArrayList<StackTraceElement>();
- stackJexl.add(stack[0]);
- for (int s = 1; s < stack.length; ++s) {
+ for (int s = 0; s < stack.length; ++s) {
StackTraceElement se = stack[s];
String className = se.getClassName();
- if (!className.startsWith("org.apache.commons.jexl3")) {
+ if (!className.startsWith("org.apache.commons.jexl3.internal")
+ && !className.startsWith("org.apache.commons.jexl3.parser")) {
stackJexl.add(se);
}
}
@@ -121,7 +117,7 @@ public class JexlException extends Runti
/**
* Accesses detailed message.
- * @return the message
+ * @return the message
*/
protected String detailedMessage() {
return super.getMessage();
@@ -130,21 +126,21 @@ public class JexlException extends Runti
/**
* Formats an error message from the parser.
* @param prefix the prefix to the message
- * @param expr the expression in error
+ * @param expr the expression in error
* @return the formatted message
*/
protected String parserError(String prefix, String expr) {
- int begin = info.getColumn();
- int end = begin + MIN_EXCHARLOC;
- begin -= MIN_EXCHARLOC;
- if (begin < 0) {
- end += MIN_EXCHARLOC;
- begin = 0;
- }
int length = expr.length();
if (length < MAX_EXCHARLOC) {
return prefix + " error in '" + expr + "'";
} else {
+ int begin = info.getColumn();
+ int end = begin + (MAX_EXCHARLOC / 2);
+ begin -= (MAX_EXCHARLOC / 2);
+ if (begin < 0) {
+ end -= begin;
+ begin = 0;
+ }
return prefix + " error near '... "
+ expr.substring(begin, end > length ? length : end) + " ...'";
}
@@ -157,17 +153,16 @@ public class JexlException extends Runti
public static class Tokenization extends JexlException {
/**
* Creates a new Tokenization exception instance.
- * @param info the location info
- * @param expr the expression
+ * @param info the location info
* @param cause the javacc cause
*/
- public Tokenization(JexlInfo info, CharSequence expr, TokenMgrError cause) {
- super(merge(info, cause), expr.toString(), cause);
+ public Tokenization(JexlInfo info, TokenMgrError cause) {
+ super(merge(info, cause), cause.getAfter(), null);
}
/**
* Merge the node info and the cause info to obtain best possible location.
- * @param info the node
+ * @param info the node
* @param cause the cause
* @return the info to use
*/
@@ -183,15 +178,15 @@ public class JexlException extends Runti
}
/**
- * @return the expression
+ * @return the last good token
*/
- public String getExpression() {
+ public String getDetail() {
return super.detailedMessage();
}
@Override
protected String detailedMessage() {
- return parserError("tokenization", getExpression());
+ return parserError("tokenization", getDetail());
}
}
@@ -202,17 +197,25 @@ public class JexlException extends Runti
public static class Parsing extends JexlException {
/**
* Creates a new Variable exception instance.
- * @param info the location information
- * @param expr the offending source
+ * @param info the location information
* @param cause the javacc cause
*/
- public Parsing(JexlInfo info, CharSequence expr, ParseException cause) {
- super(merge(info, cause), expr.toString(), cause);
+ public Parsing(JexlInfo info, ParseException cause) {
+ super(merge(info, cause), cause.getAfter(), null);
}
/**
- * Merge the node info and the cause info to obtain best possible location.
+ * Creates a new Variable exception instance.
* @param info the location information
+ * @param msg the message
+ */
+ public Parsing(JexlInfo info, String msg) {
+ super(info, msg, null);
+ }
+
+ /**
+ * Merge the node info and the cause info to obtain best possible location.
+ * @param info the location information
* @param cause the cause
* @return the info to use
*/
@@ -228,19 +231,15 @@ public class JexlException extends Runti
}
/**
- * @return the expression
+ * @return the last good token
*/
- public String getExpression() {
+ public String getDetail() {
return super.detailedMessage();
}
@Override
protected String detailedMessage() {
- if (getCause() == null) {
- return getExpression();
- } else {
- return parserError("parsing", getExpression());
- }
+ return parserError("parsing", getDetail());
}
}
@@ -252,7 +251,7 @@ public class JexlException extends Runti
/**
* Creates a new Variable exception instance.
* @param node the offending ASTnode
- * @param var the unknown variable
+ * @param var the unknown variable
*/
public Variable(JexlNode node, String var) {
super(node, var, null);
@@ -279,7 +278,7 @@ public class JexlException extends Runti
/**
* Creates a new Property exception instance.
* @param node the offending ASTnode
- * @param var the unknown variable
+ * @param var the unknown variable
*/
public Property(JexlNode node, String var) {
this(node, var, null);
@@ -287,8 +286,8 @@ public class JexlException extends Runti
/**
* Creates a new Property exception instance.
- * @param node the offending ASTnode
- * @param var the unknown variable
+ * @param node the offending ASTnode
+ * @param var the unknown variable
* @param cause the exception causing the error
*/
public Property(JexlNode node, String var, Throwable cause) {
@@ -315,8 +314,8 @@ public class JexlException extends Runti
public static class Method extends JexlException {
/**
* Creates a new Method exception instance.
- * @param node the offending ASTnode
- * @param name the unknown method
+ * @param node the offending ASTnode
+ * @param name the unknown method
* @param cause the exception causing the error
*/
public Method(JexlNode node, String name, Throwable cause) {
@@ -325,8 +324,8 @@ public class JexlException extends Runti
/**
* Creates a new Method exception instance.
- * @param info the location information
- * @param name the unknown method
+ * @param info the location information
+ * @param name the unknown method
* @param cause the exception causing the error
*/
public Method(JexlInfo info, String name, Throwable cause) {
@@ -356,8 +355,8 @@ public class JexlException extends Runti
/**
* Creates a new instance of Return.
- * @param node the return node
- * @param msg the message
+ * @param node the return node
+ * @param msg the message
* @param value the returned value
*/
public Return(JexlNode node, String msg, Object value) {
@@ -404,7 +403,7 @@ public class JexlException extends Runti
offsets[0] = dbg.start();
offsets[1] = dbg.end();
}
- return dbg.data();
+ return dbg.toString();
}
return "";
}
@@ -431,13 +430,13 @@ public class JexlException extends Runti
msg.append(",");
msg.append(dbg.end());
msg.append("]: '");
- msg.append(dbg.data());
+ msg.append(dbg.toString());
msg.append("'");
}
msg.append(' ');
msg.append(detailedMessage());
Throwable cause = getCause();
- if (cause != null && (Object) NULL_OPERAND == cause.getMessage()) {
+ if (cause instanceof JexlArithmetic.NullOperand) {
msg.append(" caused by null operand");
}
return msg.toString();
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlExpression.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlExpression.java?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlExpression.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlExpression.java Sat May 12 06:52:21 2012
@@ -47,7 +47,7 @@ public interface JexlExpression {
* Returns the JEXL expression this JexlExpression was created with.
* @return The JEXL expression to be evaluated
*/
- String getExpression();
+ CharSequence getParsedText();
/**
* Returns the JEXL expression by reconstructing it from the parsed tree.
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlInfo.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlInfo.java?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlInfo.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlInfo.java Sat May 12 06:52:21 2012
@@ -28,12 +28,12 @@ public class JexlInfo {
protected final int column;
/** name. */
protected final String name;
-
- /**
+
+ /**
* Create info.
* @param tn template name
* @param l line number
- * @param c column
+ * @param c column number
*/
public JexlInfo(String tn, int l, int c) {
name = tn;
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java Sat May 12 06:52:21 2012
@@ -28,16 +28,16 @@ import java.util.concurrent.Callable;
* <p>The statements can be <code>blocks</code> (curly braces containing code),
* Control statements such as <code>if</code> and <code>while</code>
* as well as expressions and assignment statements.</p>
- *
+ *
* @since 1.1
*/
public interface JexlScript extends JexlExpression {
/**
* Executes the script with the variables contained in the
- * supplied {@link JexlContext}.
- *
+ * supplied {@link JexlContext}.
+ *
* @param context A JexlContext containing variables.
- * @return The result of this script, usually the result of
+ * @return The result of this script, usually the result of
* the last statement.
*/
Object execute(JexlContext context);
@@ -46,10 +46,10 @@ public interface JexlScript extends Jexl
* Executes the script with the variables contained in the
* supplied {@link JexlContext} and a set of arguments corresponding to the
* parameters used during parsing.
- *
+ *
* @param context A JexlContext containing variables.
* @param args the arguments
- * @return The result of this script, usually the result of
+ * @return The result of this script, usually the result of
* the last statement.
* @since 2.1
*/
@@ -59,7 +59,7 @@ public interface JexlScript extends Jexl
* Returns the text of this Script.
* @return The script to be executed.
*/
- String getText();
+ String getSourceText();
/**
* Gets this script parameters.
@@ -77,7 +77,7 @@ public interface JexlScript extends Jexl
/**
* Gets this script variables.
- * <p>Note that since variables can be in an ant-ish form (ie foo.bar.quux), each variable is returned as
+ * <p>Note that since variables can be in an ant-ish form (ie foo.bar.quux), each variable is returned as
* a list of strings where each entry is a fragment of the variable ({"foo", "bar", "quux"} in the example.</p>
* @return the variables or null
* @since 2.1
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Main.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Main.java?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Main.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Main.java Sat May 12 06:52:21 2012
@@ -30,16 +30,16 @@ import java.io.InputStreamReader;
public class Main {
/**
* Test application for JEXL
- *
+ *
* If a single argument is present, it is treated as a filename of a JEXL
* script to be executed as a script. Any exceptions terminate the application.
- *
+ *
* Otherwise, lines are read from standard input and evaluated.
* ParseExceptions and JexlExceptions are logged, and do not cause the application to exit.
* This is done so that interactive testing is easier.
- *
+ *
* @param args (optional) filename to execute. Stored in the args variable.
- *
+ *
* @throws Exception if parsing or IO fail
*/
public static void main(String[] args) throws Exception {
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java Sat May 12 06:52:21 2012
@@ -44,10 +44,10 @@ public class Closure extends Script {
}
@Override
- public String getExpression() {
+ public String getParsedText() {
Debugger debug = new Debugger();
boolean d = debug.debug(script);
- return debug.data();
+ return debug.toString();
}
@Override
@@ -92,5 +92,5 @@ public class Closure extends Script {
}
};
}
-
+
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java?rev=1337453&r1=1337452&r2=1337453&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java Sat May 12 06:52:21 2012
@@ -16,7 +16,6 @@
*/
package org.apache.commons.jexl3.internal;
-
import org.apache.commons.jexl3.JexlExpression;
import org.apache.commons.jexl3.JexlScript;
import org.apache.commons.jexl3.parser.ASTAddNode;
@@ -86,22 +85,22 @@ import java.util.regex.Pattern;
*/
public final class Debugger extends ParserVisitor {
/** The builder to compose messages. */
- private final StringBuilder builder;
+ private final StringBuilder builder = new StringBuilder();
/** The cause of the issue to debug. */
- private JexlNode cause;
+ private JexlNode cause = null;
/** The starting character location offset of the cause in the builder. */
- private int start;
+ private int start = 0;
/** The ending character location offset of the cause in the builder. */
- private int end;
+ private int end = 0;
+ /** The indentation level. */
+ private int indentLevel = 0;
+ /** Perform indentation?. */
+ private boolean indent = true;
/**
* Creates a Debugger.
*/
public Debugger() {
- builder = new StringBuilder();
- cause = null;
- start = 0;
- end = 0;
}
/**
@@ -138,9 +137,11 @@ public final class Debugger extends Pars
public boolean debug(JexlNode node) {
start = 0;
end = 0;
+ indentLevel = 0;
+ indent = true;
if (node != null) {
builder.setLength(0);
- this.cause = node;
+ cause = node;
// make arg cause become the root cause
JexlNode root = node;
while (root.jjtGetParent() != null) {
@@ -154,7 +155,8 @@ public final class Debugger extends Pars
/**
* @return The rebuilt expression
*/
- public String data() {
+ @Override
+ public String toString() {
return builder.toString();
}
@@ -167,6 +169,8 @@ public final class Debugger extends Pars
public String data(JexlNode node) {
start = 0;
end = 0;
+ indentLevel = 0;
+ indent = true;
if (node != null) {
builder.setLength(0);
this.cause = node;
@@ -209,27 +213,37 @@ public final class Debugger extends Pars
/**
* Adds a statement node to the rebuilt expression.
* @param child the child node
- * @param data visitor pattern argument
+ * @param data visitor pattern argument
* @return visitor pattern value
*/
private Object acceptStatement(JexlNode child, Object data) {
+ if (indent) {
+ for (int i = 0; i < indentLevel; ++i) {
+ builder.append(" ");
+ }
+ }
Object value = accept(child, data);
// blocks, if, for & while dont need a ';' at end
- if (child instanceof ASTBlock
+ if (!(child instanceof ASTJexlScript
+ || child instanceof ASTBlock
|| child instanceof ASTIfStatement
|| child instanceof ASTForeachStatement
- || child instanceof ASTWhileStatement) {
- return value;
+ || child instanceof ASTWhileStatement)) {
+ builder.append(";");
+ if (indent) {
+ builder.append("\n");
+ } else {
+ builder.append(' ');
+ }
}
- builder.append(";");
return value;
}
/**
* Checks if a terminal node is the the cause to debug & adds its representation to the rebuilt expression.
- * @param node the child node
+ * @param node the child node
* @param image the child node token image (may be null)
- * @param data visitor pattern argument
+ * @param data visitor pattern argument
* @return visitor pattern value
*/
private Object check(JexlNode node, String image, Object data) {
@@ -250,10 +264,10 @@ public final class Debugger extends Pars
/**
* Checks if the children of a node using infix notation is the cause to debug, adds their representation to the
* rebuilt expression.
- * @param node the child node
+ * @param node the child node
* @param infix the child node token
* @param paren whether the child should be parenthesized
- * @param data visitor pattern argument
+ * @param data visitor pattern argument
* @return visitor pattern value
*/
private Object infixChildren(JexlNode node, String infix, boolean paren, Object data) {
@@ -276,9 +290,9 @@ public final class Debugger extends Pars
/**
* Checks if the child of a node using prefix notation is the cause to debug, adds their representation to the
* rebuilt expression.
- * @param node the node
+ * @param node the node
* @param prefix the node token
- * @param data visitor pattern argument
+ * @param data visitor pattern argument
* @return visitor pattern value
*/
private Object prefixChild(JexlNode node, String prefix, Object data) {
@@ -307,7 +321,7 @@ public final class Debugger extends Pars
/**
* Rebuilds an additive expression.
* @param node the node
- * @param op the operator
+ * @param op the operator
* @param data visitor pattern argument
* @return visitor pattern value
*/
@@ -391,13 +405,20 @@ public final class Debugger extends Pars
@Override
protected Object visit(ASTBlock node, Object data) {
- builder.append("{ ");
+ builder.append("{");
+ if (indent) {
+ builder.append("\n");
+ } else {
+ builder.append(' ');
+ }
+ indentLevel += 1;
int num = node.jjtGetNumChildren();
for (int i = 0; i < num; ++i) {
JexlNode child = node.jjtGetChild(i);
acceptStatement(child, data);
}
- builder.append(" }");
+ indentLevel -= 1;
+ builder.append("}");
return data;
}
@@ -496,8 +517,6 @@ public final class Debugger extends Pars
if (node.jjtGetNumChildren() > 2) {
builder.append(" else ");
acceptStatement(node.jjtGetChild(2), data);
- } else {
- builder.append(';');
}
} else {
builder.append(';');
@@ -512,6 +531,7 @@ public final class Debugger extends Pars
@Override
protected Object visit(ASTJexlScript node, Object data) {
+ boolean ii = true;
if (node instanceof ASTJexlLambda) {
JexlNode parent = node.jjtGetParent();
// use lambda syntax if not assigned
@@ -533,12 +553,23 @@ public final class Debugger extends Pars
builder.append(' ');
} else {
builder.append("->");
+ ii = false;
}
}
+ if (!ii) {
+ indent = false;
+ }
int num = node.jjtGetNumChildren();
- for (int i = 0; i < num; ++i) {
- JexlNode child = node.jjtGetChild(i);
- acceptStatement(child, data);
+ if (num == 1 && !(node instanceof ASTJexlLambda)) {
+ data = accept(node.jjtGetChild(0), data);
+ } else {
+ for (int i = 0; i < num; ++i) {
+ JexlNode child = node.jjtGetChild(i);
+ acceptStatement(child, data);
+ }
+ }
+ if (!ii) {
+ indent = true;
}
return data;
}
@@ -568,7 +599,7 @@ public final class Debugger extends Pars
if (num > 0) {
accept(node.jjtGetChild(0), data);
for (int i = 1; i < num; ++i) {
- builder.append(", ");
+ builder.append(",");
accept(node.jjtGetChild(i), data);
}
} else {