Author: cbrisson
Date: Fri Dec 13 13:25:26 2019
New Revision: 1871332
URL: http://svn.apache.org/viewvc?rev=1871332&view=rev
Log:
[engine][VELOCITY-904] Handle nested macro calls in
'velocimacro.arguments.preserve_literals' backward compatibility mode
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity904TestCase.java
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java?rev=1871332&r1=1871331&r2=1871332&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java
Fri Dec 13 13:25:26 2019
@@ -32,6 +32,8 @@ import org.apache.velocity.util.StringUt
import java.io.IOException;
import java.io.Writer;
+import java.util.Deque;
+import java.util.LinkedList;
import java.util.List;
/**
@@ -45,7 +47,7 @@ import java.util.List;
public class VelocimacroProxy extends Directive
{
private String macroName;
- private List<Macro.MacroArg> macroArgs = null;
+ private List<MacroArg> macroArgs = null;
private String[] literalArgArray = null;
private SimpleNode nodeTree = null;
private int numMacroArgs = 0;
@@ -54,6 +56,8 @@ public class VelocimacroProxy extends Di
private String bodyReference;
private boolean preserveArgumentsLiterals;
+ private static final Object NULL_VALUE_MARKER = new Object();
+
/**
* Return name of this Velocimacro.
* @return The name of this Velocimacro.
@@ -244,23 +248,29 @@ public class VelocimacroProxy extends Di
if (current == values[(i-1) * 2 + 1])
{
Object old = values[(i-1) * 2];
- if (old != null)
+ if (old == null)
{
- context.put(macroArg.name, old);
+ context.remove(macroArg.name);
+ }
+ else if (old == NULL_VALUE_MARKER)
+ {
+ context.put(macroArg.name, null);
}
else
{
- context.remove(macroArg.name);
+ context.put(macroArg.name, old);
}
}
- }
- if (preserveArgumentsLiterals)
- {
- for (String literalKey : literalArgArray)
+ if (preserveArgumentsLiterals)
{
- // The behavior is not recursive.
- context.remove(literalKey);
+ /* allow for nested calls */
+ Deque<String> literalsStack =
(Deque<String>)context.get(literalArgArray[i]);
+ literalsStack.removeFirst();
+ if (literalsStack.size() == 0)
+ {
+ context.remove(literalArgArray[i]);
+ }
}
}
}
@@ -343,7 +353,11 @@ public class VelocimacroProxy extends Di
for (int i = 1; i < macroArgs.size(); i++)
{
MacroArg macroArg = macroArgs.get(i);
- values[(i-1) * 2] = context.get(macroArg.name);
+ Object oldVal = context.get(macroArg.name);
+ values[(i-1) * 2] =
+ oldVal == null
+ ? context.containsKey(macroArg.name) ? NULL_VALUE_MARKER : null
+ : oldVal;
// put the new value in
Object newVal = null;
@@ -389,12 +403,18 @@ public class VelocimacroProxy extends Di
we still expect the passed argument literal to be displayed to
be fully backward compatible. */
if (preserveArgumentsLiterals && /* newVal == null && */ argNode
!= null)
{
- context.put(literalArgArray[i], argNode);
+ /* allow nested macro calls for B.C. */
+ Deque<String> literalsStack =
(Deque<String>)context.get(literalArgArray[i]);
+ if (literalsStack == null)
+ {
+ literalsStack = new LinkedList();
+ context.put(literalArgArray[i], literalsStack);
+ }
+ literalsStack.addFirst(argNode.literal());
}
}
// return the array of replaced and new values
return values;
}
-
}
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java?rev=1871332&r1=1871331&r2=1871332&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java
Fri Dec 13 13:25:26 2019
@@ -28,7 +28,6 @@ import org.apache.velocity.io.Filter;
import org.apache.velocity.runtime.Renderable;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.directive.Block.Reference;
-import org.apache.velocity.runtime.parser.LogContext;
import org.apache.velocity.runtime.parser.Parser;
import org.apache.velocity.runtime.parser.Token;
import org.apache.velocity.util.ClassUtils;
@@ -41,6 +40,7 @@ import org.apache.velocity.util.introspe
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
+import java.util.Deque;
/**
* This class is responsible for handling the references in
@@ -65,6 +65,7 @@ public class ASTReference extends Simple
private int referenceType;
private String nullString;
+ private String alternateNullStringKey;
private String rootString;
private boolean escaped = false;
private boolean computableReference = true;
@@ -165,6 +166,11 @@ public class ASTReference extends Simple
*/
rootString = rsvc.useStringInterning() ? getRoot().intern() :
getRoot();
+ if (lookupAlternateLiteral)
+ {
+ /* cache alternate null tring key */
+ alternateNullStringKey = ".literal." + nullString;
+ }
numChildren = jjtGetNumChildren();
@@ -644,10 +650,10 @@ public class ASTReference extends Simple
if (lookupAlternateLiteral)
{
- Node callingArgument = (Node)context.get(".literal." + nullString);
- if (callingArgument != null)
+ Deque<String> alternateLiteralsStack =
(Deque<String>)context.get(alternateNullStringKey);
+ if (alternateLiteralsStack != null &&
alternateLiteralsStack.size() > 0)
{
- ret = ((Node) callingArgument).literal();
+ ret = alternateLiteralsStack.peekFirst();
}
}
return ret;
Modified:
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity904TestCase.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity904TestCase.java?rev=1871332&r1=1871331&r2=1871332&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity904TestCase.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity904TestCase.java
Fri Dec 13 13:25:26 2019
@@ -58,4 +58,14 @@ public class Velocity904TestCase extends
assertEvalEquals("$variable", "#macro(mymacro $input)#set($input =
$null)$input#end#set($variable = 'value')#mymacro($variable)");
}
+ public void testSubMacroNoPreserve()
+ {
+ assertEvalEquals("$return$return$return", "#macro(macro1
$return)$return#macro2($param2)$return#end#macro(macro2
$return)$return#end#macro1($param)");
+ }
+
+ public void testSubMacroPreserve()
+ {
+ assertEvalEquals("$param$param2$param", "#macro(macro1
$return)$return#macro2($param2)$return#end#macro(macro2
$return)$return#end#macro1($param)");
+ }
+
}