001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import java.net.MalformedURLException;
018    import java.net.URL;
019    
020    import java.util.Arrays;
021    import java.util.regex.Matcher;
022    import java.util.regex.Pattern;
023    
024    /**
025     * Provides utility methods related to data validation and format checking.
026     *
027     * @author Brian Wing Shun Chan
028     * @author Alysa Carver
029     */
030    public class Validator {
031    
032            /**
033             * Returns <code>true</code> if the booleans are equal.
034             *
035             * @param  boolean1 the first boolean
036             * @param  boolean2 the second boolean
037             * @return <code>true</code> if the booleans are equal; <code>false</code>
038             *         otherwise
039             */
040            public static boolean equals(boolean boolean1, boolean boolean2) {
041                    if (boolean1 == boolean2) {
042                            return true;
043                    }
044                    else {
045                            return false;
046                    }
047            }
048    
049            /**
050             * Returns <code>true</code> if the bytes are equal.
051             *
052             * @param  byte1 the first byte
053             * @param  byte2 the second byte
054             * @return <code>true</code> if the bytes are equal; <code>false</code>
055             *         otherwise
056             */
057            public static boolean equals(byte byte1, byte byte2) {
058                    if (byte1 == byte2) {
059                            return true;
060                    }
061                    else {
062                            return false;
063                    }
064            }
065    
066            /**
067             * Returns <code>true</code> if the characters are equal.
068             *
069             * @param  char1 the first character
070             * @param  char2 the second character
071             * @return <code>true</code> if the characters are equal; <code>false</code>
072             *         otherwise
073             */
074            public static boolean equals(char char1, char char2) {
075                    if (char1 == char2) {
076                            return true;
077                    }
078                    else {
079                            return false;
080                    }
081            }
082    
083            /**
084             * Returns <code>true</code> if the doubles are equal.
085             *
086             * @param  double1 the first double
087             * @param  double2 the second double
088             * @return <code>true</code> if the doubles are equal; <code>false</code>
089             *         otherwise
090             */
091            public static boolean equals(double double1, double double2) {
092                    if (Double.compare(double1, double2) == 0) {
093                            return true;
094                    }
095                    else {
096                            return false;
097                    }
098            }
099    
100            /**
101             * Returns <code>true</code> if the floats are equal.
102             *
103             * @param  float1 the first float
104             * @param  float2 the second float
105             * @return <code>true</code> if the floats are equal; <code>false</code>
106             *         otherwise
107             */
108            public static boolean equals(float float1, float float2) {
109                    if (Float.compare(float1, float2) == 0) {
110                            return true;
111                    }
112                    else {
113                            return false;
114                    }
115            }
116    
117            /**
118             * Returns <code>true</code> if the integers are equal.
119             *
120             * @param  int1 the first integer
121             * @param  int2 the second integer
122             * @return <code>true</code> if the integers are equal; <code>false</code>
123             *         otherwise
124             */
125            public static boolean equals(int int1, int int2) {
126                    if (int1 == int2) {
127                            return true;
128                    }
129                    else {
130                            return false;
131                    }
132            }
133    
134            /**
135             * Returns <code>true</code> if the long integers are equal.
136             *
137             * @param  long1 the first long integer
138             * @param  long2 the second long integer
139             * @return <code>true</code> if the long integers are equal;
140             *         <code>false</code> otherwise
141             */
142            public static boolean equals(long long1, long long2) {
143                    if (long1 == long2) {
144                            return true;
145                    }
146                    else {
147                            return false;
148                    }
149            }
150    
151            /**
152             * Returns <code>true</code> if the objects are either equal, the same
153             * instance, or both <code>null</code>.
154             *
155             * @param  obj1 the first object
156             * @param  obj2 the second object
157             * @return <code>true</code> if the objects are either equal, the same
158             *         instance, or both <code>null</code>; <code>false</code> otherwise
159             */
160            public static boolean equals(Object obj1, Object obj2) {
161                    if ((obj1 == null) && (obj2 == null)) {
162                            return true;
163                    }
164                    else if ((obj1 == null) || (obj2 == null)) {
165                            return false;
166                    }
167                    else {
168                            return obj1.equals(obj2);
169                    }
170            }
171    
172            /**
173             * Returns <code>true</code> if the short integers are equal.
174             *
175             * @param  short1 the first short integer
176             * @param  short2 the second short integer
177             * @return <code>true</code> if the short integers are equal;
178             *         <code>false</code> otherwise
179             */
180            public static boolean equals(short short1, short short2) {
181                    if (short1 == short2) {
182                            return true;
183                    }
184                    else {
185                            return false;
186                    }
187            }
188    
189            /**
190             * Returns <code>true</code> if the boolean arrays are equal.
191             *
192             * @param  booleanArray1 the first boolean array
193             * @param  booleanArray2 the second boolean array
194             * @return <code>true</code> if the booleans arrays are equal; <code>false
195             *         </code>otherwise
196             */
197            public static boolean equalsSorted(
198                    boolean[] booleanArray1, boolean[] booleanArray2) {
199    
200                    Boolean[] booleanObjArray1 = ArrayUtil.toArray(booleanArray1);
201    
202                    Arrays.sort(booleanObjArray1);
203    
204                    Boolean[] booleanObjArray2 = ArrayUtil.toArray(booleanArray2);
205    
206                    Arrays.sort(booleanObjArray2);
207    
208                    return Arrays.equals(booleanObjArray1, booleanObjArray2);
209            }
210    
211            /**
212             * Returns <code>true</code> if the byte arrays are equal.
213             *
214             * @param  byteArray1 the first byte array
215             * @param  byteArray2 the second byte array
216             * @return <code>true</code> if the byte arrays are equal; <code>false
217             *         </code>otherwise
218             */
219            public static boolean equalsSorted(byte[] byteArray1, byte[] byteArray2) {
220                    byteArray1 = ArrayUtil.clone(byteArray1);
221    
222                    Arrays.sort(byteArray1);
223    
224                    byteArray2 = ArrayUtil.clone(byteArray2);
225    
226                    Arrays.sort(byteArray2);
227    
228                    return Arrays.equals(byteArray1, byteArray2);
229            }
230    
231            /**
232             * Returns <code>true</code> if the char arrays are equal.
233             *
234             * @param  charArray1 the first char array
235             * @param  charArray2 the second char array
236             * @return <code>true</code> if the char arrays are equal; <code>false
237             *         </code>otherwise
238             */
239            public static boolean equalsSorted(char[] charArray1, char[] charArray2) {
240                    charArray1 = ArrayUtil.clone(charArray1);
241    
242                    Arrays.sort(charArray1);
243    
244                    charArray2 = ArrayUtil.clone(charArray2);
245    
246                    Arrays.sort(charArray2);
247    
248                    return Arrays.equals(charArray1, charArray2);
249            }
250    
251            /**
252             * Returns <code>true</code> if the double arrays are equal.
253             *
254             * @param  doubleArray1 the first double array
255             * @param  doubleArray2 the second double array
256             * @return <code>true</code> if the double arrays are equal; <code>false
257             *         </code>otherwise
258             */
259            public static boolean equalsSorted(
260                    double[] doubleArray1, double[] doubleArray2) {
261    
262                    doubleArray1 = ArrayUtil.clone(doubleArray1);
263    
264                    Arrays.sort(doubleArray1);
265    
266                    doubleArray2 = ArrayUtil.clone(doubleArray2);
267    
268                    Arrays.sort(doubleArray2);
269    
270                    return Arrays.equals(doubleArray1, doubleArray2);
271            }
272    
273            /**
274             * Returns <code>true</code> if the float arrays are equal.
275             *
276             * @param  floatArray1 the first float array
277             * @param  floatArray2 the second char array
278             * @return <code>true</code> if the float arrays are equal; <code>false
279             *         </code>otherwise
280             */
281            public static boolean equalsSorted(
282                    float[] floatArray1, float[] floatArray2) {
283    
284                    floatArray1 = ArrayUtil.clone(floatArray1);
285    
286                    Arrays.sort(floatArray1);
287    
288                    floatArray2 = ArrayUtil.clone(floatArray2);
289    
290                    Arrays.sort(floatArray2);
291    
292                    return Arrays.equals(floatArray1, floatArray2);
293            }
294    
295            /**
296             * Returns <code>true</code> if the int arrays are equal.
297             *
298             * @param  intArray1 the first int array
299             * @param  intArray2 the second int array
300             * @return <code>true</code> if the int arrays are equal; <code>false</code>
301             *         otherwise
302             */
303            public static boolean equalsSorted(int[] intArray1, int[] intArray2) {
304                    intArray1 = ArrayUtil.clone(intArray1);
305    
306                    Arrays.sort(intArray1);
307    
308                    intArray2 = ArrayUtil.clone(intArray2);
309    
310                    Arrays.sort(intArray2);
311    
312                    return Arrays.equals(intArray1, intArray2);
313            }
314    
315            /**
316             * Returns <code>true</code> if the long arrays are equal.
317             *
318             * @param  longArray1 the first long array
319             * @param  longArray2 the second long array
320             * @return <code>true</code> if the long arrays are equal; <code>false
321             *         </code>otherwise
322             */
323            public static boolean equalsSorted(long[] longArray1, long[] longArray2) {
324                    longArray1 = ArrayUtil.clone(longArray1);
325    
326                    Arrays.sort(longArray1);
327    
328                    longArray2 = ArrayUtil.clone(longArray2);
329    
330                    Arrays.sort(longArray2);
331    
332                    return Arrays.equals(longArray1, longArray2);
333            }
334    
335            /**
336             * Returns <code>true</code> if the object arrays are equal.
337             *
338             * @param  objArray1 the first object array
339             * @param  objArray2 the second object array
340             * @return <code>true</code> if the object arrays are equal; <code>false
341             *         </code>otherwise
342             */
343            public static boolean equalsSorted(Object[] objArray1, Object[] objArray2) {
344                    objArray1 = ArrayUtil.clone(objArray1);
345    
346                    Arrays.sort(objArray1);
347    
348                    objArray2 = ArrayUtil.clone(objArray2);
349    
350                    Arrays.sort(objArray2);
351    
352                    return Arrays.equals(objArray1, objArray2);
353            }
354    
355            /**
356             * Returns <code>true</code> if the short arrays are equal.
357             *
358             * @param  shortArray1 the first short array
359             * @param  shortArray2 the second short array
360             * @return <code>true</code> if the short arrays are equal; <code>false
361             *         </code>otherwise
362             */
363            public static boolean equalsSorted(
364                    short[] shortArray1, short[] shortArray2) {
365    
366                    shortArray1 = ArrayUtil.clone(shortArray1);
367    
368                    Arrays.sort(shortArray1);
369    
370                    shortArray2 = ArrayUtil.clone(shortArray2);
371    
372                    Arrays.sort(shortArray2);
373    
374                    return Arrays.equals(shortArray1, shortArray2);
375            }
376    
377            /**
378             * Returns <code>true</code> if the string is an email address. The only
379             * requirements are that the string consist of two parts separated by an @
380             * symbol, and that it contain no whitespace.
381             *
382             * @param  address the string to check
383             * @return <code>true</code> if the string is an email address;
384             *         <code>false</code> otherwise
385             */
386            public static boolean isAddress(String address) {
387                    if (isNull(address)) {
388                            return false;
389                    }
390    
391                    String[] tokens = address.split(StringPool.AT);
392    
393                    if (tokens.length != 2) {
394                            return false;
395                    }
396    
397                    for (String token : tokens) {
398                            for (char c : token.toCharArray()) {
399                                    if (Character.isWhitespace(c)) {
400                                            return false;
401                                    }
402                            }
403                    }
404    
405                    return true;
406            }
407    
408            /**
409             * Returns <code>true</code> if the string is an alphanumeric name, meaning
410             * it contains nothing but English letters, numbers, and spaces.
411             *
412             * @param  name the string to check
413             * @return <code>true</code> if the string is an Alphanumeric name;
414             *         <code>false</code> otherwise
415             */
416            public static boolean isAlphanumericName(String name) {
417                    if (isNull(name)) {
418                            return false;
419                    }
420    
421                    for (char c : name.trim().toCharArray()) {
422                            if (!isChar(c) && !isDigit(c) && !Character.isWhitespace(c)) {
423                                    return false;
424                            }
425                    }
426    
427                    return true;
428            }
429    
430            /**
431             * Returns <code>true</code> if the character is in the ASCII character set.
432             * This includes characters with integer values between 32 and 126
433             * (inclusive).
434             *
435             * @param  c the character to check
436             * @return <code>true</code> if the character is in the ASCII character set;
437             *         <code>false</code> otherwise
438             */
439            public static boolean isAscii(char c) {
440                    int i = c;
441    
442                    if ((i >= 32) && (i <= 126)) {
443                            return true;
444                    }
445                    else {
446                            return false;
447                    }
448            }
449    
450            public static boolean isBlank(String s) {
451                    if (s == null) {
452                            return true;
453                    }
454    
455                    if (s.length() == 0) {
456                            return true;
457                    }
458    
459                    return false;
460            }
461    
462            /**
463             * Returns <code>true</code> if the character is an upper or lower case
464             * English letter.
465             *
466             * @param  c the character to check
467             * @return <code>true</code> if the character is an upper or lower case
468             *         English letter; <code>false</code> otherwise
469             */
470            public static boolean isChar(char c) {
471                    int x = c;
472    
473                    if (((x >= _CHAR_LOWER_CASE_BEGIN) && (x <= _CHAR_LOWER_CASE_END)) ||
474                            ((x >= _CHAR_UPPER_CASE_BEGIN) && (x <= _CHAR_UPPER_CASE_END))) {
475    
476                            return true;
477                    }
478    
479                    return false;
480            }
481    
482            /**
483             * Returns <code>true</code> if string consists only of upper and lower case
484             * English letters.
485             *
486             * @param  s the string to check
487             * @return <code>true</code> if the string consists only of upper and lower
488             *         case English letters
489             */
490            public static boolean isChar(String s) {
491                    if (isNull(s)) {
492                            return false;
493                    }
494    
495                    for (char c : s.toCharArray()) {
496                            if (!isChar(c)) {
497                                    return false;
498                            }
499                    }
500    
501                    return true;
502            }
503    
504            /**
505             * Returns <code>true</code> if the date is valid in the Gregorian calendar.
506             *
507             * @param  month the month to check
508             * @param  day the day to check
509             * @param  year the year to check
510             * @return <code>true</code> if the date is valid in the Gregorian calendar;
511             *         <code>false</code> otherwise
512             */
513            public static boolean isDate(int month, int day, int year) {
514                    return isGregorianDate(month, day, year);
515            }
516    
517            /**
518             * Returns <code>true</code> if the character is a digit between 0 and 9
519             * (inclusive).
520             *
521             * @param  c the character to check
522             * @return <code>true</code> if the character is a digit between 0 and 9
523             *         (inclusive); <code>false</code> otherwise
524             */
525            public static boolean isDigit(char c) {
526                    int x = c;
527    
528                    if ((x >= _DIGIT_BEGIN) && (x <= _DIGIT_END)) {
529                            return true;
530                    }
531    
532                    return false;
533            }
534    
535            /**
536             * Returns <code>true</code> if the string consists of only digits between 0
537             * and 9 (inclusive).
538             *
539             * @param  s the string to check
540             * @return <code>true</code> if the string consists of only digits between 0
541             *         and 9 (inclusive); <code>false</code> otherwise
542             */
543            public static boolean isDigit(String s) {
544                    if (isNull(s)) {
545                            return false;
546                    }
547    
548                    for (char c : s.toCharArray()) {
549                            if (!isDigit(c)) {
550                                    return false;
551                            }
552                    }
553    
554                    return true;
555            }
556    
557            /**
558             * Returns <code>true</code> if the string is a valid domain name. See
559             * RFC-1034 (section 3), RFC-1123 (section 2.1), and RFC-952 (section B.
560             * Lexical grammar).
561             *
562             * @param  domainName the string to check
563             * @return <code>true</code> if the string is a valid domain name;
564             *         <code>false</code> otherwise
565             */
566            public static boolean isDomain(String domainName) {
567    
568                    // See RFC-1034 (section 3), RFC-1123 (section 2.1), and RFC-952
569                    // (section B. Lexical grammar)
570    
571                    if (isNull(domainName)) {
572                            return false;
573                    }
574    
575                    if (domainName.length() > 255) {
576                            return false;
577                    }
578    
579                    if (domainName.startsWith(StringPool.PERIOD) ||
580                            domainName.endsWith(StringPool.PERIOD)) {
581    
582                            return false;
583                    }
584    
585                    if (!domainName.contains(StringPool.PERIOD) &&
586                            !domainName.equals(_LOCALHOST)) {
587    
588                            return false;
589                    }
590    
591                    String[] domainNameArray = StringUtil.split(
592                            domainName, CharPool.PERIOD);
593    
594                    for (String domainNamePart : domainNameArray) {
595                            char[] domainNamePartCharArray = domainNamePart.toCharArray();
596    
597                            for (int i = 0; i < domainNamePartCharArray.length; i++) {
598                                    char c = domainNamePartCharArray[i];
599    
600                                    if ((i == 0) && (c == CharPool.DASH)) {
601                                            return false;
602                                    }
603    
604                                    if ((i == (domainNamePartCharArray.length - 1)) &&
605                                            (c == CharPool.DASH)) {
606    
607                                            return false;
608                                    }
609    
610                                    if (!isChar(c) && !isDigit(c) && (c != CharPool.DASH)) {
611                                            return false;
612                                    }
613                            }
614                    }
615    
616                    return true;
617            }
618    
619            /**
620             * Returns <code>true</code> if the string is a valid email address.
621             *
622             * @param  emailAddress the string to check
623             * @return <code>true</code> if the string is a valid email address;
624             *         <code>false</code> otherwise
625             */
626            public static boolean isEmailAddress(String emailAddress) {
627                    Matcher matcher = _emailAddressPattern.matcher(emailAddress);
628    
629                    return matcher.matches();
630            }
631    
632            /**
633             * Returns <code>true</code> if the character is a special character in an
634             * email address.
635             *
636             * @param  c the character to check
637             * @return <code>true</code> if the character is a special character in an
638             *         email address; <code>false</code> otherwise
639             */
640            public static boolean isEmailAddressSpecialChar(char c) {
641    
642                    // LEP-1445
643    
644                    for (char specialChar : _EMAIL_ADDRESS_SPECIAL_CHAR) {
645                            if (c == specialChar) {
646                                    return true;
647                            }
648                    }
649    
650                    return false;
651            }
652    
653            /**
654             * Returns <code>true</code> if the file extension is valid.
655             *
656             * @param  fileExtension string to check
657             * @return <code>true</code> if the extension is valid; <code>false</code>
658             *         otherwise
659             */
660            public static boolean isFileExtension(String fileExtension) {
661                    if (isNull(fileExtension) ||
662                            fileExtension.contains(StringPool.BACK_SLASH) ||
663                            fileExtension.contains(StringPool.NULL_CHAR) ||
664                            fileExtension.contains(StringPool.SLASH)) {
665    
666                            return false;
667                    }
668    
669                    return true;
670            }
671    
672            public static boolean isFileName(String name) {
673                    if (isNull(name) || name.equals(StringPool.PERIOD) ||
674                            name.equals(StringPool.DOUBLE_PERIOD) ||
675                            name.contains(StringPool.BACK_SLASH) ||
676                            name.contains(StringPool.NULL_CHAR) ||
677                            name.contains(StringPool.SLASH)) {
678    
679                            return false;
680                    }
681    
682                    return true;
683            }
684    
685            public static boolean isFilePath(String path, boolean isParentDirAllowed) {
686                    if (Validator.isNull(path)) {
687                            return false;
688                    }
689    
690                    if (path.contains(StringPool.NULL_CHAR)) {
691                            return false;
692                    }
693    
694                    if (isParentDirAllowed) {
695                            return true;
696                    }
697    
698                    if (path.equals(StringPool.DOUBLE_PERIOD)) {
699                            return false;
700                    }
701    
702                    String normalizedPath = path.replace(
703                            CharPool.BACK_SLASH, CharPool.SLASH);
704    
705                    if (normalizedPath.startsWith(
706                                    StringPool.DOUBLE_PERIOD.concat(StringPool.SLASH))) {
707    
708                            return false;
709                    }
710    
711                    if (normalizedPath.endsWith(
712                                    StringPool.SLASH.concat(StringPool.DOUBLE_PERIOD))) {
713    
714                            return false;
715                    }
716    
717                    if (normalizedPath.contains(
718                                    StringPool.SLASH.concat(
719                                            StringPool.DOUBLE_PERIOD).concat(StringPool.SLASH))) {
720    
721                            return false;
722                    }
723    
724                    return true;
725            }
726    
727            /**
728             * Returns <code>true</code> if the date is valid in the Gregorian calendar.
729             *
730             * @param  month the month (0-based, meaning 0 for January)
731             * @param  day the day of the month
732             * @param  year the year
733             * @return <code>true</code> if the date is valid; <code>false</code>
734             *         otherwise
735             */
736            public static boolean isGregorianDate(int month, int day, int year) {
737                    if ((month < 0) || (month > 11)) {
738                            return false;
739                    }
740    
741                    int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
742    
743                    if (month == 1) {
744                            int febMax = 28;
745    
746                            if (((year % 4) == 0) && ((year % 100) != 0) ||
747                                    ((year % 400) == 0)) {
748    
749                                    febMax = 29;
750                            }
751    
752                            if ((day < 1) || (day > febMax)) {
753                                    return false;
754                            }
755                    }
756                    else if ((day < 1) || (day > months[month])) {
757                            return false;
758                    }
759    
760                    return true;
761            }
762    
763            /**
764             * Returns <code>true</code> if the string is a hexidecimal number. At
765             * present the only requirement is that the string is not <code>null</code>;
766             * it does not actually check the format of the string.
767             *
768             * @param  s the string to check
769             * @return <code>true</code> if the string is a hexidecimal number;
770             *         <code>false</code> otherwise
771             * @see    #isNull(String)
772             */
773            public static boolean isHex(String s) {
774                    if (isNull(s)) {
775                            return false;
776                    }
777    
778                    return true;
779            }
780    
781            /**
782             * Returns <code>true</code> if the string is a valid host name.
783             *
784             * @param  name the string to check
785             * @return <code>true</code> if the string is a valid host name;
786             *         <code>false</code> otherwise
787             */
788            public static boolean isHostName(String name) {
789                    if (isNull(name)) {
790                            return false;
791                    }
792    
793                    char[] nameCharArray = name.toCharArray();
794    
795                    if ((nameCharArray[0] == CharPool.DASH) ||
796                            (nameCharArray[0] == CharPool.PERIOD) ||
797                            (nameCharArray[nameCharArray.length - 1] == CharPool.DASH)) {
798    
799                            return false;
800                    }
801    
802                    for (char c : nameCharArray) {
803                            if (!isChar(c) && !isDigit(c) && (c != CharPool.CLOSE_BRACKET) &&
804                                    (c != CharPool.COLON) && (c != CharPool.DASH) &&
805                                    (c != CharPool.OPEN_BRACKET) && (c != CharPool.PERIOD)) {
806    
807                                    return false;
808                            }
809                    }
810    
811                    return true;
812            }
813    
814            /**
815             * Returns <code>true</code> if the string is an HTML document. The only
816             * requirement is that it contain the opening and closing html tags.
817             *
818             * @param  s the string to check
819             * @return <code>true</code> if the string is an HTML document;
820             *         <code>false</code> otherwise
821             */
822            public static boolean isHTML(String s) {
823                    if (isNull(s)) {
824                            return false;
825                    }
826    
827                    if ((s.contains("<html>") || s.contains("<HTML>")) &&
828                            (s.contains("</html>") || s.contains("</HTML>"))) {
829    
830                            return true;
831                    }
832    
833                    return false;
834            }
835    
836            /**
837             * Returns <code>true</code> if the string is a valid IPv4 or IPv6 IP
838             * address.
839             *
840             * @param  ipAddress the string to check
841             * @return <code>true</code> if the string is a valid IPv4 or IPv6 IP
842             *         address; <code>false</code> otherwise
843             */
844            public static boolean isIPAddress(String ipAddress) {
845                    if (isIPv4Address(ipAddress) || isIPv6Address(ipAddress)) {
846                            return true;
847                    }
848    
849                    return false;
850            }
851    
852            /**
853             * Returns <code>true</code> if the string is a valid IPv4 IP address.
854             *
855             * @param  ipAddress the string to check
856             * @return <code>true</code> if the string is a valid IPv4 IP address;
857             *         <code>false</code> otherwise
858             */
859            public static boolean isIPv4Address(String ipAddress) {
860                    Matcher matcher = _ipv4AddressPattern.matcher(ipAddress);
861    
862                    return matcher.matches();
863            }
864    
865            /**
866             * Returns <code>true</code> if the string is a valid IPv6 IP address.
867             *
868             * @param  ipAddress the string to check
869             * @return <code>true</code> if the string is a valid IPv6 IP address;
870             *         <code>false</code> otherwise
871             */
872            public static boolean isIPv6Address(String ipAddress) {
873                    if (isNull(ipAddress)) {
874                            return false;
875                    }
876    
877                    if (StringUtil.startsWith(ipAddress, CharPool.OPEN_BRACKET) &&
878                            StringUtil.endsWith(ipAddress, CharPool.CLOSE_BRACKET)) {
879    
880                            ipAddress = ipAddress.substring(1, ipAddress.length() - 1);
881                    }
882    
883                    Matcher matcher = _ipv6AddressPattern.matcher(ipAddress);
884    
885                    return matcher.matches();
886            }
887    
888            /**
889             * Returns <code>true</code> if the date is valid in the Julian calendar.
890             *
891             * @param  month the month (0-based, meaning 0 for January)
892             * @param  day the day of the month
893             * @param  year the year
894             * @return <code>true</code> if the date is valid in the Julian calendar;
895             *         <code>false</code> otherwise
896             */
897            public static boolean isJulianDate(int month, int day, int year) {
898                    if ((month < 0) || (month > 11)) {
899                            return false;
900                    }
901    
902                    int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
903    
904                    if (month == 1) {
905                            int febMax = 28;
906    
907                            if ((year % 4) == 0) {
908                                    febMax = 29;
909                            }
910    
911                            if ((day < 1) || (day > febMax)) {
912                                    return false;
913                            }
914                    }
915                    else if ((day < 1) || (day > months[month])) {
916                            return false;
917                    }
918    
919                    return true;
920            }
921    
922            /**
923             * Returns <code>true</code> if the string contains a valid number according
924             * to the Luhn algorithm, commonly used to validate credit card numbers.
925             *
926             * @param  number the string to check
927             * @return <code>true</code> if the string contains a valid number according
928             *         to the Luhn algorithm; <code>false</code> otherwise
929             */
930            public static boolean isLUHN(String number) {
931                    if (number == null) {
932                            return false;
933                    }
934    
935                    number = StringUtil.reverse(number);
936    
937                    int total = 0;
938    
939                    for (int i = 0; i < number.length(); i++) {
940                            int x = 0;
941    
942                            if (((i + 1) % 2) == 0) {
943                                    x = GetterUtil.getInteger(number.substring(i, i + 1)) * 2;
944    
945                                    if (x >= 10) {
946                                            String s = String.valueOf(x);
947    
948                                            x =
949                                                    GetterUtil.getInteger(s.substring(0, 1)) +
950                                                            GetterUtil.getInteger(s.substring(1, 2));
951                                    }
952                            }
953                            else {
954                                    x = GetterUtil.getInteger(number.substring(i, i + 1));
955                            }
956    
957                            total = total + x;
958                    }
959    
960                    if ((total % 10) == 0) {
961                            return true;
962                    }
963                    else {
964                            return false;
965                    }
966            }
967    
968            /**
969             * Returns <code>true</code> if the string is a name, meaning it contains
970             * nothing but English letters and spaces.
971             *
972             * @param  name the string to check
973             * @return <code>true</code> if the string is a name; <code>false</code>
974             *         otherwise
975             */
976            public static boolean isName(String name) {
977                    if (isNull(name)) {
978                            return false;
979                    }
980    
981                    for (char c : name.trim().toCharArray()) {
982                            if (!isChar(c) && !Character.isWhitespace(c)) {
983                                    return false;
984                            }
985                    }
986    
987                    return true;
988            }
989    
990            /**
991             * Returns <code>true</code> if the long number object is not
992             * <code>null</code>, meaning it is neither a <code>null</code> reference or
993             * zero.
994             *
995             * @param  l the long number object to check
996             * @return <code>true</code> if the long number object is not
997             *         <code>null</code>; <code>false</code> otherwise
998             */
999            public static boolean isNotNull(Long l) {
1000                    return !isNull(l);
1001            }
1002    
1003            /**
1004             * Returns <code>true</code> if the object is not <code>null</code>, using
1005             * the rules from {@link #isNotNull(Long)} or {@link #isNotNull(String)} if
1006             * the object is one of these types.
1007             *
1008             * @param  obj the object to check
1009             * @return <code>true</code> if the object is not <code>null</code>;
1010             *         <code>false</code> otherwise
1011             */
1012            public static boolean isNotNull(Object obj) {
1013                    return !isNull(obj);
1014            }
1015    
1016            /**
1017             * Returns <code>true</code> if the array is not <code>null</code>, meaning
1018             * it is neither a <code>null</code> reference or empty.
1019             *
1020             * @param  array the array to check
1021             * @return <code>true</code> if the array is not <code>null</code>;
1022             *         <code>false</code> otherwise
1023             */
1024            public static boolean isNotNull(Object[] array) {
1025                    return !isNull(array);
1026            }
1027    
1028            /**
1029             * Returns <code>true</code> if the string is not <code>null</code>, meaning
1030             * it is not a <code>null</code> reference, nothing but spaces, or the
1031             * string "<code>null</code>".
1032             *
1033             * @param  s the string to check
1034             * @return <code>true</code> if the string is not <code>null</code>;
1035             *         <code>false</code> otherwise
1036             */
1037            public static boolean isNotNull(String s) {
1038                    return !isNull(s);
1039            }
1040    
1041            /**
1042             * Returns <code>true</code> if the long number object is <code>null</code>,
1043             * meaning it is either a <code>null</code> reference or zero.
1044             *
1045             * @param  l the long number object to check
1046             * @return <code>true</code> if the long number object is <code>null</code>;
1047             *         <code>false</code> otherwise
1048             */
1049            public static boolean isNull(Long l) {
1050                    if ((l == null) || (l.longValue() == 0)) {
1051                            return true;
1052                    }
1053                    else {
1054                            return false;
1055                    }
1056            }
1057    
1058            /**
1059             * Returns <code>true</code> if the object is <code>null</code>, using the
1060             * rules from {@link #isNull(Long)} or {@link #isNull(String)} if the object
1061             * is one of these types.
1062             *
1063             * @param  obj the object to check
1064             * @return <code>true</code> if the object is <code>null</code>;
1065             *         <code>false</code> otherwise
1066             */
1067            public static boolean isNull(Object obj) {
1068                    if (obj instanceof Long) {
1069                            return isNull((Long)obj);
1070                    }
1071                    else if (obj instanceof String) {
1072                            return isNull((String)obj);
1073                    }
1074                    else if (obj == null) {
1075                            return true;
1076                    }
1077                    else {
1078                            return false;
1079                    }
1080            }
1081    
1082            /**
1083             * Returns <code>true</code> if the array is <code>null</code>, meaning it
1084             * is either a <code>null</code> reference or empty.
1085             *
1086             * @param  array the array to check
1087             * @return <code>true</code> if the array is <code>null</code>;
1088             *         <code>false</code> otherwise
1089             */
1090            public static boolean isNull(Object[] array) {
1091                    if ((array == null) || (array.length == 0)) {
1092                            return true;
1093                    }
1094                    else {
1095                            return false;
1096                    }
1097            }
1098    
1099            /**
1100             * Returns <code>true</code> if the string is <code>null</code>, meaning it
1101             * is a <code>null</code> reference, nothing but spaces, or the string
1102             * "<code>null</code>".
1103             *
1104             * @param  s the string to check
1105             * @return <code>true</code> if the string is <code>null</code>;
1106             *         <code>false</code> otherwise
1107             */
1108            public static boolean isNull(String s) {
1109                    if (s == null) {
1110                            return true;
1111                    }
1112    
1113                    int counter = 0;
1114    
1115                    for (int i = 0; i < s.length(); i++) {
1116                            char c = s.charAt(i);
1117    
1118                            if (c == CharPool.SPACE) {
1119                                    continue;
1120                            }
1121                            else if (counter > 3) {
1122                                    return false;
1123                            }
1124    
1125                            if (counter == 0) {
1126                                    if (c != CharPool.LOWER_CASE_N) {
1127                                            return false;
1128                                    }
1129                            }
1130                            else if (counter == 1) {
1131                                    if (c != CharPool.LOWER_CASE_U) {
1132                                            return false;
1133                                    }
1134                            }
1135                            else if ((counter == 2) || (counter == 3)) {
1136                                    if (c != CharPool.LOWER_CASE_L) {
1137                                            return false;
1138                                    }
1139                            }
1140    
1141                            counter++;
1142                    }
1143    
1144                    if ((counter == 0) || (counter == 4)) {
1145                            return true;
1146                    }
1147    
1148                    return false;
1149            }
1150    
1151            /**
1152             * Returns <code>true</code> if the string is a decimal integer number,
1153             * meaning it contains nothing but decimal digits.
1154             *
1155             * @param  number the string to check
1156             * @return <code>true</code> if the string is a decimal integer number;
1157             *         <code>false</code> otherwise
1158             */
1159            public static boolean isNumber(String number) {
1160                    if (isNull(number)) {
1161                            return false;
1162                    }
1163    
1164                    for (char c : number.toCharArray()) {
1165                            if (!isDigit(c)) {
1166                                    return false;
1167                            }
1168                    }
1169    
1170                    return true;
1171            }
1172    
1173            /**
1174             * Returns <code>true</code> if the string is a valid password, meaning it
1175             * is at least four characters long and contains only letters and decimal
1176             * digits.
1177             *
1178             * @param  password the string to check
1179             * @return <code>true</code> if the string is a valid password;
1180             *         <code>false</code> otherwise
1181             */
1182            public static boolean isPassword(String password) {
1183                    if (isNull(password)) {
1184                            return false;
1185                    }
1186    
1187                    if (password.length() < 4) {
1188                            return false;
1189                    }
1190    
1191                    for (char c : password.toCharArray()) {
1192                            if (!isChar(c) && !isDigit(c)) {
1193                                    return false;
1194                            }
1195                    }
1196    
1197                    return true;
1198            }
1199    
1200            /**
1201             * Returns <code>true</code> if the string is a valid phone number. The only
1202             * requirement is that there are decimal digits in the string; length and
1203             * format are not checked.
1204             *
1205             * @param  phoneNumber the string to check
1206             * @return <code>true</code> if the string is a valid phone number;
1207             *         <code>false</code> otherwise
1208             */
1209            public static boolean isPhoneNumber(String phoneNumber) {
1210                    return isNumber(StringUtil.extractDigits(phoneNumber));
1211            }
1212    
1213            /**
1214             * Returns <code>true</code> if the string is a valid URL based on the rules
1215             * in {@link java.net.URL}.
1216             *
1217             * @param  url the string to check
1218             * @return <code>true</code> if the string is a valid URL;
1219             *         <code>false</code> otherwise
1220             */
1221            public static boolean isUrl(String url) {
1222                    if (Validator.isNotNull(url)) {
1223                            if (url.indexOf(CharPool.COLON) == -1) {
1224                                    return false;
1225                            }
1226    
1227                            try {
1228                                    new URL(url);
1229    
1230                                    return true;
1231                            }
1232                            catch (MalformedURLException murle) {
1233                            }
1234                    }
1235    
1236                    return false;
1237            }
1238    
1239            /**
1240             * Returns <code>true</code> if the string is a valid variable name in Java.
1241             *
1242             * @param  variableName the string to check
1243             * @return <code>true</code> if the string is a valid variable name in Java;
1244             *         <code>false</code> otherwise
1245             */
1246            public static boolean isVariableName(String variableName) {
1247                    if (isNull(variableName)) {
1248                            return false;
1249                    }
1250    
1251                    Matcher matcher = _variableNamePattern.matcher(variableName);
1252    
1253                    if (matcher.matches()) {
1254                            return true;
1255                    }
1256                    else {
1257                            return false;
1258                    }
1259            }
1260    
1261            /**
1262             * Returns <code>true</code> if the string is a valid variable term, meaning
1263             * it begins with "[$" and ends with "$]".
1264             *
1265             * @param  s the string to check
1266             * @return <code>true</code> if the string is a valid variable term;
1267             *         <code>false</code> otherwise
1268             */
1269            public static boolean isVariableTerm(String s) {
1270                    if (s.startsWith(_VARIABLE_TERM_BEGIN) &&
1271                            s.endsWith(_VARIABLE_TERM_END)) {
1272    
1273                            return true;
1274                    }
1275                    else {
1276                            return false;
1277                    }
1278            }
1279    
1280            /**
1281             * Returns <code>true</code> if the character is whitespace, meaning it is
1282             * either the <code>null</code> character '0' or whitespace according to
1283             * {@link java.lang.Character#isWhitespace(char)}.
1284             *
1285             * @param  c the character to check
1286             * @return <code>true</code> if the character is whitespace;
1287             *         <code>false</code> otherwise
1288             */
1289            public static boolean isWhitespace(char c) {
1290                    int i = c;
1291    
1292                    if ((i == 0) || Character.isWhitespace(c)) {
1293                            return true;
1294                    }
1295                    else {
1296                            return false;
1297                    }
1298            }
1299    
1300            /**
1301             * Returns <code>true</code> if the string is an XML document. The only
1302             * requirement is that it contain either the xml start tag "<?xml" or the
1303             * empty document tag "<root />".
1304             *
1305             * @param  s the string to check
1306             * @return <code>true</code> if the string is an XML document;
1307             *         <code>false</code> otherwise
1308             */
1309            public static boolean isXml(String s) {
1310                    if (s.startsWith(_XML_BEGIN) || s.startsWith(_XML_EMPTY)) {
1311                            return true;
1312                    }
1313                    else {
1314                            return false;
1315                    }
1316            }
1317    
1318            private static final int _CHAR_LOWER_CASE_BEGIN = 97;
1319    
1320            private static final int _CHAR_LOWER_CASE_END = 122;
1321    
1322            private static final int _CHAR_UPPER_CASE_BEGIN = 65;
1323    
1324            private static final int _CHAR_UPPER_CASE_END = 90;
1325    
1326            private static final int _DIGIT_BEGIN = 48;
1327    
1328            private static final int _DIGIT_END = 57;
1329    
1330            private static final char[] _EMAIL_ADDRESS_SPECIAL_CHAR = new char[] {
1331                    '.', '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^',
1332                    '_', '`', '{', '|', '}', '~'
1333            };
1334    
1335            private static final String _LOCALHOST = "localhost";
1336    
1337            private static final String _VARIABLE_TERM_BEGIN = "[$";
1338    
1339            private static final String _VARIABLE_TERM_END = "$]";
1340    
1341            private static final String _XML_BEGIN = "<?xml";
1342    
1343            private static final String _XML_EMPTY = "<root />";
1344    
1345            private static Pattern _emailAddressPattern = Pattern.compile(
1346                    "[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@" +
1347                    "(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?");
1348            private static Pattern _ipv4AddressPattern = Pattern.compile(
1349                    "^" +
1350                    "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." +
1351                    "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." +
1352                    "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." +
1353                    "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" +
1354                    "$");
1355            private static Pattern _ipv6AddressPattern = Pattern.compile(
1356                    "^" +
1357                    "\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|" +
1358                    "(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|" +
1359                    "((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)" +
1360                    "(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|" +
1361                    "(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:" +
1362                    "((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)" +
1363                    "(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|" +
1364                    "(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|" +
1365                    "((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)" +
1366                    "(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|" +
1367                    "(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|" +
1368                    "((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)" +
1369                    "(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|" +
1370                    "(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|" +
1371                    "((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)" +
1372                    "(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|" +
1373                    "(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|" +
1374                    "((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)" +
1375                    "(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|" +
1376                    "(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:" +
1377                    "((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\." +
1378                    "(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*" +
1379                    "$");
1380            private static Pattern _variableNamePattern = Pattern.compile(
1381                    "[_a-zA-Z]+[_a-zA-Z0-9]*");
1382    
1383    }