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