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