001    /**
002     * Copyright (c) 2000-2012 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             * Returns <code>true</code> if the object arrays are equal.
336             *
337             * @param  objArray1 the first object array
338             * @param  objArray2 the second object array
339             * @return <code>true</code> if the object arrays are equal; <code>false
340             *         </code>otherwise
341             */
342            public static boolean equalsSorted(Object[] objArray1, Object[] objArray2) {
343                    objArray1 = ArrayUtil.clone(objArray1);
344    
345                    Arrays.sort(objArray1);
346    
347                    objArray2 = ArrayUtil.clone(objArray2);
348    
349                    Arrays.sort(objArray2);
350    
351                    return Arrays.equals(objArray1, objArray2); }
352    
353            /**
354             * Returns <code>true</code> if the short arrays are equal.
355             *
356             * @param  shortArray1 the first short array
357             * @param  shortArray2 the second short array
358             * @return <code>true</code> if the short arrays are equal; <code>false
359             *         </code>otherwise
360             */
361            public static boolean equalsSorted(
362                    short[] shortArray1, short[] shortArray2) {
363    
364                    shortArray1 = ArrayUtil.clone(shortArray1);
365    
366                    Arrays.sort(shortArray1);
367    
368                    shortArray2 = ArrayUtil.clone(shortArray2);
369    
370                    Arrays.sort(shortArray2);
371    
372                    return Arrays.equals(shortArray1, shortArray2);
373            }
374    
375            /**
376             * Returns <code>true</code> if the string is an email address. The only
377             * requirements are that the string consist of two parts separated by an @
378             * symbol, and that it contain no whitespace.
379             *
380             * @param  address the string to check
381             * @return <code>true</code> if the string is an email address;
382             *         <code>false</code> otherwise
383             */
384            public static boolean isAddress(String address) {
385                    if (isNull(address)) {
386                            return false;
387                    }
388    
389                    String[] tokens = address.split(StringPool.AT);
390    
391                    if (tokens.length != 2) {
392                            return false;
393                    }
394    
395                    for (String token : tokens) {
396                            for (char c : token.toCharArray()) {
397                                    if (Character.isWhitespace(c)) {
398                                            return false;
399                                    }
400                            }
401                    }
402    
403                    return true;
404            }
405    
406            /**
407             * Returns <code>true</code> if the string is an alphanumeric name, meaning
408             * it contains nothing but English letters, numbers, and spaces.
409             *
410             * @param  name the string to check
411             * @return <code>true</code> if the string is an Alphanumeric name;
412             *         <code>false</code> otherwise
413             */
414            public static boolean isAlphanumericName(String name) {
415                    if (isNull(name)) {
416                            return false;
417                    }
418    
419                    for (char c : name.trim().toCharArray()) {
420                            if (!isChar(c) && !isDigit(c) && !Character.isWhitespace(c)) {
421                                    return false;
422                            }
423                    }
424    
425                    return true;
426            }
427    
428            /**
429             * Returns <code>true</code> if the character is in the ASCII character set.
430             * This includes characters with integer values between 32 and 126
431             * (inclusive).
432             *
433             * @param  c the character to check
434             * @return <code>true</code> if the character is in the ASCII character set;
435             *         <code>false</code> otherwise
436             */
437            public static boolean isAscii(char c) {
438                    int i = c;
439    
440                    if ((i >= 32) && (i <= 126)) {
441                            return true;
442                    }
443                    else {
444                            return false;
445                    }
446            }
447    
448            public static boolean isBlank(String s) {
449                    if (s == null) {
450                            return true;
451                    }
452    
453                    if (s.length() == 0) {
454                            return true;
455                    }
456    
457                    return false;
458            }
459    
460            /**
461             * Returns <code>true</code> if the character is an upper or lower case
462             * English letter.
463             *
464             * @param  c the character to check
465             * @return <code>true</code> if the character is an upper or lower case
466             *         English letter; <code>false</code> otherwise
467             */
468            public static boolean isChar(char c) {
469                    int x = c;
470    
471                    if (((x >= _CHAR_LOWER_CASE_BEGIN) && (x <= _CHAR_LOWER_CASE_END)) ||
472                            ((x >= _CHAR_UPPER_CASE_BEGIN) && (x <= _CHAR_UPPER_CASE_END))) {
473    
474                            return true;
475                    }
476    
477                    return false;
478            }
479    
480            /**
481             * Returns <code>true</code> if string consists only of upper and lower case
482             * English letters.
483             *
484             * @param  s the string to check
485             * @return <code>true</code> if the string consists only of upper and lower
486             *         case English letters
487             */
488            public static boolean isChar(String s) {
489                    if (isNull(s)) {
490                            return false;
491                    }
492    
493                    for (char c : s.toCharArray()) {
494                            if (!isChar(c)) {
495                                    return false;
496                            }
497                    }
498    
499                    return true;
500            }
501    
502            /**
503             * Returns <code>true</code> if the date is valid in the Gregorian calendar.
504             *
505             * @param  month the month to check
506             * @param  day the day to check
507             * @param  year the year to check
508             * @return <code>true</code> if the date is valid in the Gregorian calendar;
509             *         <code>false</code> otherwise
510             */
511            public static boolean isDate(int month, int day, int year) {
512                    return isGregorianDate(month, day, year);
513            }
514    
515            /**
516             * Returns <code>true</code> if the character is a digit between 0 and 9
517             * (inclusive).
518             *
519             * @param  c the character to check
520             * @return <code>true</code> if the character is a digit between 0 and 9
521             *         (inclusive); <code>false</code> otherwise
522             */
523            public static boolean isDigit(char c) {
524                    int x = c;
525    
526                    if ((x >= _DIGIT_BEGIN) && (x <= _DIGIT_END)) {
527                            return true;
528                    }
529    
530                    return false;
531            }
532    
533            /**
534             * Returns <code>true</code> if the string consists of only digits between 0
535             * and 9 (inclusive).
536             *
537             * @param  s the string to check
538             * @return <code>true</code> if the string consists of only digits between 0
539             *         and 9 (inclusive); <code>false</code> otherwise
540             */
541            public static boolean isDigit(String s) {
542                    if (isNull(s)) {
543                            return false;
544                    }
545    
546                    for (char c : s.toCharArray()) {
547                            if (!isDigit(c)) {
548                                    return false;
549                            }
550                    }
551    
552                    return true;
553            }
554    
555            /**
556             * Returns <code>true</code> if the string is a valid domain name. See
557             * RFC-1034 (section 3), RFC-1123 (section 2.1), and RFC-952 (section B.
558             * Lexical grammar).
559             *
560             * @param  domainName the string to check
561             * @return <code>true</code> if the string is a valid domain name;
562             *         <code>false</code> otherwise
563             */
564            public static boolean isDomain(String domainName) {
565    
566                    // See RFC-1034 (section 3), RFC-1123 (section 2.1), and RFC-952
567                    // (section B. Lexical grammar)
568    
569                    if (isNull(domainName)) {
570                            return false;
571                    }
572    
573                    if (domainName.length() > 255) {
574                            return false;
575                    }
576    
577                    if (domainName.startsWith(StringPool.PERIOD) ||
578                            domainName.endsWith(StringPool.PERIOD)) {
579    
580                            return false;
581                    }
582    
583                    if (!domainName.contains(StringPool.PERIOD) &&
584                            !domainName.equals(_LOCALHOST)) {
585    
586                            return false;
587                    }
588    
589                    String[] domainNameArray = StringUtil.split(
590                            domainName, CharPool.PERIOD);
591    
592                    for (String domainNamePart : domainNameArray) {
593                            char[] domainNamePartCharArray = domainNamePart.toCharArray();
594    
595                            for (int i = 0; i < domainNamePartCharArray.length; i++) {
596                                    char c = domainNamePartCharArray[i];
597    
598                                    if ((i == 0) && (c == CharPool.DASH)) {
599                                            return false;
600                                    }
601    
602                                    if ((i == (domainNamePartCharArray.length - 1)) &&
603                                            (c == CharPool.DASH)) {
604    
605                                            return false;
606                                    }
607    
608                                    if (!isChar(c) && !isDigit(c) && (c != CharPool.DASH)) {
609                                            return false;
610                                    }
611                            }
612                    }
613    
614                    return true;
615            }
616    
617            /**
618             * Returns <code>true</code> if the string is a valid email address.
619             *
620             * @param  emailAddress the string to check
621             * @return <code>true</code> if the string is a valid email address;
622             *         <code>false</code> otherwise
623             */
624            public static boolean isEmailAddress(String emailAddress) {
625                    Matcher matcher = _emailAddressPattern.matcher(emailAddress);
626    
627                    return matcher.matches();
628            }
629    
630            /**
631             * Returns <code>true</code> if the character is a special character in an
632             * email address.
633             *
634             * @param  c the character to check
635             * @return <code>true</code> if the character is a special character in an
636             *         email address; <code>false</code> otherwise
637             */
638            public static boolean isEmailAddressSpecialChar(char c) {
639    
640                    // LEP-1445
641    
642                    for (char specialChar : _EMAIL_ADDRESS_SPECIAL_CHAR) {
643                            if (c == specialChar) {
644                                    return true;
645                            }
646                    }
647    
648                    return false;
649            }
650    
651            /**
652             * Returns <code>true</code> if the file extension is valid.
653             *
654             * @param  fileExtension file extension
655             * @return <code>true</code> if the extension is valid; <code>false</code>
656             *         otherwise
657             */
658            public static boolean isFileExtension(String fileExtension) {
659                    if (isNull(fileExtension) ||
660                            fileExtension.contains(StringPool.BACK_SLASH) ||
661                            fileExtension.contains(StringPool.NULL_CHAR) ||
662                            fileExtension.contains(StringPool.SLASH)) {
663    
664                            return false;
665                    }
666    
667                    return true;
668            }
669    
670            public static boolean isFileName(String name) {
671                    if (isNull(name) || name.equals(StringPool.PERIOD) ||
672                            name.equals(StringPool.DOUBLE_PERIOD) ||
673                            name.contains(StringPool.BACK_SLASH) ||
674                            name.contains(StringPool.NULL_CHAR) ||
675                            name.contains(StringPool.SLASH)) {
676    
677                            return false;
678                    }
679    
680                    return true;
681            }
682    
683            public static boolean isFilePath(String path, boolean isParentDirAllowed) {
684                    if (Validator.isNull(path)) {
685                            return false;
686                    }
687    
688                    if (path.contains(StringPool.NULL_CHAR)) {
689                            return false;
690                    }
691    
692                    if (isParentDirAllowed) {
693                            return true;
694                    }
695    
696                    if (path.equals(StringPool.DOUBLE_PERIOD)) {
697                            return false;
698                    }
699    
700                    String normalizedPath = path.replace(
701                            CharPool.BACK_SLASH, CharPool.SLASH);
702    
703                    if (normalizedPath.startsWith(
704                                    StringPool.DOUBLE_PERIOD.concat(StringPool.SLASH))) {
705    
706                            return false;
707                    }
708    
709                    if (normalizedPath.endsWith(
710                                    StringPool.SLASH.concat(StringPool.DOUBLE_PERIOD))) {
711    
712                            return false;
713                    }
714    
715                    if (normalizedPath.contains(
716                                    StringPool.SLASH.concat(
717                                            StringPool.DOUBLE_PERIOD).concat(StringPool.SLASH))) {
718    
719                            return false;
720                    }
721    
722                    return true;
723            }
724    
725            /**
726             * Returns <code>true</code> if the date is valid in the Gregorian calendar.
727             *
728             * @param  month the month (0-based, meaning 0 for January)
729             * @param  day the day of the month
730             * @param  year the year
731             * @return <code>true</code> if the date is valid; <code>false</code>
732             *         otherwise
733             */
734            public static boolean isGregorianDate(int month, int day, int year) {
735                    if ((month < 0) || (month > 11)) {
736                            return false;
737                    }
738    
739                    int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
740    
741                    if (month == 1) {
742                            int febMax = 28;
743    
744                            if (((year % 4) == 0) && ((year % 100) != 0) ||
745                                    ((year % 400) == 0)) {
746    
747                                    febMax = 29;
748                            }
749    
750                            if ((day < 1) || (day > febMax)) {
751                                    return false;
752                            }
753                    }
754                    else if ((day < 1) || (day > months[month])) {
755                            return false;
756                    }
757    
758                    return true;
759            }
760    
761            /**
762             * Returns <code>true</code> if the string is a hexidecimal number. At
763             * present the only requirement is that the string is not <code>null</code>;
764             * it does not actually check the format of the string.
765             *
766             * @param  s the string to check
767             * @return <code>true</code> if the string is a hexidecimal number;
768             *         <code>false</code> otherwise
769             * @see    #isNull(String)
770             */
771            public static boolean isHex(String s) {
772                    if (isNull(s)) {
773                            return false;
774                    }
775    
776                    return true;
777            }
778    
779            /**
780             * Returns <code>true</code> if the string is a valid host name.
781             *
782             * @param  name the string to check
783             * @return <code>true</code> if the string is a valid host name;
784             *         <code>false</code> otherwise
785             */
786            public static boolean isHostName(String name) {
787                    if (isNull(name)) {
788                            return false;
789                    }
790    
791                    char[] nameCharArray = name.toCharArray();
792    
793                    if ((nameCharArray[0] == CharPool.DASH) ||
794                            (nameCharArray[0] == CharPool.PERIOD) ||
795                            (nameCharArray[nameCharArray.length - 1] == CharPool.DASH)) {
796    
797                            return false;
798                    }
799    
800                    for (char c : nameCharArray) {
801                            if (!isChar(c) && !isDigit(c) && (c != CharPool.CLOSE_BRACKET) &&
802                                    (c != CharPool.COLON) && (c != CharPool.DASH) &&
803                                    (c != CharPool.OPEN_BRACKET) && (c != CharPool.PERIOD)) {
804    
805                                    return false;
806                            }
807                    }
808    
809                    return true;
810            }
811    
812            /**
813             * Returns <code>true</code> if the string is an HTML document. The only
814             * requirement is that it contain the opening and closing html tags.
815             *
816             * @param  s the string to check
817             * @return <code>true</code> if the string is an HTML document;
818             *         <code>false</code> otherwise
819             */
820            public static boolean isHTML(String s) {
821                    if (isNull(s)) {
822                            return false;
823                    }
824    
825                    if ((s.contains("<html>") || s.contains("<HTML>")) &&
826                            (s.contains("</html>") || s.contains("</HTML>"))) {
827    
828                            return true;
829                    }
830    
831                    return false;
832            }
833    
834            /**
835             * Returns <code>true</code> if the string is a valid IPv4 IP address.
836             *
837             * @param  ipAddress the string to check
838             * @return <code>true</code> if the string is an IPv4 IP address;
839             *         <code>false</code> otherwise
840             */
841            public static boolean isIPAddress(String ipAddress) {
842                    Matcher matcher = _ipAddressPattern.matcher(ipAddress);
843    
844                    return matcher.matches();
845            }
846    
847            /**
848             * Returns <code>true</code> if the date is valid in the Julian calendar.
849             *
850             * @param  month the month (0-based, meaning 0 for January)
851             * @param  day the day of the month
852             * @param  year the year
853             * @return <code>true</code> if the date is valid; <code>false</code>
854             *         otherwise
855             */
856            public static boolean isJulianDate(int month, int day, int year) {
857                    if ((month < 0) || (month > 11)) {
858                            return false;
859                    }
860    
861                    int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
862    
863                    if (month == 1) {
864                            int febMax = 28;
865    
866                            if ((year % 4) == 0) {
867                                    febMax = 29;
868                            }
869    
870                            if ((day < 1) || (day > febMax)) {
871                                    return false;
872                            }
873                    }
874                    else if ((day < 1) || (day > months[month])) {
875                            return false;
876                    }
877    
878                    return true;
879            }
880    
881            /**
882             * Returns <code>true</code> if the string contains a valid number according
883             * to the Luhn algorithm, commonly used to validate credit card numbers.
884             *
885             * @param  number the string to check
886             * @return <code>true</code> if the string contains a valid number according
887             *         to the Luhn algorithm; <code>false</code> otherwise
888             */
889            public static boolean isLUHN(String number) {
890                    if (number == null) {
891                            return false;
892                    }
893    
894                    number = StringUtil.reverse(number);
895    
896                    int total = 0;
897    
898                    for (int i = 0; i < number.length(); i++) {
899                            int x = 0;
900    
901                            if (((i + 1) % 2) == 0) {
902                                    x = GetterUtil.getInteger(number.substring(i, i + 1)) * 2;
903    
904                                    if (x >= 10) {
905                                            String s = String.valueOf(x);
906    
907                                            x =
908                                                    GetterUtil.getInteger(s.substring(0, 1)) +
909                                                            GetterUtil.getInteger(s.substring(1, 2));
910                                    }
911                            }
912                            else {
913                                    x = GetterUtil.getInteger(number.substring(i, i + 1));
914                            }
915    
916                            total = total + x;
917                    }
918    
919                    if ((total % 10) == 0) {
920                            return true;
921                    }
922                    else {
923                            return false;
924                    }
925            }
926    
927            /**
928             * Returns <code>true</code> if the string is a name, meaning it contains
929             * nothing but English letters and spaces.
930             *
931             * @param  name the string to check
932             * @return <code>true</code> if the string is a name; <code>false</code>
933             *         otherwise
934             */
935            public static boolean isName(String name) {
936                    if (isNull(name)) {
937                            return false;
938                    }
939    
940                    for (char c : name.trim().toCharArray()) {
941                            if (!isChar(c) && !Character.isWhitespace(c)) {
942                                    return false;
943                            }
944                    }
945    
946                    return true;
947            }
948    
949            /**
950             * Returns <code>true</code> if the long number object is not
951             * <code>null</code>, meaning it is neither a <code>null</code> reference or
952             * zero.
953             *
954             * @param  l the long number object to check
955             * @return <code>true</code> if the long number object is not
956             *         <code>null</code>; <code>false</code> otherwise
957             */
958            public static boolean isNotNull(Long l) {
959                    return !isNull(l);
960            }
961    
962            /**
963             * Returns <code>true</code> if the object is not <code>null</code>, using
964             * the rules from {@link #isNotNull(Long)} or {@link #isNotNull(String)} if
965             * the object is one of these types.
966             *
967             * @param  obj the object to check
968             * @return <code>true</code> if the object is not <code>null</code>;
969             *         <code>false</code> otherwise
970             */
971            public static boolean isNotNull(Object obj) {
972                    return !isNull(obj);
973            }
974    
975            /**
976             * Returns <code>true</code> if the array is not <code>null</code>, meaning
977             * it is neither a <code>null</code> reference or empty.
978             *
979             * @param  array the array to check
980             * @return <code>true</code> if the array is not <code>null</code>;
981             *         <code>false</code> otherwise
982             */
983            public static boolean isNotNull(Object[] array) {
984                    return !isNull(array);
985            }
986    
987            /**
988             * Returns <code>true</code> if the string is not <code>null</code>, meaning
989             * it is not a <code>null</code> reference, nothing but spaces, or the
990             * string "<code>null</code>".
991             *
992             * @param  s the string to check
993             * @return <code>true</code> if the string is not <code>null</code>;
994             *         <code>false</code> otherwise
995             */
996            public static boolean isNotNull(String s) {
997                    return !isNull(s);
998            }
999    
1000            /**
1001             * Returns <code>true</code> if the long number object is <code>null</code>,
1002             * meaning it is either a <code>null</code> reference or zero.
1003             *
1004             * @param  l the long number object to check
1005             * @return <code>true</code> if the long number object is <code>null</code>;
1006             *         <code>false</code> otherwise
1007             */
1008            public static boolean isNull(Long l) {
1009                    if ((l == null) || (l.longValue() == 0)) {
1010                            return true;
1011                    }
1012                    else {
1013                            return false;
1014                    }
1015            }
1016    
1017            /**
1018             * Returns <code>true</code> if the object is <code>null</code>, using the
1019             * rules from {@link #isNull(Long)} or {@link #isNull(String)} if the object
1020             * is one of these types.
1021             *
1022             * @param  obj the object to check
1023             * @return <code>true</code> if the object is <code>null</code>;
1024             *         <code>false</code> otherwise
1025             */
1026            public static boolean isNull(Object obj) {
1027                    if (obj instanceof Long) {
1028                            return isNull((Long)obj);
1029                    }
1030                    else if (obj instanceof String) {
1031                            return isNull((String)obj);
1032                    }
1033                    else if (obj == null) {
1034                            return true;
1035                    }
1036                    else {
1037                            return false;
1038                    }
1039            }
1040    
1041            /**
1042             * Returns <code>true</code> if the array is <code>null</code>, meaning it
1043             * is either a <code>null</code> reference or empty.
1044             *
1045             * @param  array the array to check
1046             * @return <code>true</code> if the array is <code>null</code>;
1047             *         <code>false</code> otherwise
1048             */
1049            public static boolean isNull(Object[] array) {
1050                    if ((array == null) || (array.length == 0)) {
1051                            return true;
1052                    }
1053                    else {
1054                            return false;
1055                    }
1056            }
1057    
1058            /**
1059             * Returns <code>true</code> if the string is <code>null</code>, meaning it
1060             * is a <code>null</code> reference, nothing but spaces, or the string
1061             * "<code>null</code>".
1062             *
1063             * @param  s the string to check
1064             * @return <code>true</code> if the string is <code>null</code>;
1065             *         <code>false</code> otherwise
1066             */
1067            public static boolean isNull(String s) {
1068                    if (s == null) {
1069                            return true;
1070                    }
1071    
1072                    int counter = 0;
1073    
1074                    for (int i = 0; i < s.length(); i++) {
1075                            char c = s.charAt(i);
1076    
1077                            if (c == CharPool.SPACE) {
1078                                    continue;
1079                            }
1080                            else if (counter > 3) {
1081                                    return false;
1082                            }
1083    
1084                            if (counter == 0) {
1085                                    if (c != CharPool.LOWER_CASE_N) {
1086                                            return false;
1087                                    }
1088                            }
1089                            else if (counter == 1) {
1090                                    if (c != CharPool.LOWER_CASE_U) {
1091                                            return false;
1092                                    }
1093                            }
1094                            else if ((counter == 2) || (counter == 3)) {
1095                                    if (c != CharPool.LOWER_CASE_L) {
1096                                            return false;
1097                                    }
1098                            }
1099    
1100                            counter++;
1101                    }
1102    
1103                    if ((counter == 0) || (counter == 4)) {
1104                            return true;
1105                    }
1106    
1107                    return false;
1108            }
1109    
1110            /**
1111             * Returns <code>true</code> if the string is a decimal integer number,
1112             * meaning it contains nothing but decimal digits.
1113             *
1114             * @param  number the string to check
1115             * @return <code>true</code> if the string is a decimal integer number;
1116             *         <code>false</code> otherwise
1117             */
1118            public static boolean isNumber(String number) {
1119                    if (isNull(number)) {
1120                            return false;
1121                    }
1122    
1123                    for (char c : number.toCharArray()) {
1124                            if (!isDigit(c)) {
1125                                    return false;
1126                            }
1127                    }
1128    
1129                    return true;
1130            }
1131    
1132            /**
1133             * Returns <code>true</code> if the string is a valid password, meaning it
1134             * is at least four characters long and contains only letters and decimal
1135             * digits.
1136             *
1137             * @param  password the password to check
1138             * @return <code>true</code> if the string is a valid password;
1139             *         <code>false</code> otherwise
1140             */
1141            public static boolean isPassword(String password) {
1142                    if (isNull(password)) {
1143                            return false;
1144                    }
1145    
1146                    if (password.length() < 4) {
1147                            return false;
1148                    }
1149    
1150                    for (char c : password.toCharArray()) {
1151                            if (!isChar(c) && !isDigit(c)) {
1152                                    return false;
1153                            }
1154                    }
1155    
1156                    return true;
1157            }
1158    
1159            /**
1160             * Returns <code>true</code> if the string is a valid phone number. The only
1161             * requirement is that there are decimal digits in the string; length and
1162             * format are not checked.
1163             *
1164             * @param  phoneNumber the string to check
1165             * @return <code>true</code> if the string is a valid phone number;
1166             *         <code>false</code> otherwise
1167             */
1168            public static boolean isPhoneNumber(String phoneNumber) {
1169                    return isNumber(StringUtil.extractDigits(phoneNumber));
1170            }
1171    
1172            /**
1173             * Returns <code>true</code> if the string is a valid URL based on the rules
1174             * in {@link java.net.URL}.
1175             *
1176             * @param  url the string to check
1177             * @return <code>true</code> if the string is a valid URL;
1178             *         <code>false</code> otherwise
1179             */
1180            public static boolean isUrl(String url) {
1181                    if (Validator.isNotNull(url)) {
1182                            if (url.indexOf(CharPool.COLON) == -1) {
1183                                    return false;
1184                            }
1185    
1186                            try {
1187                                    new URL(url);
1188    
1189                                    return true;
1190                            }
1191                            catch (MalformedURLException murle) {
1192                            }
1193                    }
1194    
1195                    return false;
1196            }
1197    
1198            /**
1199             * Returns <code>true</code> if the string is a valid variable name in Java.
1200             *
1201             * @param  variableName the string to check
1202             * @return <code>true</code> if the string is a valid variable name in Java;
1203             *         <code>false</code> otherwise
1204             */
1205            public static boolean isVariableName(String variableName) {
1206                    if (isNull(variableName)) {
1207                            return false;
1208                    }
1209    
1210                    Matcher matcher = _variableNamePattern.matcher(variableName);
1211    
1212                    if (matcher.matches()) {
1213                            return true;
1214                    }
1215                    else {
1216                            return false;
1217                    }
1218            }
1219    
1220            /**
1221             * Returns <code>true</code> if the string is a valid variable term, meaning
1222             * it begins with "[$" and ends with "$]".
1223             *
1224             * @param  s the string to check
1225             * @return <code>true</code> if the string is a valid variable term;
1226             *         <code>false</code> otherwise
1227             */
1228            public static boolean isVariableTerm(String s) {
1229                    if (s.startsWith(_VARIABLE_TERM_BEGIN) &&
1230                            s.endsWith(_VARIABLE_TERM_END)) {
1231    
1232                            return true;
1233                    }
1234                    else {
1235                            return false;
1236                    }
1237            }
1238    
1239            /**
1240             * Returns <code>true</code> if the character is whitespace, meaning it is
1241             * either the <code>null</code> character '0' or whitespace according to
1242             * {@link java.lang.Character#isWhitespace(char)}.
1243             *
1244             * @param  c the character to check
1245             * @return <code>true</code> if the character is whitespace;
1246             *         <code>false</code> otherwise
1247             */
1248            public static boolean isWhitespace(char c) {
1249                    int i = c;
1250    
1251                    if ((i == 0) || Character.isWhitespace(c)) {
1252                            return true;
1253                    }
1254                    else {
1255                            return false;
1256                    }
1257            }
1258    
1259            /**
1260             * Returns <code>true</code> if the string is an XML document. The only
1261             * requirement is that it contain either the xml start tag "<?xml" or the
1262             * empty document tag "<root />".
1263             *
1264             * @param  s the string to check
1265             * @return <code>true</code> if the string is an XML document;
1266             *         <code>false</code> otherwise
1267             */
1268            public static boolean isXml(String s) {
1269                    if (s.startsWith(_XML_BEGIN) || s.startsWith(_XML_EMPTY)) {
1270                            return true;
1271                    }
1272                    else {
1273                            return false;
1274                    }
1275            }
1276    
1277            private static final int _CHAR_LOWER_CASE_BEGIN = 97;
1278    
1279            private static final int _CHAR_LOWER_CASE_END = 122;
1280    
1281            private static final int _CHAR_UPPER_CASE_BEGIN = 65;
1282    
1283            private static final int _CHAR_UPPER_CASE_END = 90;
1284    
1285            private static final int _DIGIT_BEGIN = 48;
1286    
1287            private static final int _DIGIT_END = 57;
1288    
1289            private static final char[] _EMAIL_ADDRESS_SPECIAL_CHAR = new char[] {
1290                    '.', '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^',
1291                    '_', '`', '{', '|', '}', '~'
1292            };
1293    
1294            private static final String _LOCALHOST = "localhost";
1295    
1296            private static final String _VARIABLE_TERM_BEGIN = "[$";
1297    
1298            private static final String _VARIABLE_TERM_END = "$]";
1299    
1300            private static final String _XML_BEGIN = "<?xml";
1301    
1302            private static final String _XML_EMPTY = "<root />";
1303    
1304            private static Pattern _emailAddressPattern = Pattern.compile(
1305                    "[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@" +
1306                    "(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?");
1307            private static Pattern _ipAddressPattern = Pattern.compile(
1308                    "\\b" +
1309                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
1310                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
1311                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
1312                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])" +
1313                    "\\b");
1314            private static Pattern _variableNamePattern = Pattern.compile(
1315                    "[_a-zA-Z]+[_a-zA-Z0-9]*");
1316    
1317    }