Return-Path: X-Original-To: apmail-commons-commits-archive@minotaur.apache.org Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id CE0609940 for ; Wed, 16 Nov 2011 16:33:28 +0000 (UTC) Received: (qmail 50794 invoked by uid 500); 16 Nov 2011 16:33:28 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 50734 invoked by uid 500); 16 Nov 2011 16:33:28 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 50727 invoked by uid 99); 16 Nov 2011 16:33:28 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 Nov 2011 16:33:28 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 Nov 2011 16:33:24 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id C2C1E23889B3 for ; Wed, 16 Nov 2011 16:33:02 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1202769 - in /commons/proper/jexl/trunk/src: main/java/org/apache/commons/jexl2/ test/java/org/apache/commons/jexl2/ Date: Wed, 16 Nov 2011 16:33:02 -0000 To: commits@commons.apache.org From: henrib@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111116163302.C2C1E23889B3@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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. - * + *

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.

* @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. *

@@ -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. *

* In expressions like "ns:function(...)", the resolver is called with resolveNamespace("ns"). + *

+ * JEXL itself reserves 'jexl' and 'ujexl' as namespaces for internal purpose; resolving those may lead to unexpected + * results. + *

*/ 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 * *

+ * 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: + *

+     * $$ for(var cell : cells) { $jexl.print(cell); $jexl.print(';') }
+     * 
+ *

+ *

* 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. + *

This context exposes its writer as '$jexl' to the scripts.

*

public for introspection purpose.

*/ 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()); + } }