diff --git a/core/src/main/java/org/apache/struts2/components/Label.java b/core/src/main/java/org/apache/struts2/components/Label.java index 4498a7fd5..23f9acdc6 100644 --- a/core/src/main/java/org/apache/struts2/components/Label.java +++ b/core/src/main/java/org/apache/struts2/components/Label.java @@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletResponse; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.util.TextProviderHelper; import com.opensymphony.xwork2.util.ValueStack; @@ -82,8 +83,9 @@ public class Label extends UIBean { if (value != null) { addParameter("nameValue", findString(value)); } else if (key != null) { - String expr = "%{getText('"+ key +"')}"; - addParameter("nameValue", findString(expr)); + // get the label from a TextProvider + String providedLabel = TextProviderHelper.getText(key, "", stack); + addParameter("nameValue", providedLabel); } else if (name != null) { String expr = name; if (altSyntax()) { diff --git a/core/src/main/java/org/apache/struts2/components/Text.java b/core/src/main/java/org/apache/struts2/components/Text.java index c6ed8bbd3..eaee4170f 100644 --- a/core/src/main/java/org/apache/struts2/components/Text.java +++ b/core/src/main/java/org/apache/struts2/components/Text.java @@ -24,13 +24,12 @@ import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.util.TextProviderHelper; -import com.opensymphony.xwork2.TextProvider; import com.opensymphony.xwork2.util.TextUtils; import com.opensymphony.xwork2.util.ValueStack; import com.opensymphony.xwork2.util.logging.Logger; @@ -149,20 +148,8 @@ public class Text extends ContextBean implements Param.UnnamedParametric { } else { defaultMessage = actualName; } - String msg = null; - ValueStack stack = getStack(); - for (Iterator iterator = getStack().getRoot().iterator(); - iterator.hasNext();) { - Object o = iterator.next(); - - if (o instanceof TextProvider) { - TextProvider tp = (TextProvider) o; - msg = tp.getText(actualName, defaultMessage, values, stack); - - break; - } - } + String msg = TextProviderHelper.getText(actualName, defaultMessage, values, getStack()); if (msg != null) { try { 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 2a34c53fa..43eaad4f0 100644 --- a/core/src/main/java/org/apache/struts2/components/UIBean.java +++ b/core/src/main/java/org/apache/struts2/components/UIBean.java @@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.StrutsConstants; +import org.apache.struts2.util.TextProviderHelper; import org.apache.struts2.components.template.Template; import org.apache.struts2.components.template.TemplateEngine; import org.apache.struts2.components.template.TemplateEngineManager; @@ -616,17 +617,17 @@ public abstract class UIBean extends Component { addParameter("dynamicAttributes", dynamicAttributes); String name = null; + String providedLabel = null; if (this.key != null) { - if(this.name == null) { + if(this.name == null) { this.name = key; } if(this.label == null) { - // Escape the key prior to sending it down - String escaped = key.replace("'", "\\'"); - this.label = "%{getText('" + escaped + "')}"; + // lookup the label from a TextProvider + providedLabel = TextProviderHelper.getText(key, "", stack); } } @@ -638,6 +639,11 @@ public abstract class UIBean extends Component { if (label != null) { addParameter("label", findString(label)); + } else { + if (providedLabel != null) { + // label found via a TextProvider + addParameter("label", providedLabel); + } } if (labelSeparator != null) { diff --git a/core/src/main/java/org/apache/struts2/util/TextProviderHelper.java b/core/src/main/java/org/apache/struts2/util/TextProviderHelper.java new file mode 100644 index 000000000..4d36d3ad2 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/util/TextProviderHelper.java @@ -0,0 +1,59 @@ +package org.apache.struts2.util; + +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.TextProvider; + +import java.util.Iterator; +import java.util.List; +import java.util.LinkedList; + +/** + * Helper methods to access text from TextProviders + */ +public class TextProviderHelper { + + /** + *

Get a message from the first TextProvider encountered in the stack. + * If the first TextProvider doesn't provide the message the default message is returned.

+ *

The search for a TextProvider is iterative from the root of the stack.

+ *

This method was refactored from {@link org.apache.struts2.components.Text} to use a + * consistent implementation across UIBean components.

+ * @param key the message key in the resource bundle + * @param defaultMessage the message to return if not found + * @param args an array args to be used in a {@link java.text.MessageFormat} message + * @param stack the value stack to use for finding the text + * + * @return the message if found, otherwise the defaultMessage + */ + public static String getText(String key, String defaultMessage, List args, ValueStack stack) { + String msg = defaultMessage; + + for (Iterator iterator = stack.getRoot().iterator(); iterator.hasNext();) { + Object o = iterator.next(); + + if (o instanceof TextProvider) { + TextProvider tp = (TextProvider) o; + msg = tp.getText(key, defaultMessage, args, stack); + + break; + } + } + return msg; + } + + /** + *

Get a message from the first TextProvider encountered in the stack. + * If the first TextProvider doesn't provide the message the default message is returned.

+ *

The search for a TextProvider is iterative from the root of the stack.

+ *

This method was refactored from {@link org.apache.struts2.components.Text} to use a + * consistent implementation across UIBean components.

+ * @param key the message key in the resource bundle + * @param defaultMessage the message to return if not found + * @param stack the value stack to use for finding the text + * + * @return the message if found, otherwise the defaultMessage + */ + public static String getText(String key, String defaultMessage,ValueStack stack) { + return getText(key, defaultMessage, new LinkedList(), stack); + } +} diff --git a/core/src/test/java/org/apache/struts2/TestAction.java b/core/src/test/java/org/apache/struts2/TestAction.java index dfc3f3357..49b734288 100644 --- a/core/src/test/java/org/apache/struts2/TestAction.java +++ b/core/src/test/java/org/apache/struts2/TestAction.java @@ -26,6 +26,7 @@ import org.apache.struts2.views.jsp.ui.User; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.util.ValueStack; /** @@ -47,19 +48,38 @@ public class TestAction extends ActionSupport { private List list3; private SomeEnum status = SomeEnum.COMPLETED; - private final Map texts = new HashMap(); + private final Map texts = new HashMap(); + /** + * Define a text resource within this action that will be returned by the getText methods + * here before delegating to the default TextProvider + * + * call + * @param key + * @param value + */ public void setText(String key, String value) { this.texts.put(key, value); } + /** Returns the test value if defined otherwise delegates to the default TextProvider */ public String getText(String key) { if (this.texts.containsKey(key)) { - return (String) this.texts.get(key); + return this.texts.get(key); } return super.getText(key); } + /** This is the method invoked by the {@link org.apache.struts2.util.TextProviderHelper}. + * Returns the test value if defined otherwise delegates to the default TextProvider */ + public String getText(String key, String defaultValue, List args, ValueStack stack) { + if (this.texts.containsKey(key)) { + return this.texts.get(key); + } else { + return super.getText(key, defaultValue, args, stack); + } + } + public Collection getCollection() { return collection; }