Author: nbubna
Date: Sat Feb 21 05:41:24 2009
New Revision: 746438
URL: http://svn.apache.org/viewvc?rev=746438&view=rev
Log:
VELOCITY-704 initial implementation of scope controls
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/Template.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Block.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/BlockMacro.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Directive.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Evaluate.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Include.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Literal.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Macro.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Parse.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/RuntimeMacro.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTMethod.java
Modified: velocity/engine/trunk/src/java/org/apache/velocity/Template.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/Template.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/Template.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/Template.java Sat Feb 21
05:41:24 2009
@@ -34,6 +34,9 @@
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.directive.Scope;
+import org.apache.velocity.runtime.directive.StopCommand;
import org.apache.velocity.runtime.parser.ParseException;
import org.apache.velocity.runtime.parser.node.SimpleNode;
import org.apache.velocity.runtime.parser.node.ASTStop.StopThrowable;
@@ -64,6 +67,13 @@
*/
public class Template extends Resource
{
+ /*
+ * The name of the variable to use when placing
+ * the scope object into the context.
+ */
+ private String scopeName = "template";
+ private boolean provideScope = true;
+
private VelocityException errorCondition = null;
/** Default constructor */
@@ -216,6 +226,9 @@
*/
((SimpleNode)data).init( ica, rsvc);
+
+ String property =
scopeName+'.'+RuntimeConstants.PROVIDE_SCOPE_CONTROL;
+ provideScope = rsvc.getBoolean(property, provideScope);
}
finally
{
@@ -332,6 +345,10 @@
}
}
+ if (provideScope)
+ {
+ ica.put(scopeName, new Scope(this, ica.get(scopeName)));
+ }
try
{
ica.pushCurrentTemplateName( name );
@@ -339,6 +356,13 @@
( (SimpleNode) data ).render( ica, writer);
}
+ catch (StopCommand stop)
+ {
+ if (!stop.isFor(this))
+ {
+ throw stop;
+ }
+ }
catch (StopThrowable st)
{
// The stop throwable is thrown by ASTStop (the #stop directive)
@@ -358,6 +382,27 @@
*/
ica.popCurrentTemplateName();
ica.setCurrentResource( null );
+
+ if (provideScope)
+ {
+ Object obj = ica.get(scopeName);
+ if (obj instanceof Scope)
+ {
+ 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
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
Sat Feb 21 05:41:24 2009
@@ -169,6 +169,12 @@
*/
String EVALUATE_CONTEXT_CLASS = "directive.evaluate.context.class";
+ /**
+ * Used to suppress various scope control objects.
+ * @since 1.7
+ */
+ String PROVIDE_SCOPE_CONTROL = "provide.scope.control";
+
/*
* ----------------------------------------------------------------------
* R E S O U R C E M A N A G E R C O N F I G U R A T I O N
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
Sat Feb 21 05:41:24 2009
@@ -49,6 +49,8 @@
import org.apache.velocity.exception.TemplateInitException;
import org.apache.velocity.exception.VelocityException;
import org.apache.velocity.runtime.directive.Directive;
+import org.apache.velocity.runtime.directive.Scope;
+import org.apache.velocity.runtime.directive.StopCommand;
import org.apache.velocity.runtime.log.Log;
import org.apache.velocity.runtime.log.LogManager;
import org.apache.velocity.runtime.parser.ParseException;
@@ -189,6 +191,11 @@
*/
private Introspector introspector = null;
+ /*
+ * Settings for provision of root scope for evaluate(...) calls.
+ */
+ private String evaluateScopeName = "evaluate";
+ private boolean provideEvaluateScope = true;
/*
* Opaque reference to something specificed by the
@@ -255,6 +262,7 @@
initializeParserPool();
initializeIntrospection();
+ initializeEvaluateScopeSettings();
/*
* initialize the VM Factory. It will use the properties
* accessable from Runtime, so keep this here at the end.
@@ -1215,6 +1223,12 @@
}
}
+ private void initializeEvaluateScopeSettings()
+ {
+ String property = evaluateScopeName+'.'+PROVIDE_SCOPE_CONTROL;
+ provideEvaluateScope = getBoolean(property, provideEvaluateScope);
+ }
+
/**
* Renders the input string using the context into the output writer.
* To be used when a template is dynamically constructed, or want to use
@@ -1344,8 +1358,20 @@
try
{
+ if (provideEvaluateScope)
+ {
+ Object previous = ica.get(evaluateScopeName);
+ context.put(evaluateScopeName, new Scope(this, previous));
+ }
nodeTree.render(ica, writer);
- }
+ }
+ catch (StopCommand stop)
+ {
+ if (!stop.isFor(this))
+ {
+ throw stop;
+ }
+ }
catch (StopThrowable st)
{
// The stop throwable is thrown by ASTStop (the #stop
directive)
@@ -1362,6 +1388,26 @@
finally
{
ica.popCurrentTemplateName();
+ if (provideEvaluateScope)
+ {
+ Object obj = ica.get(evaluateScopeName);
+ if (obj instanceof Scope)
+ {
+ Scope scope = (Scope)obj;
+ if (scope.getParent() != null)
+ {
+ ica.put(evaluateScopeName, scope.getParent());
+ }
+ else if (scope.getReplaced() != null)
+ {
+ ica.put(evaluateScopeName, scope.getReplaced());
+ }
+ else
+ {
+ ica.remove(evaluateScopeName);
+ }
+ }
+ }
}
return true;
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Block.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Block.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Block.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Block.java
Sat Feb 21 05:41:24 2009
@@ -75,6 +75,35 @@
block = node.jjtGetChild(node.jjtGetNumChildren() - 1);
}
+ public boolean render(InternalContextAdapter context, Writer writer)
+ {
+ preRender(context);
+ try
+ {
+ return block.render(context, writer);
+ }
+ catch (IOException e)
+ {
+ String msg = "Failed to render " + id(context) + " to writer "
+ + " at " + Log.formatFileString(this);
+
+ log.error(msg, e);
+ throw new RuntimeException(msg, e);
+ }
+ catch (StopCommand stop)
+ {
+ if (!stop.isFor(this))
+ {
+ throw stop;
+ }
+ return true;
+ }
+ finally
+ {
+ postRender(context);
+ }
+ }
+
/**
* Creates a string identifying the source and location of the block
* definition, and the current template being rendered if that is
@@ -113,37 +142,26 @@
*/
public boolean render(InternalContextAdapter context, Writer writer)
{
- try
+ depth++;
+ if (depth > parent.maxDepth)
{
- depth++;
- if (depth > parent.maxDepth)
- {
- /* this is only a debug message, as recursion can
- * happen in quasi-innocent situations and is relatively
- * harmless due to how we handle it here.
- * this is more to help anyone nuts enough to intentionally
- * use recursive block definitions and having problems
- * pulling it off properly.
- */
- parent.log.debug("Max recursion depth reached for " +
parent.id(context)
- + " at " + Log.formatFileString(parent));
- depth--;
- return false;
- }
- else
- {
- parent.block.render(context, writer);
- depth--;
- return true;
- }
+ /* this is only a debug message, as recursion can
+ * happen in quasi-innocent situations and is relatively
+ * harmless due to how we handle it here.
+ * this is more to help anyone nuts enough to intentionally
+ * use recursive block definitions and having problems
+ * pulling it off properly.
+ */
+ parent.log.debug("Max recursion depth reached for " +
parent.id(context)
+ + " at " + Log.formatFileString(parent));
+ depth--;
+ return false;
}
- catch (IOException e)
+ else
{
- String msg = "Failed to render " + parent.id(context) + " to
writer "
- + " at " + Log.formatFileString(parent);
-
- parent.log.error(msg, e);
- throw new RuntimeException(msg, e);
+ parent.render(context, writer);
+ depth--;
+ return true;
}
}
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/BlockMacro.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/BlockMacro.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/BlockMacro.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/BlockMacro.java
Sat Feb 21 05:41:24 2009
@@ -67,10 +67,19 @@
this.name = name;
}
- // This is required, but not actually used.
public String getName()
{
- throw new UnsupportedOperationException("BlockMacro is not actually a
named macro.");
+ return key;
+ }
+
+ /**
+ * Override to use the macro name, since it is within an
+ * #...@mymacro() ... #end block that the scope in question
+ * would be used.
+ */
+ public String getScopeName()
+ {
+ return name;
}
/**
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java
Sat Feb 21 05:41:24 2009
@@ -68,6 +68,15 @@
}
/**
+ * Since there is no processing of content,
+ * there is never a need for an internal scope.
+ */
+ public boolean isScopeProvided()
+ {
+ return false;
+ }
+
+ /**
* simple init - init the tree and get the elementKey from
* the AST
* @param rs
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Directive.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Directive.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Directive.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Directive.java
Sat Feb 21 05:41:24 2009
@@ -22,6 +22,7 @@
import java.io.Writer;
import java.io.IOException;
+import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.context.InternalContextAdapter;
@@ -37,12 +38,14 @@
* Base class for all directives used in Velocity.
*
* @author <a href="mailto:[email protected]">Jason van Zyl</a>
+ * @author Nathan Bubna
* @version $Id$
*/
public abstract class Directive implements DirectiveConstants, Cloneable
{
private int line = 0;
private int column = 0;
+ private boolean provideScope = true;
private String templateName;
/**
@@ -112,6 +115,24 @@
}
/**
+ * @returns the name to be used when a scope control is provided for this
+ * directive.
+ */
+ public String getScopeName()
+ {
+ return getName();
+ }
+
+ /**
+ * @return true if there will be a scope control injected into the context
+ * when rendering this directive.
+ */
+ public boolean isScopeProvided()
+ {
+ return provideScope;
+ }
+
+ /**
* How this directive is to be initialized.
* @param rs
* @param context
@@ -124,10 +145,8 @@
{
rsvc = rs;
- // int i, k = node.jjtGetNumChildren();
-
- //for (i = 0; i < k; i++)
- // node.jjtGetChild(i).init(context, rs);
+ String property =
getScopeName()+'.'+RuntimeConstants.PROVIDE_SCOPE_CONTROL;
+ this.provideScope = rsvc.getBoolean(property, true);
}
/**
@@ -145,4 +164,56 @@
Writer writer, Node node )
throws IOException, ResourceNotFoundException, ParseErrorException,
MethodInvocationException;
+
+
+ /**
+ * This creates and places the scope control for this directive
+ * into the context (if scope provision is turned on).
+ */
+ protected void preRender(InternalContextAdapter context)
+ {
+ if (isScopeProvided())
+ {
+ String name = getScopeName();
+ Object previous = context.get(name);
+ context.put(name, new Scope(this, previous));
+ }
+ }
+
+ /**
+ * This cleans up any scope control for this directive after rendering,
+ * assuming the scope control was turned on.
+ */
+ protected void postRender(InternalContextAdapter context)
+ {
+ if (isScopeProvided())
+ {
+ String name = getScopeName();
+ Object obj = context.get(name);
+
+ // the user can override the scope with a #set,
+ // since that means they don't care about a replaced value
+ // and obviously aren't too keen on their scope control,
+ // and especially since #set is meant to be handled globally,
+ // we'll assume they know what they're doing and not worry
+ // about replacing anything superseded by this directive's scope
+ if (obj instanceof Scope)
+ {
+ Scope scope = (Scope)obj;
+ if (scope.getParent() != null)
+ {
+ context.put(name, scope.getParent());
+ }
+ else if (scope.getReplaced() != null)
+ {
+ context.put(name, scope.getReplaced());
+ }
+ else
+ {
+ context.remove(name);
+ }
+ }
+ }
+ }
+
}
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Evaluate.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Evaluate.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Evaluate.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Evaluate.java
Sat Feb 21 05:41:24 2009
@@ -198,11 +198,20 @@
try
{
+ preRender(ica);
+
/*
* now render, and let any exceptions fly
*/
nodeTree.render( ica, writer );
}
+ catch (StopCommand stop)
+ {
+ if (!stop.isFor(this))
+ {
+ throw stop;
+ }
+ }
catch (StopThrowable st)
{
// The stop throwable is thrown by ASTStop (the #stop
directive)
@@ -221,12 +230,11 @@
finally
{
ica.popCurrentTemplateName();
+ postRender(ica);
}
-
return true;
}
-
return false;
}
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java
Sat Feb 21 05:41:24 2009
@@ -331,7 +331,18 @@
Object o = context.get(elementKey);
Object savedCounter = context.get(counterName);
Object nextFlag = context.get(hasNextName);
-
+
+ /*
+ * roll our own scope class instead of using preRender(ctx)'s
+ */
+ ForeachScope foreach = null;
+ if (isScopeProvided())
+ {
+ String name = getScopeName();
+ foreach = new ForeachScope(this, context.get(name));
+ context.put(name, foreach);
+ }
+
/*
* Instantiate the null holder context if a null value
* is returned by the foreach iterator. Only one instance is
@@ -341,6 +352,13 @@
while (!maxNbrLoopsExceeded && i.hasNext())
{
+ if (isScopeProvided())
+ {
+ // update the scope control
+ foreach.index++;
+ foreach.hasNext = i.hasNext();
+ }
+
// TODO: JDK 1.5+ -> Integer.valueOf()
put(context, counterName , new Integer(counter));
Object value = i.next();
@@ -366,6 +384,19 @@
node.jjtGetChild(3).render(context, writer);
}
}
+ catch (StopCommand stop)
+ {
+ if (stop.isFor(this))
+ {
+ break;
+ }
+ else
+ {
+ // clean up first
+ clean(context, o, savedCounter, nextFlag);
+ throw stop;
+ }
+ }
catch (Break.BreakException ex)
{
// encountered #break directive inside #foreach loop
@@ -378,40 +409,43 @@
// ASSUMPTION: counterInitialValue is not negative!
maxNbrLoopsExceeded = (counter - counterInitialValue) >=
maxNbrLoops;
}
+ clean(context, o, savedCounter, nextFlag);
+ return true;
+ }
+ protected void clean(InternalContextAdapter context,
+ Object o, Object savedCounter, Object nextFlag)
+ {
/*
- * restores the loop counter (if we were nested)
- * if we have one, else just removes
+ * restores element key if exists
+ * otherwise just removes
*/
-
- if (savedCounter != null)
+ if (o != null)
{
- context.put(counterName, savedCounter);
+ context.put(elementKey, o);
}
else
{
- context.remove(counterName);
+ context.remove(elementKey);
}
-
/*
- * restores element key if exists
- * otherwise just removes
+ * restores the loop counter (if we were nested)
+ * if we have one, else just removes
*/
-
- if (o != null)
+ if (savedCounter != null)
{
- context.put(elementKey, o);
+ context.put(counterName, savedCounter);
}
else
{
- context.remove(elementKey);
+ context.remove(counterName);
}
/*
* restores the "hasNext" boolean flag if it exists
*/
- if( nextFlag != null )
+ if (nextFlag != null)
{
context.put(hasNextName, nextFlag);
}
@@ -420,6 +454,7 @@
context.remove(hasNextName);
}
- return true;
+ // clean up after the ForeachScope
+ postRender(context);
}
}
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Include.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Include.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Include.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Include.java
Sat Feb 21 05:41:24 2009
@@ -94,6 +94,15 @@
}
/**
+ * Since there is no processing of content,
+ * there is never a need for an internal scope.
+ */
+ public boolean isScopeProvided()
+ {
+ return false;
+ }
+
+ /**
* simple init - init the tree and get the elementKey from
* the AST
* @param rs
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Literal.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Literal.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Literal.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Literal.java
Sat Feb 21 05:41:24 2009
@@ -62,6 +62,15 @@
}
/**
+ * Since there is no processing of content,
+ * there is never a need for an internal scope.
+ */
+ public boolean isScopeProvided()
+ {
+ return false;
+ }
+
+ /**
* Store the literal rendition of a node using
* the Node.literal().
* @param rs
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Macro.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Macro.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Macro.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Macro.java
Sat Feb 21 05:41:24 2009
@@ -71,6 +71,15 @@
}
/**
+ * Since this class does no processing of content,
+ * there is never a need for an internal scope.
+ */
+ public boolean isScopeProvided()
+ {
+ return false;
+ }
+
+ /**
* render() doesn't do anything in the final output rendering.
* There is no output from a #macro() directive.
* @param context
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Parse.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Parse.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Parse.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Parse.java
Sat Feb 21 05:41:24 2009
@@ -75,6 +75,16 @@
}
/**
+ * Overrides the default to use "template", so that all templates
+ * can use the same scope reference, whether rendered via #parse
+ * or direct merge.
+ */
+ public String getScopeName()
+ {
+ return "template";
+ }
+
+ /**
* Return type of this directive.
* @return The type of this directive.
*/
@@ -247,10 +257,18 @@
try
{
if (!blockinput) {
+ preRender(context);
context.pushCurrentTemplateName(arg);
((SimpleNode) t.getData()).render( context, writer );
}
}
+ catch( StopCommand stop )
+ {
+ if (!stop.isFor(this))
+ {
+ throw stop;
+ }
+ }
/**
* pass through application level runtime exceptions
*/
@@ -273,7 +291,10 @@
finally
{
if (!blockinput)
+ {
context.popCurrentTemplateName();
+ postRender(context);
+ }
}
/*
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/RuntimeMacro.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/RuntimeMacro.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/RuntimeMacro.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/RuntimeMacro.java
Sat Feb 21 05:41:24 2009
@@ -104,6 +104,17 @@
}
/**
+ * Override to always return "macro". We don't want to use
+ * the macro name here, since when writing VTL that uses the
+ * scope, we are within a #macro call. The macro name will instead
+ * be used as the scope name when defining the body of a BlockMacro.
+ */
+ public String getScopeName()
+ {
+ return "macro";
+ }
+
+ /**
* Velocimacros are always LINE
* type directives.
*
@@ -296,8 +307,17 @@
try
{
+ preRender(context);
return vmProxy.render(context, writer, node, body);
}
+ catch (StopCommand stop)
+ {
+ if (!stop.isFor(this))
+ {
+ throw stop;
+ }
+ return true;
+ }
catch (RuntimeException e)
{
/**
@@ -317,6 +337,10 @@
Log.formatFileString(node));
throw e;
}
+ finally
+ {
+ postRender(context);
+ }
}
else if (strictRef)
{
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTMethod.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTMethod.java?rev=746438&r1=746437&r2=746438&view=diff
==============================================================================
---
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTMethod.java
(original)
+++
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTMethod.java
Sat Feb 21 05:41:24 2009
@@ -29,6 +29,7 @@
import org.apache.velocity.exception.TemplateInitException;
import org.apache.velocity.exception.VelocityException;
import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.directive.StopCommand;
import org.apache.velocity.runtime.parser.Parser;
import org.apache.velocity.util.ClassUtils;
import org.apache.velocity.util.introspection.Info;
@@ -212,18 +213,21 @@
private Object handleInvocationException(Object o, InternalContextAdapter
context, Throwable t)
{
/*
+ * We let StopCommands go up to the directive they are for/from
+ */
+ if (t instanceof StopCommand)
+ {
+ throw (StopCommand)t;
+ }
+
+ /*
* In the event that the invocation of the method
* itself throws an exception, we want to catch that
* wrap it, and throw. We don't log here as we want to figure
* out which reference threw the exception, so do that
* above
*/
-
- /*
- * let non-Exception Throwables go...
- */
-
- if (t instanceof Exception)
+ else if (t instanceof Exception)
{
try
{
@@ -245,6 +249,10 @@
e, methodName, getTemplateName(), this.getLine(),
this.getColumn());
}
}
+
+ /*
+ * let non-Exception Throwables go...
+ */
else
{
/*