View Javadoc

1   /*
2    * $Id: Resources.java 421119 2006-07-12 04:49:11Z wsmoak $
3    *
4    * Copyright 2000-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.struts.validator;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.apache.commons.validator.Arg;
23  import org.apache.commons.validator.Field;
24  import org.apache.commons.validator.Msg;
25  import org.apache.commons.validator.Validator;
26  import org.apache.commons.validator.ValidatorAction;
27  import org.apache.commons.validator.ValidatorResources;
28  import org.apache.commons.validator.Var;
29  import org.apache.struts.Globals;
30  import org.apache.struts.action.ActionMessage;
31  import org.apache.struts.action.ActionMessages;
32  import org.apache.struts.config.ModuleConfig;
33  import org.apache.struts.util.MessageResources;
34  import org.apache.struts.util.ModuleUtils;
35  import org.apache.struts.util.RequestUtils;
36  
37  import javax.servlet.ServletContext;
38  import javax.servlet.http.HttpServletRequest;
39  
40  import java.util.Locale;
41  
42  /***
43   * This class helps provides some useful methods for retrieving objects from
44   * different scopes of the application.
45   *
46   * @version $Rev: 421119 $ $Date: 2005-09-16 23:34:41 -0400 (Fri, 16 Sep 2005)
47   *          $
48   * @since Struts 1.1
49   */
50  public class Resources {
51      /***
52       * The message resources for this package.
53       */
54      private static MessageResources sysmsgs =
55          MessageResources.getMessageResources(
56              "org.apache.struts.validator.LocalStrings");
57  
58      /***
59       * <p>Commons Logging instance.</p>
60       */
61      private static Log log = LogFactory.getLog(Resources.class);
62  
63      /***
64       * Resources key the <code>ServletContext</code> is stored under.
65       */
66      private static String SERVLET_CONTEXT_PARAM =
67          "javax.servlet.ServletContext";
68  
69      /***
70       * Resources key the <code>HttpServletRequest</code> is stored under.
71       */
72      private static String HTTP_SERVLET_REQUEST_PARAM =
73          "javax.servlet.http.HttpServletRequest";
74  
75      /***
76       * Resources key the <code>ActionMessages</code> is stored under.
77       */
78      private static String ACTION_MESSAGES_PARAM =
79          "org.apache.struts.action.ActionMessages";
80  
81      /***
82       * Retrieve <code>ValidatorResources</code> for the current module.
83       *
84       * @param application Application Context
85       * @param request     The ServletRequest
86       */
87      public static ValidatorResources getValidatorResources(
88          ServletContext application, HttpServletRequest request) {
89          String prefix =
90              ModuleUtils.getInstance().getModuleConfig(request, application)
91                         .getPrefix();
92  
93          return (ValidatorResources) application.getAttribute(ValidatorPlugIn.VALIDATOR_KEY
94              + prefix);
95      }
96  
97      /***
98       * Retrieve <code>MessageResources</code> for the module.
99       *
100      * @param request the servlet request
101      */
102     public static MessageResources getMessageResources(
103         HttpServletRequest request) {
104         return (MessageResources) request.getAttribute(Globals.MESSAGES_KEY);
105     }
106 
107     /***
108      * Retrieve <code>MessageResources</code> for the module and bundle.
109      *
110      * @param application the servlet context
111      * @param request     the servlet request
112      * @param bundle      the bundle key
113      */
114     public static MessageResources getMessageResources(
115         ServletContext application, HttpServletRequest request, String bundle) {
116         if (bundle == null) {
117             bundle = Globals.MESSAGES_KEY;
118         }
119 
120         MessageResources resources =
121             (MessageResources) request.getAttribute(bundle);
122 
123         if (resources == null) {
124             ModuleConfig moduleConfig =
125                 ModuleUtils.getInstance().getModuleConfig(request, application);
126 
127             resources =
128                 (MessageResources) application.getAttribute(bundle
129                     + moduleConfig.getPrefix());
130         }
131 
132         if (resources == null) {
133             resources = (MessageResources) application.getAttribute(bundle);
134         }
135 
136         if (resources == null) {
137             throw new NullPointerException(
138                 "No message resources found for bundle: " + bundle);
139         }
140 
141         return resources;
142     }
143 
144     /***
145      * Get the value of a variable.
146      *
147      * @param varName   The variable name
148      * @param field     the validator Field
149      * @param validator The Validator
150      * @param request   the servlet request
151      * @param required  Whether the variable is mandatory
152      * @return The variable's value
153      */
154     public static String getVarValue(String varName, Field field,
155         Validator validator, HttpServletRequest request, boolean required) {
156         Var var = field.getVar(varName);
157 
158         if (var == null) {
159             String msg = sysmsgs.getMessage("variable.missing", varName);
160 
161             if (required) {
162                 throw new IllegalArgumentException(msg);
163             }
164 
165             if (log.isDebugEnabled()) {
166                 log.debug(field.getProperty() + ": " + msg);
167             }
168 
169             return null;
170         }
171 
172         ServletContext application =
173             (ServletContext) validator.getParameterValue(SERVLET_CONTEXT_PARAM);
174 
175         return getVarValue(var, application, request, required);
176     }
177 
178     /***
179      * Get the value of a variable.
180      *
181      * @param var         the validator variable
182      * @param application The ServletContext
183      * @param request     the servlet request
184      * @param required    Whether the variable is mandatory
185      * @return The variables values
186      */
187     public static String getVarValue(Var var, ServletContext application,
188         HttpServletRequest request, boolean required) {
189         String varName = var.getName();
190         String varValue = var.getValue();
191 
192         // Non-resource variable
193         if (!var.isResource()) {
194             return varValue;
195         }
196 
197         // Get the message resources
198         String bundle = var.getBundle();
199         MessageResources messages =
200             getMessageResources(application, request, bundle);
201 
202         // Retrieve variable's value from message resources
203         Locale locale = RequestUtils.getUserLocale(request, null);
204         String value = messages.getMessage(locale, varValue, null);
205 
206         // Not found in message resources
207         if ((value == null) && required) {
208             throw new IllegalArgumentException(sysmsgs.getMessage(
209                     "variable.resource.notfound", varName, varValue, bundle));
210         }
211 
212         if (log.isDebugEnabled()) {
213             log.debug("Var=[" + varName + "], " + "bundle=[" + bundle + "], "
214                 + "key=[" + varValue + "], " + "value=[" + value + "]");
215         }
216 
217         return value;
218     }
219 
220     /***
221      * Gets the <code>Locale</code> sensitive value based on the key passed
222      * in.
223      *
224      * @param messages The Message resources
225      * @param locale   The locale.
226      * @param key      Key used to lookup the message
227      */
228     public static String getMessage(MessageResources messages, Locale locale,
229         String key) {
230         String message = null;
231 
232         if (messages != null) {
233             message = messages.getMessage(locale, key);
234         }
235 
236         return (message == null) ? "" : message;
237     }
238 
239     /***
240      * Gets the <code>Locale</code> sensitive value based on the key passed
241      * in.
242      *
243      * @param request servlet request
244      * @param key     the request key
245      */
246     public static String getMessage(HttpServletRequest request, String key) {
247         MessageResources messages = getMessageResources(request);
248 
249         return getMessage(messages, RequestUtils.getUserLocale(request, null),
250             key);
251     }
252 
253     /***
254      * Gets the locale sensitive message based on the <code>ValidatorAction</code>
255      * message and the <code>Field</code>'s arg objects.
256      *
257      * @param messages The Message resources
258      * @param locale   The locale
259      * @param va       The Validator Action
260      * @param field    The Validator Field
261      */
262     public static String getMessage(MessageResources messages, Locale locale,
263         ValidatorAction va, Field field) {
264         String[] args = getArgs(va.getName(), messages, locale, field);
265         String msg =
266             (field.getMsg(va.getName()) != null) ? field.getMsg(va.getName())
267                                                  : va.getMsg();
268 
269         return messages.getMessage(locale, msg, args);
270     }
271 
272     /***
273      * Gets the <code>Locale</code> sensitive value based on the key passed
274      * in.
275      *
276      * @param application     the servlet context
277      * @param request         the servlet request
278      * @param defaultMessages The default Message resources
279      * @param locale          The locale
280      * @param va              The Validator Action
281      * @param field           The Validator Field
282      */
283     public static String getMessage(ServletContext application,
284         HttpServletRequest request, MessageResources defaultMessages,
285         Locale locale, ValidatorAction va, Field field) {
286         Msg msg = field.getMessage(va.getName());
287 
288         if ((msg != null) && !msg.isResource()) {
289             return msg.getKey();
290         }
291 
292         String msgKey = null;
293         String msgBundle = null;
294         MessageResources messages = defaultMessages;
295 
296         if (msg == null) {
297             msgKey = va.getMsg();
298         } else {
299             msgKey = msg.getKey();
300             msgBundle = msg.getBundle();
301 
302             if (msg.getBundle() != null) {
303                 messages =
304                     getMessageResources(application, request, msg.getBundle());
305             }
306         }
307 
308         if ((msgKey == null) || (msgKey.length() == 0)) {
309             return "??? " + va.getName() + "." + field.getProperty() + " ???";
310         }
311 
312         // Get the arguments
313         Arg[] args = field.getArgs(va.getName());
314         String[] argValues =
315             getArgValues(application, request, messages, locale, args);
316 
317         // Return the message
318         return messages.getMessage(locale, msgKey, argValues);
319     }
320 
321     /***
322      * Gets the <code>ActionMessage</code> based on the
323      * <code>ValidatorAction</code> message and the <code>Field</code>'s arg
324      * objects.
325      *
326      * @param request the servlet request
327      * @param va      Validator action
328      * @param field   the validator Field
329      */
330     public static ActionMessage getActionMessage(HttpServletRequest request,
331         ValidatorAction va, Field field) {
332         String[] args =
333             getArgs(va.getName(), getMessageResources(request),
334                 RequestUtils.getUserLocale(request, null), field);
335 
336         String msg =
337             (field.getMsg(va.getName()) != null) ? field.getMsg(va.getName())
338                                                  : va.getMsg();
339 
340         return new ActionMessage(msg, args);
341     }
342 
343     /***
344      * Gets the <code>ActionMessage</code> based on the
345      * <code>ValidatorAction</code> message and the <code>Field</code>'s arg
346      * objects.
347      *
348      * @param validator the Validator
349      * @param request   the servlet request
350      * @param va        Validator action
351      * @param field     the validator Field
352      */
353     public static ActionMessage getActionMessage(Validator validator,
354         HttpServletRequest request, ValidatorAction va, Field field) {
355         Msg msg = field.getMessage(va.getName());
356 
357         if ((msg != null) && !msg.isResource()) {
358             return new ActionMessage(msg.getKey(), false);
359         }
360 
361         String msgKey = null;
362         String msgBundle = null;
363 
364         if (msg == null) {
365             msgKey = va.getMsg();
366         } else {
367             msgKey = msg.getKey();
368             msgBundle = msg.getBundle();
369         }
370 
371         if ((msgKey == null) || (msgKey.length() == 0)) {
372             return new ActionMessage("??? " + va.getName() + "."
373                 + field.getProperty() + " ???", false);
374         }
375 
376         ServletContext application =
377             (ServletContext) validator.getParameterValue(SERVLET_CONTEXT_PARAM);
378         MessageResources messages =
379             getMessageResources(application, request, msgBundle);
380         Locale locale = RequestUtils.getUserLocale(request, null);
381 
382         Arg[] args = field.getArgs(va.getName());
383         String[] argValues =
384             getArgValues(application, request, messages, locale, args);
385 
386         ActionMessage actionMessage = null;
387 
388         if (msgBundle == null) {
389             actionMessage = new ActionMessage(msgKey, argValues);
390         } else {
391             String message = messages.getMessage(locale, msgKey, argValues);
392 
393             actionMessage = new ActionMessage(message, false);
394         }
395 
396         return actionMessage;
397     }
398 
399     /***
400      * Gets the message arguments based on the current <code>ValidatorAction</code>
401      * and <code>Field</code>.
402      *
403      * @param actionName action name
404      * @param messages   message resources
405      * @param locale     the locale
406      * @param field      the validator field
407      */
408     public static String[] getArgs(String actionName,
409         MessageResources messages, Locale locale, Field field) {
410         String[] argMessages = new String[4];
411 
412         Arg[] args =
413             new Arg[] {
414                 field.getArg(actionName, 0), field.getArg(actionName, 1),
415                 field.getArg(actionName, 2), field.getArg(actionName, 3)
416             };
417 
418         for (int i = 0; i < args.length; i++) {
419             if (args[i] == null) {
420                 continue;
421             }
422 
423             if (args[i].isResource()) {
424                 argMessages[i] = getMessage(messages, locale, args[i].getKey());
425             } else {
426                 argMessages[i] = args[i].getKey();
427             }
428         }
429 
430         return argMessages;
431     }
432 
433     /***
434      * Gets the message arguments based on the current <code>ValidatorAction</code>
435      * and <code>Field</code>.
436      *
437      * @param application     the servlet context
438      * @param request         the servlet request
439      * @param defaultMessages Default message resources
440      * @param locale          the locale
441      * @param args            The arguments for the message
442      */
443     private static String[] getArgValues(ServletContext application,
444         HttpServletRequest request, MessageResources defaultMessages,
445         Locale locale, Arg[] args) {
446         if ((args == null) || (args.length == 0)) {
447             return null;
448         }
449 
450         String[] values = new String[args.length];
451 
452         for (int i = 0; i < args.length; i++) {
453             if (args[i] != null) {
454                 if (args[i].isResource()) {
455                     MessageResources messages = defaultMessages;
456 
457                     if (args[i].getBundle() != null) {
458                         messages =
459                             getMessageResources(application, request,
460                                 args[i].getBundle());
461                     }
462 
463                     values[i] = messages.getMessage(locale, args[i].getKey());
464                 } else {
465                     values[i] = args[i].getKey();
466                 }
467             }
468         }
469 
470         return values;
471     }
472 
473     /***
474      * Initialize the <code>Validator</code> to perform validation.
475      *
476      * @param key         The key that the validation rules are under (the
477      *                    form elements name attribute).
478      * @param bean        The bean validation is being performed on.
479      * @param application servlet context
480      * @param request     The current request object.
481      * @param errors      The object any errors will be stored in.
482      * @param page        This in conjunction with  the page property of a
483      *                    <code>Field<code> can control the processing of
484      *                    fields.  If the field's page is less than or equal
485      *                    to this page value, it will be processed.
486      */
487     public static Validator initValidator(String key, Object bean,
488         ServletContext application, HttpServletRequest request,
489         ActionMessages errors, int page) {
490         ValidatorResources resources =
491             Resources.getValidatorResources(application, request);
492 
493         Locale locale = RequestUtils.getUserLocale(request, null);
494 
495         Validator validator = new Validator(resources, key);
496 
497         validator.setUseContextClassLoader(true);
498 
499         validator.setPage(page);
500 
501         validator.setParameter(SERVLET_CONTEXT_PARAM, application);
502         validator.setParameter(HTTP_SERVLET_REQUEST_PARAM, request);
503         validator.setParameter(Validator.LOCALE_PARAM, locale);
504         validator.setParameter(ACTION_MESSAGES_PARAM, errors);
505         validator.setParameter(Validator.BEAN_PARAM, bean);
506 
507         return validator;
508     }
509 }