View Javadoc

1   /*
2    * $Id: MessagesTag.java 471754 2006-11-06 14:55:09Z husted $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts.taglib.html;
22  
23  import org.apache.struts.Globals;
24  import org.apache.struts.action.ActionMessage;
25  import org.apache.struts.action.ActionMessages;
26  import org.apache.struts.taglib.TagUtils;
27  import org.apache.struts.util.MessageResources;
28  
29  import javax.servlet.jsp.JspException;
30  import javax.servlet.jsp.tagext.BodyTagSupport;
31  
32  import java.util.Iterator;
33  
34  /**
35   * Custom tag that iterates the elements of a message collection. It defaults
36   * to retrieving the messages from <code>Globals.ERROR_KEY</code>, but if the
37   * message attribute is set to true then the messages will be retrieved from
38   * <code>Globals.MESSAGE_KEY</code>. This is an alternative to the default
39   * <code>ErrorsTag</code>.
40   *
41   * @version $Rev: 471754 $ $Date: 2005-11-08 23:50:53 -0500 (Tue, 08 Nov 2005)
42   *          $
43   * @since Struts 1.1
44   */
45  public class MessagesTag extends BodyTagSupport {
46      /**
47       * The message resources for this package.
48       */
49      protected static MessageResources messageResources =
50          MessageResources.getMessageResources(Constants.Package
51              + ".LocalStrings");
52  
53      /**
54       * Iterator of the elements of this error collection, while we are
55       * actually running.
56       */
57      protected Iterator iterator = null;
58  
59      /**
60       * Whether or not any error messages have been processed.
61       */
62      protected boolean processed = false;
63  
64      /**
65       * The name of the scripting variable to be exposed.
66       */
67      protected String id = null;
68  
69      /**
70       * The servlet context attribute key for our resources.
71       */
72      protected String bundle = null;
73  
74      /**
75       * The session attribute key for our locale.
76       */
77      protected String locale = Globals.LOCALE_KEY;
78  
79      /**
80       * The request attribute key for our error messages (if any).
81       */
82      protected String name = Globals.ERROR_KEY;
83  
84      /**
85       * The name of the property for which error messages should be returned,
86       * or <code>null</code> to return all errors.
87       */
88      protected String property = null;
89  
90      /**
91       * The message resource key for errors header.
92       */
93      protected String header = null;
94  
95      /**
96       * The message resource key for errors footer.
97       */
98      protected String footer = null;
99  
100     /**
101      * If this is set to 'true', then the <code>Globals.MESSAGE_KEY</code>
102      * will be used to retrieve the messages from scope.
103      */
104     protected String message = null;
105 
106     public String getId() {
107         return (this.id);
108     }
109 
110     public void setId(String id) {
111         this.id = id;
112     }
113 
114     public String getBundle() {
115         return (this.bundle);
116     }
117 
118     public void setBundle(String bundle) {
119         this.bundle = bundle;
120     }
121 
122     public String getLocale() {
123         return (this.locale);
124     }
125 
126     public void setLocale(String locale) {
127         this.locale = locale;
128     }
129 
130     public String getName() {
131         return (this.name);
132     }
133 
134     public void setName(String name) {
135         this.name = name;
136     }
137 
138     public String getProperty() {
139         return (this.property);
140     }
141 
142     public void setProperty(String property) {
143         this.property = property;
144     }
145 
146     public String getHeader() {
147         return (this.header);
148     }
149 
150     public void setHeader(String header) {
151         this.header = header;
152     }
153 
154     public String getFooter() {
155         return (this.footer);
156     }
157 
158     public void setFooter(String footer) {
159         this.footer = footer;
160     }
161 
162     public String getMessage() {
163         return (this.message);
164     }
165 
166     public void setMessage(String message) {
167         this.message = message;
168     }
169 
170     /**
171      * Construct an iterator for the specified collection, and begin looping
172      * through the body once per element.
173      *
174      * @throws JspException if a JSP exception has occurred
175      */
176     public int doStartTag() throws JspException {
177         // Initialize for a new request.
178         processed = false;
179 
180         // Were any messages specified?
181         ActionMessages messages = null;
182 
183         // Make a local copy of the name attribute that we can modify.
184         String name = this.name;
185 
186         if ((message != null) && "true".equalsIgnoreCase(message)) {
187             name = Globals.MESSAGE_KEY;
188         }
189 
190         try {
191             messages =
192                 TagUtils.getInstance().getActionMessages(pageContext, name);
193         } catch (JspException e) {
194             TagUtils.getInstance().saveException(pageContext, e);
195             throw e;
196         }
197 
198         // Acquire the collection we are going to iterate over
199         this.iterator =
200             (property == null) ? messages.get() : messages.get(property);
201 
202         // Store the first value and evaluate, or skip the body if none
203         if (!this.iterator.hasNext()) {
204             return SKIP_BODY;
205         }
206 
207         // process the first message
208         processMessage((ActionMessage) iterator.next());
209 
210         if ((header != null) && (header.length() > 0)) {
211             String headerMessage =
212                 TagUtils.getInstance().message(pageContext, bundle, locale,
213                     header);
214 
215             if (headerMessage != null) {
216                 TagUtils.getInstance().write(pageContext, headerMessage);
217             }
218         }
219 
220         // Set the processed variable to true so the
221         // doEndTag() knows processing took place
222         processed = true;
223 
224         return (EVAL_BODY_TAG);
225     }
226 
227     /**
228      * Make the next collection element available and loop, or finish the
229      * iterations if there are no more elements.
230      *
231      * @throws JspException if a JSP exception has occurred
232      */
233     public int doAfterBody() throws JspException {
234         // Render the output from this iteration to the output stream
235         if (bodyContent != null) {
236             TagUtils.getInstance().writePrevious(pageContext,
237                 bodyContent.getString());
238             bodyContent.clearBody();
239         }
240 
241         // Decide whether to iterate or quit
242         if (iterator.hasNext()) {
243             processMessage((ActionMessage) iterator.next());
244 
245             return (EVAL_BODY_TAG);
246         } else {
247             return (SKIP_BODY);
248         }
249     }
250 
251     /**
252      * Process a message.
253      */
254     private void processMessage(ActionMessage report)
255         throws JspException {
256         String msg = null;
257 
258         if (report.isResource()) {
259             msg = TagUtils.getInstance().message(pageContext, bundle, locale,
260                     report.getKey(), report.getValues());
261 
262             if (msg == null) {
263                 String bundleName = (bundle == null) ? "default" : bundle;
264 
265                 msg = messageResources.getMessage("messagesTag.notfound",
266                         report.getKey(), bundleName);
267             }
268         } else {
269             msg = report.getKey();
270         }
271 
272         if (msg == null) {
273             pageContext.removeAttribute(id);
274         } else {
275             pageContext.setAttribute(id, msg);
276         }
277     }
278 
279     /**
280      * Clean up after processing this enumeration.
281      *
282      * @throws JspException if a JSP exception has occurred
283      */
284     public int doEndTag() throws JspException {
285         if (processed && (footer != null) && (footer.length() > 0)) {
286             String footerMessage =
287                 TagUtils.getInstance().message(pageContext, bundle, locale,
288                     footer);
289 
290             if (footerMessage != null) {
291                 TagUtils.getInstance().write(pageContext, footerMessage);
292             }
293         }
294 
295         return EVAL_PAGE;
296     }
297 
298     /**
299      * Release all allocated resources.
300      */
301     public void release() {
302         super.release();
303         iterator = null;
304         processed = false;
305         id = null;
306         bundle = null;
307         locale = Globals.LOCALE_KEY;
308         name = Globals.ERROR_KEY;
309         property = null;
310         header = null;
311         footer = null;
312         message = null;
313     }
314 }