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 2011/11/16 17:33:02 UTC

svn commit: r1202769 - in /commons/proper/jexl/trunk/src: main/java/org/apache/commons/jexl2/ test/java/org/apache/commons/jexl2/

Author: henrib
Date: Wed Nov 16 16:33:02 2011
New Revision: 1202769

URL: http://svn.apache.org/viewvc?rev=1202769&view=rev
Log:
Deduplication of error formatting code;
Commented $jexl variable and jexl: namespace;
Added test on UJEXL using writer directly

Modified:
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlContext.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlException.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/NamespaceResolver.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/UnifiedJEXL.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/UnifiedJEXLTest.java

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlContext.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlContext.java?rev=1202769&r1=1202768&r2=1202769&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlContext.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlContext.java Wed Nov 16 16:33:02 2011
@@ -18,7 +18,8 @@ package org.apache.commons.jexl2;
 
 /**
  * Manages variables which can be referenced in a JEXL expression.
- *
+ * <p>Note that JEXL may use '$jexl' and '$ujexl' variables for internal purpose; setting or getting those
+ * variables may lead to unexpected results unless specified otherwise.</p>
  *  @since 1.0
  *  @version $Id$
  */

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlException.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlException.java?rev=1202769&r1=1202768&r2=1202769&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlException.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlException.java Wed Nov 16 16:33:02 2011
@@ -37,7 +37,7 @@ public class JexlException extends Runti
     private static final int MIN_EXCHARLOC = 5;
     /** Maximum number of characters around exception location. */
     private static final int MAX_EXCHARLOC = 10;
-    
+
     /**
      * Creates a new JexlException.
      * @param node the node causing the error
@@ -46,7 +46,7 @@ public class JexlException extends Runti
     public JexlException(JexlNode node, String msg) {
         super(msg);
         mark = node;
-        info = node != null? node.debugInfo() : null;
+        info = node != null ? node.debugInfo() : null;
 
     }
 
@@ -59,9 +59,9 @@ public class JexlException extends Runti
     public JexlException(JexlNode node, String msg, Throwable cause) {
         super(msg, unwrap(cause));
         mark = node;
-        info = node != null? node.debugInfo() : null;
+        info = node != null ? node.debugInfo() : null;
     }
-    
+
     /**
      * Creates a new JexlException.
      * @param dbg the debugging information associated
@@ -84,7 +84,7 @@ public class JexlException extends Runti
         mark = null;
         info = dbg;
     }
-    
+
     /**
      * Unwraps the cause of a throwable due to reflection. 
      * @param xthrow the throwable
@@ -95,11 +95,11 @@ public class JexlException extends Runti
             return ((InvocationTargetException) xthrow).getTargetException();
         } else if (xthrow instanceof UndeclaredThrowableException) {
             return ((UndeclaredThrowableException) xthrow).getUndeclaredThrowable();
-        } else{
+        } else {
             return xthrow;
         }
     }
-        
+
     /**
      * Accesses detailed message.
      * @return  the message
@@ -107,7 +107,30 @@ public class JexlException extends Runti
     protected String detailedMessage() {
         return super.getMessage();
     }
-    
+
+    /**
+     * Formats an error message from the parser.
+     * @param prefix the prefix to the message
+     * @param expr the expression in error
+     * @return the formatted message
+     */
+    protected String parserError(String prefix, String expr) {
+        int begin = info.debugInfo().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 {
+            return prefix + " error near '... "
+                    + expr.substring(begin, end > length ? length : end) + " ...'";
+        }
+    }
+
     /**
      * Thrown when tokenization fails.
      */
@@ -121,7 +144,7 @@ public class JexlException extends Runti
         public Tokenization(JexlInfo node, CharSequence expr, TokenMgrError cause) {
             super(merge(node, cause), expr.toString(), cause);
         }
-                
+
         /**
          * Merge the node info and the cause info to obtain best possible location.
          * @param node the node
@@ -129,7 +152,7 @@ public class JexlException extends Runti
          * @return the info to use
          */
         private static DebugInfo merge(JexlInfo node, TokenMgrError cause) {
-            DebugInfo dbgn = node != null? node.debugInfo() : null;
+            DebugInfo dbgn = node != null ? node.debugInfo() : null;
             if (cause == null) {
                 return dbgn;
             } else if (dbgn == null) {
@@ -138,33 +161,20 @@ public class JexlException extends Runti
                 return new DebugInfo(dbgn.getName(), cause.getLine(), cause.getColumn());
             }
         }
-                            
+
         /**
          * @return the expression
-         */ 
+         */
         public String getExpression() {
             return super.detailedMessage();
         }
