001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import java.net.MalformedURLException;
018    import java.net.URL;
019    
020    import java.util.regex.Matcher;
021    import java.util.regex.Pattern;
022    
023    /**
024     * Provides utility methods related to data validation and format checking.
025     *
026     * @author Brian Wing Shun Chan
027     * @author Alysa Carver
028     */
029    public class Validator {
030    
031            /**
032             * Returns <code>true</code> if the booleans are equal.
033             *
034             * @param  boolean1 the first boolean
035             * @param  boolean2 the second boolean
036             * @return <code>true</code> if the booleans are equal; <code>false</code>
037             *         otherwise
038             */
039            public static boolean equals(boolean boolean1, boolean boolean2) {
040                    if (boolean1 == boolean2) {
041                            return true;
042                    }
043                    else {
044                            return false;
045                    }
046            }
047    
048            /**
049             * Returns <code>true</code> if the bytes are equal.
050             *
051             * @param  byte1 the first byte
052             * @param  byte2 the second byte
053             * @return <code>true</code> if the bytes are equal; <code>false</code>
054             *         otherwise
055             */
056            public static boolean equals(byte byte1, byte byte2) {
057                    if (byte1 == byte2) {
058                            return true;
059                    }
060                    else {
061                            return false;
062                    }
063            }
064    
065            /**
066             * Returns <code>true</code> if the characters are equal.
067             *
068             * @param  char1 the first character
069             * @param  char2 the second character
070             * @return <code>true</code> if the characters are equal; <code>false</code>
071             *         otherwise
072             */
073            public static boolean equals(char char1, char char2) {
074                    if (char1 == char2) {
075                            return true;
076                    }
077                    else {
078                            return false;
079                    }
080            }
081    
082            /**
083             * Returns <code>true</code> if the doubles are equal.
084             *
085             * @param  double1 the first double
086             * @param  double2 the second double
087             * @return <code>true</code> if the doubles are equal; <code>false</code>
088             *         otherwise
089             */
090            public static boolean equals(double double1, double double2) {
091                    if (Double.compare(double1, double2) == 0) {
092                            return true;
093                    }
094                    else {
095                            return false;
096                    }
097            }
098    
099            /**
100             * Returns <code>true</code> if the floats are equal.
101             *
102             * @param  float1 the first float
103             * @param  float2 the second float
104             * @return <code>true</code> if the floats are equal; <code>false</code>
105             *         otherwise
106             */
107            public static boolean equals(float float1, float float2) {
108                    if (Float.compare(float1, float2) == 0) {
109                            return true;
110                    }
111                    else {
112                            return false;
113                    }
114            }
115    
116            /**
117             * Returns <code>true</code> if the integers are equal.
118             *
119             * @param  int1 the first integer
120             * @param  int2 the second integer
121             * @return <code>true</code> if the integers are equal; <code>false</code>
122             *         otherwise
123             */
124            public static boolean equals(int int1, int int2) {
125                    if (int1 == int2) {
126                            return true;
127                    }
128                    else {
129                            return false;
130                    }
131            }
132    
133            /**
134             * Returns <code>true</code> if the long integers are equal.
135             *
136             * @param  long1 the first long integer
137             * @param  long2 the second long integer
138             * @return <code>true</code> if the long integers are equal;
139             *         <code>false</code> otherwise
140             */
141            public static boolean equals(long long1, long long2) {
142                    if (long1 == long2) {
143                            return true;
144                    }
145                    else {
146                            return false;
147                    }
148            }
149    
150            /**
151             * Returns <code>true</code> if the objects are either equal, the same
152             * instance, or both <code>null</code>.
153             *
154             * @param  obj1 the first object
155             * @param  obj2 the second object
156             * @return <code>true</code> if the objects are either equal, the same
157             *         instance, or both <code>null</code>; <code>false</code> otherwise
158             */
159            public static boolean equals(Object obj1, Object obj2) {
160                    if ((obj1 == null) && (obj2 == null)) {
161                            return true;
162                    }
163                    else if ((obj1 == null) || (obj2 == null)) {
164                            return false;
165                    }
166                    else {
167                            return obj1.equals(obj2);
168                    }
169            }
170    
171            /**
172             * Returns <code>true</code> if the short integers are equal.
173             *
174             * @param  short1 the first short integer
175             * @param  short2 the second short integer
176             * @return <code>true</code> if the short integers are equal;
177             *         <code>false</code> otherwise
178             */
179            public static boolean equals(short short1, short short2) {
180                    if (short1 == short2) {
181                            return true;
182                    }
183                    else {
184                            return false;
185                    }
186            }
187    
188            /**
189             * Returns <code>true</code> if the string is an email address. The only
190             * requirements are that the string consist of two parts separated by an @
191             * symbol, and that it contain no whitespace.
192             *
193             * @param  address the string to check
194             * @return <code>true</code> if the string is an email address;
195             *         <code>false</code> otherwise
196             */
197            public static boolean isAddress(String address) {
198                    if (isNull(address)) {
199                            return false;
200                    }
201    
202                    String[] tokens = address.split(StringPool.AT);
203    
204                    if (tokens.length != 2) {
205                            return false;
206                    }
207    
208                    for (String token : tokens) {
209                            for (char c : token.toCharArray()) {
210                                    if (Character.isWhitespace(c)) {
211                                            return false;
212                                    }
213                            }
214                    }
215    
216                    return true;
217            }
218    
219            /**
220             * Returns <code>true</code> if the string is an alphanumeric name, meaning
221             * it contains nothing but English letters, numbers, and spaces.
222             *
223             * @param  name the string to check
224             * @return <code>true</code> if the string is an Alphanumeric name;
225             *         <code>false</code> otherwise
226             */
227            public static boolean isAlphanumericName(String name) {
228                    if (isNull(name)) {
229                            return false;
230                    }
231    
232                    for (char c : name.trim().toCharArray()) {
233                            if (!isChar(c) && !isDigit(c) && !Character.isWhitespace(c)) {
234                                    return false;
235                            }
236                    }
237    
238                    return true;
239            }
240    
241            /**
242             * Returns <code>true</code> if the character is in the ASCII character set.
243             * This includes characters with integer values between 32 and 126
244             * (inclusive).
245             *
246             * @param  c the character to check
247             * @return <code>true</code> if the character is in the ASCII character set;
248             *         <code>false</code> otherwise
249             */
250            public static boolean isAscii(char c) {
251                    int i = c;
252    
253                    if ((i >= 32) && (i <= 126)) {
254                            return true;
255                    }
256                    else {
257                            return false;
258                    }
259            }
260    
261            /**
262             * Returns <code>true</code> if the character is an upper or lower case
263             * English letter.
264             *
265             * @param  c the character to check
266             * @return <code>true</code> if the character is an upper or lower case
267             *         English letter; <code>false</code> otherwise
268             */
269            public static boolean isChar(char c) {
270                    int x = c;
271    
272                    if (((x >= _CHAR_LOWER_CASE_BEGIN) && (x <= _CHAR_LOWER_CASE_END)) ||
273                            ((x >= _CHAR_UPPER_CASE_BEGIN) && (x <= _CHAR_UPPER_CASE_END))) {
274    
275                            return true;
276                    }
277    
278                    return false;
279            }
280    
281            /**
282             * Returns <code>true</code> if string consists only of upper and lower case
283             * English letters.
284             *
285             * @param  s the string to check
286             * @return <code>true</code> if the string consists only of upper and lower
287             *         case English letters
288             */
289            public static boolean isChar(String s) {
290                    if (isNull(s)) {
291                            return false;
292                    }
293    
294                    for (char c : s.toCharArray()) {
295                            if (!isChar(c)) {
296                                    return false;
297                            }
298                    }
299    
300                    return true;
301            }
302    
303            /**
304             * Returns <code>true</code> if the date is valid in the Gregorian calendar.
305             *
306             * @param  month the month to check
307             * @param  day the day to check
308             * @return <code>true</code> if the date is valid in the Gregorian calendar;
309             *         <code>false</code> otherwise
310             */
311            public static boolean isDate(int month, int day, int year) {
312                    return isGregorianDate(month, day, year);
313            }
314    
315            /**
316             * Returns <code>true</code> if the character is a digit between 0 and 9
317             * (inclusive).
318             *
319             * @param  c the character to check
320             * @return <code>true</code> if the character is a digit between 0 and 9
321             *         (inclusive); <code>false</code> otherwise
322             */
323            public static boolean isDigit(char c) {
324                    int x = c;
325    
326                    if ((x >= _DIGIT_BEGIN) && (x <= _DIGIT_END)) {
327                            return true;
328                    }
329    
330                    return false;
331            }
332    
333            /**
334             * Returns <code>true</code> if the string consists of only digits between 0
335             * and 9 (inclusive).
336             *
337             * @param  s the string to check
338             * @return <code>true</code> if the string consists of only digits between 0
339             *         and 9 (inclusive); <code>false</code> otherwise
340             */
341            public static boolean isDigit(String s) {
342                    if (isNull(s)) {
343                            return false;
344                    }
345    
346                    for (char c : s.toCharArray()) {
347                            if (!isDigit(c)) {
348                                    return false;
349                            }
350                    }
351    
352                    return true;
353            }
354    
355            /**
356             * Returns <code>true</code> if the string is a valid domain name. See
357             * RFC-1034 (section 3), RFC-1123 (section 2.1), and RFC-952 (section B.
358             * Lexical grammar).
359             *
360             * @param  domainName the string to check
361             * @return <code>true</code> if the string is a valid domain name;
362             *         <code>false</code> otherwise
363             */
364            public static boolean isDomain(String domainName) {
365    
366                    // See RFC-1034 (section 3), RFC-1123 (section 2.1), and RFC-952
367                    // (section B. Lexical grammar)
368    
369                    if (isNull(domainName)) {
370                            return false;
371                    }
372    
373                    if (domainName.length() > 255) {
374                            return false;
375                    }
376    
377                    if (domainName.startsWith(StringPool.PERIOD) ||
378                            domainName.endsWith(StringPool.PERIOD)) {
379    
380                            return false;
381                    }
382    
383                    if (!domainName.contains(StringPool.PERIOD) &&
384                            !domainName.equals(_LOCALHOST)) {
385    
386                            return false;
387                    }
388    
389                    String[] domainNameArray = StringUtil.split(
390                            domainName, CharPool.PERIOD);
391    
392                    for (String domainNamePart : domainNameArray) {
393                            char[] domainNamePartCharArray = domainNamePart.toCharArray();
394    
395                            for (int i = 0; i < domainNamePartCharArray.length; i++) {
396                                    char c = domainNamePartCharArray[i];
397    
398                                    if ((i == 0) && (c == CharPool.DASH)) {
399                                            return false;
400                                    }
401    
402                                    if ((i == (domainNamePartCharArray.length - 1)) &&
403                                            (c == CharPool.DASH)) {
404    
405                                            return false;
406                                    }
407    
408                                    if (!isChar(c) && !isDigit(c) && (c != CharPool.DASH)) {
409                                            return false;
410                                    }
411                            }
412                    }
413    
414                    return true;
415            }
416    
417            /**
418             * Returns <code>true</code> if the string is a valid email address.
419             *
420             * @param  emailAddress the string to check
421             * @return <code>true</code> if the string is a valid email address;
422             *         <code>false</code> otherwise
423             */
424            public static boolean isEmailAddress(String emailAddress) {
425                    Matcher matcher = _emailAddressPattern.matcher(emailAddress);
426    
427                    return matcher.matches();
428            }
429    
430            /**
431             * Returns <code>true</code> if the character is a special character in an
432             * email address.
433             *
434             * @param  c the character to check
435             * @return <code>true</code> if the character is a special character in an
436             *         email address; <code>false</code> otherwise
437             */
438            public static boolean isEmailAddressSpecialChar(char c) {
439    
440                    // LEP-1445
441    
442                    for (char specialChar : _EMAIL_ADDRESS_SPECIAL_CHAR) {
443                            if (c == specialChar) {
444                                    return true;
445                            }
446                    }
447    
448                    return false;
449            }
450    
451            /**
452             * Returns <code>true</code> if the file extension is valid.
453             *
454             * @param  fileExtension file extension
455             * @return <code>true</code> if the extension is valid; <code>false</code>
456             *         otherwise
457             */
458            public static boolean isFileExtension(String fileExtension) {
459                    if (isNull(fileExtension) || fileExtension.contains(StringPool.SLASH) ||
460                            fileExtension.contains(StringPool.BACK_SLASH) ||
461                            fileExtension.contains(StringPool.NULL_CHAR)) {
462    
463                            return false;
464                    }
465    
466                    return true;
467            }
468    
469            /**
470             * Returns <code>true</code> if the date is valid in the Gregorian calendar.
471             *
472             * @param  month the month (0-based, meaning 0 for January)
473             * @param  day the day of the month
474             * @param  year the year
475             * @return <code>true</code> if the date is valid; <code>false</code>
476             *         otherwise
477             */
478            public static boolean isGregorianDate(int month, int day, int year) {
479                    if ((month < 0) || (month > 11)) {
480                            return false;
481                    }
482    
483                    int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
484    
485                    if (month == 1) {
486                            int febMax = 28;
487    
488                            if (((year % 4) == 0) && ((year % 100) != 0) ||
489                                    ((year % 400) == 0)) {
490    
491                                    febMax = 29;
492                            }
493    
494                            if ((day < 1) || (day > febMax)) {
495                                    return false;
496                            }
497                    }
498                    else if ((day < 1) || (day > months[month])) {
499                            return false;
500                    }
501    
502                    return true;
503            }
504    
505            /**
506             * Returns <code>true</code> if the string is a hexidecimal number. At
507             * present the only requirement is that the string is not <code>null</code>;
508             * it does not actually check the format of the string.
509             *
510             * @param  s the string to check
511             * @return <code>true</code> if the string is a hexidecimal number;
512             *         <code>false</code> otherwise
513             * @see    #isNull(String)
514             */
515            public static boolean isHex(String s) {
516                    if (isNull(s)) {
517                            return false;
518                    }
519    
520                    return true;
521            }
522    
523            /**
524             * Returns <code>true</code> if the string is a valid host name.
525             *
526             * @param  name the string to check
527             * @return <code>true</code> if the string is a valid host name;
528             *         <code>false</code> otherwise
529             */
530            public static boolean isHostName(String name) {
531                    if (isNull(name)) {
532                            return false;
533                    }
534    
535                    char[] nameCharArray = name.toCharArray();
536    
537                    if ((nameCharArray[0] == CharPool.DASH) ||
538                            (nameCharArray[0] == CharPool.PERIOD) ||
539                            (nameCharArray[nameCharArray.length - 1] == CharPool.DASH)) {
540    
541                            return false;
542                    }
543    
544                    for (char c : nameCharArray) {
545                            if (!isChar(c) && !isDigit(c) && (c != CharPool.CLOSE_BRACKET) &&
546                                    (c != CharPool.COLON) && (c != CharPool.DASH) &&
547                                    (c != CharPool.OPEN_BRACKET) && (c != CharPool.PERIOD)) {
548    
549                                    return false;
550                            }
551                    }
552    
553                    return true;
554            }
555    
556            /**
557             * Returns <code>true</code> if the string is an HTML document. The only
558             * requirement is that it contain the opening and closing html tags.
559             *
560             * @param  s the string to check
561             * @return <code>true</code> if the string is an HTML document;
562             *         <code>false</code> otherwise
563             */
564            public static boolean isHTML(String s) {
565                    if (isNull(s)) {
566                            return false;
567                    }
568    
569                    if (((s.indexOf("<html>") != -1) || (s.indexOf("<HTML>") != -1)) &&
570                            ((s.indexOf("</html>") != -1) || (s.indexOf("</HTML>") != -1))) {
571    
572                            return true;
573                    }
574    
575                    return false;
576            }
577    
578            /**
579             * Returns <code>true</code> if the string is a valid IPv4 IP address.
580             *
581             * @param  ipAddress the string to check
582             * @return <code>true</code> if the string is an IPv4 IP address;
583             *         <code>false</code> otherwise
584             */
585            public static boolean isIPAddress(String ipAddress) {
586                    Matcher matcher = _ipAddressPattern.matcher(ipAddress);
587    
588                    return matcher.matches();
589            }
590    
591            /**
592             * Returns <code>true</code> if the date is valid in the Julian calendar.
593             *
594             * @param  month the month (0-based, meaning 0 for January)
595             * @param  day the day of the month
596             * @param  year the year
597             * @return <code>true</code> if the date is valid; <code>false</code>
598             *         otherwise
599             */
600            public static boolean isJulianDate(int month, int day, int year) {
601                    if ((month < 0) || (month > 11)) {
602                            return false;
603                    }
604    
605                    int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
606    
607                    if (month == 1) {
608                            int febMax = 28;
609    
610                            if ((year % 4) == 0) {
611                                    febMax = 29;
612                            }
613    
614                            if ((day < 1) || (day > febMax)) {
615                                    return false;
616                            }
617                    }
618                    else if ((day < 1) || (day > months[month])) {
619                            return false;
620                    }
621    
622                    return true;
623            }
624    
625            /**
626             * Returns <code>true</code> if the string contains a valid number according
627             * to the Luhn algorithm, commonly used to validate credit card numbers.
628             *
629             * @param  number the string to check
630             * @return <code>true</code> if the string contains a valid number according
631             *         to the Luhn algorithm; <code>false</code> otherwise
632             */
633            public static boolean isLUHN(String number) {
634                    if (number == null) {
635                            return false;
636                    }
637    
638                    number = StringUtil.reverse(number);
639    
640                    int total = 0;
641    
642                    for (int i = 0; i < number.length(); i++) {
643                            int x = 0;
644    
645                            if (((i + 1) % 2) == 0) {
646                                    x = GetterUtil.getInteger(number.substring(i, i + 1)) * 2;
647    
648                                    if (x >= 10) {
649                                            String s = String.valueOf(x);
650    
651                                            x =
652                                                    GetterUtil.getInteger(s.substring(0, 1)) +
653                                                            GetterUtil.getInteger(s.substring(1, 2));
654                                    }
655                            }
656                            else {
657                                    x = GetterUtil.getInteger(number.substring(i, i + 1));
658                            }
659    
660                            total = total + x;
661                    }
662    
663                    if ((total % 10) == 0) {
664                            return true;
665                    }
666                    else {
667                            return false;
668                    }
669            }
670    
671            /**
672             * Returns <code>true</code> if the string is a name, meaning it contains
673             * nothing but English letters and spaces.
674             *
675             * @param  name the string to check
676             * @return <code>true</code> if the string is a name; <code>false</code>
677             *         otherwise
678             */
679            public static boolean isName(String name) {
680                    if (isNull(name)) {
681                            return false;
682                    }
683    
684                    for (char c : name.trim().toCharArray()) {
685                            if (!isChar(c) && !Character.isWhitespace(c)) {
686                                    return false;
687                            }
688                    }
689    
690                    return true;
691            }
692    
693            /**
694             * Returns <code>true</code> if the long number object is not
695             * <code>null</code>, meaning it is neither a <code>null</code> reference or
696             * zero.
697             *
698             * @param  l the long number object to check
699             * @return <code>true</code> if the long number object is not
700             *         <code>null</code>; <code>false</code> otherwise
701             */
702            public static boolean isNotNull(Long l) {
703                    return !isNull(l);
704            }
705    
706            /**
707             * Returns <code>true</code> if the object is not <code>null</code>, using
708             * the rules from {@link #isNotNull(Long)} or {@link #isNotNull(String)} if
709             * the object is one of these types.
710             *
711             * @param  obj the object to check
712             * @return <code>true</code> if the object is not <code>null</code>;
713             *         <code>false</code> otherwise
714             */
715            public static boolean isNotNull(Object obj) {
716                    return !isNull(obj);
717            }
718    
719            /**
720             * Returns <code>true</code> if the array is not <code>null</code>, meaning
721             * it is neither a <code>null</code> reference or empty.
722             *
723             * @param  array the array to check
724             * @return <code>true</code> if the array is not <code>null</code>;
725             *         <code>false</code> otherwise
726             */
727            public static boolean isNotNull(Object[] array) {
728                    return !isNull(array);
729            }
730    
731            /**
732             * Returns <code>true</code> if the string is not <code>null</code>, meaning
733             * it is not a <code>null</code> reference, nothing but spaces, or the
734             * string "<code>null</code>".
735             *
736             * @param  s the string to check
737             * @return <code>true</code> if the string is not <code>null</code>;
738             *         <code>false</code> otherwise
739             */
740            public static boolean isNotNull(String s) {
741                    return !isNull(s);
742            }
743    
744            /**
745             * Returns <code>true</code> if the long number object is <code>null</code>,
746             * meaning it is either a <code>null</code> reference or zero.
747             *
748             * @param  l the long number object to check
749             * @return <code>true</code> if the long number object is <code>null</code>;
750             *         <code>false</code> otherwise
751             */
752            public static boolean isNull(Long l) {
753                    if ((l == null) || (l.longValue() == 0)) {
754                            return true;
755                    }
756                    else {
757                            return false;
758                    }
759            }
760    
761            /**
762             * Returns <code>true</code> if the object is <code>null</code>, using the
763             * rules from {@link #isNull(Long)} or {@link #isNull(String)} if the object
764             * is one of these types.
765             *
766             * @param  obj the object to check
767             * @return <code>true</code> if the object is <code>null</code>;
768             *         <code>false</code> otherwise
769             */
770            public static boolean isNull(Object obj) {
771                    if (obj instanceof Long) {
772                            return isNull((Long)obj);
773                    }
774                    else if (obj instanceof String) {
775                            return isNull((String)obj);
776                    }
777                    else if (obj == null) {
778                            return true;
779                    }
780                    else {
781                            return false;
782                    }
783            }
784    
785            /**
786             * Returns <code>true</code> if the array is <code>null</code>, meaning it
787             * is either a <code>null</code> reference or empty.
788             *
789             * @param  array the array to check
790             * @return <code>true</code> if the array is <code>null</code>;
791             *         <code>false</code> otherwise
792             */
793            public static boolean isNull(Object[] array) {
794                    if ((array == null) || (array.length == 0)) {
795                            return true;
796                    }
797                    else {
798                            return false;
799                    }
800            }
801    
802            /**
803             * Returns <code>true</code> if the string is <code>null</code>, meaning it
804             * is a <code>null</code> reference, nothing but spaces, or the string
805             * "<code>null</code>".
806             *
807             * @param  s the string to check
808             * @return <code>true</code> if the string is <code>null</code>;
809             *         <code>false</code> otherwise
810             */
811            public static boolean isNull(String s) {
812                    if (s == null) {
813                            return true;
814                    }
815    
816                    int counter = 0;
817    
818                    for (int i = 0; i < s.length(); i++) {
819                            char c = s.charAt(i);
820    
821                            if (c == CharPool.SPACE) {
822                                    continue;
823                            }
824                            else if (counter > 3) {
825                                    return false;
826                            }
827    
828                            if (counter == 0) {
829                                    if (c != CharPool.LOWER_CASE_N) {
830                                            return false;
831                                    }
832                            }
833                            else if (counter == 1) {
834                                    if (c != CharPool.LOWER_CASE_U) {
835                                            return false;
836                                    }
837                            }
838                            else if ((counter == 2) || (counter == 3)) {
839                                    if (c != CharPool.LOWER_CASE_L) {
840                                            return false;
841                                    }
842                            }
843    
844                            counter++;
845                    }
846    
847                    if ((counter == 0) || (counter == 4)) {
848                            return true;
849                    }
850    
851                    return false;
852            }
853    
854            /**
855             * Returns <code>true</code> if the string is a decimal integer number,
856             * meaning it contains nothing but decimal digits.
857             *
858             * @param  number the string to check
859             * @return <code>true</code> if the string is a decimal integer number;
860             *         <code>false</code> otherwise
861             */
862            public static boolean isNumber(String number) {
863                    if (isNull(number)) {
864                            return false;
865                    }
866    
867                    for (char c : number.toCharArray()) {
868                            if (!isDigit(c)) {
869                                    return false;
870                            }
871                    }
872    
873                    return true;
874            }
875    
876            /**
877             * Returns <code>true</code> if the string is a valid password, meaning it
878             * is at least four characters long and contains only letters and decimal
879             * digits.
880             *
881             * @return <code>true</code> if the string is a valid password;
882             *         <code>false</code> otherwise
883             */
884            public static boolean isPassword(String password) {
885                    if (isNull(password)) {
886                            return false;
887                    }
888    
889                    if (password.length() < 4) {
890                            return false;
891                    }
892    
893                    for (char c : password.toCharArray()) {
894                            if (!isChar(c) && !isDigit(c)) {
895                                    return false;
896                            }
897                    }
898    
899                    return true;
900            }
901    
902            /**
903             * Returns <code>true</code> if the string is a valid phone number. The only
904             * requirement is that there are decimal digits in the string; length and
905             * format are not checked.
906             *
907             * @param  phoneNumber the string to check
908             * @return <code>true</code> if the string is a valid phone number;
909             *         <code>false</code> otherwise
910             */
911            public static boolean isPhoneNumber(String phoneNumber) {
912                    return isNumber(StringUtil.extractDigits(phoneNumber));
913            }
914    
915            /**
916             * Returns <code>true</code> if the string is a valid URL based on the rules
917             * in {@link java.net.URL}.
918             *
919             * @param  url the string to check
920             * @return <code>true</code> if the string is a valid URL;
921             *         <code>false</code> otherwise
922             */
923            public static boolean isUrl(String url) {
924                    if (Validator.isNotNull(url)) {
925                            if (url.indexOf(CharPool.COLON) == -1) {
926                                    return false;
927                            }
928    
929                            try {
930                                    new URL(url);
931    
932                                    return true;
933                            }
934                            catch (MalformedURLException murle) {
935                            }
936                    }
937    
938                    return false;
939            }
940    
941            /**
942             * Returns <code>true</code> if the string is a valid variable name in Java.
943             *
944             * @param  variableName the string to check
945             * @return <code>true</code> if the string is a valid variable name in Java;
946             *         <code>false</code> otherwise
947             */
948            public static boolean isVariableName(String variableName) {
949                    if (isNull(variableName)) {
950                            return false;
951                    }
952    
953                    Matcher matcher = _variableNamePattern.matcher(variableName);
954    
955                    if (matcher.matches()) {
956                            return true;
957                    }
958                    else {
959                            return false;
960                    }
961            }
962    
963            /**
964             * Returns <code>true</code> if the string is a valid variable term, meaning
965             * it begins with "[$" and ends with "$]".
966             *
967             * @param  s the string to check
968             * @return <code>true</code> if the string is a valid variable term;
969             *         <code>false</code> otherwise
970             */
971            public static boolean isVariableTerm(String s) {
972                    if (s.startsWith(_VARIABLE_TERM_BEGIN) &&
973                            s.endsWith(_VARIABLE_TERM_END)) {
974    
975                            return true;
976                    }
977                    else {
978                            return false;
979                    }
980            }
981    
982            /**
983             * Returns <code>true</code> if the character is whitespace, meaning it is
984             * either the <code>null</code> character '0' or whitespace according to
985             * {@link java.lang.Character#isWhitespace(char)}.
986             *
987             * @param  c the character to check
988             * @return <code>true</code> if the character is whitespace;
989             *         <code>false</code> otherwise
990             */
991            public static boolean isWhitespace(char c) {
992                    int i = c;
993    
994                    if ((i == 0) || Character.isWhitespace(c)) {
995                            return true;
996                    }
997                    else {
998                            return false;
999                    }
1000            }
1001    
1002            /**
1003             * Returns <code>true</code> if the string is an XML document. The only
1004             * requirement is that it contain either the xml start tag "<?xml" or the
1005             * empty document tag "<root />".
1006             *
1007             * @param  s the string to check
1008             * @return <code>true</code> if the string is an XML document;
1009             *         <code>false</code> otherwise
1010             */
1011            public static boolean isXml(String s) {
1012                    if (s.startsWith(_XML_BEGIN) || s.startsWith(_XML_EMPTY)) {
1013                            return true;
1014                    }
1015                    else {
1016                            return false;
1017                    }
1018            }
1019    
1020            private static final int _CHAR_LOWER_CASE_BEGIN = 97;
1021    
1022            private static final int _CHAR_LOWER_CASE_END = 122;
1023    
1024            private static final int _CHAR_UPPER_CASE_BEGIN = 65;
1025    
1026            private static final int _CHAR_UPPER_CASE_END = 90;
1027    
1028            private static final int _DIGIT_BEGIN = 48;
1029    
1030            private static final int _DIGIT_END = 57;
1031    
1032            private static final char[] _EMAIL_ADDRESS_SPECIAL_CHAR = new char[] {
1033                    '.', '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^',
1034                    '_', '`', '{', '|', '}', '~'
1035            };
1036    
1037            private static final String _LOCALHOST = "localhost";
1038    
1039            private static final String _VARIABLE_TERM_BEGIN = "[$";
1040    
1041            private static final String _VARIABLE_TERM_END = "$]";
1042    
1043            private static final String _XML_BEGIN = "<?xml";
1044    
1045            private static final String _XML_EMPTY = "<root />";
1046    
1047            private static Pattern _emailAddressPattern = Pattern.compile(
1048                    "[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@" +
1049                    "(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?");
1050            private static Pattern _ipAddressPattern = Pattern.compile(
1051                    "\\b" +
1052                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
1053                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
1054                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
1055                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])" +
1056                    "\\b");
1057            private static Pattern _variableNamePattern = Pattern.compile(
1058                    "[_a-zA-Z]+[_a-zA-Z0-9]*");
1059    
1060    }