Source code: org/apache/struts/validator/FieldChecks.java
1 /*
2 * $Id: FieldChecks.java 54929 2004-10-16 16:38:42Z germuska $
3 *
4 * Copyright 2000-2004 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
19 package org.apache.struts.validator;
20
21 import java.io.Serializable;
22 import java.util.Date;
23 import java.util.Locale;
24 import java.util.StringTokenizer;
25
26 import javax.servlet.http.HttpServletRequest;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.commons.validator.Field;
31 import org.apache.commons.validator.GenericTypeValidator;
32 import org.apache.commons.validator.GenericValidator;
33 import org.apache.commons.validator.UrlValidator;
34 import org.apache.commons.validator.ValidatorAction;
35 import org.apache.commons.validator.util.ValidatorUtils;
36 import org.apache.struts.action.ActionMessages;
37 import org.apache.struts.util.RequestUtils;
38
39 /**
40 * <p>
41 * This class contains the default validations that are used in the
42 * validator-rules.xml file.
43 * </p>
44 * <p>
45 * In general passing in a null or blank will return a null Object or a false
46 * boolean. However, nulls and blanks do not result in an error being added to the
47 * errors.
48 * </p>
49 *
50 * @since Struts 1.1
51 */
52 public class FieldChecks implements Serializable {
53
54 /**
55 * Commons Logging instance.
56 */
57 private static final Log log = LogFactory.getLog(FieldChecks.class);
58
59 public static final String FIELD_TEST_NULL = "NULL";
60 public static final String FIELD_TEST_NOTNULL = "NOTNULL";
61 public static final String FIELD_TEST_EQUAL = "EQUAL";
62
63 /**
64 * Checks if the field isn't null and length of the field is greater than zero not
65 * including whitespace.
66 *
67 * @param bean The bean validation is being performed on.
68 * @param va The <code>ValidatorAction</code> that is currently being performed.
69 * @param field The <code>Field</code> object associated with the current
70 * field being validated.
71 * @param errors The <code>ActionMessages</code> object to add errors to if
72 * any validation errors occur.
73 * @param request Current request object.
74 * @return true if meets stated requirements, false otherwise.
75 */
76 public static boolean validateRequired(Object bean,
77 ValidatorAction va, Field field,
78 ActionMessages errors,
79 HttpServletRequest request) {
80
81 String value = null;
82 if (isString(bean)) {
83 value = (String) bean;
84 } else {
85 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
86 }
87
88 if (GenericValidator.isBlankOrNull(value)) {
89 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
90 return false;
91 } else {
92 return true;
93 }
94
95 }
96
97 /**
98 * Checks if the field isn't null based on the values of other fields.
99 *
100 * @param bean The bean validation is being performed on.
101 * @param va The <code>ValidatorAction</code> that is currently being
102 * performed.
103 * @param field The <code>Field</code> object associated with the current
104 * field being validated.
105 * @param errors The <code>ActionMessages</code> object to add errors to if
106 * any validation errors occur.
107 * @param validator The <code>Validator</code> instance, used to access
108 * other field values.
109 * @param request Current request object.
110 * @return true if meets stated requirements, false otherwise.
111 */
112 public static boolean validateRequiredIf(Object bean,
113 ValidatorAction va, Field field,
114 ActionMessages errors,
115 org.apache.commons.validator.Validator validator,
116 HttpServletRequest request) {
117
118 Object form = validator.getParameterValue(org.apache.commons.validator.Validator.BEAN_PARAM);
119 String value = null;
120 boolean required = false;
121
122 if (isString(bean)) {
123 value = (String) bean;
124 } else {
125 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
126 }
127
128 int i = 0;
129 String fieldJoin = "AND";
130 if (!GenericValidator.isBlankOrNull(field.getVarValue("fieldJoin"))) {
131 fieldJoin = field.getVarValue("fieldJoin");
132 }
133
134 if (fieldJoin.equalsIgnoreCase("AND")) {
135 required = true;
136 }
137
138 while (!GenericValidator.isBlankOrNull(field.getVarValue("field[" + i + "]"))) {
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 if (field.isIndexed() && dependIndexed.equalsIgnoreCase("true")) {
151 String key = field.getKey();
152 if ((key.indexOf("[") > -1) && (key.indexOf("]") > -1)) {
153 String ind = key.substring(0, key.indexOf(".") + 1);
154 dependProp = ind + dependProp;
155 }
156 }
157
158 dependVal = ValidatorUtils.getValueAsString(form, dependProp);
159 if (dependTest.equals(FIELD_TEST_NULL)) {
160 if ((dependVal != null) && (dependVal.length() > 0)) {
161 thisRequired = false;
162 } else {
163 thisRequired = true;
164 }
165 }
166
167 if (dependTest.equals(FIELD_TEST_NOTNULL)) {
168 if ((dependVal != null) && (dependVal.length() > 0)) {
169 thisRequired = true;
170 } else {
171 thisRequired = false;
172 }
173 }
174
175 if (dependTest.equals(FIELD_TEST_EQUAL)) {
176 thisRequired = dependTestValue.equalsIgnoreCase(dependVal);
177 }
178
179 if (fieldJoin.equalsIgnoreCase("AND")) {
180 required = required && thisRequired;
181 } else {
182 required = required || thisRequired;
183 }
184
185 i++;
186 }
187
188 if (required) {
189 if (GenericValidator.isBlankOrNull(value)) {
190 errors.add(
191 field.getKey(),
192 Resources.getActionMessage(request, va, field));
193
194 return false;
195
196 } else {
197 return true;
198 }
199 }
200 return true;
201 }
202
203 /**
204 * Checks if the field matches the regular expression in the field's mask attribute.
205 *
206 * @param bean The bean validation is being performed on.
207 * @param va The <code>ValidatorAction</code> that is currently being
208 * performed.
209 * @param field The <code>Field</code> object associated with the current
210 * field being validated.
211 * @param errors The <code>ActionMessages</code> object to add errors to if
212 * any validation errors occur.
213 * @param request Current request object.
214 * @return true if field matches mask, false otherwise.
215 */
216 public static boolean validateMask(Object bean,
217 ValidatorAction va, Field field,
218 ActionMessages errors,
219 HttpServletRequest request) {
220
221 String mask = field.getVarValue("mask");
222 String value = null;
223 if (isString(bean)) {
224 value = (String) bean;
225 } else {
226 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
227 }
228
229 try {
230 if (!GenericValidator.isBlankOrNull(value)
231 && !GenericValidator.matchRegexp(value, mask)) {
232
233 errors.add(
234 field.getKey(),
235 Resources.getActionMessage(request, va, field));
236
237 return false;
238 } else {
239 return true;
240 }
241 } catch (Exception e) {
242 log.error(e.getMessage(), e);
243 }
244 return true;
245 }
246
247
248 /**
249 * Checks if the field can safely be converted to a byte primitive.
250 *
251 *@param bean The bean validation is being performed on.
252 *@param va The <code>ValidatorAction</code> that is currently being performed.
253 *@param field The <code>Field</code> object associated with the current
254 *field being validated.
255 *@param errors The <code>ActionMessages</code> object to add errors to if
256 *any validation errors occur.
257 *@param request Current request object.
258 *@return true if valid, false otherwise.
259 */
260 public static Object validateByte(Object bean,
261 ValidatorAction va, Field field,
262 ActionMessages errors,
263 HttpServletRequest request) {
264
265 Object result = null;
266 String value = null;
267 if (isString(bean)) {
268 value = (String) bean;
269 } else {
270 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
271 }
272
273 if (GenericValidator.isBlankOrNull(value)) {
274 return Boolean.TRUE;
275 }
276
277 result = GenericTypeValidator.formatByte(value);
278
279 if (result == null) {
280 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
281 }
282
283 return result == null ? Boolean.FALSE : result;
284 }
285
286
287 /**
288 * Checks if the field can safely be converted to a short primitive.
289 *
290 * @param bean The bean validation is being performed on.
291 * @param va The <code>ValidatorAction</code> that is currently being performed.
292 * @param field The <code>Field</code> object associated with the current
293 * field being validated.
294 * @param errors The <code>ActionMessages</code> object to add errors to if
295 * any validation errors occur.
296 * @param request Current request object.
297 * @return true if valid, false otherwise.
298 */
299 public static Object validateShort(Object bean,
300 ValidatorAction va, Field field,
301 ActionMessages errors,
302 HttpServletRequest request) {
303 Object result = null;
304 String value = null;
305 if (isString(bean)) {
306 value = (String) bean;
307 } else {
308 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
309 }
310
311 if (GenericValidator.isBlankOrNull(value)) {
312 return Boolean.TRUE;
313 }
314
315 result = GenericTypeValidator.formatShort(value);
316
317 if (result == null) {
318 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
319 }
320
321 return result == null ? Boolean.FALSE : result;
322 }
323
324
325 /**
326 * Checks if the field can safely be converted to an int primitive.
327 *
328 * @param bean The bean validation is being performed on.
329 * @param va The <code>ValidatorAction</code> that is currently being performed.
330 * @param field The <code>Field</code> object associated with the current
331 * field being validated.
332 * @param errors The <code>ActionMessages</code> object to add errors to if any
333 * validation errors occur.
334 * @param request Current request object.
335 * @return true if valid, false otherwise.
336 */
337 public static Object validateInteger(Object bean,
338 ValidatorAction va, Field field,
339 ActionMessages errors,
340 HttpServletRequest request) {
341 Object result = null;
342 String value = null;
343 if (isString(bean)) {
344 value = (String) bean;
345 } else {
346 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
347 }
348
349 if (GenericValidator.isBlankOrNull(value)) {
350 return Boolean.TRUE;
351 }
352
353 result = GenericTypeValidator.formatInt(value);
354
355 if (result == null) {
356 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
357 }
358
359 return result == null ? Boolean.FALSE : result;
360 }
361
362
363 /**
364 * Checks if the field can safely be converted to a long primitive.
365 *
366 * @param bean The bean validation is being performed on.
367 * @param va The <code>ValidatorAction</code> that is currently being performed.
368 * @param field The <code>Field</code> object associated with the current
369 * field being validated.
370 * @param errors The <code>ActionMessages</code> object to add errors to if any
371 * validation errors occur.
372 * @param request Current request object.
373 * @return true if valid, false otherwise.
374 */
375 public static Object validateLong(Object bean,
376 ValidatorAction va, Field field,
377 ActionMessages errors,
378 HttpServletRequest request) {
379 Object result = null;
380 String value = null;
381 if (isString(bean)) {
382 value = (String) bean;
383 } else {
384 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
385 }
386
387 if (GenericValidator.isBlankOrNull(value)) {
388 return Boolean.TRUE;
389 }
390
391 result = GenericTypeValidator.formatLong(value);
392
393 if (result == null) {
394 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
395 }
396
397 return result == null ? Boolean.FALSE : result;
398 }
399
400
401 /**
402 * Checks if the field can safely be converted to a float primitive.
403 *
404 * @param bean The bean validation is being performed on.
405 * @param va The <code>ValidatorAction</code> that is currently being performed.
406 * @param field The <code>Field</code> object associated with the current
407 * field being validated.
408 * @param errors The <code>ActionMessages</code> object to add errors to if any
409 * validation errors occur.
410 * @param request Current request object.
411 * @return true if valid, false otherwise.
412 */
413 public static Object validateFloat(Object bean,
414 ValidatorAction va, Field field,
415 ActionMessages errors,
416 HttpServletRequest request) {
417 Object result = null;
418 String value = null;
419 if (isString(bean)) {
420 value = (String) bean;
421 } else {
422 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
423 }
424
425 if (GenericValidator.isBlankOrNull(value)) {
426 return Boolean.TRUE;
427 }
428
429 result = GenericTypeValidator.formatFloat(value);
430
431 if (result == null) {
432 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
433 }
434
435 return result == null ? Boolean.FALSE : result;
436 }
437
438
439 /**
440 * Checks if the field can safely be converted to a double primitive.
441 *
442 * @param bean The bean validation is being performed on.
443 * @param va The <code>ValidatorAction</code> that is currently being performed.
444 * @param field The <code>Field</code> object associated with the current
445 * field being validated.
446 * @param errors The <code>ActionMessages</code> object to add errors to if any
447 * validation errors occur.
448 * @param request Current request object.
449 * @return true if valid, false otherwise.
450 */
451 public static Object validateDouble(Object bean,
452 ValidatorAction va, Field field,
453 ActionMessages errors,
454 HttpServletRequest request) {
455 Object result = null;
456 String value = null;
457 if (isString(bean)) {
458 value = (String) bean;
459 } else {
460 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
461 }
462
463 if (GenericValidator.isBlankOrNull(value)) {
464 return Boolean.TRUE;
465 }
466
467 result = GenericTypeValidator.formatDouble(value);
468
469 if (result == null) {
470 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
471 }
472
473 return result == null ? Boolean.FALSE : result;
474 }
475
476
477 /**
478 * Checks if the field is a valid date. If the field has a datePattern variable,
479 * that will be used to format <code>java.text.SimpleDateFormat</code>. If the
480 * field has a datePatternStrict variable, that will be used to format <code>java.text.SimpleDateFormat</code>
481 * and the length will be checked so '2/12/1999' will not pass validation with
482 * the format 'MM/dd/yyyy' because the month isn't two digits. If no datePattern
483 * variable is specified, then the field gets the DateFormat.SHORT format for
484 * the locale. The setLenient method is set to <code>false</code> for all variations.
485 *
486 * @param bean The bean validation is being performed on.
487 * @param va The <code>ValidatorAction</code> that is currently being performed.
488 * @param field The <code>Field</code> object associated with the current
489 * field being validated.
490 * @param errors The <code>ActionMessages</code> object to add errors to if any
491 * validation errors occur.
492 * @param request Current request object.
493 * @return true if valid, false otherwise.
494 */
495 public static Object validateDate(Object bean,
496 ValidatorAction va, Field field,
497 ActionMessages errors,
498 HttpServletRequest request) {
499
500 Object result = null;
501 String value = null;
502 if (isString(bean)) {
503 value = (String) bean;
504 } else {
505 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
506 }
507 String datePattern = field.getVarValue("datePattern");
508 String datePatternStrict = field.getVarValue("datePatternStrict");
509 Locale locale = RequestUtils.getUserLocale(request, null);
510
511 if (GenericValidator.isBlankOrNull(value)) {
512 return Boolean.TRUE;
513 }
514
515 try {
516 if (datePattern != null && datePattern.length() > 0) {
517 result = GenericTypeValidator.formatDate(value, datePattern, false);
518 } else if (datePatternStrict != null && datePatternStrict.length() > 0) {
519 result = GenericTypeValidator.formatDate(value, datePatternStrict, true);
520 } else {
521 result = GenericTypeValidator.formatDate(value, locale);
522 }
523 } catch (Exception e) {
524 log.error(e.getMessage(), e);
525 }
526
527 if (result == null) {
528 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
529 }
530
531 return result == null ? Boolean.FALSE : result;
532 }
533
534 /**
535 * Checks if a fields value is within a range (min & max specified in the
536 * vars attribute).
537 *
538 * @param bean The bean validation is being performed on.
539 * @param va The <code>ValidatorAction</code> that is currently being performed.
540 * @param field The <code>Field</code> object associated with the current
541 * field being validated.
542 * @param errors The <code>ActionMessages</code> object to add errors to if any
543 * validation errors occur.
544 * @param request Current request object.
545 * @return True if in range, false otherwise.
546 */
547 public static boolean validateIntRange(Object bean,
548 ValidatorAction va, Field field,
549 ActionMessages errors,
550 HttpServletRequest request) {
551
552 String value = null;
553 if (isString(bean)) {
554 value = (String) bean;
555 } else {
556 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
557 }
558
559 if (!GenericValidator.isBlankOrNull(value)) {
560 try {
561 int intValue = Integer.parseInt(value);
562 int min = Integer.parseInt(field.getVarValue("min"));
563 int max = Integer.parseInt(field.getVarValue("max"));
564
565 if (!GenericValidator.isInRange(intValue, min, max)) {
566 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
567
568 return false;
569 }
570 } catch (Exception e) {
571 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
572 return false;
573 }
574 }
575
576 return true;
577 }
578
579 /**
580 * Checks if a fields value is within a range (min & max specified in the
581 * vars attribute).
582 *
583 * @param bean The bean validation is being performed on.
584 * @param va The <code>ValidatorAction</code> that is currently being performed.
585 * @param field The <code>Field</code> object associated with the current
586 * field being validated.
587 * @param errors The <code>ActionMessages</code> object to add errors to if any
588 * validation errors occur.
589 * @param request Current request object.
590 * @return True if in range, false otherwise.
591 */
592 public static boolean validateDoubleRange(Object bean,
593 ValidatorAction va, Field field,
594 ActionMessages errors,
595 HttpServletRequest request) {
596
597 String value = null;
598 if (isString(bean)) {
599 value = (String) bean;
600 } else {
601 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
602 }
603
604 if (!GenericValidator.isBlankOrNull(value)) {
605 try {
606 double doubleValue = Double.parseDouble(value);
607 double min = Double.parseDouble(field.getVarValue("min"));
608 double max = Double.parseDouble(field.getVarValue("max"));
609
610 if (!GenericValidator.isInRange(doubleValue, min, max)) {
611 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
612
613 return false;
614 }
615 } catch (Exception e) {
616 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
617 return false;
618 }
619 }
620
621 return true;
622 }
623
624 /**
625 * Checks if a fields value is within a range (min & max specified in the
626 * vars attribute).
627 *
628 * @param bean The bean validation is being performed on.
629 * @param va The <code>ValidatorAction</code> that is currently being performed.
630 * @param field The <code>Field</code> object associated with the current
631 * field being validated.
632 * @param errors The <code>ActionMessages</code> object to add errors to if any
633 * validation errors occur.
634 * @param request Current request object.
635 * @return True if in range, false otherwise.
636 */
637 public static boolean validateFloatRange(Object bean,
638 ValidatorAction va, Field field,
639 ActionMessages errors,
640 HttpServletRequest request) {
641
642 String value = null;
643 if (isString(bean)) {
644 value = (String) bean;
645 } else {
646 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
647 }
648
649 if (!GenericValidator.isBlankOrNull(value)) {
650 try {
651 float floatValue = Float.parseFloat(value);
652 float min = Float.parseFloat(field.getVarValue("min"));
653 float max = Float.parseFloat(field.getVarValue("max"));
654
655 if (!GenericValidator.isInRange(floatValue, min, max)) {
656 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
657
658 return false;
659 }
660 } catch (Exception e) {
661 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
662 return false;
663 }
664 }
665
666 return true;
667 }
668
669
670 /**
671 * Checks if the field is a valid credit card number.
672 *
673 * @param bean The bean validation is being performed on.
674 * @param va The <code>ValidatorAction</code> that is currently being performed.
675 * @param field The <code>Field</code> object associated with the current
676 * field being validated.
677 * @param errors The <code>ActionMessages</code> object to add errors to if any
678 * validation errors occur.
679 * @param request Current request object.
680 * @return true if valid, false otherwise.
681 */
682 public static Object validateCreditCard(Object bean,
683 ValidatorAction va, Field field,
684 ActionMessages errors,
685 HttpServletRequest request) {
686
687 Object result = null;
688 String value = null;
689 if (isString(bean)) {
690 value = (String) bean;
691 } else {
692 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
693 }
694
695 if (GenericValidator.isBlankOrNull(value)) {
696 return Boolean.TRUE;
697 }
698
699 result = GenericTypeValidator.formatCreditCard(value);
700
701 if (result == null) {
702 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
703 }
704
705 return result == null ? Boolean.FALSE : result;
706
707 }
708
709
710 /**
711 * Checks if a field has a valid e-mail address.
712 *
713 * @param bean The bean validation is being performed on.
714 * @param va The <code>ValidatorAction</code> that is currently being performed.
715 * @param field The <code>Field</code> object associated with the current
716 * field being validated.
717 * @param errors The <code>ActionMessages</code> object to add errors to if any
718 * validation errors occur.
719 * @param request Current request object.
720 * @return True if valid, false otherwise.
721 */
722 public static boolean validateEmail(Object bean,
723 ValidatorAction va, Field field,
724 ActionMessages errors,
725 HttpServletRequest request) {
726
727 String value = null;
728 if (isString(bean)) {
729 value = (String) bean;
730 } else {
731 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
732 }
733
734 if (!GenericValidator.isBlankOrNull(value) && !GenericValidator.isEmail(value)) {
735 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
736 return false;
737 } else {
738 return true;
739 }
740 }
741
742
743 /**
744 * Checks if the field's length is less than or equal to the maximum value.
745 * A <code>Null</code> will be considered an error.
746 *
747 * @param bean The bean validation is being performed on.
748 * @param va The <code>ValidatorAction</code> that is currently being performed.
749 * @param field The <code>Field</code> object associated with the current
750 * field being validated.
751 * @param errors The <code>ActionMessages</code> object to add errors to if any
752 * validation errors occur.
753 * @param request Current request object.
754 * @return True if stated conditions met.
755 */
756 public static boolean validateMaxLength(Object bean,
757 ValidatorAction va, Field field,
758 ActionMessages errors,
759 HttpServletRequest request) {
760
761 String value = null;
762 if (isString(bean)) {
763 value = (String) bean;
764 } else {
765 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
766 }
767
768 if (value != null) {
769 try {
770 int max = Integer.parseInt(field.getVarValue("maxlength"));
771
772 if (!GenericValidator.maxLength(value, max)) {
773 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
774
775 return false;
776 }
777 } catch (Exception e) {
778 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
779 return false;
780 }
781 }
782
783 return true;
784 }
785
786
787 /**
788 * Checks if the field's length is greater than or equal to the minimum value.
789 * A <code>Null</code> will be considered an error.
790 *
791 * @param bean The bean validation is being performed on.
792 * @param va The <code>ValidatorAction</code> that is currently being performed.
793 * @param field The <code>Field</code> object associated with the current
794 * field being validated.
795 * @param errors The <code>ActionMessages</code> object to add errors to if any
796 * validation errors occur.
797 * @param request Current request object.
798 * @return True if stated conditions met.
799 */
800 public static boolean validateMinLength(Object bean,
801 ValidatorAction va, Field field,
802 ActionMessages errors,
803 HttpServletRequest request) {
804
805 String value = null;
806 if (isString(bean)) {
807 value = (String) bean;
808 } else {
809 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
810 }
811
812 if (!GenericValidator.isBlankOrNull(value)) {
813 try {
814 int min = Integer.parseInt(field.getVarValue("minlength"));
815
816 if (!GenericValidator.minLength(value, min)) {
817 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
818
819 return false;
820 }
821 } catch (Exception e) {
822 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
823 return false;
824 }
825 }
826
827 return true;
828 }
829
830 /**
831 * Checks if a field has a valid url. Four optional variables can be
832 * specified to configure url validation.
833 * <ul>
834 * <li>Variable <code>allow2slashes</code> can be set to <code>true</code> or
835 * <code>false</code> to control whether two slashes are allowed -
836 * default is <code>false</code> (i.e. two slashes are NOT allowed).</li>
837 * <li>Variable <code>nofragments</code> can be set to <code>true</code> or
838 * <code>false</code> to control whether fragments are allowed -
839 * default is <code>false</code> (i.e. fragments ARE allowed).</li>
840 * <li>Variable <code>allowallschemes</code> can be set to <code>true</code> or
841 * <code>false</code> to control if all schemes are allowed - default
842 * is <code>false</code> (i.e. all schemes are NOT allowed).</li>
843 * <li>Variable <code>schemes</code> can be set to a comma delimited list of
844 * valid schemes. This value is ignored if <code>allowallschemes</code>
845 * is set to <code>true</code>. Default schemes allowed are "http",
846 * "https" and "ftp" if this variable is not specified.</li>
847 * </ul>
848 *
849 * @param bean The bean validation is being performed on.
850 * @param va The <code>ValidatorAction</code> that is currently being performed.
851 * @param field The <code>Field</code> object associated with the current
852 * field being validated.
853 * @param errors The <code>ActionMessages</code> object to add errors to if any
854 * validation errors occur.
855 * @param request Current request object.
856 * @return True if valid, false otherwise.
857 */
858 public static boolean validateUrl(Object bean,
859 ValidatorAction va, Field field,
860 ActionMessages errors,
861 HttpServletRequest request) {
862
863 String value = null;
864 if (isString(bean)) {
865 value = (String) bean;
866 } else {
867 value = ValidatorUtils.getValueAsString(bean, field.getProperty());
868 }
869
870 if (GenericValidator.isBlankOrNull(value)) {
871 return true;
872 }
873
874 // Get the options and schemes Vars
875 boolean allowallschemes = "true".equalsIgnoreCase(field.getVarValue("allowallschemes"));
876 int options = allowallschemes ? UrlValidator.ALLOW_ALL_SCHEMES : 0;
877
878 if ("true".equalsIgnoreCase(field.getVarValue("allow2slashes"))) {
879 options += UrlValidator.ALLOW_2_SLASHES;
880 }
881
882 if ("true".equalsIgnoreCase(field.getVarValue("nofragments"))) {
883 options += UrlValidator.NO_FRAGMENTS;
884 }
885
886 String schemesVar = allowallschemes ? null : field.getVarValue("schemes");
887
888 // No options or schemes - use GenericValidator as default
889 if (options == 0 && schemesVar == null) {
890 if (GenericValidator.isUrl(value)) {
891 return true;
892 } else {
893 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
894 return false;
895 }
896 }
897
898 // Parse comma delimited list of schemes into a String[]
899 String[] schemes = null;
900 if (schemesVar != null) {
901
902 StringTokenizer st = new StringTokenizer(schemesVar, ",");
903 schemes = new String[st.countTokens()];
904
905 int i = 0;
906 while (st.hasMoreTokens()) {
907 schemes[i++] = st.nextToken().trim();
908 }
909
910 }
911
912 // Create UrlValidator and validate with options/schemes
913 UrlValidator urlValidator = new UrlValidator(schemes, options);
914 if (urlValidator.isValid(value)) {
915 return true;
916 } else {
917 errors.add(field.getKey(), Resources.getActionMessage(request, va, field));
918 return false;
919 }
920 }
921
922 /**
923 * Return <code>true</code> if the specified object is a String or a <code>null</code>
924 * value.
925 *
926 * @param o Object to be tested
927 * @return The string value
928 */
929 protected static boolean isString(Object o) {
930 return (o == null) ? true : String.class.isInstance(o);
931 }
932
933 }
934