diff options
Diffstat (limited to 'velocity-engine-core/src')
43 files changed, 498 insertions, 195 deletions
diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/Template.java b/velocity-engine-core/src/main/java/org/apache/velocity/Template.java index 7528e88a..b23d746c 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/Template.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/Template.java @@ -26,7 +26,7 @@ import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.exception.ResourceNotFoundException; import org.apache.velocity.exception.TemplateInitException; import org.apache.velocity.exception.VelocityException; -import org.apache.velocity.runtime.RuntimeConstants; +import org.apache.velocity.runtime.RuntimeInstance; import org.apache.velocity.runtime.directive.Scope; import org.apache.velocity.runtime.directive.StopCommand; import org.apache.velocity.runtime.parser.ParseException; @@ -165,7 +165,7 @@ public class Template extends Resource catch( RuntimeException e ) { errorCondition = new VelocityException("Exception thrown processing Template " - +getName(), e); + +getName(), e, rsvc.getLogContext().getStackTrace()); throw errorCondition; } finally @@ -183,7 +183,7 @@ public class Template extends Resource // exception to be continued to be thrown, otherwise, throw a new Exception. if (errorCondition == null) { - throw new VelocityException(e); + throw new VelocityException(e, rsvc.getLogContext().getStackTrace()); } } } @@ -193,7 +193,7 @@ public class Template extends Resource /* * is == null, therefore we have some kind of file issue */ - errorCondition = new ResourceNotFoundException("Unknown resource error for resource " + name ); + errorCondition = new ResourceNotFoundException("Unknown resource error for resource " + name, null, rsvc.getLogContext().getStackTrace() ); throw errorCondition; } } @@ -280,139 +280,157 @@ public class Template extends Resource public void merge( Context context, Writer writer, List macroLibraries) throws ResourceNotFoundException, ParseErrorException, MethodInvocationException { - /* - * we shouldn't have to do this, as if there is an error condition, - * the application code should never get a reference to the - * Template - */ - - if (errorCondition != null) - { - throw errorCondition; - } - - if( data != null) + try { /* - * create an InternalContextAdapter to carry the user Context down - * into the rendering engine. Set the template name and render() + * we shouldn't have to do this, as if there is an error condition, + * the application code should never get a reference to the + * Template */ - InternalContextAdapterImpl ica = new InternalContextAdapterImpl( context ); - - /** - * Set the macro libraries - */ - List libTemplates = new ArrayList(); - ica.setMacroLibraries(libTemplates); + if (errorCondition != null) + { + throw errorCondition; + } - if (macroLibraries != null) + if (data != null) { - for (String macroLibrary : (List<String>)macroLibraries) + /* + * create an InternalContextAdapter to carry the user Context down + * into the rendering engine. Set the template name and render() + */ + + InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context); + + /** + * Set the macro libraries + */ + List libTemplates = new ArrayList(); + ica.setMacroLibraries(libTemplates); + + if (macroLibraries != null) { - /** - * Build the macro library - */ - try + for (String macroLibrary : (List<String>) macroLibraries) { - Template t = rsvc.getTemplate(macroLibrary); - libTemplates.add(t); + /** + * Build the macro library + */ + try + { + Template t = rsvc.getTemplate(macroLibrary); + libTemplates.add(t); + } + catch (ResourceNotFoundException re) + { + /* + * the macro lib wasn't found. Note it and throw + */ + log.error("cannot find template {}", macroLibrary); + throw re; + } + catch (ParseErrorException pe) + { + /* + * the macro lib was found, but didn't parse - syntax error + * note it and throw + */ + rsvc.getLog("parser").error("syntax error in template {}: {}", + macroLibrary, pe.getMessage(), pe); + throw pe; + } + catch (Exception e) + { + throw new RuntimeException("parse failed in template " + + (String) macroLibrary + ".", e); + } } - catch (ResourceNotFoundException re) + } + + if (provideScope) + { + ica.put(scopeName, new Scope(this, ica.get(scopeName))); + } + try + { + ica.pushCurrentTemplateName(name); + ica.setCurrentResource(this); + + ((SimpleNode) data).render(ica, writer); + } + catch (StopCommand stop) + { + if (!stop.isFor(this)) { - /* - * the macro lib wasn't found. Note it and throw - */ - log.error("cannot find template {}", macroLibrary); - throw re; + throw stop; } - catch (ParseErrorException pe) + else { - /* - * the macro lib was found, but didn't parse - syntax error - * note it and throw - */ - rsvc.getLog("parser").error("syntax error in template {}: {}", - macroLibrary, pe.getMessage(), pe); - throw pe; - } - - catch (Exception e) - { - throw new RuntimeException("parse failed in template " + - (String) macroLibrary + ".", e); + Logger renderingLog = rsvc.getLog("rendering"); + renderingLog.debug(stop.getMessage()); } } - } - - if (provideScope) - { - ica.put(scopeName, new Scope(this, ica.get(scopeName))); - } - try - { - ica.pushCurrentTemplateName( name ); - ica.setCurrentResource( this ); - - ( (SimpleNode) data ).render( ica, writer); - } - catch (StopCommand stop) - { - if (!stop.isFor(this)) + catch (IOException e) { - throw stop; + throw new VelocityException("IO Error rendering template '" + name + "'", e, rsvc.getLogContext().getStackTrace()); } - else + finally { - Logger renderingLog = rsvc.getLog("rendering"); - renderingLog.debug(stop.getMessage()); - } - } - catch (IOException e) - { - throw new VelocityException("IO Error rendering template '"+ name + "'", e); - } - finally - { - /* - * lets make sure that we always clean up the context - */ - ica.popCurrentTemplateName(); - ica.setCurrentResource( null ); + /* + * lets make sure that we always clean up the context + */ + ica.popCurrentTemplateName(); + ica.setCurrentResource(null); - if (provideScope) - { - Object obj = ica.get(scopeName); - if (obj instanceof Scope) + if (provideScope) { - Scope scope = (Scope)obj; - if (scope.getParent() != null) - { - ica.put(scopeName, scope.getParent()); - } - else if (scope.getReplaced() != null) - { - ica.put(scopeName, scope.getReplaced()); - } - else + Object obj = ica.get(scopeName); + if (obj instanceof Scope) { - ica.remove(scopeName); + Scope scope = (Scope) obj; + if (scope.getParent() != null) + { + ica.put(scopeName, scope.getParent()); + } + else if (scope.getReplaced() != null) + { + ica.put(scopeName, scope.getReplaced()); + } + else + { + ica.remove(scopeName); + } } } } } - } - else - { - /* - * this shouldn't happen either, but just in case. - */ + else + { + /* + * this shouldn't happen either, but just in case. + */ - String msg = "Template merging failed. The document is null, " + - "most likely due to a parsing error."; + String msg = "Template merging failed. The document is null, " + + "most likely due to a parsing error."; - throw new RuntimeException(msg); + throw new RuntimeException(msg); + } + } + catch (VelocityException ve) + { + /* it's a good place to display the VTL stack trace if we have one */ + String[] vtlStacktrace = ve.getVtlStackTrace(); + if (vtlStacktrace != null) + { + Logger renderingLog = rsvc.getLog("rendering"); + renderingLog.error(ve.getMessage()); + renderingLog.error("VTL stacktrace:"); + for (String level : vtlStacktrace) + { + renderingLog.error(level); + } + } + throw ve; } } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/app/event/EventHandlerUtil.java b/velocity-engine-core/src/main/java/org/apache/velocity/app/event/EventHandlerUtil.java index fbe61147..cbb54be6 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/app/event/EventHandlerUtil.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/app/event/EventHandlerUtil.java @@ -71,7 +71,7 @@ public class EventHandlerUtil { } catch (Exception e) { - throw new VelocityException("Exception in event handler.",e); + throw new VelocityException("Exception in event handler.",e, rsvc.getLogContext().getStackTrace()); } } @@ -117,7 +117,7 @@ public class EventHandlerUtil { } catch (Exception ex) { - throw new VelocityException("Exception in event handler.", ex); + throw new VelocityException("Exception in event handler.", ex, rsvc.getLogContext().getStackTrace()); } /* default behaviour is to re-throw exception */ @@ -165,7 +165,7 @@ public class EventHandlerUtil { } catch (Exception e) { - throw new VelocityException("Exception in event handler.",e); + throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); } } @@ -202,7 +202,7 @@ public class EventHandlerUtil { } catch (Exception e) { - throw new VelocityException("Exception in event handler.",e); + throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); } } @@ -237,7 +237,7 @@ public class EventHandlerUtil { } catch (Exception e) { - throw new VelocityException("Exception in event handler.",e); + throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); } } @@ -273,7 +273,7 @@ public class EventHandlerUtil { } catch (Exception e) { - throw new VelocityException("Exception in event handler.",e); + throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); } } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/exception/MacroOverflowException.java b/velocity-engine-core/src/main/java/org/apache/velocity/exception/MacroOverflowException.java index 4e75aa08..77cde148 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/exception/MacroOverflowException.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/exception/MacroOverflowException.java @@ -50,10 +50,32 @@ public class MacroOverflowException extends VelocityException } /** + * @param exceptionMessage The message to register. + * @param wrapped A throwable object that caused the Exception. + * @param stacktrace VTL stacktrace + * @since 2.2 + */ + public MacroOverflowException(final String exceptionMessage, final Throwable wrapped, final String[] stacktrace) + { + super(exceptionMessage, wrapped, stacktrace); + } + + /** * @param wrapped A throwable object that caused the Exception. */ public MacroOverflowException(final Throwable wrapped) { super(wrapped); } + + /** + * @param wrapped A throwable object that caused the Exception. + * @param stacktrace VTL stacktrace + * @since 2.2 + */ + public MacroOverflowException(final Throwable wrapped, final String[] stacktrace) + { + super(wrapped, stacktrace); + } + } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/exception/MathException.java b/velocity-engine-core/src/main/java/org/apache/velocity/exception/MathException.java index b92826a8..14b4f3e4 100755 --- a/velocity-engine-core/src/main/java/org/apache/velocity/exception/MathException.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/exception/MathException.java @@ -30,8 +30,21 @@ public class MathException extends VelocityException { private static final long serialVersionUID = -7966507088645215583L; + /** + * @param exceptionMessage The message to register. + */ public MathException(final String exceptionMessage) { super(exceptionMessage); } + + /** + * @param exceptionMessage The message to register. + * @param stacktrace VTL stacktrace + * @since 2.2 + */ + public MathException(final String exceptionMessage, final String[] stacktrace) + { + super(exceptionMessage, null, stacktrace); + } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/exception/MethodInvocationException.java b/velocity-engine-core/src/main/java/org/apache/velocity/exception/MethodInvocationException.java index 0c16bc33..a88b14b2 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/exception/MethodInvocationException.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/exception/MethodInvocationException.java @@ -69,6 +69,28 @@ public class MethodInvocationException extends VelocityException implements Exte } /** + * CTOR - wraps the passed in exception for + * examination later + * + * @param message + * @param e Throwable that we are wrapping + * @param stacktrace VTL stacktrace + * @param methodName name of method that threw the exception + * @param templateName The name of the template where the exception occurred + * @param lineNumber line number + * @param columnNumber column number + */ + public MethodInvocationException(final String message, final Throwable e, final String[] stacktrace, final String methodName, final String templateName, final int lineNumber, final int columnNumber) + { + super(message, e, stacktrace); + + this.methodName = methodName; + this.templateName = templateName; + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + } + + /** * Returns the name of the method that threw the * exception. * diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/exception/ParseErrorException.java b/velocity-engine-core/src/main/java/org/apache/velocity/exception/ParseErrorException.java index 824675c4..34c9c264 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/exception/ParseErrorException.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/exception/ParseErrorException.java @@ -186,11 +186,25 @@ public class ParseErrorException extends VelocityException * * @param exceptionMessage the error exception message * @param info an Info object with the current template info + * @since 2.2 + */ + public ParseErrorException(String exceptionMessage, Info info, String[] stacktrace) + { + super(exceptionMessage, null, stacktrace); + columnNumber = info.getColumn(); + lineNumber = info.getLine(); + templateName = info.getTemplateName(); + } + + /** + * Create a ParseErrorRuntimeException with the given message and info + * + * @param exceptionMessage the error exception message + * @param info an Info object with the current template info * @param invalidSyntax the invalid syntax or reference triggering this exception * @since 1.5 */ - public ParseErrorException(String exceptionMessage, - Info info, String invalidSyntax) + public ParseErrorException(String exceptionMessage, Info info, String invalidSyntax) { super(exceptionMessage); columnNumber = info.getColumn(); diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/exception/ResourceNotFoundException.java b/velocity-engine-core/src/main/java/org/apache/velocity/exception/ResourceNotFoundException.java index 807acb02..7bc2b4cf 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/exception/ResourceNotFoundException.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/exception/ResourceNotFoundException.java @@ -59,6 +59,18 @@ public class ResourceNotFoundException extends VelocityException } /** + * @param exceptionMessage + * @param t + * @param stacktrace VTL stacktrace + * @see VelocityException#VelocityException(String, Throwable) + * @since 2.2 + */ + public ResourceNotFoundException(final String exceptionMessage, final Throwable t, final String[] stacktrace) + { + super(exceptionMessage, t, stacktrace); + } + + /** * @param t * @see VelocityException#VelocityException(Throwable) * @since 1.5 @@ -67,4 +79,15 @@ public class ResourceNotFoundException extends VelocityException { super(t); } + + /** + * @param t + * @param stacktrace VTL stacktrace + * @see VelocityException#VelocityException(Throwable) + * @since 2.2 + */ + public ResourceNotFoundException(final Throwable t, String[] stacktrace) + { + super(t, stacktrace); + } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/exception/TemplateInitException.java b/velocity-engine-core/src/main/java/org/apache/velocity/exception/TemplateInitException.java index 186ba5ba..20620cfe 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/exception/TemplateInitException.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/exception/TemplateInitException.java @@ -41,6 +41,12 @@ public class TemplateInitException extends VelocityException */ private static final long serialVersionUID = -4985224672336070621L; + /** + * @param msg + * @param templateName + * @param col + * @param line + */ public TemplateInitException(final String msg, final String templateName, final int col, final int line) { @@ -50,6 +56,14 @@ public class TemplateInitException extends VelocityException this.line = line; } + /** + * + * @param msg + * @param parseException + * @param templateName + * @param col + * @param line + */ public TemplateInitException(final String msg, ParseException parseException, final String templateName, final int col, final int line) { @@ -60,6 +74,25 @@ public class TemplateInitException extends VelocityException } /** + * + * @param msg + * @param parseException + * @param stacktrace + * @param templateName + * @param col + * @param line + * @since 2.2 + */ + public TemplateInitException(final String msg, ParseException parseException, String[] stacktrace, + final String templateName, final int col, final int line) + { + super(msg,parseException, stacktrace); + this.templateName = templateName; + this.col = col; + this.line = line; + } + + /** * Returns the Template name where this exception occurred. * @return the template name */ diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/exception/VelocityException.java b/velocity-engine-core/src/main/java/org/apache/velocity/exception/VelocityException.java index 8dccb151..dc6de702 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/exception/VelocityException.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/exception/VelocityException.java @@ -19,6 +19,8 @@ package org.apache.velocity.exception; * under the License. */ +import org.apache.velocity.runtime.parser.LogContext; + /** * Base class for Velocity runtime exceptions thrown to the * application layer. @@ -34,6 +36,16 @@ public class VelocityException extends RuntimeException private static final long serialVersionUID = 1251243065134956045L; /** + * LogContext VTL location tracking context + */ + private LogContext logContext = null; + + /** + * VTL vtlStackTrace, populated at construction when runtime.log.track_location is true + */ + private String vtlStackTrace[] = null; + + /** * @param exceptionMessage The message to register. */ public VelocityException(final String exceptionMessage) @@ -52,6 +64,18 @@ public class VelocityException extends RuntimeException } /** + * @param exceptionMessage The message to register. + * @param wrapped A throwable object that caused the Exception. + * @param vtlStackTrace VTL stacktrace + * @since 2.2 + */ + public VelocityException(final String exceptionMessage, final Throwable wrapped, final String[] vtlStackTrace) + { + super(exceptionMessage, wrapped); + this.vtlStackTrace = vtlStackTrace; + } + + /** * @param wrapped A throwable object that caused the Exception. * @since 1.5 */ @@ -61,6 +85,17 @@ public class VelocityException extends RuntimeException } /** + * @param wrapped A throwable object that caused the Exception. + * @param vtlStackTrace VTL stacktrace + * @since 2.2 + */ + public VelocityException(final Throwable wrapped, final String[] vtlStackTrace) + { + super(wrapped); + this.vtlStackTrace = vtlStackTrace; + } + + /** * returns the wrapped Throwable that caused this * MethodInvocationException to be thrown * @@ -73,4 +108,8 @@ public class VelocityException extends RuntimeException return getCause(); } + public String[] getVtlStackTrace() + { + return vtlStackTrace; + } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java index 89aac7ec..9b640e8d 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java @@ -57,7 +57,11 @@ public interface RuntimeConstants extends DeprecatedRuntimeConstants /** Logging of invalid method calls. */ String RUNTIME_LOG_METHOD_CALL_LOG_INVALID = "runtime.log.log_invalid_method_calls"; - /** Whether to populate slf4j's MDC with location in template file + /** <p>Whether to:</p> + * <ul> + * <li>populate slf4j's MDC with location in template file</li> + * <li>display VTL stack trace on errors</li> + * </ul> * @since 2.2 */ String RUNTIME_LOG_TRACK_LOCATION = "runtime.log.track_location"; diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeInstance.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeInstance.java index ed5f9193..3049e76e 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeInstance.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeInstance.java @@ -1488,7 +1488,7 @@ public class RuntimeInstance implements RuntimeConstants, RuntimeServices { String msg = "RuntimeInstance.render(): init exception for tag = "+logTag; log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, getLogContext().getStackTrace()); } try @@ -1518,7 +1518,7 @@ public class RuntimeInstance implements RuntimeConstants, RuntimeServices } catch (IOException e) { - throw new VelocityException("IO Error in writer: " + e.getMessage(), e); + throw new VelocityException("IO Error in writer: " + e.getMessage(), e, getLogContext().getStackTrace()); } } finally @@ -1596,7 +1596,7 @@ public class RuntimeInstance implements RuntimeConstants, RuntimeServices String msg = "RuntimeInstance.invokeVelocimacro(): VM '" + vmName + "' is not registered."; log.error(msg); - throw new VelocityException(msg); + throw new VelocityException(msg, null, getLogContext().getStackTrace()); } /* now just create the VM call, and use evaluate */ diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/VelocimacroFactory.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/VelocimacroFactory.java index da66d8fb..7a1ea79c 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/VelocimacroFactory.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/VelocimacroFactory.java @@ -219,7 +219,7 @@ public class VelocimacroFactory { String msg = "Velocimacro: Error using VM library: " + lib; log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } log.trace("VM library registration complete."); @@ -548,7 +548,7 @@ public class VelocimacroFactory { String msg = "Velocimacro: Error using VM library: " + lib; log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } vp = vmManager.get(vmName, sourceTemplate, renderingTemplate); diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Break.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Break.java index e1c061ed..220f521b 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Break.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Break.java @@ -99,7 +99,9 @@ public class Break extends Directive { throw new VelocityException(node.jjtGetChild(0).literal()+ " is not a valid " + Scope.class.getName() + " instance at " - + StringUtils.formatFileString(this)); + + StringUtils.formatFileString(this), + null, + rsvc.getLogContext().getStackTrace()); } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Define.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Define.java index e444c965..35f4d5cd 100755 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Define.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Define.java @@ -64,7 +64,9 @@ public class Define extends Block if ( node.jjtGetNumChildren() != 2 ) { throw new VelocityException("parameter missing: block name at " - + StringUtils.formatFileString(this)); + + StringUtils.formatFileString(this), + null, + rsvc.getLogContext().getStackTrace()); } /* diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Evaluate.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Evaluate.java index dc5037c1..c261ba6e 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Evaluate.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Evaluate.java @@ -87,6 +87,8 @@ public class Evaluate extends Directive { throw new TemplateInitException( "#" + getName() + "() requires exactly one argument", + null, + rsvc.getLogContext().getStackTrace(), context.getCurrentTemplateName(), node.getColumn(), node.getLine()); @@ -99,6 +101,8 @@ public class Evaluate extends Directive throw new TemplateInitException( "#" + getName() + "() requires exactly one argument", + null, + rsvc.getLogContext().getStackTrace(), context.getCurrentTemplateName(), node.jjtGetChild(1).getColumn(), node.jjtGetChild(1).getLine()); @@ -110,6 +114,8 @@ public class Evaluate extends Directive { throw new TemplateInitException( "#" + getName() + "() argument must be a string literal or reference", + null, + rsvc.getLogContext().getStackTrace(), context.getCurrentTemplateName(), childNode.getColumn(), childNode.getLine()); @@ -169,7 +175,7 @@ public class Evaluate extends Directive { // use the line/column from the template Info info = new Info( templateName, node.getLine(), node.getColumn() ); - throw new ParseErrorException( pex.getMessage(), info ); + throw new ParseErrorException( pex.getMessage(), info, rsvc.getLogContext().getStackTrace() ); } /* @@ -190,7 +196,7 @@ public class Evaluate extends Directive catch (TemplateInitException pex) { Info info = new Info( templateName, node.getLine(), node.getColumn() ); - throw new ParseErrorException( pex.getMessage(), info ); + throw new ParseErrorException( pex.getMessage(), info, rsvc.getLogContext().getStackTrace() ); } try @@ -213,7 +219,7 @@ public class Evaluate extends Directive { // convert any parsing errors to the correct line/col Info info = new Info( templateName, node.getLine(), node.getColumn() ); - throw new ParseErrorException( pex.getMessage(), info ); + throw new ParseErrorException( pex.getMessage(), info, rsvc.getLogContext().getStackTrace() ); } } finally diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Foreach.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Foreach.java index ab09f7fd..19730baf 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Foreach.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Foreach.java @@ -192,7 +192,7 @@ public class Foreach extends Directive String msg = "Error getting iterator for #foreach parameter " + node.literal() + " at " + StringUtils.formatFileString(node); log.error(msg, ee); - throw new VelocityException(msg, ee); + throw new VelocityException(msg, ee, rsvc.getLogContext().getStackTrace()); } if (i == null && !skipInvalidIterator) @@ -201,7 +201,7 @@ public class Foreach extends Directive + StringUtils.formatFileString(node) + " is of type " + iterable.getClass().getName() + " and cannot be iterated by " + rsvc.getUberspect().getClass().getName(); log.error(msg); - throw new VelocityException(msg); + throw new VelocityException(msg, null, rsvc.getLogContext().getStackTrace()); } } return i; diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Include.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Include.java index dd9c8a8a..f3a603b7 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Include.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Include.java @@ -172,7 +172,7 @@ public class Include extends InputBase log.error(msg); outputErrorToStream( writer, "error with arg " + i + " please see log."); - throw new VelocityException(msg); + throw new VelocityException(msg, null, rsvc.getLogContext().getStackTrace()); } } @@ -261,7 +261,7 @@ public class Include extends InputBase String msg = "#include(): arg = '" + arg + "', called at " + StringUtils.formatFileString(this); log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Parse.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Parse.java index 0a472273..a1999c88 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Parse.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Parse.java @@ -142,7 +142,7 @@ public class Parse extends InputBase if ( node.jjtGetNumChildren() == 0 ) { throw new VelocityException("#parse(): argument missing at " + - StringUtils.formatFileString(this)); + StringUtils.formatFileString(this), null, rsvc.getLogContext().getStackTrace()); } /* @@ -170,7 +170,7 @@ public class Parse extends InputBase if (strictRef && value == null && arg == null) { throw new VelocityException("The argument to #parse returned null at " - + StringUtils.formatFileString(this)); + + StringUtils.formatFileString(this), null, rsvc.getLogContext().getStackTrace()); } /* @@ -247,7 +247,7 @@ public class Parse extends InputBase String msg = "Exception rendering #parse(" + arg + ") at " + StringUtils.formatFileString(this); log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } /** @@ -302,7 +302,7 @@ public class Parse extends InputBase String msg = "Exception rendering #parse(" + arg + ") at " + StringUtils.formatFileString(this); log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } finally { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/RuntimeMacro.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/RuntimeMacro.java index 655e9b79..7811babf 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/RuntimeMacro.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/RuntimeMacro.java @@ -161,7 +161,9 @@ public class RuntimeMacro extends Directive /* indicate col/line assuming it starts at 0 * this will be corrected one call up */ throw new TemplateInitException(badArgsErrorMsg, - context.getCurrentTemplateName(), 0, 0); + null, + rsvc.getLogContext().getStackTrace(), + context.getCurrentTemplateName(), 0, 0); } } } @@ -316,6 +318,7 @@ public class RuntimeMacro extends Directive if (badArgsErrorMsg != null) { throw new TemplateInitException(badArgsErrorMsg, + null, rsvc.getLogContext().getStackTrace(), context.getCurrentTemplateName(), node.getColumn(), node.getLine()); } @@ -353,7 +356,7 @@ public class RuntimeMacro extends Directive else if (strictRef) { throw new VelocityException("Macro '#" + macroName + "' is not defined at " - + StringUtils.formatFileString(node)); + + StringUtils.formatFileString(node), null, rsvc.getLogContext().getStackTrace()); } /** diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java index 0b412dc4..6a3e250d 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java @@ -218,7 +218,7 @@ public class VelocimacroProxy extends Directive { String msg = "VelocimacroProxy.render() : exception VM = #" + macroName + "()"; log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } finally { @@ -280,7 +280,7 @@ public class VelocimacroProxy extends Directive { throw new VelocityException("Provided " + callArgNum + " arguments but macro #" + macroArgs.get(0).name + " accepts at most " + (macroArgs.size()-1) - + " at " + StringUtils.formatFileString(node)); + + " at " + StringUtils.formatFileString(node), null, rsvc.getLogContext().getStackTrace()); } // Backward compatibility logging, Mainly for MacroForwardDefinedTestCase log.debug("VM #{}: too many arguments to macro. Wanted {} got {}", @@ -319,7 +319,7 @@ public class VelocimacroProxy extends Directive { context.popCurrentMacroName(); } - throw new MacroOverflowException(out.toString()); + throw new MacroOverflowException(out.toString(), null, rsvc.getLogContext().getStackTrace()); } } @@ -371,7 +371,7 @@ public class VelocimacroProxy extends Directive } throw new VelocityException("Need at least " + minArgNum + " argument for macro #" + macroArgs.get(0).name + " but only " + callArgNum + " where provided at " - + StringUtils.formatFileString(node)); + + StringUtils.formatFileString(node), null, rsvc.getLogContext().getStackTrace()); } else { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/LogContext.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/LogContext.java index 455f2675..75056383 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/LogContext.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/LogContext.java @@ -19,13 +19,17 @@ package org.apache.velocity.runtime.parser; * under the License. */ +import org.apache.velocity.runtime.parser.node.SimpleNode; import org.apache.velocity.util.introspection.Info; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Deque; +import java.util.Iterator; +import java.util.List; /** * <p>Track location in template files during rendering by populating the slf4j MDC tags <code>file</code>, <code>line</code> and <code>column</code>.</p> @@ -42,7 +46,7 @@ import java.util.Deque; public class LogContext { - protected static Logger logger = LoggerFactory.getLogger(LogContext.class); + protected static Logger logger = LoggerFactory.getLogger("rendering"); public static final String MDC_FILE = "file"; public static final String MDC_LINE = "line"; @@ -66,18 +70,18 @@ public class LogContext private static class StackElement { - protected StackElement(Object src, Info info) + protected StackElement(SimpleNode src, Info info) { this.src = src; this.info = info; } - protected Object src; + protected SimpleNode src; protected int count = 1; protected Info info; } - public void pushLogContext(Object src, Info info) + public void pushLogContext(SimpleNode src, Info info) { if (!trackLocation) { @@ -137,4 +141,26 @@ public class LogContext MDC.remove(MDC_LINE); MDC.remove(MDC_COLUMN); } + + private static final String STACKTRACE_LINE = " %s at %s[line %d, column %d]"; + + public String[] getStackTrace() + { + if (!trackLocation) + { + return null; + } + Deque<StackElement> stack = contextStack.get(); + List<String> levels = new ArrayList<>(); + for (StackElement level : stack) + { + String line = String.format(STACKTRACE_LINE, + level.src.literal(), + level.info.getTemplateName(), + level.info.getLine(), + level.info.getColumn()); + levels.add(line); + } + return levels.size() > 0 ? levels.toArray(new String[levels.size()]) : null; + } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTComparisonNode.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTComparisonNode.java index d65d0abc..1e11a947 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTComparisonNode.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTComparisonNode.java @@ -98,7 +98,7 @@ public abstract class ASTComparisonNode extends ASTBinaryOperator + StringUtils.formatFileString(this); if (rsvc.getBoolean(RuntimeConstants.RUNTIME_REFERENCES_STRICT, false)) { - throw new VelocityException(msg); + throw new VelocityException(msg, null, rsvc.getLogContext().getStackTrace()); } log.error(msg); return false; @@ -152,7 +152,7 @@ public abstract class ASTComparisonNode extends ASTBinaryOperator + StringUtils.formatFileString(this); if (rsvc.getBoolean(RuntimeConstants.RUNTIME_REFERENCES_STRICT, false)) { - throw new VelocityException(msg); + throw new VelocityException(msg, null, rsvc.getLogContext().getStackTrace()); } log.error(msg); return false; diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDirective.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDirective.java index 82cf3b4e..0425ff45 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDirective.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDirective.java @@ -139,7 +139,7 @@ public class ASTDirective extends SimpleNode throw new VelocityException( "Couldn't initialize directive of class " + parser.getDirective(directiveName).getClass().getName(), - e); + e, rsvc.getLogContext().getStackTrace()); } t = getFirstToken(); @@ -165,6 +165,7 @@ public class ASTDirective extends SimpleNode { throw new TemplateInitException(die.getMessage(), (ParseException) die.getCause(), + rsvc.getLogContext().getStackTrace(), die.getTemplateName(), die.getColumnNumber() + getColumn(), die.getLineNumber() + getLine()); @@ -201,6 +202,7 @@ public class ASTDirective extends SimpleNode { throw new TemplateInitException(die.getMessage(), (ParseException) die.getCause(), + rsvc.getLogContext().getStackTrace(), die.getTemplateName(), die.getColumnNumber() + getColumn(), die.getLineNumber() + getLine()); @@ -346,4 +348,22 @@ public class ASTDirective extends SimpleNode + directiveName + "]"; } + /** + * Returns the string "#<i>directive_name</i>(...)". Arguments literals are not rendered. This method is only + * used for displaying the VTL stacktrace when a rendering error is encountered when runtime.log.track_location is true. + * @return + */ + @Override + public String literal() + { + if (literal != null) + { + return literal; + } + StringBuilder builder = new StringBuilder(); + builder.append('#').append(getDirectiveName()).append("(...)"); + + return literal = builder.toString(); + } + } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDivNode.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDivNode.java index 977226d2..317a86b8 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDivNode.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDivNode.java @@ -72,7 +72,7 @@ public class ASTDivNode extends ASTMathNode if (strictMode) { log.error(msg); - throw new MathException(msg); + throw new MathException(msg, rsvc.getLogContext().getStackTrace()); } else { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTIdentifier.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTIdentifier.java index 37eaf19e..f57d2d1c 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTIdentifier.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTIdentifier.java @@ -184,7 +184,7 @@ public class ASTIdentifier extends SimpleNode { String msg = "ASTIdentifier.execute() : identifier = "+identifier; log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } /* @@ -196,7 +196,8 @@ public class ASTIdentifier extends SimpleNode if (strictRef) { throw new MethodInvocationException("Object '" + o.getClass().getName() + - "' does not contain property '" + identifier + "'", null, identifier, + "' does not contain property '" + identifier + "'", + null, rsvc.getLogContext().getStackTrace(), identifier, uberInfo.getTemplateName(), uberInfo.getLine(), uberInfo.getColumn()); } else @@ -240,7 +241,7 @@ public class ASTIdentifier extends SimpleNode + " in " + o.getClass() + " threw exception " + ite.getTargetException().toString(), - ite.getTargetException(), vg.getMethodName(), getTemplateName(), this.getLine(), this.getColumn()); + ite.getTargetException(), rsvc.getLogContext().getStackTrace(), vg.getMethodName(), getTemplateName(), this.getLine(), this.getColumn()); } } else @@ -254,7 +255,7 @@ public class ASTIdentifier extends SimpleNode + " in " + o.getClass() + " threw exception " + ite.getTargetException().toString(), - ite.getTargetException(), vg.getMethodName(), getTemplateName(), this.getLine(), this.getColumn()); + ite.getTargetException(), rsvc.getLogContext().getStackTrace(), vg.getMethodName(), getTemplateName(), this.getLine(), this.getColumn()); } @@ -276,7 +277,7 @@ public class ASTIdentifier extends SimpleNode + "for identifier '" + identifier + "' in " + o.getClass(); log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } } finally @@ -284,4 +285,19 @@ public class ASTIdentifier extends SimpleNode rsvc.getLogContext().popLogContext(); } } + + /** + * Returns the string ".<i>identifier</i>". This method is only used for displaying the VTL stacktrace + * when a rendering error is encountered when runtime.log.track_location is true. + * @return + */ + @Override + public String literal() + { + if (literal != null) + { + return literal; + } + return literal = '.' + getIdentifier(); + } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTIndex.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTIndex.java index 9d90ca7f..c5c529cd 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTIndex.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTIndex.java @@ -122,7 +122,8 @@ public class ASTIndex extends SimpleNode throw new VelocityException( "A 'size()' method required for negative value " + (Integer) argument + " does not exist for class '" - + o.getClass().getName() + "' at " + StringUtils.formatFileString(node)); + + o.getClass().getName() + "' at " + StringUtils.formatFileString(node), + null, node.getRuntimeServices().getLogContext().getStackTrace()); } Object size = null; @@ -133,7 +134,8 @@ public class ASTIndex extends SimpleNode catch (Exception e) { throw new VelocityException("Error trying to calls the 'size()' method on '" - + o.getClass().getName() + "' at " + StringUtils.formatFileString(node), e); + + o.getClass().getName() + "' at " + StringUtils.formatFileString(node), e, + node.getRuntimeServices().getLogContext().getStackTrace()); } int sizeint = 0; @@ -146,7 +148,8 @@ public class ASTIndex extends SimpleNode // If size() doesn't return an Integer we want to report a pretty error throw new VelocityException("Method 'size()' on class '" + o.getClass().getName() + "' returned '" + size.getClass().getName() - + "' when Integer was expected at " + StringUtils.formatFileString(node)); + + "' when Integer was expected at " + StringUtils.formatFileString(node), + null, node.getRuntimeServices().getLogContext().getStackTrace()); } argument = sizeint + ((Integer) argument).intValue(); @@ -212,7 +215,7 @@ public class ASTIndex extends SimpleNode + ")' in " + o.getClass().getName() + " at " + StringUtils.formatFileString(this); log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMathNode.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMathNode.java index c47b9ad5..9faa897e 100755 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMathNode.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMathNode.java @@ -121,7 +121,7 @@ public abstract class ASTMathNode extends ASTBinaryOperator if (strictMode) { log.error(msg); - throw new MathException(msg); + throw new MathException(msg, rsvc.getLogContext().getStackTrace()); } else { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMethod.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMethod.java index 7e912e6e..c7fab881 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMethod.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMethod.java @@ -251,7 +251,7 @@ public class ASTMethod extends SimpleNode String msg = "ASTMethod.execute() : exception invoking method '" + methodName + "' in " + o.getClass(); log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } } finally @@ -303,7 +303,7 @@ public class ASTMethod extends SimpleNode + methodName + "' in " + o.getClass() + " threw exception " + e.toString(), - e, methodName, getTemplateName(), this.getLine(), this.getColumn()); + e, rsvc.getLogContext().getStackTrace(), methodName, getTemplateName(), this.getLine(), this.getColumn()); } } @@ -321,7 +321,7 @@ public class ASTMethod extends SimpleNode + methodName + "' in " + o.getClass() + " threw exception " + t.toString(), - t, methodName, getTemplateName(), this.getLine(), this.getColumn()); + t, rsvc.getLogContext().getStackTrace(), methodName, getTemplateName(), this.getLine(), this.getColumn()); } } @@ -417,5 +417,23 @@ public class ASTMethod extends SimpleNode return methodName; } + /** + * Returns the string ".<i>method_name</i>(...)". Arguments literals are not rendered. This method is only + * used for displaying the VTL stacktrace when a rendering error is encountered when runtime.log.track_location is true. + * @return + */ + @Override + public String literal() + { + if (literal != null) + { + return literal; + } + StringBuilder builder = new StringBuilder(); + builder.append('.').append(getMethodName()).append("(...)"); + + return literal = builder.toString(); + } + } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTModNode.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTModNode.java index 69f0559a..5978faf8 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTModNode.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTModNode.java @@ -66,7 +66,7 @@ public class ASTModNode extends ASTMathNode if (strictMode) { log.error(msg); - throw new MathException(msg); + throw new MathException(msg, rsvc.getLogContext().getStackTrace()); } else { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNegateNode.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNegateNode.java index 16e75941..92303041 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNegateNode.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNegateNode.java @@ -72,7 +72,7 @@ public class ASTNegateNode extends SimpleNode if (strictMode) { log.error(msg); - throw new MathException(msg); + throw new MathException(msg, rsvc.getLogContext().getStackTrace()); } else { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java index 0a007e23..2dd97b4c 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java @@ -76,8 +76,6 @@ public class ASTReference extends SimpleNode private boolean checkEmpty; - private String literal = null; - /** * Indicates if we are running in strict reference mode. */ @@ -171,7 +169,7 @@ public class ASTReference extends SimpleNode numChildren = jjtGetNumChildren(); // This is an expensive call, so get it now. - literal = literal(); + literal(); /* * and if appropriate... @@ -358,7 +356,8 @@ public class ASTReference extends SimpleNode throw new VelocityException("Attempted to access '" + name + "' on a null value at " + StringUtils.formatFileString(uberInfo.getTemplateName(), - + jjtGetChild(i).getLine(), jjtGetChild(i).getColumn())); + + jjtGetChild(i).getLine(), jjtGetChild(i).getColumn()), + null, rsvc.getLogContext().getStackTrace()); } previousResult = result; result = jjtGetChild(i).execute(result,context); @@ -563,7 +562,8 @@ public class ASTReference extends SimpleNode { throw new VelocityException("Reference " + literal() + " evaluated to null when attempting to render at " - + StringUtils.formatFileString(this)); + + StringUtils.formatFileString(this) + , null, rsvc.getLogContext().getStackTrace()); } else // toString == null { @@ -573,7 +573,8 @@ public class ASTReference extends SimpleNode throw new VelocityException("Reference " + literal() + " evaluated to object " + value.getClass().getName() + " whose toString() method returned null at " - + StringUtils.formatFileString(this)); + + StringUtils.formatFileString(this) + , null, rsvc.getLogContext().getStackTrace()); } } return true; @@ -677,7 +678,7 @@ public class ASTReference extends SimpleNode catch(Exception e) { throw new VelocityException("Reference evaluation threw an exception at " - + StringUtils.formatFileString(this), e); + + StringUtils.formatFileString(this), e, rsvc.getLogContext().getStackTrace()); } finally { @@ -766,7 +767,7 @@ public class ASTReference extends SimpleNode { String name = jjtGetChild(i+1).getFirstTokenImage(); throw new MethodInvocationException("Attempted to access '" - + name + "' on a null value", null, name, uberInfo.getTemplateName(), + + name + "' on a null value", null, rsvc.getLogContext().getStackTrace(), name, uberInfo.getTemplateName(), jjtGetChild(i+1).getLine(), jjtGetChild(i+1).getColumn()); } @@ -816,7 +817,8 @@ public class ASTReference extends SimpleNode "Found neither a 'set' or 'put' method with param types '(" + printClass(paramClasses[0]) + "," + printClass(paramClasses[1]) + ")' on class '" + result.getClass().getName() - + "' at " + StringUtils.formatFileString(astIndex)); + + "' at " + StringUtils.formatFileString(astIndex) + , null, rsvc.getLogContext().getStackTrace()); } return false; } @@ -837,7 +839,7 @@ public class ASTReference extends SimpleNode + methodName + "(" + printClass(paramClasses[0]) + "," + printClass(paramClasses[1]) + ")' in " + result.getClass(), - e.getCause(), identifier, astIndex.getTemplateName(), astIndex.getLine(), + e.getCause(), rsvc.getLogContext().getStackTrace(), identifier, astIndex.getTemplateName(), astIndex.getLine(), astIndex.getColumn()); } @@ -862,7 +864,7 @@ public class ASTReference extends SimpleNode if (strictRef) { throw new MethodInvocationException("Object '" + result.getClass().getName() + - "' does not contain property '" + identifier + "'", null, identifier, + "' does not contain property '" + identifier + "'", null, rsvc.getLogContext().getStackTrace(), identifier, uberInfo.getTemplateName(), uberInfo.getLine(), uberInfo.getColumn()); } else @@ -884,7 +886,7 @@ public class ASTReference extends SimpleNode + identifier + "' in " + result.getClass() + " threw exception " + ite.getTargetException().toString(), - ite.getTargetException(), identifier, getTemplateName(), this.getLine(), this.getColumn()); + ite.getTargetException(), rsvc.getLogContext().getStackTrace(), identifier, getTemplateName(), this.getLine(), this.getColumn()); } /** * pass through application level runtime exceptions @@ -901,7 +903,7 @@ public class ASTReference extends SimpleNode String msg = "ASTReference setValue(): exception: " + e + " template at " + StringUtils.formatFileString(uberInfo); log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } return true; @@ -1145,7 +1147,7 @@ public class ASTReference extends SimpleNode log.error("Variable ${} has not been set at {}", rootString, StringUtils.formatFileString(uberInfo)); throw new MethodInvocationException("Variable $" + rootString + - " has not been set", null, identifier, + " has not been set", null, rsvc.getLogContext().getStackTrace(), identifier, uberInfo.getTemplateName(), uberInfo.getLine(), uberInfo.getColumn()); } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTSetDirective.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTSetDirective.java index 4af186d6..91259dd4 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTSetDirective.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTSetDirective.java @@ -264,6 +264,23 @@ public class ASTSetDirective extends SimpleNode } /** + * Returns the string "#set($<i>reference</i> = ...)". RHS is not rendered. This method is only + * used for displaying the VTL stacktrace when a rendering error is encountered when runtime.log.track_location is true. + * @return + */ + @Override + public String literal() + { + if (literal != null) + { + return literal; + } + StringBuilder builder = new StringBuilder(); + builder.append("#set(").append(left.literal()).append(" = ...)"); + return literal = builder.toString(); + } + + /** * returns the ASTReference that is the LHS of the set statement * * @return left hand side of #set statement diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTStringLiteral.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTStringLiteral.java index 78a462d8..460a7b76 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTStringLiteral.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTStringLiteral.java @@ -149,7 +149,7 @@ public class ASTStringLiteral extends SimpleNode { String msg = "Failed to parse String literal at "+ StringUtils.formatFileString(template.getName(), getLine(), getColumn()); - throw new TemplateInitException(msg, e, template.getName(), getColumn(), getLine()); + throw new TemplateInitException(msg, e, rsvc.getLogContext().getStackTrace(), template.getName(), getColumn(), getLine()); } adjTokenLineNums(nodeTree); @@ -335,7 +335,7 @@ public class ASTStringLiteral extends SimpleNode { String msg = "Error in interpolating string literal"; log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ContentResource.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ContentResource.java index 27d53238..adccb7f0 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ContentResource.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ContentResource.java @@ -85,7 +85,7 @@ public class ContentResource extends Resource { String msg = "Cannot process content resource"; log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } finally { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ResourceManagerImpl.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ResourceManagerImpl.java index eb7054de..472286bc 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ResourceManagerImpl.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ResourceManagerImpl.java @@ -132,7 +132,7 @@ public class ResourceManagerImpl ".class' specification in configuration." + " This is a critical value. Please adjust configuration."; log.error(msg); - throw new VelocityException(msg); + throw new VelocityException(msg, null, rsvc.getLogContext().getStackTrace()); } resourceLoader.commonInit(rsvc, configuration); @@ -458,7 +458,7 @@ public class ResourceManagerImpl */ if (resource.getData() == null) { - throw new ResourceNotFoundException("Unable to find resource '" + resourceName + "'"); + throw new ResourceNotFoundException("Unable to find resource '" + resourceName + "'", null, rsvc.getLogContext().getStackTrace()); } /* diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java index 50443df8..7ba64a38 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java @@ -133,14 +133,14 @@ public class ClasspathResourceLoader extends ResourceLoader } catch (IOException ioe) {} } - throw new ResourceNotFoundException("ClasspathResourceLoader problem with template: " + name, fnfe ); + throw new ResourceNotFoundException("ClasspathResourceLoader problem with template: " + name, fnfe, rsvc.getLogContext().getStackTrace() ); } if (result == null) { String msg = "ClasspathResourceLoader Error: cannot find resource " + name; - throw new ResourceNotFoundException( msg ); + throw new ResourceNotFoundException( msg, null, rsvc.getLogContext().getStackTrace() ); } return result; diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java index 6e9db6ff..5ef6d446 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java @@ -340,7 +340,7 @@ public class DataSourceResourceLoader extends ResourceLoader + operation + " of '" + name + "': "; log.error(msg, sqle); - throw new VelocityException(msg, sqle); + throw new VelocityException(msg, sqle, rsvc.getLogContext().getStackTrace()); } finally { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java index f8c5a811..aa219591 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java @@ -143,7 +143,7 @@ public class FileResourceLoader extends ResourceLoader closeQuiet(rawStream); String msg = "Exception while loading Template " + template; log.error(msg, ioe); - throw new VelocityException(msg, ioe); + throw new VelocityException(msg, ioe, rsvc.getLogContext().getStackTrace()); } if (reader != null) { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java index f7ae8f2d..3adb3efb 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java @@ -230,7 +230,7 @@ public class JarResourceLoader extends ResourceLoader } String msg = "JAR resource error: Exception while loading " + source; log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace()); } } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java index 98c47934..8cfa4fde 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java @@ -389,7 +389,7 @@ public class StringResourceLoader extends ResourceLoader } catch (IOException ioe) {} } - throw new VelocityException("Could not convert String using encoding " + resource.getEncoding(), ue); + throw new VelocityException("Could not convert String using encoding " + resource.getEncoding(), ue, rsvc.getLogContext().getStackTrace()); } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/URLResourceLoader.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/URLResourceLoader.java index f5eac4a5..4d5435fc 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/URLResourceLoader.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/URLResourceLoader.java @@ -195,7 +195,7 @@ public class URLResourceLoader extends ResourceLoader // the file is not reachable at its previous address String msg = "URLResourceLoader: '"+name+"' is no longer reachable at '"+root+"'"; log.error(msg, ioe); - throw new ResourceNotFoundException(msg, ioe); + throw new ResourceNotFoundException(msg, ioe, rsvc.getLogContext().getStackTrace()); } } diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java b/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java index 769029c9..96dd7956 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java @@ -171,7 +171,7 @@ public class UberspectImpl implements Uberspect, RuntimeServicesAware + "; Velocity is not initialized correctly."; log.error(err); - throw new VelocityException(err); + throw new VelocityException(err, null, rsvc.getLogContext().getStackTrace()); } else { @@ -254,7 +254,7 @@ public class UberspectImpl implements Uberspect, RuntimeServicesAware catch (Exception e) { throw new VelocityException("Error invoking the method 'iterator' on class '" - + obj.getClass().getName() +"'", e); + + obj.getClass().getName() +"'", e, rsvc.getLogContext().getStackTrace()); } } else diff --git a/velocity-engine-core/src/main/parser/Parser.jjt b/velocity-engine-core/src/main/parser/Parser.jjt index 448ed03c..3fbfe28b 100644 --- a/velocity-engine-core/src/main/parser/Parser.jjt +++ b/velocity-engine-core/src/main/parser/Parser.jjt @@ -284,7 +284,7 @@ public class ${parser.basename}Parser implements Parser { String msg = template.getName() + ": " + e.getMessage(); log.error(msg, e); - throw new VelocityException(msg, e); + throw new VelocityException(msg, e, getRuntimeServices().getLogContext().getStackTrace()); } currentTemplate = null; |