Source code: com/jcorporate/expresso/core/controller/validation/ExpressoFieldChecks.java
1 /* ====================================================================
2 * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3 *
4 * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * 3. The end-user documentation included with the redistribution,
19 * if any, must include the following acknowledgment:
20 * "This product includes software developed by Jcorporate Ltd.
21 * (http://www.jcorporate.com/)."
22 * Alternately, this acknowledgment may appear in the software itself,
23 * if and wherever such third-party acknowledgments normally appear.
24 *
25 * 4. "Jcorporate" and product names such as "Expresso" must
26 * not be used to endorse or promote products derived from this
27 * software without prior written permission. For written permission,
28 * please contact info@jcorporate.com.
29 *
30 * 5. Products derived from this software may not be called "Expresso",
31 * or other Jcorporate product names; nor may "Expresso" or other
32 * Jcorporate product names appear in their name, without prior
33 * written permission of Jcorporate Ltd.
34 *
35 * 6. No product derived from this software may compete in the same
36 * market space, i.e. framework, without prior written permission
37 * of Jcorporate Ltd. For written permission, please contact
38 * partners@jcorporate.com.
39 *
40 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43 * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This software consists of voluntary contributions made by many
55 * individuals on behalf of the Jcorporate Ltd. Contributions back
56 * to the project(s) are encouraged when you make modifications.
57 * Please send them to support@jcorporate.com. For more information
58 * on Jcorporate Ltd. and its products, please see
59 * <http://www.jcorporate.com/>.
60 *
61 * Portions of this software are based upon other open source
62 * products and are subject to their respective licenses.
63 */
64
65 package com.jcorporate.expresso.core.controller.validation;
66
67 import com.jcorporate.expresso.core.controller.ControllerException;
68 import com.jcorporate.expresso.core.controller.DefaultForm;
69 import org.apache.commons.beanutils.PropertyUtils;
70 import org.apache.commons.logging.Log;
71 import org.apache.commons.logging.LogFactory;
72 import org.apache.commons.validator.Field;
73 import org.apache.commons.validator.GenericTypeValidator;
74 import org.apache.commons.validator.GenericValidator;
75 import org.apache.commons.validator.ValidatorAction;
76 import org.apache.struts.action.ActionErrors;
77 import org.apache.struts.validator.Resources;
78
79 import javax.servlet.http.HttpServletRequest;
80 import java.io.Serializable;
81 import java.net.URI;
82 import java.net.URISyntaxException;
83 import java.util.Date;
84 import java.util.Locale;
85
86 /**
87 * <p>
88 * This class contains the default validations that are used in the
89 * validator-rules.xml file modified to use Expresso's DefaultForm.
90 * </p>
91 * <p>
92 * In general passing in a null or blank will return a null Object or a false
93 * boolean. However, nulls and blanks do not result in an error being added to the
94 * errors.
95 * </p>
96 *
97 * @author Raul Davidovich
98 * @since Expresso 5.6
99 */
100
101 /**
102 * @todo add this whole class *RD* Mon Jul 27 2004
103 */
104 public class ExpressoFieldChecks
105 implements Serializable {
106 /**
107 * Commons Logging instance.
108 */
109 private static final Log log = LogFactory.getLog(ExpressoFieldChecks.class);
110
111 public static final String FIELD_TEST_NULL = "NULL";
112 public static final String FIELD_TEST_NOTNULL = "NOTNULL";
113 public static final String FIELD_TEST_EQUAL = "EQUAL";
114
115 /**
116 * Checks if the field isn't null and length of the field is greater than zero not
117 * including whitespace.
118 *
119 * @param bean The bean validation is being performed on.
120 * @param va The <code>ValidatorAction</code> that is currently being performed.
121 * @param field The <code>Field</code> object associated with the current
122 * field being validated.
123 * @param errors The <code>ActionErrors</code> object to add errors to if
124 * any validation errors occur.
125 * @param request Current request object.
126 * @return true if meets stated requirements, false otherwise.
127 */
128 public static boolean validateRequired(Object bean,
129 ValidatorAction va, Field field,
130 ActionErrors errors,
131 HttpServletRequest request) {
132
133 String value = null;
134 if (isString(bean)) {
135 value = (String) bean;
136 } else {
137 value = getValueAsString(bean, field.getProperty());
138 }
139
140 if (GenericValidator.isBlankOrNull(value)) {
141 errors.add(field.getKey(), Resources.getActionError(request, va, field));
142 return false;
143 } else {
144 return true;
145 }
146
147 }
148
149 /**
150 * Checks if the field isn't null based on the values of other fields.
151 *
152 * @param bean The bean validation is being performed on.
153 * @param va The <code>ValidatorAction</code> that is currently being
154 * performed.
155 * @param field The <code>Field</code> object associated with the current
156 * field being validated.
157 * @param errors The <code>ActionErrors</code> object to add errors to if
158 * any validation errors occur.
159 * @param validator The <code>Validator</code> instance, used to access
160 * other field values.
161 * @param request Current request object.
162 * @return true if meets stated requirements, false otherwise.
163 */
164 public static boolean validateRequiredIf(Object bean,
165 ValidatorAction va, Field field,
166 ActionErrors errors,
167 org.apache.commons.validator.
168 Validator validator,
169 HttpServletRequest request) {
170
171 Object form = validator.getResource(org.apache.commons.validator.Validator.
172 BEAN_KEY);
173 String value = null;
174 boolean required = false;
175
176 if (isString(bean)) {
177 value = (String) bean;
178 } else {
179 value = getValueAsString(bean, field.getProperty());
180 }
181
182 int i = 0;
183 String fieldJoin = "AND";
184 if (!GenericValidator.isBlankOrNull(field.getVarValue("fieldJoin"))) {
185 fieldJoin = field.getVarValue("fieldJoin");
186 }
187
188 if (fieldJoin.equalsIgnoreCase("AND")) {
189 required = true;
190 }
191
192 while (!GenericValidator.isBlankOrNull(field.getVarValue("field[" + i + "]"))) {
193 String dependProp = field.getVarValue("field[" + i + "]");
194 String dependTest = field.getVarValue("fieldTest[" + i + "]");
195 String dependTestValue = field.getVarValue("fieldValue[" + i + "]");
196 String dependIndexed = field.getVarValue("fieldIndexed[" + i + "]");
197
198 if (dependIndexed == null) {
199 dependIndexed = "false";
200 }
201
202 String dependVal = null;
203 boolean thisRequired = false;
204 if (field.isIndexed() && dependIndexed.equalsIgnoreCase("true")) {
205 String key = field.getKey();
206 if ((key.indexOf("[") > -1) && (key.indexOf("]") > -1)) {
207 String ind = key.substring(0, key.indexOf(".") + 1);
208 dependProp = ind + dependProp;
209 }
210 }
211
212 dependVal = getValueAsString(form, dependProp);
213 if (dependTest.equals(FIELD_TEST_NULL)) {
214 if ((dependVal != null) && (dependVal.length() > 0)) {
215 thisRequired = false;
216 } else {
217 thisRequired = true;
218 }
219 }
220
221 if (dependTest.equals(FIELD_TEST_NOTNULL)) {
222 if ((dependVal != null) && (dependVal.length() > 0)) {
223 thisRequired = true;
224 } else {
225 thisRequired = false;
226 }
227 }
228
229 if (dependTest.equals(FIELD_TEST_EQUAL)) {
230 thisRequired = dependTestValue.equalsIgnoreCase(dependVal);
231 }
232
233 if (fieldJoin.equalsIgnoreCase("AND")) {
234 required = required && thisRequired;
235 } else {
236 required = required || thisRequired;
237 }
238
239 i++;
240 }
241
242 if (required) {
243 if (GenericValidator.isBlankOrNull(value)) {
244 errors.add(field.getKey(),
245 Resources.getActionError(request, va, field));
246
247 return false;
248
249 } else {
250 return true;
251 }
252 }
253 return true;
254 }
255
256 /**
257 * Checks if the field matches the regular expression in the field's mask attribute.
258 *
259 * @param bean The bean validation is being performed on.
260 * @param va The <code>ValidatorAction</code> that is currently being
261 * performed.
262 * @param field The <code>Field</code> object associated with the current
263 * field being validated.
264 * @param errors The <code>ActionErrors</code> object to add errors to if
265 * any validation errors occur.
266 * @param request Current request object.
267 * @return true if field matches mask, false otherwise.
268 */
269 public static boolean validateMask(Object bean,
270 ValidatorAction va, Field field,
271 ActionErrors errors,
272 HttpServletRequest request) {
273
274 String mask = field.getVarValue("mask");
275 String value = null;
276 if (isString(bean)) {
277 value = (String) bean;
278 } else {
279 value = getValueAsString(bean, field.getProperty());
280 }
281
282 try {
283 if (!GenericValidator.isBlankOrNull(value)
284 && !GenericValidator.matchRegexp(value, mask)) {
285
286 errors.add(field.getKey(),
287 Resources.getActionError(request, va, field));
288
289 return false;
290 } else {
291 return true;
292 }
293 } catch (Exception e) {
294 log.error(e.getMessage(), e);
295 }
296 return true;
297 }
298
299 /**
300 * Checks if the field can safely be converted to a byte primitive.
301 *
302 * @param bean The bean validation is being performed on.
303 * @param va The <code>ValidatorAction</code> that is currently being performed.
304 * @param field The <code>Field</code> object associated with the current
305 * field being validated.
306 * @param errors The <code>ActionErrors</code> object to add errors to if
307 * any validation errors occur.
308 * @param request Current request object.
309 * @return A Byte if valid, null otherwise.
310 */
311 public static Byte validateByte(Object bean,
312 ValidatorAction va, Field field,
313 ActionErrors errors,
314 HttpServletRequest request) {
315
316 Byte result = null;
317 String value = null;
318 if (isString(bean)) {
319 value = (String) bean;
320 } else {
321 value = getValueAsString(bean, field.getProperty());
322 }
323
324 if (!GenericValidator.isBlankOrNull(value)) {
325 result = GenericTypeValidator.formatByte(value);
326
327 if (result == null) {
328 errors.add(field.getKey(), Resources.getActionError(request, va, field));
329 }
330 }
331
332 return result;
333 }
334
335 /**
336 * Checks if the field can safely be converted to a short primitive.
337 *
338 * @param bean The bean validation is being performed on.
339 * @param va The <code>ValidatorAction</code> that is currently being performed.
340 * @param field The <code>Field</code> object associated with the current
341 * field being validated.
342 * @param errors The <code>ActionErrors</code> object to add errors to if
343 * any validation errors occur.
344 * @param request Current request object.
345 * @return A Short if valid, otherwise null.
346 */
347 public static Short validateShort(Object bean,
348 ValidatorAction va, Field field,
349 ActionErrors errors,
350 HttpServletRequest request) {
351 Short result = null;
352 String value = null;
353 if (isString(bean)) {
354 value = (String) bean;
355 } else {
356 value = getValueAsString(bean, field.getProperty());
357 }
358
359 if (!GenericValidator.isBlankOrNull(value)) {
360 result = GenericTypeValidator.formatShort(value);
361
362 if (result == null) {
363 errors.add(field.getKey(), Resources.getActionError(request, va, field));
364 }
365 }
366
367 return result;
368 }
369
370 /**
371 * Checks if the field can safely be converted to an int primitive.
372 *
373 * @param bean The bean validation is being performed on.
374 * @param va The <code>ValidatorAction</code> that is currently being performed.
375 * @param field The <code>Field</code> object associated with the current
376 * field being validated.
377 * @param errors The <code>ActionErrors</code> object to add errors to if any
378 * validation errors occur.
379 * @param request Current request object.
380 * @return An Integer if valid, a null otherwise.
381 */
382 public static Integer validateInteger(Object bean,
383 ValidatorAction va, Field field,
384 ActionErrors errors,
385 HttpServletRequest request) {
386 Integer result = null;
387 String value = null;
388 if (isString(bean)) {
389 value = (String) bean;
390 } else {
391 value = getValueAsString(bean, field.getProperty());
392 }
393
394 if (!GenericValidator.isBlankOrNull(value)) {
395 result = GenericTypeValidator.formatInt(value);
396
397 if (result == null) {
398 errors.add(field.getKey(), Resources.getActionError(request, va, field));
399 }
400 }
401
402 return result;
403 }
404
405 /**
406 * Checks if the field can safely be converted to a long primitive.
407 *
408 * @param bean The bean validation is being performed on.
409 * @param va The <code>ValidatorAction</code> that is currently being performed.
410 * @param field The <code>Field</code> object associated with the current
411 * field being validated.
412 * @param errors The <code>ActionErrors</code> object to add errors to if any
413 * validation errors occur.
414 * @param request Current request object.
415 * @return A Long if valid, a null otherwise.
416 */
417 public static Long validateLong(Object bean,
418 ValidatorAction va, Field field,
419 ActionErrors errors,
420 HttpServletRequest request) {
421 Long result = null;
422 String value = null;
423 if (isString(bean)) {
424 value = (String) bean;
425 } else {
426 value = getValueAsString(bean, field.getProperty());
427 }
428
429 if (!GenericValidator.isBlankOrNull(value)) {
430 result = GenericTypeValidator.formatLong(value);
431
432 if (result == null) {
433 errors.add(field.getKey(), Resources.getActionError(request, va, field));
434 }
435 }
436
437 return result;
438 }
439
440 /**
441 * Checks if the field can safely be converted to a float primitive.
442 *
443 * @param bean The bean validation is being performed on.
444 * @param va The <code>ValidatorAction</code> that is currently being performed.
445 * @param field The <code>Field</code> object associated with the current
446 * field being validated.
447 * @param errors The <code>ActionErrors</code> object to add errors to if any
448 * validation errors occur.
449 * @param request Current request object.
450 * @return A Float if valid, a null otherwise.
451 */
452 public static Float validateFloat(Object bean,
453 ValidatorAction va, Field field,
454 ActionErrors errors,
455 HttpServletRequest request) {
456 Float result = null;
457 String value = null;
458 if (isString(bean)) {
459 value = (String) bean;
460 } else {
461 value = getValueAsString(bean, field.getProperty());
462 }
463
464 if (!GenericValidator.isBlankOrNull(value)) {
465 result = GenericTypeValidator.formatFloat(value);
466
467 if (result == null) {
468 errors.add(field.getKey(), Resources.getActionError(request, va, field));
469 }
470 }
471
472 return result;
473 }
474
475 /**
476 * Checks if the field can safely be converted to a double primitive.
477 *
478 * @param bean The bean validation is being performed on.
479 * @param va The <code>ValidatorAction</code> that is currently being performed.
480 * @param field The <code>Field</code> object associated with the current
481 * field being validated.
482 * @param errors The <code>ActionErrors</code> object to add errors to if any
483 * validation errors occur.
484 * @param request Current request object.
485 * @return A Double if valid, a null otherwise.
486 */
487 public static Double validateDouble(Object bean,
488 ValidatorAction va, Field field,
489 ActionErrors errors,
490 HttpServletRequest request) {
491 Double result = null;
492 String value = null;
493 if (isString(bean)) {
494 value = (String) bean;
495 } else {
496 value = getValueAsString(bean, field.getProperty());
497 }
498
499 if (!GenericValidator.isBlankOrNull(value)) {
500 result = GenericTypeValidator.formatDouble(value);
501
502 if (result == null) {
503 errors.add(field.getKey(), Resources.getActionError(request, va, field));
504 }
505 }
506
507 return result;
508 }
509
510 /**
511 * Checks if the field is a valid date. If the field has a datePattern variable,
512 * that will be used to format <code>java.text.SimpleDateFormat</code>. If the
513 * field has a datePatternStrict variable, that will be used to format <code>java.text.SimpleDateFormat</code>
514 * and the length will be checked so '2/12/1999' will not pass validation with
515 * the format 'MM/dd/yyyy' because the month isn't two digits. If no datePattern
516 * variable is specified, then the field gets the DateFormat.SHORT format for
517 * the locale. The setLenient method is set to <code>false</code> for all variations.
518 *
519 * @param bean The bean validation is being performed on.
520 * @param va The <code>ValidatorAction</code> that is currently being performed.
521 * @param field The <code>Field</code> object associated with the current
522 * field being validated.
523 * @param errors The <code>ActionErrors</code> object to add errors to if any
524 * validation errors occur.
525 * @param request Current request object.
526 * @return A Date if valid, a null if blank or invalid.
527 */
528 public static Date validateDate(Object bean,
529 ValidatorAction va, Field field,
530 ActionErrors errors,
531 HttpServletRequest request) {
532
533 Date result = null;
534 String value = null;
535 if (isString(bean)) {
536 value = (String) bean;
537 } else {
538 value = getValueAsString(bean, field.getProperty());
539 }
540 String datePattern = field.getVarValue("datePattern");
541 String datePatternStrict = field.getVarValue("datePatternStrict");
542 Locale locale = Resources.getLocale(request);
543
544 if (!GenericValidator.isBlankOrNull(value)) {
545 try {
546 if (datePattern != null && datePattern.length() > 0) {
547 result = GenericTypeValidator.formatDate(value, datePattern, false);
548 } else if (datePatternStrict != null && datePatternStrict.length() > 0) {
549 result = GenericTypeValidator.formatDate(value, datePatternStrict, true);
550 } else {
551 result = GenericTypeValidator.formatDate(value, locale);
552 }
553 } catch (Exception e) {
554 log.error(e.getMessage(), e);
555 }
556
557 if (result == null) {
558 errors.add(field.getKey(), Resources.getActionError(request, va, field));
559 }
560 }
561
562 return result;
563 }
564
565 /**
566 * Checks if a fields value is within a range (min & max specified in the
567 * vars attribute).
568 *
569 * @param bean The bean validation is being performed on.
570 * @param va The <code>ValidatorAction</code> that is currently being performed.
571 * @param field The <code>Field</code> object associated with the current
572 * field being validated.
573 * @param errors The <code>ActionErrors</code> object to add errors to if any
574 * validation errors occur.
575 * @param request Current request object.
576 * @return True if in range, false otherwise.
577 * @deprecated As of Struts 1.1, replaced by {@link #validateIntRange(java.lang.Object,org.apache.commons.validator.ValidatorAction,org.apache.commons.validator.Field,org.apache.struts.action.ActionErrors,javax.servlet.http.HttpServletRequest)}
578 */
579 public static boolean validateRange(Object bean,
580 ValidatorAction va, Field field,
581 ActionErrors errors,
582 HttpServletRequest request) {
583 return validateIntRange(bean, va, field, errors, request);
584 }
585
586 /**
587 * Checks if a fields value is within a range (min & max specified in the
588 * vars attribute).
589 *
590 * @param bean The bean validation is being performed on.
591 * @param va The <code>ValidatorAction</code> that is currently being performed.
592 * @param field The <code>Field</code> object associated with the current
593 * field being validated.
594 * @param errors The <code>ActionErrors</code> object to add errors to if any
595 * validation errors occur.
596 * @param request Current request object.
597 * @return True if in range, false otherwise.
598 */
599 public static boolean validateIntRange(Object bean,
600 ValidatorAction va, Field field,
601 ActionErrors errors,
602 HttpServletRequest request) {
603
604 String value = null;
605 if (isString(bean)) {
606 value = (String) bean;
607 } else {
608 value = getValueAsString(bean, field.getProperty());
609 }
610
611 if (!GenericValidator.isBlankOrNull(value)) {
612 try {
613 int intValue = Integer.parseInt(value);
614 int min = Integer.parseInt(field.getVarValue("min"));
615 int max = Integer.parseInt(field.getVarValue("max"));
616
617 if (!GenericValidator.isInRange(intValue, min, max)) {
618 errors.add(field.getKey(),
619 Resources.getActionError(request, va, field));
620
621 return false;
622 }
623 } catch (Exception e) {
624 errors.add(field.getKey(), Resources.getActionError(request, va, field));
625 return false;
626 }
627 }
628
629 return true;
630 }
631
632 /**
633 * Checks if a fields value is within a range (min & max specified in the
634 * vars attribute).
635 *
636 * @param bean The bean validation is being performed on.
637 * @param va The <code>ValidatorAction</code> that is currently being performed.
638 * @param field The <code>Field</code> object associated with the current
639 * field being validated.
640 * @param errors The <code>ActionErrors</code> object to add errors to if any
641 * validation errors occur.
642 * @param request Current request object.
643 * @return True if in range, false otherwise.
644 */
645 public static boolean validateDoubleRange(Object bean,
646 ValidatorAction va, Field field,
647 ActionErrors errors,
648 HttpServletRequest request) {
649
650 String value = null;
651 if (isString(bean)) {
652 value = (String) bean;
653 } else {
654 value = getValueAsString(bean, field.getProperty());
655 }
656
657 if (!GenericValidator.isBlankOrNull(value)) {
658 try {
659 double doubleValue = Double.parseDouble(value);
660 double min = Double.parseDouble(field.getVarValue("min"));
661 double max = Double.parseDouble(field.getVarValue("max"));
662
663 if (!GenericValidator.isInRange(doubleValue, min, max)) {
664 errors.add(field.getKey(),
665 Resources.getActionError(request, va, field));
666
667 return false;
668 }
669 } catch (Exception e) {
670 errors.add(field.getKey(), Resources.getActionError(request, va, field));
671 return false;
672 }
673 }
674
675 return true;
676 }
677
678 /**
679 * Checks if a fields value is within a range (min & max specified in the
680 * vars attribute).
681 *
682 * @param bean The bean validation is being performed on.
683 * @param va The <code>ValidatorAction</code> that is currently being performed.
684 * @param field The <code>Field</code> object associated with the current
685 * field being validated.
686 * @param errors The <code>ActionErrors</code> object to add errors to if any
687 * validation errors occur.
688 * @param request Current request object.
689 * @return True if in range, false otherwise.
690 */
691 public static boolean validateFloatRange(Object bean,
692 ValidatorAction va, Field field,
693 ActionErrors errors,
694 HttpServletRequest request) {
695
696 String value = null;
697 if (isString(bean)) {
698 value = (String) bean;
699 } else {
700 value = getValueAsString(bean, field.getProperty());
701 }
702
703 if (!GenericValidator.isBlankOrNull(value)) {
704 try {
705 float floatValue = Float.parseFloat(value);
706 float min = Float.parseFloat(field.getVarValue("min"));
707 float max = Float.parseFloat(field.getVarValue("max"));
708
709 if (!GenericValidator.isInRange(floatValue, min, max)) {
710 errors.add(field.getKey(),
711 Resources.getActionError(request, va, field));
712
713 return false;
714 }
715 } catch (Exception e) {
716 errors.add(field.getKey(), Resources.getActionError(request, va, field));
717 return false;
718 }
719 }
720
721 return true;
722 }
723
724 /**
725 * Checks if the field is a valid credit card number.
726 *
727 * @param bean The bean validation is being performed on.
728 * @param va The <code>ValidatorAction</code> that is currently being performed.
729 * @param field The <code>Field</code> object associated with the current
730 * field being validated.
731 * @param errors The <code>ActionErrors</code> object to add errors to if any
732 * validation errors occur.
733 * @param request Current request object.
734 * @return The credit card as a Long, a null if invalid, blank, or null.
735 */
736 public static Long validateCreditCard(Object bean,
737 ValidatorAction va, Field field,
738 ActionErrors errors,
739 HttpServletRequest request) {
740
741 Long result = null;
742 String value = null;
743 if (isString(bean)) {
744 value = (String) bean;
745 } else {
746 value = getValueAsString(bean, field.getProperty());
747 }
748
749 if (!GenericValidator.isBlankOrNull(value)) {
750 result = GenericTypeValidator.formatCreditCard(value);
751
752 if (result == null) {
753 errors.add(field.getKey(), Resources.getActionError(request, va, field));
754 }
755 }
756
757 return result;
758 }
759
760 /**
761 * Checks if a field has a valid e-mail address.
762 *
763 * @param bean The bean validation is being performed on.
764 * @param va The <code>ValidatorAction</code> that is currently being performed.
765 * @param field The <code>Field</code> object associated with the current
766 * field being validated.
767 * @param errors The <code>ActionErrors</code> object to add errors to if any
768 * validation errors occur.
769 * @param request Current request object.
770 * @return True if valid, false otherwise.
771 */
772 public static boolean validateEmail(Object bean,
773 ValidatorAction va, Field field,
774 ActionErrors errors,
775 HttpServletRequest request) {
776
777 String value = null;
778 if (isString(bean)) {
779 value = (String) bean;
780 } else {
781 value = getValueAsString(bean, field.getProperty());
782 }
783
784 if (!GenericValidator.isBlankOrNull(value) &&
785 !GenericValidator.isEmail(value)) {
786 errors.add(field.getKey(), Resources.getActionError(request, va, field));
787 return false;
788 } else {
789 return true;
790 }
791 }
792
793 /**
794 * Checks if the field's length is less than or equal to the maximum value.
795 * A <code>Null</code> will be considered an error.
796 *
797 * @param bean The bean validation is being performed on.
798 * @param va The <code>ValidatorAction</code> that is currently being performed.
799 * @param field The <code>Field</code> object associated with the current
800 * field being validated.
801 * @param errors The <code>ActionErrors</code> object to add errors to if any
802 * validation errors occur.
803 * @param request Current request object.
804 * @return True if stated conditions met.
805 */
806 public static boolean validateMaxLength(Object bean,
807 ValidatorAction va, Field field,
808 ActionErrors errors,
809 HttpServletRequest request) {
810
811 String value = null;
812 if (isString(bean)) {
813 value = (String) bean;
814 } else {
815 value = getValueAsString(bean, field.getProperty());
816 }
817
818 if (value != null) {
819 try {
820 int max = Integer.parseInt(field.getVarValue("maxlength"));
821
822 if (!GenericValidator.maxLength(value, max)) {
823 errors.add(field.getKey(),
824 Resources.getActionError(request, va, field));
825
826 return false;
827 }
828 } catch (Exception e) {
829 errors.add(field.getKey(), Resources.getActionError(request, va, field));
830 return false;
831 }
832 }
833
834 return true;
835 }
836
837 /**
838 * Checks if the field's length is greater than or equal to the minimum value.
839 * A <code>Null</code> will be considered an error.
840 *
841 * @param bean The bean validation is being performed on.
842 * @param va The <code>ValidatorAction</code> that is currently being performed.
843 * @param field The <code>Field</code> object associated with the current
844 * field being validated.
845 * @param errors The <code>ActionErrors</code> object to add errors to if any
846 * validation errors occur.
847 * @param request Current request object.
848 * @return True if stated conditions met.
849 */
850 public static boolean validateMinLength(Object bean,
851 ValidatorAction va, Field field,
852 ActionErrors errors,
853 HttpServletRequest request) {
854
855 String value = null;
856 if (isString(bean)) {
857 value = (String) bean;
858 } else {
859 value = getValueAsString(bean, field.getProperty());
860 }
861
862 if (!GenericValidator.isBlankOrNull(value)) {
863 try {
864 int min = Integer.parseInt(field.getVarValue("minlength"));
865
866 if (!GenericValidator.minLength(value, min)) {
867 errors.add(field.getKey(),
868 Resources.getActionError(request, va, field));
869
870 return false;
871 }
872 } catch (Exception e) {
873 errors.add(field.getKey(), Resources.getActionError(request, va, field));
874 return false;
875 }
876 }
877
878 return true;
879 }
880
881 /**
882 * Checks if a field is a valid url. Does not currently
883 * honor Struts URL checking options such as allowallschemes
884 * and nofragment.
885 *
886 * @param bean The bean validation is being performed on.
887 * @param va The <code>ValidatorAction</code> that is currently being
888 * performed.
889 * @param field The <code>Field</code> object associated with the current
890 * field being validated.
891 * @param errors The <code>ActionErrors</code> object to add errors to if any
892 * validation errors occur.
893 * @param request Current request object.
894 * @return True if valid, false otherwise.
895 * @author Chris DiGiano
896 */
897 public static boolean validateURL(Object bean, ValidatorAction va,
898 Field field, ActionErrors errors,
899 HttpServletRequest request) {
900
901 String value = null;
902 if (isString(bean)) {
903 value = (String) bean;
904 } else {
905 value = getValueAsString(bean, field.getProperty());
906 }
907
908 if (!GenericValidator.isBlankOrNull(value) && !isURL(value)) {
909 errors.add(field.getKey(), Resources.getActionError(request, va, field));
910 return false;
911 } else {
912 return true;
913 }
914 }
915
916 /**
917 * Determine if the given <code>value</code> is formatted as a proper URL.
918 *
919 * @param value
920 * @return
921 * @author Chris DiGiano
922 */
923 private static boolean isURL(String value) {
924 try {
925 URI uri = new URI(value);
926 } catch (URISyntaxException e) {
927 return false;
928 }
929 return true;
930 }
931
932 //Utility methods
933
934 /**
935 * Return <code>true</code> if the specified object is a String or a <code>null</code>
936 * value.
937 *
938 * @param o Object to be tested
939 * @return The string value
940 */
941 protected static boolean isString(Object o) {
942 return (o == null) ? true : String.class.isInstance(o);
943 }
944
945 /**
946 * Convenience method for getting a value from a bean property as a <code>String</code>.
947 */
948 public static String getValueAsString(Object bean, String property) {
949 Object value = null;
950 DefaultForm abean = null;
951
952 if (bean instanceof DefaultForm) {
953 abean = (DefaultForm) bean;
954 try {
955 value = abean.getAttribute(property) != null ?
956 abean.getAttribute(property) : abean.getField(property);
957 } catch (ControllerException ex) {
958 log.error(ex.getMessage(), ex);
959 }
960 } else {
961 try {
962 value = PropertyUtils.getProperty(bean, property);
963 } catch (Exception e) {
964 log.error(e.getMessage(), e);
965 }
966 }
967
968 return (value != null ? value.toString() : null);
969 }
970
971 }