aboutsummaryrefslogtreecommitdiff
path: root/velocity-engine-core/src
diff options
context:
space:
mode:
authorClaude Brisson <cbrisson@apache.org>2019-09-08 10:42:47 +0000
committerClaude Brisson <cbrisson@apache.org>2019-09-08 10:42:47 +0000
commit5782c4cfa7beab546f778d51d5af2c3503e76aec (patch)
tree5bd4ca076135fa41f3d8be47c15cba1f323d3312 /velocity-engine-core/src
parentacf40deb4da66c5852b16244f3d818e46ed2b7c2 (diff)
downloadapache-velocity-engine-5782c4cfa7beab546f778d51d5af2c3503e76aec.tar.gz
[VELOCITY-916] Add a second effect for the debugging flag runtime.log.track_location: display VTL stacktrace on errors
git-svn-id: https://svn.apache.org/repos/asf/velocity/engine/trunk@1866609 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'velocity-engine-core/src')
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/Template.java238
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/app/event/EventHandlerUtil.java12
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/exception/MacroOverflowException.java22
-rwxr-xr-xvelocity-engine-core/src/main/java/org/apache/velocity/exception/MathException.java13
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/exception/MethodInvocationException.java22
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/exception/ParseErrorException.java18
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/exception/ResourceNotFoundException.java23
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/exception/TemplateInitException.java33
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/exception/VelocityException.java39
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java6
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeInstance.java6
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/VelocimacroFactory.java4
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Break.java4
-rwxr-xr-xvelocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Define.java4
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Evaluate.java12
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Foreach.java4
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Include.java4
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/Parse.java8
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/RuntimeMacro.java7
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java8
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/LogContext.java34
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTComparisonNode.java4
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDirective.java22
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDivNode.java2
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTIdentifier.java26
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTIndex.java11
-rwxr-xr-xvelocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMathNode.java2
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMethod.java24
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTModNode.java2
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNegateNode.java2
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java30
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTSetDirective.java17
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTStringLiteral.java4
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ContentResource.java2
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ResourceManagerImpl.java4
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java4
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java2
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java2
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java2
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java2
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/URLResourceLoader.java2
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java4
-rw-r--r--velocity-engine-core/src/main/parser/Parser.jjt2
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;