View Javadoc

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