View Javadoc

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