View Javadoc

1   /*
2    * $Id: ErrorsRenderer.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  
22  package org.apache.struts.faces.renderer;
23  
24  
25  import java.beans.Beans;
26  import java.io.IOException;
27  import java.util.Iterator;
28  import java.util.Locale;
29  
30  import javax.faces.application.FacesMessage;
31  import javax.faces.component.UIComponent;
32  import javax.faces.context.FacesContext;
33  import javax.faces.context.ResponseWriter;
34  
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  import org.apache.struts.Globals;
38  import org.apache.struts.action.ActionMessages;
39  import org.apache.struts.action.ActionMessage;
40  import org.apache.struts.util.MessageResources;
41  
42  
43  /**
44   * <p><code>Renderer</code> implementation for the <code>errors</code> tag
45   * from the <em>Struts-Faces Integration Library</em>.</p>
46   *
47   * @version $Rev: 471754 $ $Date: 2006-11-06 08:55:09 -0600 (Mon, 06 Nov 2006) $
48   */
49  
50  public class ErrorsRenderer extends AbstractRenderer {
51  
52  
53      // -------------------------------------------------------- Static Variables
54  
55  
56      /**
57       * <p>The <code>Log</code> instance for this class.</p>
58       */
59      private static Log log = LogFactory.getLog(ErrorsRenderer.class);
60  
61  
62      /**
63       * The dummy message resources for this package.
64       */
65      protected static MessageResources dummy =
66        MessageResources.getMessageResources
67          ("org.apache.struts.faces.renderer.Dummy");
68  
69      // ---------------------------------------------------------- Public Methods
70  
71  
72      /**
73       * <p>Render a combination of error messages from JavaServer Faces
74       * <code>Validator</code>s, and Struts messages from form bean
75       * <code>validate()</code> methods and corresponding business logic
76       * error checks.</p>
77       *
78       * @param context FacesContext for the request we are processing
79       * @param component UIComponent to be rendered
80       *
81       * @exception IOException if an input/output error occurs while rendering
82       * @exception NullPointerException if <code>context</code>
83       *  or <code>component</code> is null
84       */
85      public void encodeEnd(FacesContext context, UIComponent component)
86          throws IOException {
87  
88          if ((context == null) || (component == null)) {
89              throw new NullPointerException();
90          }
91  
92          if (log.isDebugEnabled()) {
93              log.debug("encodeEnd() started");
94          }
95  
96          // Look up availability of our predefined resource keys
97          MessageResources resources = resources(context, component);
98          if (Beans.isDesignTime() && (resources == null)) {
99              resources = dummy;
100         }
101         Locale locale = context.getViewRoot().getLocale();
102         boolean headerPresent = resources.isPresent(locale, "errors.header");
103         boolean footerPresent = resources.isPresent(locale, "errors.footer");
104         boolean prefixPresent = resources.isPresent(locale, "errors.prefix");
105         boolean suffixPresent = resources.isPresent(locale, "errors.suffix");
106 
107         // Set up to render the error messages appropriately
108         boolean headerDone = false;
109         ResponseWriter writer = context.getResponseWriter();
110         String id = component.getId();
111         String property = (String) component.getAttributes().get("property");
112         if (id != null) {
113             writer.startElement("span", component);
114             if (id != null) {
115                 writer.writeAttribute("id", component.getClientId(context),
116                                       "id");
117             }
118         }
119 
120         // Render any JavaServer Faces messages
121         Iterator messages = context.getMessages(property);
122         while (messages.hasNext()) {
123             FacesMessage message = (FacesMessage) messages.next();
124             if (log.isTraceEnabled()) {
125                 log.trace("Processing FacesMessage: " + message.getSummary());
126             }
127             if (!headerDone) {
128                 if (headerPresent) {
129                     writer.write
130                         (resources.getMessage(locale, "errors.header"));
131                 }
132                 headerDone = true;
133             }
134             if (prefixPresent) {
135                 writer.write(resources.getMessage(locale, "errors.prefix"));
136             }
137             writer.write(message.getSummary());
138             if (suffixPresent) {
139                 writer.write(resources.getMessage(locale, "errors.suffix"));
140             }
141         }
142 
143         // Render any Struts messages
144         ActionMessages errors = (ActionMessages)
145             context.getExternalContext().getRequestMap().get
146             (Globals.ERROR_KEY);
147         if (errors != null) {
148             if (log.isTraceEnabled()) {
149                 log.trace("Processing Struts messages for property '" +
150                           property + "'");
151             }
152             Iterator reports = null;
153             if (property == null) {
154                 reports = errors.get();
155             } else {
156                 reports = errors.get(property);
157             }
158             while (reports.hasNext()) {
159                 ActionMessage report = (ActionMessage) reports.next();
160                 if (log.isTraceEnabled()) {
161                     log.trace("Processing Struts message key='" +
162                               report.getKey() + "'");
163                 }
164                 if (!headerDone) {
165                     writer = context.getResponseWriter();
166                     if (headerPresent) {
167                         writer.write
168                             (resources.getMessage(locale, "errors.header"));
169                     }
170                     headerDone = true;
171                 }
172                 if (prefixPresent) {
173                     writer.write
174                         (resources.getMessage(locale, "errors.prefix"));
175                 }
176                 writer.write(resources.getMessage(locale, report.getKey(),
177                                                   report.getValues()));
178                 if (suffixPresent) {
179                     writer.write
180                         (resources.getMessage(locale, "errors.suffix"));
181                 }
182             }
183         }
184 
185         // Append the list footer if needed
186         if (headerDone && footerPresent) {
187             writer.write(resources.getMessage(locale, "errors.footer"));
188         }
189         if (id != null) {
190             writer.endElement("span");
191         }
192 
193         if (log.isDebugEnabled()) {
194             log.debug("encodeEnd() finished");
195         }
196 
197     }
198 
199 
200 
201     // ------------------------------------------------------ Protected Methods
202 
203 
204     /**
205      * <p>Return the <code>MessageResources</code> bundle from which
206      * we should return any Struts based error messages.  If no such
207      * bundle can be located, return <code>null</code>.</p>
208      *
209      * @param context FacesContext for the request we are processing
210      * @param component UIComponent to be rendered
211      */
212     protected MessageResources resources(FacesContext context,
213                                          UIComponent component) {
214 
215         String bundle = (String) component.getAttributes().get("bundle");
216         if (bundle == null) {
217             bundle = Globals.MESSAGES_KEY;
218         }
219         return ((MessageResources)
220                 context.getExternalContext().getApplicationMap().get(bundle));
221 
222     }
223 
224 
225 }