diff --git a/core/src/main/java/org/apache/struts2/components/Component.java b/core/src/main/java/org/apache/struts2/components/Component.java index d291f99d7..2612ea005 100644 --- a/core/src/main/java/org/apache/struts2/components/Component.java +++ b/core/src/main/java/org/apache/struts2/components/Component.java @@ -300,7 +300,7 @@ public class Component { * expression otherwise. */ protected String completeExpressionIfAltSyntax(String expr) { - if (altSyntax()) { + if (altSyntax() && !ComponentUtils.containsExpression(expr)) { return "%{" + expr + "}"; } return expr; @@ -382,6 +382,15 @@ public class Component { } } + /** + * Detects if altSyntax is enabled and then checks if expression contains %{...} + * @param expr a string to examined + * @return true if altSyntax is enabled and expr contains %{...} + */ + protected boolean recursion(String expr) { + return ComponentUtils.altSyntax(stack) && ComponentUtils.containsExpression(expr); + } + /** * Renders an action URL by consulting the {@link org.apache.struts2.dispatcher.mapper.ActionMapper}. * @param action the action diff --git a/core/src/main/java/org/apache/struts2/components/UIBean.java b/core/src/main/java/org/apache/struts2/components/UIBean.java index b7c4432e4..528809e5d 100644 --- a/core/src/main/java/org/apache/struts2/components/UIBean.java +++ b/core/src/main/java/org/apache/struts2/components/UIBean.java @@ -795,8 +795,11 @@ public abstract class UIBean extends Component { addParameter("nameValue", findValue(value, valueClazz)); } else if (name != null) { String expr = completeExpressionIfAltSyntax(name); - - addParameter("nameValue", findValue(expr, valueClazz)); + if (recursion(name)) { + addParameter("nameValue", expr); + } else { + addParameter("nameValue", findValue(expr, valueClazz)); + } } } else { if (value != null) { @@ -1021,9 +1024,7 @@ public abstract class UIBean extends Component { @StrutsTagAttribute(description="HTML id attribute") public void setId(String id) { - if (id != null) { - this.id = findString(id); - } + this.id = id; } @StrutsTagAttribute(description="The template directory.") @@ -1241,8 +1242,8 @@ public abstract class UIBean extends Component { this.tooltipIconPath = tooltipIconPath; } - public void setDynamicAttributes(Map tagDynamicAttributes) { - for (Map.Entry entry : tagDynamicAttributes.entrySet()) { + public void setDynamicAttributes(Map tagDynamicAttributes) { + for (Map.Entry entry : tagDynamicAttributes.entrySet()) { String key = entry.getKey(); if (!isValidTagAttribute(key)) { diff --git a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java index 3e4b8db42..677892efe 100644 --- a/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java +++ b/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java @@ -78,7 +78,7 @@ public abstract class AbstractUITag extends ComponentTagSupport implements Dynam protected String tooltipIconPath; // dynamic attributes. - protected Map dynamicAttributes = new HashMap<>(); + protected Map dynamicAttributes = new HashMap<>(); protected void populateParams() { super.populateParams(); @@ -302,11 +302,7 @@ public abstract class AbstractUITag extends ComponentTagSupport implements Dynam } public void setDynamicAttribute(String uri, String localName, Object value) throws JspException { - if (ComponentUtils.altSyntax(getStack()) && ComponentUtils.isExpression(value.toString())) { - dynamicAttributes.put(localName, String.valueOf(ObjectUtils.defaultIfNull(findValue(value.toString()), value))); - } else { - dynamicAttributes.put(localName, value); - } + dynamicAttributes.put(localName, String.valueOf(value)); } } diff --git a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java index 9317397d2..ca2ffa28a 100644 --- a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java +++ b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java @@ -280,6 +280,27 @@ public class UIBeanTest extends StrutsInternalTestCase { assertEquals(value, txtFld.getParameters().get("nameValue")); } + public void testValueParameterRecursion() { + ValueStack stack = ActionContext.getContext().getValueStack(); + MockHttpServletRequest req = new MockHttpServletRequest(); + MockHttpServletResponse res = new MockHttpServletResponse(); + + stack.push(new Object() { + public String getMyValue() { + return "%{myBad}"; + } + public String getMyBad() { + throw new IllegalStateException("Recursion detected!"); + } + }); + + TextField txtFld = new TextField(stack, req, res); + txtFld.setName("%{myValue}"); + txtFld.evaluateParams(); + + assertEquals("%{myBad}", txtFld.getParameters().get("nameValue")); + } + public void testSetClass() { String cssClass = "insertCssClassHere"; ValueStack stack = ActionContext.getContext().getValueStack(); diff --git a/core/src/test/java/org/apache/struts2/util/StrutsUtilTest.java b/core/src/test/java/org/apache/struts2/util/StrutsUtilTest.java index 28c4b3406..02be0f287 100644 --- a/core/src/test/java/org/apache/struts2/util/StrutsUtilTest.java +++ b/core/src/test/java/org/apache/struts2/util/StrutsUtilTest.java @@ -189,6 +189,21 @@ public class StrutsUtilTest extends StrutsInternalTestCase { assertEquals(obj1, "try: bar"); } + public void testTranslateVariablesRecursion() throws Exception { + stack.push(new Object() { + public String getFoo() { + return "%{bar}"; + } + public String getBar() { + return "bar"; + } + }); + String obj1 = strutsUtil.translateVariables("try: %{foo}"); + + assertNotNull(obj1); + assertEquals("try: %{bar}", obj1); + } + // === Junit Hook protected void setUp() throws Exception { diff --git a/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/AbstractTest.java b/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/AbstractTest.java index 7dd36c9c0..69847eb23 100644 --- a/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/AbstractTest.java +++ b/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/AbstractTest.java @@ -46,7 +46,7 @@ import java.util.Stack; public abstract class AbstractTest extends TestCase { private Map scriptingAttrs = new HashMap(); private Map commonAttrs = new HashMap(); - private Map dynamicAttrs = new HashMap(); + private Map dynamicAttrs = new HashMap(); protected SimpleTheme theme; @@ -180,7 +180,7 @@ public abstract class AbstractTest extends TestCase { } protected void assertDynamicAttrs(String str) { - for (Map.Entry entry : dynamicAttrs.entrySet()) { + for (Map.Entry entry : dynamicAttrs.entrySet()) { String substr = entry.getKey() + "=\"" + entry.getValue() + "\""; assertTrue("String [" + substr + "] was not found in [" + str + "]", str.indexOf(substr) >= 0); }