View Javadoc

    1   /*
    2    * $Id: FieldChecks.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  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.Field;
    26  import org.apache.commons.validator.GenericTypeValidator;
    27  import org.apache.commons.validator.GenericValidator;
    28  import org.apache.commons.validator.UrlValidator;
    29  import org.apache.commons.validator.Validator;
    30  import org.apache.commons.validator.ValidatorAction;
    31  import org.apache.commons.validator.util.ValidatorUtils;
    32  import org.apache.struts.action.ActionMessage;
    33  import org.apache.struts.action.ActionMessages;
    34  import org.apache.struts.util.MessageResources;
    35  import org.apache.struts.util.RequestUtils;
    36
    37  import javax.servlet.http.HttpServletRequest;
    38
    39  import java.io.Serializable;
    40
    41  import java.util.Locale;
    42  import java.util.StringTokenizer;
    43
    44  /**
    45   * <p> This class contains the default validations that are used in the
    46   * validator-rules.xml file. </p> <p> In general passing in a null or blank
    47   * will return a null Object or a false boolean. However, nulls and blanks do
    48   * not result in an error being added to the errors. </p>
    49   *
    50   * @since Struts 1.1
    51   */
    52  public class FieldChecks implements Serializable {
    53      /**
    54       * Commons Logging instance.
    55       */
    56      private static final Log log = LogFactory.getLog(FieldChecks.class);
    57
    58      /**
    59       * The message resources for this package.
    60       */
    61      private static MessageResources sysmsgs =
    62          MessageResources.getMessageResources(
    63              "org.apache.struts.validator.LocalStrings");
    64      public static final String FIELD_TEST_NULL = "NULL";
    65      public static final String FIELD_TEST_NOTNULL = "NOTNULL";
    66      public static final String FIELD_TEST_EQUAL = "EQUAL";
    67
    68      /**
    69       * Checks if the field isn't null and length of the field is greater than
    70       * zero not including whitespace.
    71       *
    72       * @param bean      The bean validation is being performed on.
    73       * @param va        The <code>ValidatorAction</code> that is currently
    74       *                  being performed.
    75       * @param field     The <code>Field</code> object associated with the
    76       *                  current field being validated.
    77       * @param errors    The <code>ActionMessages</code> object to add errors
    78       *                  to if any validation errors occur.
    79       * @param validator The <code>Validator</code> instance, used to access
    80       *                  other field values.
    81       * @param request   Current request object.
    82       * @return true if meets stated requirements, false otherwise.
    83       */
    84      public static boolean validateRequired(Object bean, ValidatorAction va,
    85          Field field, ActionMessages errors, Validator validator,
    86          HttpServletRequest request) {
    87          String value = null;
    88
    89          value = evaluateBean(bean, field);
    90
    91          if (GenericValidator.isBlankOrNull(value)) {
    92              errors.add(field.getKey(),
    93                  Resources.getActionMessage(validator, request, va, field));
    94
    95              return false;
    96          } else {
    97              return true;
    98          }
    99      }
    100
    101     /**
    102      * Checks if the field isn't null based on the values of other fields.
    103      *
    104      * @param bean      The bean validation is being performed on.
    105      * @param va        The <code>ValidatorAction</code> that is currently
    106      *                  being performed.
    107      * @param field     The <code>Field</code> object associated with the
    108      *                  current field being validated.
    109      * @param errors    The <code>ActionMessages</code> object to add errors
    110      *                  to if any validation errors occur.
    111      * @param validator The <code>Validator</code> instance, used to access
    112      *                  other field values.
    113      * @param request   Current request object.
    114      * @return true if meets stated requirements, false otherwise.
    115      */
    116     public static boolean validateRequiredIf(Object bean, ValidatorAction va,
    117         Field field, ActionMessages errors, Validator validator,
    118         HttpServletRequest request) {
    119         Object form =
    120             validator.getParameterValue(org.apache.commons.validator.Validator.BEAN_PARAM);
    121         String value = null;
    122         boolean required = false;
    123
    124         value = evaluateBean(bean, field);
    125
    126         int i = 0;
    127         String fieldJoin = "AND";
    128
    129         if (!GenericValidator.isBlankOrNull(field.getVarValue("fieldJoin"))) {
    130             fieldJoin = field.getVarValue("fieldJoin");
    131         }
    132
    133         if (fieldJoin.equalsIgnoreCase("AND")) {
    134             required = true;
    135         }
    136
    137         while (!GenericValidator.isBlankOrNull(field.getVarValue("field[" + i
    138                     + "]"))) {
    139             String dependProp = field.getVarValue("field[" + i + "]");
    140             String dependTest = field.getVarValue("fieldTest[" + i + "]");
    141             String dependTestValue = field.getVarValue("fieldValue[" + i + "]");
    142             String dependIndexed = field.getVarValue("fieldIndexed[" + i + "]");
    143
    144             if (dependIndexed == null) {
    145                 dependIndexed = "false";
    146             }
    147
    148             String dependVal = null;
    149             boolean thisRequired = false;
    150
    151             if (field.isIndexed() && dependIndexed.equalsIgnoreCase("true")) {
    152                 String key = field.getKey();
    153
    154                 if ((key.indexOf("[") > -1) && (key.indexOf("]") > -1)) {
    155                     String ind = key.substring(0, key.indexOf(".") + 1);
    156
    157                     dependProp = ind + dependProp;
    158                 }
    159             }
    160
    161             dependVal = ValidatorUtils.getValueAsString(form, dependProp);
    162
    163             if (dependTest.equals(FIELD_TEST_NULL)) {
    164                 if ((dependVal != null) && (dependVal.length() > 0)) {
    165                     thisRequired = false;
    166                 } else {
    167                     thisRequired = true;
    168                 }
    169             }
    170
    171             if (dependTest.equals(FIELD_TEST_NOTNULL)) {
    172                 if ((dependVal != null) && (dependVal.length() > 0)) {
    173                     thisRequired = true;
    174                 } else {
    175                     thisRequired = false;
    176                 }
    177             }
    178
    179             if (dependTest.equals(FIELD_TEST_EQUAL)) {
    180                 thisRequired = dependTestValue.equalsIgnoreCase(dependVal);
    181             }
    182
    183             if (fieldJoin.equalsIgnoreCase("AND")) {
    184                 required = required && thisRequired;
    185             } else {
    186                 required = required || thisRequired;
    187             }
    188
    189             i++;
    190         }
    191
    192         if (required) {
    193             if (GenericValidator.isBlankOrNull(value)) {
    194                 errors.add(field.getKey(),
    195                     Resources.getActionMessage(validator, request, va, field));
    196
    197                 return false;
    198             } else {
    199                 return true;
    200             }
    201         }
    202
    203         return true;
    204     }
    205
    206     /**
    207      * Checks if the field matches the regular expression in the field's mask
    208      * attribute.
    209      *
    210      * @param bean      The bean validation is being performed on.
    211      * @param va        The <code>ValidatorAction</code> that is currently
    212      *                  being performed.
    213      * @param field     The <code>Field</code> object associated with the
    214      *                  current field being validated.
    215      * @param errors    The <code>ActionMessages</code> object to add errors
    216      *                  to if any validation errors occur.
    217      * @param validator The <code>Validator</code> instance, used to access
    218      *                  other field values.
    219      * @param request   Current request object.
    220      * @return true if field matches mask, false otherwise.
    221      */
    222     public static boolean validateMask(Object bean, ValidatorAction va,
    223         Field field, ActionMessages errors, Validator validator,
    224         HttpServletRequest request) {
    225         String value = null;
    226
    227         value = evaluateBean(bean, field);
    228
    229         try {
    230             String mask =
    231                 Resources.getVarValue("mask", field, validator, request, true);
    232
    233             if (value != null && value.length()>0
    234                 && !GenericValidator.matchRegexp(value, mask)) {
    235                 errors.add(field.getKey(),
    236                     Resources.getActionMessage(validator, request, va, field));
    237
    238                 return false;
    239             } else {
    240                 return true;
    241             }
    242         } catch (Exception e) {
    243             processFailure(errors, field, "mask", e);
    244
    245             return false;
    246         }
    247     }
    248
    249     /**
    250      * Checks if the field can safely be converted to a byte primitive.
    251      *
    252      * @param bean      The bean validation is being performed on.
    253      * @param va        The <code>ValidatorAction</code> that is currently
    254      *                  being performed.
    255      * @param field     The <code>Field</code> object associated with the
    256      *                  current field being validated.
    257      * @param errors    The <code>ActionMessages</code> object to add errors
    258      *                  to if any validation errors occur.
    259      * @param validator The <code>Validator</code> instance, used to access
    260      *                  other field values.
    261      * @param request   Current request object.
    262      * @return true if valid, false otherwise.
    263      */
    264     public static Object validateByte(Object bean, ValidatorAction va,
    265         Field field, ActionMessages errors, Validator validator,
    266         HttpServletRequest request) {
    267         Object result = null;
    268         String value = null;
    269
    270         value = evaluateBean(bean, field);
    271
    272         if (GenericValidator.isBlankOrNull(value)) {
    273             return Boolean.TRUE;
    274         }
    275
    276         result = GenericTypeValidator.formatByte(value);
    277
    278         if (result == null) {
    279             errors.add(field.getKey(),
    280                 Resources.getActionMessage(validator, request, va, field));
    281         }
    282
    283         return (result == null) ? Boolean.FALSE : result;
    284     }
    285
    286     /**
    287      * Checks if the field can safely be converted to a byte primitive.
    288      *
    289      * @param bean      The bean validation is being performed on.
    290      * @param va        The <code>ValidatorAction</code> that is currently
    291      *                  being performed.
    292      * @param field     The <code>Field</code> object associated with the
    293      *                  current field being validated.
    294      * @param errors    The <code>ActionMessages</code> object to add errors
    295      *                  to if any validation errors occur.
    296      * @param validator The <code>Validator</code> instance, used to access
    297      *                  other field values.
    298      * @param request   Current request object.
    299      * @return true if valid, false otherwise.
    300      */
    301     public static Object validateByteLocale(Object bean, ValidatorAction va,
    302         Field field, ActionMessages errors, Validator validator,
    303         HttpServletRequest request) {
    304         Object result = null;
    305         String value = null;
    306
    307         value = evaluateBean(bean, field);
    308
    309         if (GenericValidator.isBlankOrNull(value)) {
    310             return Boolean.TRUE;
    311         }
    312
    313         Locale locale = RequestUtils.getUserLocale(request, null);
    314
    315         result = GenericTypeValidator.formatByte(value, locale);
    316
    317         if (result == null) {
    318             errors.add(field.getKey(),
    319                 Resources.getActionMessage(validator, request, va, field));
    320         }
    321
    322         return (result == null) ? Boolean.FALSE : result;
    323     }
    324
    325     /**
    326      * @param bean
    327      * @param field
    328      * @return
    329      */
    330     private static String evaluateBean(Object bean, Field field) {
    331         String value;
    332
    333         if (isString(bean)) {
    334             value = (String) bean;
    335         } else {
    336             value = ValidatorUtils.getValueAsString(bean, field.getProperty());
    337         }
    338
    339         return value;
    340     }
    341
    342     /**
    343      * Checks if the field can safely be converted to a short primitive.
    344      *
    345      * @param bean      The bean validation is being performed on.
    346      * @param va        The <code>ValidatorAction</code> that is currently
    347      *                  being performed.
    348      * @param field     The <code>Field</code> object associated with the
    349      *                  current field being validated.
    350      * @param errors    The <code>ActionMessages</code> object to add errors
    351      *                  to if any validation errors occur.
    352      * @param validator The <code>Validator</code> instance, used to access
    353      *                  other field values.
    354      * @param request   Current request object.
    355      * @return true if valid, false otherwise.
    356      */
    357     public static Object validateShort(Object bean, ValidatorAction va,
    358         Field field, ActionMessages errors, Validator validator,
    359         HttpServletRequest request) {
    360         Object result = null;
    361         String value = null;
    362
    363         value = evaluateBean(bean, field);
    364
    365         if (GenericValidator.isBlankOrNull(value)) {
    366             return Boolean.TRUE;
    367         }
    368
    369         result = GenericTypeValidator.formatShort(value);
    370
    371         if (result == null) {
    372             errors.add(field.getKey(),
    373                 Resources.getActionMessage(validator, request, va, field));
    374         }
    375
    376         return (result == null) ? Boolean.FALSE : result;
    377     }
    378
    379     /**
    380      * Checks if the field can safely be converted to a short primitive.
    381      *
    382      * @param bean      The bean validation is being performed on.
    383      * @param va        The <code>ValidatorAction</code> that is currently
    384      *                  being performed.
    385      * @param field     The <code>Field</code> object associated with the
    386      *                  current field being validated.
    387      * @param errors    The <code>ActionMessages</code> object to add errors
    388      *                  to if any validation errors occur.
    389      * @param validator The <code>Validator</code> instance, used to access
    390      *                  other field values.
    391      * @param request   Current request object.
    392      * @return true if valid, false otherwise.
    393      */
    394     public static Object validateShortLocale(Object bean, ValidatorAction va,
    395         Field field, ActionMessages errors, Validator validator,
    396         HttpServletRequest request) {
    397         Object result = null;
    398         String value = null;
    399
    400         value = evaluateBean(bean, field);
    401
    402         if (GenericValidator.isBlankOrNull(value)) {
    403             return Boolean.TRUE;
    404         }
    405
    406         Locale locale = RequestUtils.getUserLocale(request, null);
    407
    408         result = GenericTypeValidator.formatShort(value, locale);
    409
    410         if (result == null) {
    411             errors.add(field.getKey(),
    412                 Resources.getActionMessage(validator, request, va, field));
    413         }
    414
    415         return (result == null) ? Boolean.FALSE : result;
    416     }
    417
    418     /**
    419      * Checks if the field can safely be converted to an int primitive.
    420      *
    421      * @param bean      The bean validation is being performed on.
    422      * @param va        The <code>ValidatorAction</code> that is currently
    423      *                  being performed.
    424      * @param field     The <code>Field</code> object associated with the
    425      *                  current field being validated.
    426      * @param errors    The <code>ActionMessages</code> object to add errors
    427      *                  to if any validation errors occur.
    428      * @param validator The <code>Validator</code> instance, used to access
    429      *                  other field values.
    430      * @param request   Current request object.
    431      * @return true if valid, false otherwise.
    432      */
    433     public static Object validateInteger(Object bean, ValidatorAction va,
    434         Field field, ActionMessages errors, Validator validator,
    435         HttpServletRequest request) {
    436         Object result = null;
    437         String value = null;
    438
    439         value = evaluateBean(bean, field);
    440
    441         if (GenericValidator.isBlankOrNull(value)) {
    442             return Boolean.TRUE;
    443         }
    444
    445         result = GenericTypeValidator.formatInt(value);
    446
    447         if (result == null) {
    448             errors.add(field.getKey(),
    449                 Resources.getActionMessage(validator, request, va, field));
    450         }
    451
    452         return (result == null) ? Boolean.FALSE : result;
    453     }
    454
    455     /**
    456      * Checks if the field can safely be converted to an int primitive.
    457      *
    458      * @param bean      The bean validation is being performed on.
    459      * @param va        The <code>ValidatorAction</code> that is currently
    460      *                  being performed.
    461      * @param field     The <code>Field</code> object associated with the
    462      *                  current field being validated.
    463      * @param errors    The <code>ActionMessages</code> object to add errors
    464      *                  to if any validation errors occur.
    465      * @param validator The <code>Validator</code> instance, used to access
    466      *                  other field values.
    467      * @param request   Current request object.
    468      * @return true if valid, false otherwise.
    469      */
    470     public static Object validateIntegerLocale(Object bean, ValidatorAction va,
    471         Field field, ActionMessages errors, Validator validator,
    472         HttpServletRequest request) {
    473         Object result = null;
    474         String value = null;
    475
    476         value = evaluateBean(bean, field);
    477
    478         if (GenericValidator.isBlankOrNull(value)) {
    479             return Boolean.TRUE;
    480         }
    481
    482         Locale locale = RequestUtils.getUserLocale(request, null);
    483
    484         result = GenericTypeValidator.formatInt(value, locale);
    485
    486         if (result == null) {
    487             errors.add(field.getKey(),
    488                 Resources.getActionMessage(validator, request, va, field));
    489         }
    490
    491         return (result == null) ? Boolean.FALSE : result;
    492     }
    493
    494     /**
    495      * Checks if the field can safely be converted to a long primitive.
    496      *
    497      * @param bean      The bean validation is being performed on.
    498      * @param va        The <code>ValidatorAction</code> that is currently
    499      *                  being performed.
    500      * @param field     The <code>Field</code> object associated with the
    501      *                  current field being validated.
    502      * @param errors    The <code>ActionMessages</code> object to add errors
    503      *                  to if any validation errors occur.
    504      * @param validator The <code>Validator</code> instance, used to access
    505      *                  other field values.
    506      * @param request   Current request object.
    507      * @return true if valid, false otherwise.
    508      */
    509     public static Object validateLong(Object bean, ValidatorAction va,
    510         Field field, ActionMessages errors, Validator validator,
    511         HttpServletRequest request) {
    512         Object result = null;
    513         String value = null;
    514
    515         value = evaluateBean(bean, field);
    516
    517         if (GenericValidator.isBlankOrNull(value)) {
    518             return Boolean.TRUE;
    519         }
    520
    521         result = GenericTypeValidator.formatLong(value);
    522
    523         if (result == null) {
    524             errors.add(field.getKey(),
    525                 Resources.getActionMessage(validator, request, va, field));
    526         }
    527
    528         return (result == null) ? Boolean.FALSE : result;
    529     }
    530
    531     /**
    532      * Checks if the field can safely be converted to a long primitive.
    533      *
    534      * @param bean      The bean validation is being performed on.
    535      * @param va        The <code>ValidatorAction</code> that is currently
    536      *                  being performed.
    537      * @param field     The <code>Field</code> object associated with the
    538      *                  current field being validated.
    539      * @param errors    The <code>ActionMessages</code> object to add errors
    540      *                  to if any validation errors occur.
    541      * @param validator The <code>Validator</code> instance, used to access
    542      *                  other field values.
    543      * @param request   Current request object.
    544      * @return true if valid, false otherwise.
    545      */
    546     public static Object validateLongLocale(Object bean, ValidatorAction va,
    547         Field field, ActionMessages errors, Validator validator,
    548         HttpServletRequest request) {
    549         Object result = null;
    550         String value = null;
    551
    552         value = evaluateBean(bean, field);
    553
    554         if (GenericValidator.isBlankOrNull(value)) {
    555             return Boolean.TRUE;
    556         }
    557
    558         Locale locale = RequestUtils.getUserLocale(request, null);
    559
    560         result = GenericTypeValidator.formatLong(value, locale);
    561
    562         if (result == null) {
    563             errors.add(field.getKey(),
    564                 Resources.getActionMessage(validator, request, va, field));
    565         }
    566
    567         return (result == null) ? Boolean.FALSE : result;
    568     }
    569
    570     /**
    571      * Checks if the field can safely be converted to a float primitive.
    572      *
    573      * @param bean      The bean validation is being performed on.
    574      * @param va        The <code>ValidatorAction</code> that is currently
    575      *                  being performed.
    576      * @param field     The <code>Field</code> object associated with the
    577      *                  current field being validated.
    578      * @param errors    The <code>ActionMessages</code> object to add errors
    579      *                  to if any validation errors occur.
    580      * @param validator The <code>Validator</code> instance, used to access
    581      *                  other field values.
    582      * @param request   Current request object.
    583      * @return true if valid, false otherwise.
    584      */
    585     public static Object validateFloat(Object bean, ValidatorAction va,
    586         Field field, ActionMessages errors, Validator validator,
    587         HttpServletRequest request) {
    588         Object result = null;
    589         String value = null;
    590
    591         value = evaluateBean(bean, field);
    592
    593         if (GenericValidator.isBlankOrNull(value)) {
    594             return Boolean.TRUE;
    595         }
    596
    597         result = GenericTypeValidator.formatFloat(value);
    598
    599         if (result == null) {
    600             errors.add(field.getKey(),
    601                 Resources.getActionMessage(validator, request, va, field));
    602         }
    603
    604         return (result == null) ? Boolean.FALSE : result;
    605     }
    606
    607     /**
    608      * Checks if the field can safely be converted to a float primitive.
    609      *
    610      * @param bean      The bean validation is being performed on.
    611      * @param va        The <code>ValidatorAction</code> that is currently
    612      *                  being performed.
    613      * @param field     The <code>Field</code> object associated with the
    614      *                  current field being validated.
    615      * @param errors    The <code>ActionMessages</code> object to add errors
    616      *                  to if any validation errors occur.
    617      * @param validator The <code>Validator</code> instance, used to access
    618      *                  other field values.
    619      * @param request   Current request object.
    620      * @return true if valid, false otherwise.
    621      */
    622     public static Object validateFloatLocale(Object bean, ValidatorAction va,
    623         Field field, ActionMessages errors, Validator validator,
    624         HttpServletRequest request) {
    625         Object result = null;
    626         String value = null;
    627
    628         value = evaluateBean(bean, field);
    629
    630         if (GenericValidator.isBlankOrNull(value)) {
    631             return Boolean.TRUE;
    632         }
    633
    634         Locale locale = RequestUtils.getUserLocale(request, null);
    635
    636         result = GenericTypeValidator.formatFloat(value, locale);
    637
    638         if (result == null) {
    639             errors.add(field.getKey(),
    640                 Resources.getActionMessage(validator, request, va, field));
    641         }
    642
    643         return (result == null) ? Boolean.FALSE : result;
    644     }
    645
    646     /**
    647      * Checks if the field can safely be converted to a double primitive.
    648      *
    649      * @param bean      The bean validation is being performed on.
    650      * @param va        The <code>ValidatorAction</code> that is currently
    651      *                  being performed.
    652      * @param field     The <code>Field</code> object associated with the
    653      *                  current field being validated.
    654      * @param errors    The <code>ActionMessages</code> object to add errors
    655      *                  to if any validation errors occur.
    656      * @param validator The <code>Validator</code> instance, used to access
    657      *                  other field values.
    658      * @param request   Current request object.
    659      * @return true if valid, false otherwise.
    660      */
    661     public static Object validateDouble(Object bean, ValidatorAction va,
    662         Field field, ActionMessages errors, Validator validator,
    663         HttpServletRequest request) {
    664         Object result = null;
    665         String value = null;
    666
    667         value = evaluateBean(bean, field);
    668
    669         if (GenericValidator.isBlankOrNull(value)) {
    670             return Boolean.TRUE;
    671         }
    672
    673         result = GenericTypeValidator.formatDouble(value);
    674
    675         if (result == null) {
    676             errors.add(field.getKey(),
    677                 Resources.getActionMessage(validator, request, va, field));
    678         }
    679
    680         return (result == null) ? Boolean.FALSE : result;
    681     }
    682
    683     /**
    684      * Checks if the field can safely be converted to a double primitive.
    685      *
    686      * @param bean      The bean validation is being performed on.
    687      * @param va        The <code>ValidatorAction</code> that is currently
    688      *                  being performed.
    689      * @param field     The <code>Field</code> object associated with the
    690      *                  current field being validated.
    691      * @param errors    The <code>ActionMessages</code> object to add errors
    692      *                  to if any validation errors occur.
    693      * @param validator The <code>Validator</code> instance, used to access
    694      *                  other field values.
    695      * @param request   Current request object.
    696      * @return true if valid, false otherwise.
    697      */
    698     public static Object validateDoubleLocale(Object bean, ValidatorAction va,
    699         Field field, ActionMessages errors, Validator validator,
    700         HttpServletRequest request) {
    701         Object result = null;
    702         String value = null;
    703
    704         value = evaluateBean(bean, field);
    705
    706         if (GenericValidator.isBlankOrNull(value)) {
    707             return Boolean.TRUE;
    708         }
    709
    710         Locale locale = RequestUtils.getUserLocale(request, null);
    711
    712         result = GenericTypeValidator.formatDouble(value, locale);
    713
    714         if (result == null) {
    715             errors.add(field.getKey(),
    716                 Resources.getActionMessage(validator, request, va, field));
    717         }
    718
    719         return (result == null) ? Boolean.FALSE : result;
    720     }
    721
    722     /**
    723      * Checks if the field is a valid date. If the field has a datePattern
    724      * variable, that will be used to format <code>java.text.SimpleDateFormat</code>.
    725      * If the field has a datePatternStrict variable, that will be used to
    726      * format <code>java.text.SimpleDateFormat</code> and the length will be
    727      * checked so '2/12/1999' will not pass validation with the format
    728      * 'MM/dd/yyyy' because the month isn't two digits. If no datePattern
    729      * variable is specified, then the field gets the DateFormat.SHORT format
    730      * for the locale. The setLenient method is set to <code>false</code> for
    731      * all variations.
    732      *
    733      * @param bean      The bean validation is being performed on.
    734      * @param va        The <code>ValidatorAction</code> that is currently
    735      *                  being performed.
    736      * @param field     The <code>Field</code> object associated with the
    737      *                  current field being validated.
    738      * @param errors    The <code>ActionMessages</code> object to add errors
    739      *                  to if any validation errors occur.
    740      * @param validator The <code>Validator</code> instance, used to access
    741      *                  other field values.
    742      * @param request   Current request object.
    743      * @return true if valid, false otherwise.
    744      */
    745     public static Object validateDate(Object bean, ValidatorAction va,
    746         Field field, ActionMessages errors, Validator validator,
    747         HttpServletRequest request) {
    748         Object result = null;
    749         String value = null;
    750
    751         value = evaluateBean(bean, field);
    752
    753         boolean isStrict = false;
    754         String datePattern =
    755             Resources.getVarValue("datePattern", field, validator, request,
    756                 false);
    757
    758         if (GenericValidator.isBlankOrNull(datePattern)) {
    759             datePattern =
    760                 Resources.getVarValue("datePatternStrict", field, validator,
    761                     request, false);
    762
    763             if (!GenericValidator.isBlankOrNull(datePattern)) {
    764                 isStrict = true;
    765             }
    766         }
    767
    768         Locale locale = RequestUtils.getUserLocale(request, null);
    769
    770         if (GenericValidator.isBlankOrNull(value)) {
    771             return Boolean.TRUE;
    772         }
    773
    774         try {
    775             if (GenericValidator.isBlankOrNull(datePattern)) {
    776                 result = GenericTypeValidator.formatDate(value, locale);
    777             } else {
    778                 result =
    779                     GenericTypeValidator.formatDate(value, datePattern, isStrict);
    780             }
    781         } catch (Exception e) {
    782             log.error(e.getMessage(), e);
    783         }
    784
    785         if (result == null) {
    786             errors.add(field.getKey(),
    787                 Resources.getActionMessage(validator, request, va, field));
    788         }
    789
    790         return (result == null) ? Boolean.FALSE : result;
    791     }
    792
    793     /**
    794      * Checks if a fields value is within a range (min &amp; max specified in
    795      * the vars attribute).
    796      *
    797      * @param bean      The bean validation is being performed on.
    798      * @param va        The <code>ValidatorAction</code> that is currently
    799      *                  being performed.
    800      * @param field     The <code>Field</code> object associated with the
    801      *                  current field being validated.
    802      * @param errors    The <code>ActionMessages</code> object to add errors
    803      *                  to if any validation errors occur.
    804      * @param validator The <code>Validator</code> instance, used to access
    805      *                  other field values.
    806      * @param request   Current request object.
    807      * @return True if in range, false otherwise.
    808      */
    809     public static boolean validateLongRange(Object bean, ValidatorAction va,
    810         Field field, ActionMessages errors, Validator validator,
    811         HttpServletRequest request) {
    812         String value = null;
    813
    814         value = evaluateBean(bean, field);
    815
    816         if (!GenericValidator.isBlankOrNull(value)) {
    817             try {
    818                 String minVar =
    819                     Resources.getVarValue("min", field, validator, request, true);
    820                 String maxVar =
    821                     Resources.getVarValue("max", field, validator, request, true);
    822                 long longValue = Long.parseLong(value);
    823                 long min = Long.parseLong(minVar);
    824                 long max = Long.parseLong(maxVar);
    825
    826                 if (min > max) {
    827                     throw new IllegalArgumentException(sysmsgs.getMessage(
    828                             "invalid.range", minVar, maxVar));
    829                 }
    830
    831                 if (!GenericValidator.isInRange(longValue, min, max)) {
    832                     errors.add(field.getKey(),
    833                         Resources.getActionMessage(validator, request, va, field));
    834
    835                     return false;
    836                 }
    837             } catch (Exception e) {
    838                 processFailure(errors, field, "longRange", e);
    839
    840                 return false;
    841             }
    842         }
    843
    844         return true;
    845     }
    846
    847     /**
    848      * Checks if a fields value is within a range (min &amp; max specified in
    849      * the vars attribute).
    850      *
    851      * @param bean      The bean validation is being performed on.
    852      * @param va        The <code>ValidatorAction</code> that is currently
    853      *                  being performed.
    854      * @param field     The <code>Field</code> object associated with the
    855      *                  current field being validated.
    856      * @param errors    The <code>ActionMessages</code> object to add errors
    857      *                  to if any validation errors occur.
    858      * @param validator The <code>Validator</code> instance, used to access
    859      *                  other field values.
    860      * @param request   Current request object.
    861      * @return True if in range, false otherwise.
    862      */
    863     public static boolean validateIntRange(Object bean, ValidatorAction va,
    864         Field field, ActionMessages errors, Validator validator,
    865         HttpServletRequest request) {
    866         String value = null;
    867
    868         value = evaluateBean(bean, field);
    869
    870         if (!GenericValidator.isBlankOrNull(value)) {
    871             try {
    872                 String minVar =
    873                     Resources.getVarValue("min", field, validator, request, true);
    874                 String maxVar =
    875                     Resources.getVarValue("max", field, validator, request, true);
    876                 int min = Integer.parseInt(minVar);
    877                 int max = Integer.parseInt(maxVar);
    878                 int intValue = Integer.parseInt(value);
    879
    880                 if (min > max) {
    881                     throw new IllegalArgumentException(sysmsgs.getMessage(
    882                             "invalid.range", minVar, maxVar));
    883                 }
    884
    885                 if (!GenericValidator.isInRange(intValue, min, max)) {
    886                     errors.add(field.getKey(),
    887                         Resources.getActionMessage(validator, request, va, field));
    888
    889                     return false;
    890                 }
    891             } catch (Exception e) {
    892                 processFailure(errors, field, "intRange", e);
    893
    894                 return false;
    895             }
    896         }
    897
    898         return true;
    899     }
    900
    901     /**
    902      * Checks if a fields value is within a range (min &amp; max specified in
    903      * the vars attribute).
    904      *
    905      * @param bean      The bean validation is being performed on.
    906      * @param va        The <code>ValidatorAction</code> that is currently
    907      *                  being performed.
    908      * @param field     The <code>Field</code> object associated with the
    909      *                  current field being validated.
    910      * @param errors    The <code>ActionMessages</code> object to add errors
    911      *                  to if any validation errors occur.
    912      * @param validator The <code>Validator</code> instance, used to access
    913      *                  other field values.
    914      * @param request   Current request object.
    915      * @return True if in range, false otherwise.
    916      */
    917     public static boolean validateDoubleRange(Object bean, ValidatorAction va,
    918         Field field, ActionMessages errors, Validator validator,
    919         HttpServletRequest request) {
    920         String value = null;
    921
    922         value = evaluateBean(bean, field);
    923
    924         if (!GenericValidator.isBlankOrNull(value)) {
    925             try {
    926                 String minVar =
    927                     Resources.getVarValue("min", field, validator, request, true);
    928                 String maxVar =
    929                     Resources.getVarValue("max", field, validator, request, true);
    930                 double doubleValue = Double.parseDouble(value);
    931                 double min = Double.parseDouble(minVar);
    932                 double max = Double.parseDouble(maxVar);
    933
    934                 if (min > max) {
    935                     throw new IllegalArgumentException(sysmsgs.getMessage(
    936                             "invalid.range", minVar, maxVar));
    937                 }
    938
    939                 if (!GenericValidator.isInRange(doubleValue, min, max)) {
    940                     errors.add(field.getKey(),
    941                         Resources.getActionMessage(validator, request, va, field));
    942
    943                     return false;
    944                 }
    945             } catch (Exception e) {
    946                 processFailure(errors, field, "doubleRange", e);
    947
    948                 return false;
    949             }
    950         }
    951
    952         return true;
    953     }
    954
    955     /**
    956      * Checks if a fields value is within a range (min &amp; max specified in
    957      * the vars attribute).
    958      *
    959      * @param bean      The bean validation is being performed on.
    960      * @param va        The <code>ValidatorAction</code> that is currently
    961      *                  being performed.
    962      * @param field     The <code>Field</code> object associated with the
    963      *                  current field being validated.
    964      * @param errors    The <code>ActionMessages</code> object to add errors
    965      *                  to if any validation errors occur.
    966      * @param validator The <code>Validator</code> instance, used to access
    967      *                  other field values.
    968      * @param request   Current request object.
    969      * @return True if in range, false otherwise.
    970      */
    971     public static boolean validateFloatRange(Object bean, ValidatorAction va,
    972         Field field, ActionMessages errors, Validator validator,
    973         HttpServletRequest request) {
    974         String value = null;
    975
    976         value = evaluateBean(bean, field);
    977
    978         if (!GenericValidator.isBlankOrNull(value)) {
    979             try {
    980                 String minVar =
    981                     Resources.getVarValue("min", field, validator, request, true);
    982                 String maxVar =
    983                     Resources.getVarValue("max", field, validator, request, true);
    984                 float floatValue = Float.parseFloat(value);
    985                 float min = Float.parseFloat(minVar);
    986                 float max = Float.parseFloat(maxVar);
    987
    988                 if (min > max) {
    989                     throw new IllegalArgumentException(sysmsgs.getMessage(
    990                             "invalid.range", minVar, maxVar));
    991                 }
    992
    993                 if (!GenericValidator.isInRange(floatValue, min, max)) {
    994                     errors.add(field.getKey(),
    995                         Resources.getActionMessage(validator, request, va, field));
    996
    997                     return false;
    998                 }
    999             } catch (Exception e) {
    1000                 processFailure(errors, field, "floatRange", e);
    1001
    1002                 return false;
    1003             }
    1004         }
    1005
    1006         return true;
    1007     }
    1008
    1009     /**
    1010      * Checks if the field is a valid credit card number.
    1011      *
    1012      * @param bean      The bean validation is being performed on.
    1013      * @param va        The <code>ValidatorAction</code> that is currently
    1014      *                  being performed.
    1015      * @param field     The <code>Field</code> object associated with the
    1016      *                  current field being validated.
    1017      * @param errors    The <code>ActionMessages</code> object to add errors
    1018      *                  to if any validation errors occur.
    1019      * @param validator The <code>Validator</code> instance, used to access
    1020      *                  other field values.
    1021      * @param request   Current request object.
    1022      * @return true if valid, false otherwise.
    1023      */
    1024     public static Object validateCreditCard(Object bean, ValidatorAction va,
    1025         Field field, ActionMessages errors, Validator validator,
    1026         HttpServletRequest request) {
    1027         Object result = null;
    1028         String value = null;
    1029
    1030         value = evaluateBean(bean, field);
    1031
    1032         if (GenericValidator.isBlankOrNull(value)) {
    1033             return Boolean.TRUE;
    1034         }
    1035
    1036         result = GenericTypeValidator.formatCreditCard(value);
    1037
    1038         if (result == null) {
    1039             errors.add(field.getKey(),
    1040                 Resources.getActionMessage(validator, request, va, field));
    1041         }
    1042
    1043         return (result == null) ? Boolean.FALSE : result;
    1044     }
    1045
    1046     /**
    1047      * Checks if a field has a valid e-mail address.
    1048      *
    1049      * @param bean      The bean validation is being performed on.
    1050      * @param va        The <code>ValidatorAction</code> that is currently
    1051      *                  being performed.
    1052      * @param field     The <code>Field</code> object associated with the
    1053      *                  current field being validated.
    1054      * @param errors    The <code>ActionMessages</code> object to add errors
    1055      *                  to if any validation errors occur.
    1056      * @param validator The <code>Validator</code> instance, used to access
    1057      *                  other field values.
    1058      * @param request   Current request object.
    1059      * @return True if valid, false otherwise.
    1060      */
    1061     public static boolean validateEmail(Object bean, ValidatorAction va,
    1062         Field field, ActionMessages errors, Validator validator,
    1063         HttpServletRequest request) {
    1064         String value = null;
    1065
    1066         value = evaluateBean(bean, field);
    1067
    1068         if (!GenericValidator.isBlankOrNull(value)
    1069             && !GenericValidator.isEmail(value)) {
    1070             errors.add(field.getKey(),
    1071                 Resources.getActionMessage(validator, request, va, field));
    1072
    1073             return false;
    1074         } else {
    1075             return true;
    1076         }
    1077     }
    1078
    1079     /**
    1080      * Checks if the field's length is less than or equal to the maximum
    1081      * value. A <code>Null</code> will be considered an error.
    1082      *
    1083      * @param bean      The bean validation is being performed on.
    1084      * @param va        The <code>ValidatorAction</code> that is currently
    1085      *                  being performed.
    1086      * @param field     The <code>Field</code> object associated with the
    1087      *                  current field being validated.
    1088      * @param errors    The <code>ActionMessages</code> object to add errors
    1089      *                  to if any validation errors occur.
    1090      * @param validator The <code>Validator</code> instance, used to access
    1091      *                  other field values.
    1092      * @param request   Current request object.
    1093      * @return True if stated conditions met.
    1094      */
    1095     public static boolean validateMaxLength(Object bean, ValidatorAction va,
    1096         Field field, ActionMessages errors, Validator validator,
    1097         HttpServletRequest request) {
    1098         String value = null;
    1099
    1100         value = evaluateBean(bean, field);
    1101
    1102         if (value != null) {
    1103             try {
    1104                 String maxVar =
    1105                     Resources.getVarValue("maxlength", field, validator,
    1106                         request, true);
    1107                 int max = Integer.parseInt(maxVar);
    1108
    1109                 boolean isValid = false;
    1110                 String endLth = Resources.getVarValue("lineEndLength", field,
    1111                     validator, request, false);
    1112                 if (GenericValidator.isBlankOrNull(endLth)) {
    1113                     isValid = GenericValidator.maxLength(value, max);
    1114                 } else {
    1115                     isValid = GenericValidator.maxLength(value, max,
    1116                         Integer.parseInt(endLth));
    1117                 }
    1118
    1119                 if (!isValid) {
    1120                     errors.add(field.getKey(),
    1121                         Resources.getActionMessage(validator, request, va, field));
    1122
    1123                     return false;
    1124                 }
    1125             } catch (Exception e) {
    1126                 processFailure(errors, field, "maxlength", e);
    1127
    1128                 return false;
    1129             }
    1130         }
    1131
    1132         return true;
    1133     }
    1134
    1135     /**
    1136      * Checks if the field's length is greater than or equal to the minimum
    1137      * value. A <code>Null</code> will be considered an error.
    1138      *
    1139      * @param bean      The bean validation is being performed on.
    1140      * @param va        The <code>ValidatorAction</code> that is currently
    1141      *                  being performed.
    1142      * @param field     The <code>Field</code> object associated with the
    1143      *                  current field being validated.
    1144      * @param errors    The <code>ActionMessages</code> object to add errors
    1145      *                  to if any validation errors occur.
    1146      * @param validator The <code>Validator</code> instance, used to access
    1147      *                  other field values.
    1148      * @param request   Current request object.
    1149      * @return True if stated conditions met.
    1150      */
    1151     public static boolean validateMinLength(Object bean, ValidatorAction va,
    1152         Field field, ActionMessages errors, Validator validator,
    1153         HttpServletRequest request) {
    1154         String value = null;
    1155
    1156         value = evaluateBean(bean, field);
    1157
    1158         if (!GenericValidator.isBlankOrNull(value)) {
    1159             try {
    1160                 String minVar =
    1161                     Resources.getVarValue("minlength", field, validator,
    1162                         request, true);
    1163                 int min = Integer.parseInt(minVar);
    1164
    1165                 boolean isValid = false;
    1166                 String endLth = Resources.getVarValue("lineEndLength", field,
    1167                     validator, request, false);
    1168                 if (GenericValidator.isBlankOrNull(endLth)) {
    1169                     isValid = GenericValidator.minLength(value, min);
    1170                 } else {
    1171                     isValid = GenericValidator.minLength(value, min,
    1172                         Integer.parseInt(endLth));
    1173                 }
    1174
    1175                 if (!isValid) {
    1176                     errors.add(field.getKey(),
    1177                         Resources.getActionMessage(validator, request, va, field));
    1178
    1179                     return false;
    1180                 }
    1181             } catch (Exception e) {
    1182                 processFailure(errors, field, "minlength", e);
    1183
    1184                 return false;
    1185             }
    1186         }
    1187
    1188         return true;
    1189     }
    1190
    1191     /**
    1192      * Checks if a field has a valid url. Four optional variables can be
    1193      * specified to configure url validation.
    1194      *
    1195      * <ul>
    1196      *
    1197      * <li>Variable <code>allow2slashes</code> can be set to <code>true</code>
    1198      * or <code>false</code> to control whether two slashes are allowed -
    1199      * default is <code>false</code> (i.e. two slashes are NOT allowed).</li>
    1200      *
    1201      * <li>Variable <code>nofragments</code> can be set to <code>true</code>
    1202      * or <code>false</code> to control whether fragments are allowed -
    1203      * default is <code>false</code> (i.e. fragments ARE allowed).</li>
    1204      *
    1205      * <li>Variable <code>allowallschemes</code> can be set to
    1206      * <code>true</code> or <code>false</code> to control if all schemes are
    1207      * allowed - default is <code>false</code> (i.e. all schemes are NOT
    1208      * allowed).</li>
    1209      *
    1210      * <li>Variable <code>schemes</code> can be set to a comma delimited list
    1211      * of valid schemes. This value is ignored if <code>allowallschemes</code>
    1212      * is set to <code>true</code>. Default schemes allowed are "http",
    1213      * "https" and "ftp" if this variable is not specified.</li>
    1214      *
    1215      * </ul>
    1216      *
    1217      * @param bean      The bean validation is being performed on.
    1218      * @param va        The <code>ValidatorAction</code> that is currently
    1219      *                  being performed.
    1220      * @param field     The <code>Field</code> object associated with the
    1221      *                  current field being validated.
    1222      * @param errors    The <code>ActionMessages</code> object to add errors
    1223      *                  to if any validation errors occur.
    1224      * @param validator The <code>Validator</code> instance, used to access
    1225      *                  other field values.
    1226      * @param request   Current request object.
    1227      * @return True if valid, false otherwise.
    1228      */
    1229     public static boolean validateUrl(Object bean, ValidatorAction va,
    1230         Field field, ActionMessages errors, Validator validator,
    1231         HttpServletRequest request) {
    1232         String value = null;
    1233
    1234         value = evaluateBean(bean, field);
    1235
    1236         if (GenericValidator.isBlankOrNull(value)) {
    1237             return true;
    1238         }
    1239
    1240         // Get the options and schemes Vars
    1241         String allowallschemesVar =
    1242             Resources.getVarValue("allowallschemes", field, validator, request,
    1243                 false);
    1244         boolean allowallschemes = "true".equalsIgnoreCase(allowallschemesVar);
    1245         int options = allowallschemes ? UrlValidator.ALLOW_ALL_SCHEMES : 0;
    1246
    1247         String allow2slashesVar =
    1248             Resources.getVarValue("allow2slashes", field, validator, request,
    1249                 false);
    1250
    1251         if ("true".equalsIgnoreCase(allow2slashesVar)) {
    1252             options += UrlValidator.ALLOW_2_SLASHES;
    1253         }
    1254
    1255         String nofragmentsVar =
    1256             Resources.getVarValue("nofragments", field, validator, request,
    1257                 false);
    1258
    1259         if ("true".equalsIgnoreCase(nofragmentsVar)) {
    1260             options += UrlValidator.NO_FRAGMENTS;
    1261         }
    1262
    1263         String schemesVar =
    1264             allowallschemes ? null
    1265                             : Resources.getVarValue("schemes", field,
    1266                 validator, request, false);
    1267
    1268         // No options or schemes - use GenericValidator as default
    1269         if ((options == 0) && (schemesVar == null)) {
    1270             if (GenericValidator.isUrl(value)) {
    1271                 return true;
    1272             } else {
    1273                 errors.add(field.getKey(),
    1274                     Resources.getActionMessage(validator, request, va, field));
    1275
    1276                 return false;
    1277             }
    1278         }
    1279
    1280         // Parse comma delimited list of schemes into a String[]
    1281         String[] schemes = null;
    1282
    1283         if (schemesVar != null) {
    1284             StringTokenizer st = new StringTokenizer(schemesVar, ",");
    1285
    1286             schemes = new String[st.countTokens()];
    1287
    1288             int i = 0;
    1289
    1290             while (st.hasMoreTokens()) {
    1291                 schemes[i++] = st.nextToken().trim();
    1292             }
    1293         }
    1294
    1295         // Create UrlValidator and validate with options/schemes
    1296         UrlValidator urlValidator = new UrlValidator(schemes, options);
    1297
    1298         if (urlValidator.isValid(value)) {
    1299             return true;
    1300         } else {
    1301             errors.add(field.getKey(),
    1302                 Resources.getActionMessage(validator, request, va, field));
    1303
    1304             return false;
    1305         }
    1306     }
    1307
    1308     /**
    1309      * Process a validation failure.
    1310      */
    1311     private static void processFailure(ActionMessages errors, Field field,
    1312         String validator, Throwable t) {
    1313         // Log the error
    1314         String logErrorMsg =
    1315             sysmsgs.getMessage("validation.failed", validator,
    1316                 field.getProperty(), t.toString());
    1317
    1318         log.error(logErrorMsg);
    1319
    1320         // Add general "system error" message to show to the user
    1321         String userErrorMsg = sysmsgs.getMessage("system.error");
    1322
    1323         errors.add(field.getKey(), new ActionMessage(userErrorMsg, false));
    1324     }
    1325
    1326     /**
    1327      * Return <code>true</code> if the specified object is a String or a
    1328      * <code>null</code> value.
    1329      *
    1330      * @param o Object to be tested
    1331      * @return The string value
    1332      */
    1333     protected static boolean isString(Object o) {
    1334         return (o == null) ? true : String.class.isInstance(o);
    1335     }
    1336 }