-                
+
         @Override
         protected String detailedMessage() {
-            int begin = info.debugInfo().getColumn();
-            int end = begin + MIN_EXCHARLOC;
-            begin -= MIN_EXCHARLOC;
-            if (begin < 0) {
-                end += MIN_EXCHARLOC;
-                begin = 0;
-            }
-            int length = getExpression().length();
-            if (length < MAX_EXCHARLOC) {
-                return "parsing error in '" + getExpression() + "'";
-            } else {
-                return "parsing error near '... "
-                       + getExpression().substring(begin, end > length? length : end) + " ...'";
-            }
+            return parserError("tokenization", getExpression());
         }
-    } 
-            
+    }
+
     /**
      * Thrown when parsing fails.
      */
@@ -178,7 +188,7 @@ public class JexlException extends Runti
         public Parsing(JexlInfo node, CharSequence expr, ParseException cause) {
             super(merge(node, cause), expr.toString(), cause);
         }
-                
+
         /**
          * Merge the node info and the cause info to obtain best possible location.
          * @param node the node
@@ -186,7 +196,7 @@ public class JexlException extends Runti
          * @return the info to use
          */
         private static DebugInfo merge(JexlInfo node, ParseException cause) {
-            DebugInfo dbgn = node != null? node.debugInfo() : null;
+            DebugInfo dbgn = node != null ? node.debugInfo() : null;
             if (cause == null) {
                 return dbgn;
             } else if (dbgn == null) {
@@ -195,33 +205,20 @@ public class JexlException extends Runti
                 return new DebugInfo(dbgn.getName(), cause.getLine(), cause.getColumn());
             }
         }
-                    
+
         /**
          * @return the expression
-         */    
+         */
         public String getExpression() {
             return super.detailedMessage();
         }
-        
+
         @Override
         protected String detailedMessage() {
-            int begin = info.debugInfo().getColumn();
-            int end = begin + MIN_EXCHARLOC;
-            begin -= MIN_EXCHARLOC;
-            if (begin < 0) {
-                end += MIN_EXCHARLOC;
-                begin = 0;
-            }
-            int length = getExpression().length();
-            if (length < MAX_EXCHARLOC) {
-                return "parsing error in '" + getExpression() + "'";
-            } else {
-                return "parsing error near '... "
-                       + getExpression().substring(begin, end > length? length : end) + " ...'";
-            }
+            return parserError("parsing", getExpression());
         }
     }
-    
+
     /**
      * Thrown when a variable is unknown.
      */
@@ -234,20 +231,20 @@ public class JexlException extends Runti
         public Variable(JexlNode node, String var) {
             super(node, var);
         }
-        
+
         /**
          * @return the variable name
          */
         public String getVariable() {
             return super.detailedMessage();
         }
-        
+
         @Override
         protected String detailedMessage() {
             return "undefined variable " + getVariable();
         }
-    } 
-        
+    }
+
     /**
      * Thrown when a property is unknown.
      */
@@ -260,20 +257,20 @@ public class JexlException extends Runti
         public Property(JexlNode node, String var) {
             super(node, var);
         }
-        
+
         /**
          * @return the property name
          */
         public String getProperty() {
             return super.detailedMessage();
         }
-        
+
         @Override
         protected String detailedMessage() {
             return "inaccessible or unknown property " + getProperty();
         }
-    } 
-    
+    }
+
     /**
      * Thrown when a method or ctor is unknown, ambiguous or inaccessible.
      */
@@ -286,26 +283,27 @@ public class JexlException extends Runti
         public Method(JexlNode node, String name) {
             super(node, name);
         }
-                      
+
         /**
          * @return the method name
-         */  
+         */
         public String getMethod() {
             return super.detailedMessage();
         }
-        
+
         @Override
         protected String detailedMessage() {
             return "unknown, ambiguous or inaccessible method " + getMethod();
         }
     }
-    
+
     /**
      * Thrown to return a value.
      */
-    protected static class Return extends JexlException {  
+    protected static class Return extends JexlException {
         /** The returned value. */
         private final Object result;
+
         /**
          * Creates a new instance of Return.
          * @param node the return node
@@ -316,6 +314,7 @@ public class JexlException extends Runti
             super(node, msg);
             this.result = value;
         }
+
         /**
          * @return the returned value
          */
@@ -323,7 +322,7 @@ public class JexlException extends Runti
             return result;
         }
     }
-    
+
     /**
      * Thrown to cancel a script execution.
      */
@@ -336,7 +335,7 @@ public class JexlException extends Runti
             super(node, "execution cancelled", null);
         }
     }
