craigmcc 01/02/19 17:48:47 Modified: src/doc struts-html.xml src/share/org/apache/struts/taglib/bean MessageTag.java src/share/org/apache/struts/taglib/html ErrorsTag.java ImgTag.java OptionTag.java src/share/org/apache/struts/util LocalStrings.properties RequestUtils.java Log: Add "bundle", "key", and "locale" attributes to the <html:option> tag so that you can specify an internationalized value to display to the user, without having to resort to a nested <bean:message> tag, although the latter approach is still supported. This can reduce the total number of custom tags on a JSP page when you use large numbers of <html:option> tags. Refactor the lookup of messages based on "bundle", "locale", and "key" type attributes into a support method named RequestUtils.message(), to centralize this functionality and reduce the amount of repetitive code found in tag implementation classes. Modify <bean:message>, <html:errors>, <html:img>, and <html:option> to use the new utility method. Submitted by: Martin Cooper <[EMAIL PROTECTED]> Revision Changes Path 1.13 +68 -16 jakarta-struts/src/doc/struts-html.xml Index: struts-html.xml =================================================================== RCS file: /home/cvs/jakarta-struts/src/doc/struts-html.xml,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- struts-html.xml 2001/02/20 00:18:48 1.12 +++ struts-html.xml 2001/02/20 01:48:44 1.13 @@ -715,6 +715,17 @@ </attribute> <attribute> + <name>locale</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <info> + The session attribute key for the Locale used to select + messages to be displayed. If not specified, defaults to + the Struts standard value. + </info> + </attribute> + + <attribute> <name>name</name> <required>false</required> <rtexprvalue>true</rtexprvalue> @@ -2493,31 +2504,72 @@ <name>option</name> <summary> - Render A Select Option + Render A Select Option </summary> <tagclass>org.apache.struts.taglib.html.OptionTag</tagclass> <info> - <p> - Renders an HTML <option> element, representing one of the choices - for a <select> element. The text displayed to the user comes from - the body of this tag. If the value of the corresponding bean - property matches the specified value, this option will be marked - selected. This tag is only valid when nested inside a select tag - body. - </p> + <p>Render an HTML <code><option></code> element, + representing one of the choices for an enclosing + <code><select></code> element. The text displayed to the + user comes from either the body of this tag, or from a message + string looked up based on the <code>bundle</code>, + <code>locale</code>, and <code>key</code> attributes.</p> + + <p>If the value of the corresponding bean property matches the + specified value, this option will be marked selected. This tag + is only valid when nested inside a + <code><html:select></code> tag body.</p> </info> + <attribute> + <name>bundle</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <info> + The servlet context attributes key for the MessageResources + instance to use. If not specified, defaults to the + application resources configured for our action servlet. + </info> + </attribute> + + <attribute> + <name>key</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <info> + If specified, defines the message key to be looked up in + the resource bundle specified by <code>bundle</code> for + the text displayed to the user for this option. If not + specified, the text to be displayed is taken from the body + content of this tag. + </info> + </attribute> + + <attribute> + <name>locale</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + <info> + The session attributes key for the Locale instance to use + for looking up the message specified by the + <code>key</code> attribute. If not specified, uses the + standard Struts session attribute name. + </info> + </attribute> + <attribute> - <name>value</name> - <required>true</required> - <rtexprvalue>true</rtexprvalue> - <info> - Value to be submitted for this field if this option is selected by - the user. - </info> + <name>value</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + <info> + Value to be submitted for this field if this option is + selected by the uuser. + </info> </attribute> + </tag> + <tag> <name>options</name> 1.4 +6 -26 jakarta-struts/src/share/org/apache/struts/taglib/bean/MessageTag.java Index: MessageTag.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/bean/MessageTag.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- MessageTag.java 2001/02/12 01:26:57 1.3 +++ MessageTag.java 2001/02/20 01:48:45 1.4 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/bean/MessageTag.java,v 1.3 2001/02/12 01:26:57 craigmcc Exp $ - * $Revision: 1.3 $ - * $Date: 2001/02/12 01:26:57 $ + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/bean/MessageTag.java,v 1.4 2001/02/20 01:48:45 craigmcc Exp $ + * $Revision: 1.4 $ + * $Date: 2001/02/20 01:48:45 $ * * ==================================================================== * @@ -82,7 +82,7 @@ * <code>ActionServlet</code> implementation. * * @author Craig R. McClanahan - * @version $Revision: 1.3 $ $Date: 2001/02/12 01:26:57 $ + * @version $Revision: 1.4 $ $Date: 2001/02/20 01:48:45 $ */ public class MessageTag extends TagSupport { @@ -227,27 +227,6 @@ */ public int doStartTag() throws JspException { - // Acquire the resources object containing our messages - MessageResources resources = (MessageResources) - pageContext.getAttribute(bundle, PageContext.APPLICATION_SCOPE); - if (resources == null) { - JspException e = new JspException - (messages.getMessage("message.resources", bundle)); - RequestUtils.saveException(pageContext, e); - throw e; - } - - // Calculate the Locale we will be using - Locale locale = null; - try { - locale = (Locale) - pageContext.getAttribute(localeKey, PageContext.SESSION_SCOPE); - } catch (IllegalStateException e) { // Invalidated session - locale = null; - } - if (locale == null) - locale = defaultLocale; - // Construct the optional arguments array we will be using Object args[] = new Object[5]; args[0] = arg0; @@ -257,7 +236,8 @@ args[4] = arg4; // Retrieve the message string we are looking for - String message = resources.getMessage(locale, key, args); + String message = RequestUtils.message(pageContext, this.bundle, + this.localeKey, this.key, args); if (message == null) { JspException e = new JspException (messages.getMessage("message.message", key)); 1.6 +33 -42 jakarta-struts/src/share/org/apache/struts/taglib/html/ErrorsTag.java Index: ErrorsTag.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/ErrorsTag.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- ErrorsTag.java 2001/02/13 17:30:00 1.5 +++ ErrorsTag.java 2001/02/20 01:48:46 1.6 @@ -1,13 +1,13 @@ /* - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/ErrorsTag.java,v 1.5 2001/02/13 17:30:00 craigmcc Exp $ - * $Revision: 1.5 $ - * $Date: 2001/02/13 17:30:00 $ + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/ErrorsTag.java,v 1.6 2001/02/20 01:48:46 craigmcc Exp $ + * $Revision: 1.6 $ + * $Date: 2001/02/20 01:48:46 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * - * Copyright (c) 1999 The Apache Software Foundation. All rights + * Copyright (c) 1999-2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * - * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software + * 4. The names "The Jakarta Project", "Struts", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] @@ -76,6 +76,8 @@ import org.apache.struts.util.BeanUtils; import org.apache.struts.util.ErrorMessages; import org.apache.struts.util.MessageResources; +import org.apache.struts.util.RequestUtils; +import org.apache.struts.util.ResponseUtils; /** @@ -96,7 +98,7 @@ * </ul> * * @author Craig R. McClanahan - * @version $Revision: 1.5 $ $Date: 2001/02/13 17:30:00 $ + * @version $Revision: 1.6 $ $Date: 2001/02/20 01:48:46 $ */ public class ErrorsTag extends TagSupport { @@ -126,9 +128,22 @@ /** - * Name of the request scope attribute containing our error messages, - * if any. + * The session attribute key for our locale. */ + protected String locale = Action.LOCALE_KEY; + + public String getLocale() { + return (this.locale); + } + + public void setLocale(String locale) { + this.locale = locale; + } + + + /** + * The request attribute key for our error messages (if any). + */ protected String name = Action.ERROR_KEY; public String getName() { @@ -197,25 +212,10 @@ if (errors.empty()) return (EVAL_BODY_INCLUDE); - // Render the error messages appropriately - Locale locale = null; - try { - locale = (Locale) pageContext.getAttribute - (Action.LOCALE_KEY, PageContext.SESSION_SCOPE); - } catch (IllegalStateException e) { // Invalidated session - locale = null; - } - if (locale == null) - locale = defaultLocale; - MessageResources messages = (MessageResources) - pageContext.getAttribute(bundle, - PageContext.APPLICATION_SCOPE); - String message = null; + // Render the error messages appropriately StringBuffer results = new StringBuffer(); - if (messages != null) - message = messages.getMessage(locale, "errors.header"); - else - message = "MISSING APPLICATION RESOURCES"; + String message = RequestUtils.message(pageContext, bundle, + locale, "errors.header"); if (message != null) { results.append(message); results.append("\r\n"); @@ -227,33 +227,23 @@ reports = errors.get(property); while (reports.hasNext()) { ActionError report = (ActionError) reports.next(); - if (messages != null) - message = - messages.getMessage(locale, - report.getKey(), report.getValues()); - else - message = null; + message = RequestUtils.message(pageContext, bundle, + locale, report.getKey(), + report.getValues()); if (message != null) { results.append(message); results.append("\r\n"); } } - if (messages != null) - message = messages.getMessage(locale, "errors.footer"); - else - message = null; + message = RequestUtils.message(pageContext, bundle, + locale, "errors.footer"); if (message != null) { results.append(message); results.append("\r\n"); } // Print the results to our output writer - JspWriter writer = pageContext.getOut(); - try { - writer.print(results.toString()); - } catch (IOException e) { - throw new JspException(e.toString()); - } + ResponseUtils.write(pageContext, results.toString()); // Continue processing this page return (EVAL_BODY_INCLUDE); @@ -268,6 +258,7 @@ super.release(); bundle = Action.MESSAGES_KEY; + locale = Action.LOCALE_KEY; name = Action.ERROR_KEY; property = null; 1.6 +8 -43 jakarta-struts/src/share/org/apache/struts/taglib/html/ImgTag.java Index: ImgTag.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/ImgTag.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- ImgTag.java 2001/02/20 00:18:52 1.5 +++ ImgTag.java 2001/02/20 01:48:46 1.6 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/ImgTag.java,v 1.5 2001/02/20 00:18:52 craigmcc Exp $ - * $Revision: 1.5 $ - * $Date: 2001/02/20 00:18:52 $ + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/ImgTag.java,v 1.6 2001/02/20 01:48:46 craigmcc Exp $ + * $Revision: 1.6 $ + * $Date: 2001/02/20 01:48:46 $ * * ==================================================================== * @@ -96,7 +96,7 @@ * * @author Michael Westbay * @author Craig McClanahan - * @version $Revision: 1.5 $ + * @version $Revision: 1.6 $ */ public class ImgTag extends BaseHandlerTag { @@ -703,26 +703,9 @@ } HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); - MessageResources resources = (MessageResources) - pageContext.getAttribute(this.bundle, - PageContext.APPLICATION_SCOPE); - if (resources == null) { - JspException e = new JspException - (messages.getMessage("imgTag.bundle", this.bundle)); - RequestUtils.saveException(pageContext, e); - } - Locale locale = null; - try { - locale = (Locale) - pageContext.getAttribute(this.locale, - PageContext.SESSION_SCOPE); - } catch (IllegalStateException e) { - locale = null; // Invalidated session - } - if (locale == null) - locale = defaultLocale; return (request.getContextPath() + - resources.getMessage(locale, this.pageKey)); + RequestUtils.message(pageContext, bundle, + locale, this.pageKey)); } // Deal with an absolute source that has been specified @@ -742,27 +725,9 @@ (messages.getMessage("imgTag.src")); RequestUtils.saveException(pageContext, e); throw e; - } - MessageResources resources = (MessageResources) - pageContext.getAttribute(this.bundle, - PageContext.APPLICATION_SCOPE); - if (resources == null) { - JspException e = new JspException - (messages.getMessage("imgTag.bundle", this.bundle)); - RequestUtils.saveException(pageContext, e); - throw e; } - Locale locale = null; - try { - locale = (Locale) - pageContext.getAttribute(this.locale, - PageContext.SESSION_SCOPE); - } catch (IllegalStateException e) { - locale = null; // Invalidated session - } - if (locale == null) - locale = defaultLocale; - return (resources.getMessage(locale, this.srcKey)); + return (RequestUtils.message(pageContext, bundle, + locale, this.srcKey)); } 1.3 +115 -28 jakarta-struts/src/share/org/apache/struts/taglib/html/OptionTag.java Index: OptionTag.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/OptionTag.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- OptionTag.java 2001/01/08 21:36:07 1.2 +++ OptionTag.java 2001/02/20 01:48:46 1.3 @@ -1,13 +1,13 @@ /* - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/OptionTag.java,v 1.2 2001/01/08 21:36:07 craigmcc Exp $ - * $Revision: 1.2 $ - * $Date: 2001/01/08 21:36:07 $ + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/taglib/html/OptionTag.java,v 1.3 2001/02/20 01:48:46 craigmcc Exp $ + * $Revision: 1.3 $ + * $Date: 2001/02/20 01:48:46 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * - * Copyright (c) 1999 The Apache Software Foundation. All rights + * Copyright (c) 1999-2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +29,7 @@ * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * - * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software + * 4. The names "The Jakarta Project", "Struts", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] @@ -65,11 +65,15 @@ import java.lang.reflect.Method; import java.io.IOException; +import java.util.Locale; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyTagSupport; +import org.apache.struts.action.Action; import org.apache.struts.util.MessageResources; +import org.apache.struts.util.RequestUtils; +import org.apache.struts.util.ResponseUtils; /** @@ -78,7 +82,7 @@ * the server if this option is selected. * * @author Craig R. McClanahan - * @version $Revision: 1.2 $ $Date: 2001/01/08 21:36:07 $ + * @version $Revision: 1.3 $ $Date: 2001/02/20 01:48:46 $ */ public class OptionTag extends BodyTagSupport { @@ -88,6 +92,12 @@ /** + * The default locale for our server. + */ + protected static final Locale defaultLocale = Locale.getDefault(); + + + /** * The message resources for this package. */ protected static MessageResources messages = @@ -95,36 +105,75 @@ /** - * The server value for this option. + * The message text to be displayed to the user for this tag (if any) */ - protected String value = null; + protected String text = null; // ------------------------------------------------------------- Properties /** - * Return the server value. + * The name of the servlet context attribute containing our message + * resources. */ - public String getValue() { + protected String bundle = Action.MESSAGES_KEY; - return (this.value); + public String getBundle() { + return (this.bundle); + } + public void setBundle(String bundle) { + this.bundle = bundle; } /** - * Set the server value. - * - * @param value The new server value + * The key used to look up the text displayed to the user for this + * option, if any. */ - public void setValue(String value) { + protected String key = null; - this.value = value; + public String getKey() { + return (this.key); + } + + public void setKey(String key) { + this.key = key; + } + + + /** + * The name of the attribute containing the Locale to be used for + * looking up internationalized messages. + */ + protected String locale = Action.LOCALE_KEY; + + public String getLocale() { + return (this.locale); + } + public void setLocale(String locale) { + this.locale = locale; } + /** + * The server value for this option, also used to match against the + * current property value to determine whether this option should be + * marked as selected. + */ + protected String value = null; + + public String getValue() { + return (this.value); + } + + public void setValue(String value) { + this.value = value; + } + + // --------------------------------------------------------- Public Methods @@ -141,7 +190,24 @@ } + /** + * Process the body text of this tag (if any). + * + * @exception JspException if a JSP exception has occurred + */ + public int doAfterBody() throws JspException { + + String text = bodyContent.getString(); + if (text != null) { + text = text.trim(); + if (text.length() > 0) + this.text = text; + } + return (SKIP_BODY); + } + + /** * Process the end of this tag. * @@ -152,11 +218,14 @@ // Acquire the select tag we are associated with SelectTag selectTag = (SelectTag) pageContext.getAttribute(Constants.SELECT_KEY); - if (selectTag == null) - throw new JspException + if (selectTag == null) { + JspException e = new JspException (messages.getMessage("optionTag.select")); + RequestUtils.saveException(pageContext, e); + throw e; + } - // Generate an HTML element + // Generate an HTML <option> element StringBuffer results = new StringBuffer(); results.append("<option value=\""); results.append(value); @@ -164,20 +233,15 @@ if (value.equals(selectTag.getMatch())) results.append(" selected"); results.append(">"); - if (bodyContent == null) + String text = text(); + if (text == null) results.append(value); else - results.append(bodyContent.getString().trim()); + results.append(text); results.append("</option>"); // Render this element to our writer - JspWriter writer = pageContext.getOut(); - try { - writer.println(results.toString()); - } catch (IOException e) { - throw new JspException - (messages.getMessage("common.io", e.toString())); - } + ResponseUtils.write(pageContext, results.toString()); // Continue evaluating this page return (EVAL_PAGE); @@ -191,7 +255,30 @@ public void release() { super.release(); + bundle = Action.MESSAGES_KEY; + key = null; + locale = Action.LOCALE_KEY; + text = null; value = null; + + } + + + // ------------------------------------------------------ Protected Methods + + + /** + * Return the text to be displayed to the user for this option (if any). + * + * @exception JspException if an error occurs + */ + protected String text() throws JspException { + + if (this.text != null) + return (this.text); + else + return (RequestUtils.message(pageContext, bundle, + locale, key)); } 1.2 +1 -0 jakarta-struts/src/share/org/apache/struts/util/LocalStrings.properties Index: LocalStrings.properties =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/LocalStrings.properties,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- LocalStrings.properties 2001/02/13 00:06:24 1.1 +++ LocalStrings.properties 2001/02/20 01:48:46 1.2 @@ -3,4 +3,5 @@ lookup.method=No getter method for property {0} of bean {1} lookup.scope=Invalid bean scope {0} lookup.target=Exception thrown by getter for property {0} of bean {1} +message.bundle=Cannot find message resources under key {0} write.io=Input/output error: {0} 1.6 +78 -4 jakarta-struts/src/share/org/apache/struts/util/RequestUtils.java Index: RequestUtils.java =================================================================== RCS file: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/RequestUtils.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- RequestUtils.java 2001/02/12 00:32:14 1.5 +++ RequestUtils.java 2001/02/20 01:48:46 1.6 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/RequestUtils.java,v 1.5 2001/02/12 00:32:14 craigmcc Exp $ - * $Revision: 1.5 $ - * $Date: 2001/02/12 00:32:14 $ + * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/util/RequestUtils.java,v 1.6 2001/02/20 01:48:46 craigmcc Exp $ + * $Revision: 1.6 $ + * $Date: 2001/02/20 01:48:46 $ * * ==================================================================== * @@ -70,6 +70,7 @@ import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; +import java.util.Locale; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -88,7 +89,7 @@ * in the Struts controller framework. * * @author Craig R. McClanahan - * @version $Revision: 1.5 $ $Date: 2001/02/12 00:32:14 $ + * @version $Revision: 1.6 $ $Date: 2001/02/20 01:48:46 $ */ public class RequestUtils { @@ -98,6 +99,12 @@ /** + * The default Locale for our server. + */ + private static final Locale defaultLocale = Locale.getDefault(); + + + /** * The message resources for this package. */ private static MessageResources messages = @@ -227,6 +234,73 @@ throw new JspException (messages.getMessage("lookup.method", property, name)); } + + } + + + /** + * Look up and return a message string, based on the specified parameters. + * + * @param pageContext The PageContext associated with this request + * @param bundle Name of the servlet context attribute for our + * message resources bundle + * @param locale Name of the session attribute for our user's Locale + * @param key Message key to be looked up and returned + * + * @exception JspException if a lookup error occurs (will have been + * saved in the request already) + */ + public static String message(PageContext pageContext, String bundle, + String locale, String key) + throws JspException { + + return (message(pageContext, bundle, locale, key, null)); + + } + + + /** + * Look up and return a message string, based on the specified parameters. + * + * @param pageContext The PageContext associated with this request + * @param bundle Name of the servlet context attribute for our + * message resources bundle + * @param locale Name of the session attribute for our user's Locale + * @param key Message key to be looked up and returned + * @param args Replacement parameters for this message + * + * @exception JspException if a lookup error occurs (will have been + * saved in the request already) + */ + public static String message(PageContext pageContext, String bundle, + String locale, String key, Object args) + throws JspException { + + // Look up the requested MessageResources + if (bundle == null) + bundle = Action.MESSAGES_KEY; + MessageResources resources = (MessageResources) + pageContext.getAttribute(bundle, PageContext.APPLICATION_SCOPE); + if (resources == null) { + JspException e = new JspException + (messages.getMessage("message.bundle", bundle)); + saveException(pageContext, e); + throw e; + } + + // Look up the requested Locale + if (locale == null) + locale = Action.LOCALE_KEY; + Locale userLocale = (Locale) + pageContext.getAttribute(locale, PageContext.SESSION_SCOPE); + if (userLocale == null) + userLocale = defaultLocale; + + // Return the requested message + if (args == null) + return (resources.getMessage(userLocale, key)); + else + return (resources.getMessage(userLocale, key, args)); }