View Javadoc

1   package org.appfuse.webapp.taglib;
2   
3   import org.apache.commons.logging.Log;
4   import org.apache.commons.logging.LogFactory;
5   import org.apache.commons.validator.Field;
6   import org.apache.commons.validator.Form;
7   import org.apache.commons.validator.ValidatorResources;
8   import org.springframework.beans.factory.BeanFactoryUtils;
9   import org.springframework.beans.factory.NoSuchBeanDefinitionException;
10  import org.springframework.context.MessageSource;
11  import org.springframework.context.NoSuchMessageException;
12  import org.springframework.validation.Errors;
13  import org.springframework.web.context.WebApplicationContext;
14  import org.springframework.web.context.support.WebApplicationContextUtils;
15  import org.springframework.web.servlet.DispatcherServlet;
16  import org.springframework.web.servlet.support.RequestContext;
17  import org.springmodules.validation.commons.ValidatorFactory;
18  
19  import javax.servlet.http.HttpServletRequest;
20  import javax.servlet.jsp.JspException;
21  import javax.servlet.jsp.tagext.TagSupport;
22  import java.io.IOException;
23  import java.util.List;
24  import java.util.Locale;
25  
26  
27  /**
28   * <p>This class is designed to render a <label> tag for labeling your forms and
29   * adds an asterik (*) for required fields.  It was originally written by Erik
30   * Hatcher (http://www.ehatchersolutions.com/JavaDevWithAnt/).
31   * <p/>
32   * <p>It is designed to be used as follows:
33   * <pre>&lt;tag:label key="userForm.username"/&gt;</pre>
34   *
35   * @jsp.tag name="label" bodycontent="empty"
36   */
37  public class LabelTag extends TagSupport {
38      private static final long serialVersionUID = -5310144023136517119L;
39      protected RequestContext requestContext;
40      protected transient final Log log = LogFactory.getLog(LabelTag.class);
41      protected String key = null;
42      protected String styleClass = null;
43      protected String errorClass = null;
44      protected boolean colon = false;
45  
46      public int doStartTag() throws JspException {
47  
48          try {
49              this.requestContext =
50                      new RequestContext((HttpServletRequest) this.pageContext.getRequest());
51          } catch (RuntimeException ex) {
52              throw ex;
53          } catch (Exception ex) {
54              pageContext.getServletContext().log("Exception in custom tag", ex);
55          }
56  
57          // Look up this key to see if its a field of the current form
58          boolean requiredField = false;
59          boolean validationError = false;
60  
61          ValidatorResources resources = getValidatorResources();
62  
63          Locale locale = pageContext.getRequest().getLocale();
64  
65          if (locale == null) {
66              locale = Locale.getDefault();
67          }
68  
69          // get the name of the bean from the key
70          String formName = key.substring(0, key.indexOf('.'));
71          String fieldName = key.substring(formName.length() + 1);
72  
73          if (resources != null) {
74              Form form = resources.getForm(locale, formName);
75  
76              if (form != null) {
77                  Field field = form.getField(fieldName);
78  
79                  if (field != null) {
80                      if (field.isDependency("required") || field.isDependency("validwhen")) {
81                          requiredField = true;
82                      }
83                  }
84              }
85          }
86  
87          Errors errors = requestContext.getErrors(formName, false);
88          List fes = null;
89          if (errors != null) {
90              fes = errors.getFieldErrors(fieldName);
91              //String errorMsg = getErrorMessages(fes);
92          }
93  
94          if (fes != null && fes.size() > 0) {
95              validationError = true;
96          }
97  
98          // Retrieve the message string we are looking for
99          String message = null;
100         try {
101             message = getMessageSource().getMessage(key, null, locale);
102         } catch (NoSuchMessageException nsm) {
103             message = "???" + key + "???";
104         }
105 
106         String cssClass = null;
107         if (styleClass != null) {
108             cssClass = styleClass;
109         } else if (requiredField) {
110             cssClass = "required";
111         }
112 
113         String cssErrorClass = (errorClass != null) ? errorClass : "error";
114         StringBuilder label = new StringBuilder();
115 
116         if ((message == null) || "".equals(message.trim())) {
117             label.append("");
118         } else {
119             label.append("<label for=\"").append(fieldName).append("\"");
120 
121             if (cssClass != null) {
122                 label.append(" class=\"").append(cssClass);
123                 if (validationError) {
124                     label.append(" ").append(cssErrorClass);
125                 }
126             }
127 
128             label.append("\">").append(message);
129             label.append((requiredField) ? " <span class=\"required\">*</span>" : "");
130             label.append((colon) ? ":" : "");
131             label.append("</label>");
132         }
133 
134         // Print the retrieved message to our output writer
135         try {
136             writeMessage(label.toString());
137         } catch (IOException io) {
138             io.printStackTrace();
139             throw new JspException("Error writing label: " + io.getMessage());
140         }
141 
142         // Continue processing this page
143         return (SKIP_BODY);
144     }
145 
146     /**
147      * Extract the error messages from the given ObjectError list.
148      */
149     /*private String getErrorMessages(List fes) throws NoSuchMessageException {
150         StringBuffer message = new StringBuffer();
151         for (int i = 0; i < fes.size(); i++) {
152             ObjectError error = (ObjectError) fes.get(i);
153             message.append(this.requestContext.getMessage(error, true));
154         }
155         return message.toString();
156     }*/
157 
158     /**
159      * Write the message to the page.
160      *
161      * @param msg the message to write
162      * @throws IOException if writing failed
163      */
164 
165     protected void writeMessage(String msg) throws IOException {
166         pageContext.getOut().write(msg);
167     }
168 
169     /**
170      * @jsp.attribute required="true" rtexprvalue="true"
171      */
172     public void setKey(String key) {
173         this.key = key;
174     }
175 
176     /**
177      * Setter for specifying whether to include colon
178      *
179      * @jsp.attribute required="false" rtexprvalue="true"
180      */
181     public void setColon(boolean colon) {
182         this.colon = colon;
183     }
184 
185     /**
186      * Setter for assigning a CSS class, default is label.
187      *
188      * @jsp.attribute required="false" rtexprvalue="true"
189      */
190     public void setStyleClass(String styleClass) {
191         this.styleClass = styleClass;
192     }
193 
194     /**
195      * Setter for assigning a CSS class when errors occur,
196      * defaults to labelError.
197      *
198      * @jsp.attribute required="false" rtexprvalue="true"
199      */
200     public void setErrorClass(String errorClass) {
201         this.errorClass = errorClass;
202     }
203 
204     /**
205      * Release all allocated resources.
206      */
207     public void release() {
208         super.release();
209         key = null;
210         colon = false;
211         styleClass = null;
212         errorClass = null;
213         requestContext = null;
214     }
215 
216 /**
217  * Do End Tag to clear objects from memory
218  */
219 public final int doEndTag()
220 {
221      super.release();
222         key = null;
223         colon = false;
224         styleClass = null;
225         errorClass = null;
226         requestContext = null;
227         return 1;
228     
229 }
230 
231 
232     /**
233      * Get the validator resources from a ValidatorFactory defined in the
234      * web application context or one of its parent contexts.
235      * The bean is resolved by type (org.springframework.validation.commons.ValidatorFactory).
236      *
237      * @return ValidatorResources from a ValidatorFactory.
238      */
239     private ValidatorResources getValidatorResources() {
240         // look in servlet beans definition (i.e. action-servlet.xml)
241         WebApplicationContext ctx = (WebApplicationContext) pageContext.getRequest()
242                 .getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);
243         ValidatorFactory factory = null;
244         try {
245             factory = (ValidatorFactory) BeanFactoryUtils
246                     .beanOfTypeIncludingAncestors(ctx, ValidatorFactory.class, true, true);
247         } catch (NoSuchBeanDefinitionException e) {
248             // look in main application context (i.e. applicationContext.xml)
249             ctx = WebApplicationContextUtils
250                     .getRequiredWebApplicationContext(pageContext.getServletContext());
251             factory = (ValidatorFactory) BeanFactoryUtils
252                     .beanOfTypeIncludingAncestors(ctx, ValidatorFactory.class, true, true);
253         }
254         return factory.getValidatorResources();
255     }
256 
257 
258     /**
259      * Use the application context itself for default message resolution.
260      */
261     private MessageSource getMessageSource() {
262         return requestContext.getWebApplicationContext();
263     }
264 }