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 2009/08/29 10:39:05 UTC
svn commit: r809099 - in /commons/proper/jexl/branches/2.0/src:
main/java/org/apache/commons/jexl/ main/java/org/apache/commons/jexl/parser/
test/java/org/apache/commons/jexl/
Author: henrib
Date: Sat Aug 29 08:39:04 2009
New Revision: 809099
URL: http://svn.apache.org/viewvc?rev=809099&view=rev
Log:
added Unicode escape sequence to String literal handling; fixed non-escapable character handling; added $ as escapable character in UnifiedJEXL
Modified:
commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/UnifiedJEXL.java
commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/parser/StringParser.java
commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/JexlTest.java
commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/UnifiedJEXLTest.java
Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/UnifiedJEXL.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/UnifiedJEXL.java?rev=809099&r1=809098&r2=809099&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/UnifiedJEXL.java (original)
+++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/UnifiedJEXL.java Sat Aug 29 08:39:04 2009
@@ -869,11 +869,11 @@
IMMEDIATE0,
/** Parsing after # .*/
DEFERRED0,
- /** Parsing afer ${ . */
+ /** Parsing afer ${ .*/
IMMEDIATE1,
- /** Parsing afer #{ . */
+ /** Parsing afer #{ .*/
DEFERRED1,
- /** Parsing afer \ . */
+ /** Parsing afer \ .*/
ESCAPE
}
@@ -944,7 +944,6 @@
case IMMEDIATE1: // ${...
if (c == '}') {
// materialize the immediate expr
- //Expression iexpr = createExpression(ExpressionType.IMMEDIATE, strb, null);
Expression iexpr = new ImmediateExpression(strb.toString(), toNode(strb), null);
builder.add(iexpr);
strb.delete(0, Integer.MAX_VALUE);
@@ -996,6 +995,8 @@
case ESCAPE:
if (c == '#') {
strb.append('#');
+ } else if (c == '$') {
+ strb.append('$');
} else {
strb.append('\\');
strb.append(c);
Modified: commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/parser/StringParser.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/parser/StringParser.java?rev=809099&r1=809098&r2=809099&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/parser/StringParser.java (original)
+++ commons/proper/jexl/branches/2.0/src/main/java/org/apache/commons/jexl/parser/StringParser.java Sat Aug 29 08:39:04 2009
@@ -18,6 +18,20 @@
/**
* Common constant strings utilities.
+ * <p>
+ * This package methods read JEXL string literals and handle escaping through the
+ * 'backslash' (ie: \) character. Escaping is used to neutralize string delimiters (the single
+ * and double quotes) and read Unicode hexadecimal encoded characters.
+ * </p>
+ * <p>
+ * The only escapable characters are the single and double quotes - ''' and '"' -,
+ * a Unicode sequence starting with 'u' followed by 4 hexadecimals and
+ * the backslash character - '\' - itself.
+ * </p>
+ * <p>
+ * A sequence where '\' occurs before any non-escapable character or sequence has no effect, the
+ * sequence output being the same as the input.
+ * </p>
*/
public class StringParser {
/**
@@ -47,7 +61,7 @@
public static int readString(StringBuilder strb, CharSequence str, int index, char sep) {
return read(strb, str, index, str.length(), sep);
}
-
+
/**
* Read the remainder of a string till a given separator,
* handles escaping through '\' syntax.
@@ -64,9 +78,17 @@
for (; index < end; ++index) {
char c = str.charAt(index);
if (escape) {
- strb.append(c);
- if (c == '\\')
- strb.append('\\');
+ if (c == 'u' && (index + 4) < end && readUnicodeChar(strb, str, index + 1) > 0) {
+ index += 4;
+ }
+ else {
+ // if c is not an escapable character, re-emmit the backslash before it
+ boolean notSeparator = sep == 0? c != '\'' && c != '"' : c != sep;
+ if (notSeparator && c != '\\' ) {
+ strb.append('\\');
+ }
+ strb.append(c);
+ }
escape = false;
continue;
}
@@ -81,4 +103,36 @@
}
return index;
}
+
+ /**
+ * Reads a Unicode escape character.
+ * @param strb the builder to write the character to
+ * @param str the sequence
+ * @param begin the begin offset in sequence (after the '\\u')
+ * @return 0 if char could not be read, 4 otherwise
+ */
+ private static final int readUnicodeChar(StringBuilder strb, CharSequence str, int begin) {
+ char xc = 0;
+ int bits = 12;
+ int value = 0;
+ for(int offset = 0; offset < 4; ++offset) {
+ char c = str.charAt(begin + offset);
+ if (c >= '0' && c <= '9') {
+ value = (c - '0');
+ }
+ else if (c >= 'a' && c <= 'h') {
+ value = (c - 'a' + 10);
+ }
+ else if (c >= 'A' && c <= 'H') {
+ value = (c - 'A' + 10);
+ }
+ else {
+ return 0;
+ }
+ xc |= value << bits;
+ bits -= 4;
+ }
+ strb.append(xc);
+ return 4;
+ }
}
\ No newline at end of file
Modified: commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/JexlTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/JexlTest.java?rev=809099&r1=809098&r2=809099&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/JexlTest.java (original)
+++ commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/JexlTest.java Sat Aug 29 08:39:04 2009
@@ -739,10 +739,15 @@
// jc.getVars().put("commons-logging", version);
// assertExpression(jc, "commons-logging", version);
}
-
+
public void testUnicodeSupport() throws Exception
{
- assertExpression(JexlHelper.createContext(), "myvar == 'Użytkownik'", Boolean.FALSE);
+ JexlContext jc = JexlHelper.createContext();
+ assertExpression(jc, "myvar == 'Użytkownik'", Boolean.FALSE);
+ assertExpression(jc, "'c:\\some\\windows\\path'", "c:\\some\\windows\\path");
+ assertExpression(jc, "'foo\\u0020bar'", "foo\u0020bar");
+ assertExpression(jc, "'foo\\u0020\\u0020bar'", "foo\u0020\u0020bar");
+ assertExpression(jc, "'\\u0020foobar\\u0020'", "\u0020foobar\u0020");
}
public static final class Duck {
Modified: commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/UnifiedJEXLTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/UnifiedJEXLTest.java?rev=809099&r1=809098&r2=809099&view=diff
==============================================================================
--- commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/UnifiedJEXLTest.java (original)
+++ commons/proper/jexl/branches/2.0/src/test/java/org/apache/commons/jexl/UnifiedJEXLTest.java Sat Aug 29 08:39:04 2009
@@ -157,10 +157,16 @@
}
public void testEscape() throws Exception {
- UnifiedJEXL.Expression expr = EL.parse("#\\{'world'\\}");
JexlContext none = null;
- Object o = expr.evaluate(none);
+ UnifiedJEXL.Expression expr;
+ Object o;
+ // $ and # are escapable in UnifiedJEXL
+ expr = EL.parse("\\#{'world'}");
+ o = expr.evaluate(none);
assertEquals("#{'world'}", o);
+ expr = EL.parse("\\${'world'}");
+ o = expr.evaluate(none);
+ assertEquals("${'world'}", o);
}
public void testEscapeString() throws Exception {
@@ -170,6 +176,13 @@
assertEquals("\"world's finest\"", o);
}
+ public void testNonEscapeString() throws Exception {
+ UnifiedJEXL.Expression expr = EL.parse("c:\\some\\windows\\path");
+ JexlContext none = null;
+ Object o = expr.evaluate(none);
+ assertEquals("c:\\some\\windows\\path", o);
+ }
+
public void testMalformed() throws Exception {
try {
UnifiedJEXL.Expression expr = EL.parse("${'world'");
@@ -237,4 +250,4 @@
test.setUp();
test.testBadContextNested();
}
-}
\ No newline at end of file
+}