-    
+
     /**
      * Gets information about the cause of this error.
      * <p>
@@ -358,7 +357,7 @@ public class JexlException extends Runti
         }
         return "";
     }
-  
+
     /**
      * Detailed info message about this error.
      * Format is "debug![begin,end]: string \n msg" where:

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/NamespaceResolver.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/NamespaceResolver.java?rev=1202769&r1=1202768&r2=1202769&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/NamespaceResolver.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/NamespaceResolver.java Wed Nov 16 16:33:02 2011
@@ -24,6 +24,10 @@ package org.apache.commons.jexl2;
  * the "math" namespace would be the proper object to expose functions like "log(...)", "sinus(...)", etc.
  * </p>
  * In expressions like "ns:function(...)", the resolver is called with resolveNamespace("ns").
+ * <p>
+ * JEXL itself reserves 'jexl' and 'ujexl' as namespaces for internal purpose; resolving those may lead to unexpected
+ * results.
+ * </p>
  */
 public interface NamespaceResolver {
     /**

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/UnifiedJEXL.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/UnifiedJEXL.java?rev=1202769&r1=1202768&r2=1202769&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/UnifiedJEXL.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/UnifiedJEXL.java Wed Nov 16 16:33:02 2011
@@ -1021,6 +1021,13 @@ public final class UnifiedJEXL {
      * The value 169 is over fourty-two
      * </pre></blockquote>
      * <p>
+     * During evaluation, the template context exposes its writer as '$jexl' which is safe to use in this case.
+     * This allows writing directly through the writer without adding new-lines as in:
+     * <p><blockquote><pre>
+     * $$ for(var cell : cells) { $jexl.print(cell); $jexl.print(';') }
+     * </pre></blockquote>
+     * </p>
+     * <p>
      * A template is expanded as one JEXL script and a list of UnifiedJEXL expressions; each UnifiedJEXL expression
      * being replace in the script by a call to jexl:print(expr) (the expr is in fact the expr number in the template).
      * This integration uses a specialized JexlContext (TemplateContext) that serves as a namespace (for jexl:)
@@ -1181,6 +1188,7 @@ public final class UnifiedJEXL {
 
     /**
      * The type of context to use during evaluation of templates.
+     * <p>This context exposes its writer as '$jexl' to the scripts.</p>
      * <p>public for introspection purpose.</p>
      */
     public final class TemplateContext implements JexlContext, NamespaceResolver {
@@ -1217,7 +1225,11 @@ public final class UnifiedJEXL {
 
         /** {@inheritDoc} */
         public Object get(String name) {
-            return wrap.get(name);
+            if ("$jexl".equals(name)) {
+                return writer;
+            } else {
+                return wrap.get(name);
+            }
         }
 
         /** {@inheritDoc} */
@@ -1250,22 +1262,6 @@ public final class UnifiedJEXL {
         public void include(Template template, Object... args) {
             template.evaluate(wrap, writer, args);
         }
-        
-        /**
-         * Prints an expression result.
-         * @param e the expression number
-         */
-        public void print(String cs) {
-            Expression expr = UnifiedJEXL.this.parse(cs);
-            if (expr.isDeferred()) {
-                expr = expr.prepare(wrap);
-            }
-            if (expr instanceof CompositeExpression) {
-                printComposite((CompositeExpression) expr);
-            } else {
-                doPrint(expr.evaluate(this));
-            }
-        }
 
         /**
          * Prints an expression result.

Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/UnifiedJEXLTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/UnifiedJEXLTest.java?rev=1202769&r1=1202768&r2=1202769&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/UnifiedJEXLTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/UnifiedJEXLTest.java Wed Nov 16 16:33:02 2011
@@ -16,8 +16,10 @@
  */
 package org.apache.commons.jexl2;
 
+import java.io.PrintWriter;
 import java.io.StringReader;
 import java.io.StringWriter;
+import java.io.Writer;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -393,4 +395,29 @@ public class UnifiedJEXLTest extends Jex
         String dstr = t.asString();
         assertNotNull(dstr);
     }
+    
+    public static class FrobozWriter extends PrintWriter {
+        public FrobozWriter(Writer w) {
+            super(w);
+        }
+        
+        public void print(Froboz froboz) {
+            super.print("froboz{");
+            super.print(froboz.value);
+            super.print("}");
+        }
+        
+        @Override
+        public String toString() {
+            return out.toString();
+        }
+    }
+    
+    public void testWriter() throws Exception {
+        Froboz froboz = new Froboz(42);
+        Writer writer = new FrobozWriter(new StringWriter());
+        UnifiedJEXL.Template t = EL.createTemplate("$$", new StringReader("$$$jexl.print(froboz)"), "froboz");
+        t.evaluate(context, writer, froboz);
+        assertEquals("froboz{42}", writer.toString());
+    }
 }