001: /*
002: * $Id: MessagesTag.java 471754 2006-11-06 14:55:09Z husted $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts.taglib.html;
022:
023: import org.apache.struts.Globals;
024: import org.apache.struts.action.ActionMessage;
025: import org.apache.struts.action.ActionMessages;
026: import org.apache.struts.taglib.TagUtils;
027: import org.apache.struts.util.MessageResources;
028:
029: import javax.servlet.jsp.JspException;
030: import javax.servlet.jsp.tagext.BodyTagSupport;
031:
032: import java.util.Iterator;
033:
034: /**
035: * Custom tag that iterates the elements of a message collection. It defaults
036: * to retrieving the messages from <code>Globals.ERROR_KEY</code>, but if the
037: * message attribute is set to true then the messages will be retrieved from
038: * <code>Globals.MESSAGE_KEY</code>. This is an alternative to the default
039: * <code>ErrorsTag</code>.
040: *
041: * @version $Rev: 471754 $ $Date: 2005-11-08 23:50:53 -0500 (Tue, 08 Nov 2005)
042: * $
043: * @since Struts 1.1
044: */
045: public class MessagesTag extends BodyTagSupport {
046: /**
047: * The message resources for this package.
048: */
049: protected static MessageResources messageResources = MessageResources
050: .getMessageResources(Constants.Package + ".LocalStrings");
051:
052: /**
053: * Iterator of the elements of this error collection, while we are
054: * actually running.
055: */
056: protected Iterator iterator = null;
057:
058: /**
059: * Whether or not any error messages have been processed.
060: */
061: protected boolean processed = false;
062:
063: /**
064: * The name of the scripting variable to be exposed.
065: */
066: protected String id = null;
067:
068: /**
069: * The servlet context attribute key for our resources.
070: */
071: protected String bundle = null;
072:
073: /**
074: * The session attribute key for our locale.
075: */
076: protected String locale = Globals.LOCALE_KEY;
077:
078: /**
079: * The request attribute key for our error messages (if any).
080: */
081: protected String name = Globals.ERROR_KEY;
082:
083: /**
084: * The name of the property for which error messages should be returned,
085: * or <code>null</code> to return all errors.
086: */
087: protected String property = null;
088:
089: /**
090: * The message resource key for errors header.
091: */
092: protected String header = null;
093:
094: /**
095: * The message resource key for errors footer.
096: */
097: protected String footer = null;
098:
099: /**
100: * If this is set to 'true', then the <code>Globals.MESSAGE_KEY</code>
101: * will be used to retrieve the messages from scope.
102: */
103: protected String message = null;
104:
105: public String getId() {
106: return (this .id);
107: }
108:
109: public void setId(String id) {
110: this .id = id;
111: }
112:
113: public String getBundle() {
114: return (this .bundle);
115: }
116:
117: public void setBundle(String bundle) {
118: this .bundle = bundle;
119: }
120:
121: public String getLocale() {
122: return (this .locale);
123: }
124:
125: public void setLocale(String locale) {
126: this .locale = locale;
127: }
128:
129: public String getName() {
130: return (this .name);
131: }
132:
133: public void setName(String name) {
134: this .name = name;
135: }
136:
137: public String getProperty() {
138: return (this .property);
139: }
140:
141: public void setProperty(String property) {
142: this .property = property;
143: }
144:
145: public String getHeader() {
146: return (this .header);
147: }
148:
149: public void setHeader(String header) {
150: this .header = header;
151: }
152:
153: public String getFooter() {
154: return (this .footer);
155: }
156:
157: public void setFooter(String footer) {
158: this .footer = footer;
159: }
160:
161: public String getMessage() {
162: return (this .message);
163: }
164:
165: public void setMessage(String message) {
166: this .message = message;
167: }
168:
169: /**
170: * Construct an iterator for the specified collection, and begin looping
171: * through the body once per element.
172: *
173: * @throws JspException if a JSP exception has occurred
174: */
175: public int doStartTag() throws JspException {
176: // Initialize for a new request.
177: processed = false;
178:
179: // Were any messages specified?
180: ActionMessages messages = null;
181:
182: // Make a local copy of the name attribute that we can modify.
183: String name = this .name;
184:
185: if ((message != null) && "true".equalsIgnoreCase(message)) {
186: name = Globals.MESSAGE_KEY;
187: }
188:
189: try {
190: messages = TagUtils.getInstance().getActionMessages(
191: pageContext, name);
192: } catch (JspException e) {
193: TagUtils.getInstance().saveException(pageContext, e);
194: throw e;
195: }
196:
197: // Acquire the collection we are going to iterate over
198: this .iterator = (property == null) ? messages.get() : messages
199: .get(property);
200:
201: // Store the first value and evaluate, or skip the body if none
202: if (!this .iterator.hasNext()) {
203: return SKIP_BODY;
204: }
205:
206: // process the first message
207: processMessage((ActionMessage) iterator.next());
208:
209: if ((header != null) && (header.length() > 0)) {
210: String headerMessage = TagUtils.getInstance().message(
211: pageContext, bundle, locale, header);
212:
213: if (headerMessage != null) {
214: TagUtils.getInstance()
215: .write(pageContext, headerMessage);
216: }
217: }
218:
219: // Set the processed variable to true so the
220: // doEndTag() knows processing took place
221: processed = true;
222:
223: return (EVAL_BODY_TAG);
224: }
225:
226: /**
227: * Make the next collection element available and loop, or finish the
228: * iterations if there are no more elements.
229: *
230: * @throws JspException if a JSP exception has occurred
231: */
232: public int doAfterBody() throws JspException {
233: // Render the output from this iteration to the output stream
234: if (bodyContent != null) {
235: TagUtils.getInstance().writePrevious(pageContext,
236: bodyContent.getString());
237: bodyContent.clearBody();
238: }
239:
240: // Decide whether to iterate or quit
241: if (iterator.hasNext()) {
242: processMessage((ActionMessage) iterator.next());
243:
244: return (EVAL_BODY_TAG);
245: } else {
246: return (SKIP_BODY);
247: }
248: }
249:
250: /**
251: * Process a message.
252: */
253: private void processMessage(ActionMessage report)
254: throws JspException {
255: String msg = null;
256:
257: if (report.isResource()) {
258: msg = TagUtils.getInstance().message(pageContext, bundle,
259: locale, report.getKey(), report.getValues());
260:
261: if (msg == null) {
262: String bundleName = (bundle == null) ? "default"
263: : bundle;
264:
265: msg = messageResources.getMessage(
266: "messagesTag.notfound", report.getKey(),
267: bundleName);
268: }
269: } else {
270: msg = report.getKey();
271: }
272:
273: if (msg == null) {
274: pageContext.removeAttribute(id);
275: } else {
276: pageContext.setAttribute(id, msg);
277: }
278: }
279:
280: /**
281: * Clean up after processing this enumeration.
282: *
283: * @throws JspException if a JSP exception has occurred
284: */
285: public int doEndTag() throws JspException {
286: if (processed && (footer != null) && (footer.length() > 0)) {
287: String footerMessage = TagUtils.getInstance().message(
288: pageContext, bundle, locale, footer);
289:
290: if (footerMessage != null) {
291: TagUtils.getInstance()
292: .write(pageContext, footerMessage);
293: }
294: }
295:
296: return EVAL_PAGE;
297: }
298:
299: /**
300: * Release all allocated resources.
301: */
302: public void release() {
303: super .release();
304: iterator = null;
305: processed = false;
306: id = null;
307: bundle = null;
308: locale = Globals.LOCALE_KEY;
309: name = Globals.ERROR_KEY;
310: property = null;
311: header = null;
312: footer = null;
313: message = null;
314: }
315: }
|