WW-5379 Add support for internal and chained contexts

This commit is contained in:
Kusal Kithul-Godage
2023-12-28 07:42:23 +11:00
parent 3dbc5c250e
commit 3eddd56d2d
@@ -24,7 +24,10 @@ import org.apache.struts2.ServletActionContext;
import org.apache.struts2.components.Component;
import org.apache.struts2.views.util.ContextUtil;
import org.apache.struts2.views.velocity.StrutsVelocityContext;
import org.apache.velocity.context.AbstractContext;
import org.apache.velocity.context.Context;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.context.InternalWrapperContext;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
@@ -56,11 +59,8 @@ public abstract class AbstractDirective extends Directive {
protected abstract Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res);
public boolean render(InternalContextAdapter ctx, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
ValueStack stack;
if (ctx.getInternalUserContext() instanceof StrutsVelocityContext) {
StrutsVelocityContext svc = (StrutsVelocityContext) ctx.getInternalUserContext();
stack = svc.getValueStack();
} else {
ValueStack stack = extractValueStack(ctx);
if (stack == null) {
// Fallback to assuming the ValueStack was put into the Velocity context (as is by default)
stack = (ValueStack) ctx.get(ContextUtil.STACK);
}
@@ -84,6 +84,27 @@ public abstract class AbstractDirective extends Directive {
return true;
}
private ValueStack extractValueStack(Context context) {
do {
if (context instanceof StrutsVelocityContext) {
return ((StrutsVelocityContext) context).getValueStack();
}
context = extractContext(context);
} while (context != null);
return null;
}
private Context extractContext(Context context) {
if (context instanceof InternalWrapperContext) {
return ((InternalWrapperContext) context).getInternalUserContext();
}
if (context instanceof AbstractContext) {
return ((AbstractContext) context).getChainedContext();
}
return null;
}
/**
* <p>
* Create a Map of properties that the user has passed in. For example: