/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.kernel.util; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Provides utility methods related to data validation and format checking. * * @author Brian Wing Shun Chan * @author Alysa Carver */ public class Validator { /** * @deprecated As of 7.0.0 */ @Deprecated public static boolean equals(boolean boolean1, boolean boolean2) { if (boolean1 == boolean2) { return true; } else { return false; } } /** * @deprecated As of 7.0.0 */ @Deprecated public static boolean equals(byte byte1, byte byte2) { if (byte1 == byte2) { return true; } else { return false; } } /** * @deprecated As of 7.0.0 */ @Deprecated public static boolean equals(char char1, char char2) { if (char1 == char2) { return true; } else { return false; } } /** * @deprecated As of 7.0.0 */ @Deprecated public static boolean equals(double double1, double double2) { if (Double.compare(double1, double2) == 0) { return true; } else { return false; } } /** * @deprecated As of 7.0.0 */ @Deprecated public static boolean equals(float float1, float float2) { if (Float.compare(float1, float2) == 0) { return true; } else { return false; } } /** * @deprecated As of 7.0.0 */ @Deprecated public static boolean equals(int int1, int int2) { if (int1 == int2) { return true; } else { return false; } } /** * @deprecated As of 7.0.0 */ @Deprecated public static boolean equals(long long1, long long2) { if (long1 == long2) { return true; } else { return false; } } /** * @deprecated As of 7.0.0 */ @Deprecated public static boolean equals(Object obj1, Object obj2) { if (obj1 == obj2) { return true; } else if ((obj1 == null) || (obj2 == null)) { return false; } else { return obj1.equals(obj2); } } /** * @deprecated As of 7.0.0 */ @Deprecated public static boolean equals(short short1, short short2) { if (short1 == short2) { return true; } else { return false; } } /** * Returns <code>true</code> if the boolean arrays are equal. * * @param booleanArray1 the first boolean array * @param booleanArray2 the second boolean array * @return <code>true</code> if the booleans arrays are equal; <code>false * </code>otherwise */ public static boolean equalsSorted( boolean[] booleanArray1, boolean[] booleanArray2) { Boolean[] booleanObjArray1 = ArrayUtil.toArray(booleanArray1); Arrays.sort(booleanObjArray1); Boolean[] booleanObjArray2 = ArrayUtil.toArray(booleanArray2); Arrays.sort(booleanObjArray2); return Arrays.equals(booleanObjArray1, booleanObjArray2); } /** * Returns <code>true</code> if the byte arrays are equal. * * @param byteArray1 the first byte array * @param byteArray2 the second byte array * @return <code>true</code> if the byte arrays are equal; <code>false * </code>otherwise */ public static boolean equalsSorted(byte[] byteArray1, byte[] byteArray2) { byteArray1 = ArrayUtil.clone(byteArray1); Arrays.sort(byteArray1); byteArray2 = ArrayUtil.clone(byteArray2); Arrays.sort(byteArray2); return Arrays.equals(byteArray1, byteArray2); } /** * Returns <code>true</code> if the char arrays are equal. * * @param charArray1 the first char array * @param charArray2 the second char array * @return <code>true</code> if the char arrays are equal; <code>false * </code>otherwise */ public static boolean equalsSorted(char[] charArray1, char[] charArray2) { charArray1 = ArrayUtil.clone(charArray1); Arrays.sort(charArray1); charArray2 = ArrayUtil.clone(charArray2); Arrays.sort(charArray2); return Arrays.equals(charArray1, charArray2); } /** * Returns <code>true</code> if the double arrays are equal. * * @param doubleArray1 the first double array * @param doubleArray2 the second double array * @return <code>true</code> if the double arrays are equal; <code>false * </code>otherwise */ public static boolean equalsSorted( double[] doubleArray1, double[] doubleArray2) { doubleArray1 = ArrayUtil.clone(doubleArray1); Arrays.sort(doubleArray1); doubleArray2 = ArrayUtil.clone(doubleArray2); Arrays.sort(doubleArray2); return Arrays.equals(doubleArray1, doubleArray2); } /** * Returns <code>true</code> if the float arrays are equal. * * @param floatArray1 the first float array * @param floatArray2 the second char array * @return <code>true</code> if the float arrays are equal; <code>false * </code>otherwise */ public static boolean equalsSorted( float[] floatArray1, float[] floatArray2) { floatArray1 = ArrayUtil.clone(floatArray1); Arrays.sort(floatArray1); floatArray2 = ArrayUtil.clone(floatArray2); Arrays.sort(floatArray2); return Arrays.equals(floatArray1, floatArray2); } /** * Returns <code>true</code> if the int arrays are equal. * * @param intArray1 the first int array * @param intArray2 the second int array * @return <code>true</code> if the int arrays are equal; <code>false</code> * otherwise */ public static boolean equalsSorted(int[] intArray1, int[] intArray2) { intArray1 = ArrayUtil.clone(intArray1); Arrays.sort(intArray1); intArray2 = ArrayUtil.clone(intArray2); Arrays.sort(intArray2); return Arrays.equals(intArray1, intArray2); } /** * Returns <code>true</code> if the long arrays are equal. * * @param longArray1 the first long array * @param longArray2 the second long array * @return <code>true</code> if the long arrays are equal; <code>false * </code>otherwise */ public static boolean equalsSorted(long[] longArray1, long[] longArray2) { longArray1 = ArrayUtil.clone(longArray1); Arrays.sort(longArray1); longArray2 = ArrayUtil.clone(longArray2); Arrays.sort(longArray2); return Arrays.equals(longArray1, longArray2); } /** * Returns <code>true</code> if the object arrays are equal. * * @param objArray1 the first object array * @param objArray2 the second object array * @return <code>true</code> if the object arrays are equal; <code>false * </code>otherwise */ public static boolean equalsSorted(Object[] objArray1, Object[] objArray2) { objArray1 = ArrayUtil.clone(objArray1); Arrays.sort(objArray1); objArray2 = ArrayUtil.clone(objArray2); Arrays.sort(objArray2); return Arrays.equals(objArray1, objArray2); } /** * Returns <code>true</code> if the short arrays are equal. * * @param shortArray1 the first short array * @param shortArray2 the second short array * @return <code>true</code> if the short arrays are equal; <code>false * </code>otherwise */ public static boolean equalsSorted( short[] shortArray1, short[] shortArray2) { shortArray1 = ArrayUtil.clone(shortArray1); Arrays.sort(shortArray1); shortArray2 = ArrayUtil.clone(shortArray2); Arrays.sort(shortArray2); return Arrays.equals(shortArray1, shortArray2); } /** * Returns <code>true</code> if the string is an email address. The only * requirements are that the string consist of two parts separated by an @ * symbol, and that it contain no whitespace. * * @param address the string to check * @return <code>true</code> if the string is an email address; * <code>false</code> otherwise */ public static boolean isAddress(String address) { if (isNull(address)) { return false; } String[] tokens = address.split(StringPool.AT); if (tokens.length != 2) { return false; } for (String token : tokens) { for (char c : token.toCharArray()) { if (Character.isWhitespace(c)) { return false; } } } return true; } /** * Returns <code>true</code> if the string is an alphanumeric name, meaning * it contains nothing but English letters, numbers, and spaces. * * @param name the string to check * @return <code>true</code> if the string is an Alphanumeric name; * <code>false</code> otherwise */ public static boolean isAlphanumericName(String name) { if (isNull(name)) { return false; } for (char c : name.trim().toCharArray()) { if (!isChar(c) && !isDigit(c) && !Character.isWhitespace(c)) { return false; } } return true; } /** * Returns <code>true</code> if the character is in the ASCII character set. * This includes characters with integer values between 32 and 126 * (inclusive). * * @param c the character to check * @return <code>true</code> if the character is in the ASCII character set; * <code>false</code> otherwise */ public static boolean isAscii(char c) { int i = c; if ((i >= 32) && (i <= 126)) { return true; } else { return false; } } public static boolean isBlank(String s) { if (s == null) { return true; } if (s.length() == 0) { return true; } return false; } public static boolean isBoolean(String value) { return ArrayUtil.contains(_BOOLEANS, value); } /** * Returns <code>true</code> if the character is an upper or lower case * English letter. * * @param c the character to check * @return <code>true</code> if the character is an upper or lower case * English letter; <code>false</code> otherwise */ public static boolean isChar(char c) { int x = c; if (((x >= _CHAR_LOWER_CASE_BEGIN) && (x <= _CHAR_LOWER_CASE_END)) || ((x >= _CHAR_UPPER_CASE_BEGIN) && (x <= _CHAR_UPPER_CASE_END))) { return true; } return false; } /** * Returns <code>true</code> if string consists only of upper and lower case * English letters. * * @param s the string to check * @return <code>true</code> if the string consists only of upper and lower * case English letters */ public static boolean isChar(String s) { if (isNull(s)) { return false; } for (char c : s.toCharArray()) { if (!isChar(c)) { return false; } } return true; } /** * Returns <code>true</code> if the string contains content. The only * requirement is that it contain content that is not whitespace. * * @param s the string to check * @return <code>true</code> if the string contains content; * <code>false</code> otherwise */ public static boolean isContent(String s) { if (isNotNull( StringUtil.removeChars(s, CharPool.NEW_LINE, CharPool.TAB))) { return true; } return false; } /** * Returns <code>true</code> if the date is valid in the Gregorian calendar. * * @param month the month to check * @param day the day to check * @param year the year to check * @return <code>true</code> if the date is valid in the Gregorian calendar; * <code>false</code> otherwise */ public static boolean isDate(int month, int day, int year) { return isGregorianDate(month, day, year); } /** * Returns <code>true</code> if the character is a digit between 0 and 9 * (inclusive). * * @param c the character to check * @return <code>true</code> if the character is a digit between 0 and 9 * (inclusive); <code>false</code> otherwise */ public static boolean isDigit(char c) { int x = c; if ((x >= _DIGIT_BEGIN) && (x <= _DIGIT_END)) { return true; } return false; } /** * Returns <code>true</code> if the string consists of only digits between 0 * and 9 (inclusive). * * @param s the string to check * @return <code>true</code> if the string consists of only digits between 0 * and 9 (inclusive); <code>false</code> otherwise */ public static boolean isDigit(String s) { if (isNull(s)) { return false; } for (char c : s.toCharArray()) { if (!isDigit(c)) { return false; } } return true; } /** * Returns <code>true</code> if the string is a valid domain name. See * RFC-1034 (section 3), RFC-1123 (section 2.1), and RFC-952 (section B. * Lexical grammar). * * @param domainName the string to check * @return <code>true</code> if the string is a valid domain name; * <code>false</code> otherwise */ public static boolean isDomain(String domainName) { // See RFC-1034 (section 3), RFC-1123 (section 2.1), and RFC-952 // (section B. Lexical grammar) if (isNull(domainName)) { return false; } if (domainName.length() > 255) { return false; } if (domainName.startsWith(StringPool.PERIOD)) { return false; } String[] domainNameArray = StringUtil.split( domainName, CharPool.PERIOD); for (String domainNamePart : domainNameArray) { char[] domainNamePartCharArray = domainNamePart.toCharArray(); for (int i = 0; i < domainNamePartCharArray.length; i++) { char c = domainNamePartCharArray[i]; if ((i == 0) && (c == CharPool.DASH)) { return false; } if ((i == (domainNamePartCharArray.length - 1)) && (c == CharPool.DASH)) { return false; } if (!Character.isLetterOrDigit(c) && (c != CharPool.DASH)) { return false; } } } return true; } /** * Returns <code>true</code> if the string is a valid email address. * * @param emailAddress the string to check * @return <code>true</code> if the string is a valid email address; * <code>false</code> otherwise */ public static boolean isEmailAddress(String emailAddress) { if (isNull(emailAddress)) { return false; } Matcher matcher = _emailAddressPattern.matcher(emailAddress); return matcher.matches(); } /** * Returns <code>true</code> if the character is a special character in an * email address. * * @param c the character to check * @return <code>true</code> if the character is a special character in an * email address; <code>false</code> otherwise */ public static boolean isEmailAddressSpecialChar(char c) { // LEP-1445 for (char specialChar : _EMAIL_ADDRESS_SPECIAL_CHAR) { if (c == specialChar) { return true; } } return false; } /** * Returns <code>true</code> if the file extension is valid. * * @param fileExtension string to check * @return <code>true</code> if the extension is valid; <code>false</code> * otherwise */ public static boolean isFileExtension(String fileExtension) { if (isNull(fileExtension) || fileExtension.contains(StringPool.BACK_SLASH) || fileExtension.contains(StringPool.NULL_CHAR) || fileExtension.contains(StringPool.SLASH)) { return false; } return true; } public static boolean isFileName(String name) { if (isNull(name) || name.equals(StringPool.PERIOD) || name.equals(StringPool.DOUBLE_PERIOD) || name.contains(StringPool.BACK_SLASH) || name.contains(StringPool.NULL_CHAR) || name.contains(StringPool.SLASH)) { return false; } return true; } public static boolean isFilePath(String path, boolean parentDirAllowed) { if (isNull(path)) { return false; } if (path.contains(StringPool.NULL_CHAR)) { return false; } if (parentDirAllowed) { return true; } if (path.equals(StringPool.DOUBLE_PERIOD)) { return false; } String normalizedPath = path.replace( CharPool.BACK_SLASH, CharPool.SLASH); if (normalizedPath.startsWith( StringPool.DOUBLE_PERIOD.concat(StringPool.SLASH))) { return false; } if (normalizedPath.endsWith( StringPool.SLASH.concat(StringPool.DOUBLE_PERIOD))) { return false; } if (normalizedPath.contains( StringPool.SLASH.concat( StringPool.DOUBLE_PERIOD).concat(StringPool.SLASH))) { return false; } return true; } /** * Returns <code>true</code> if the date is valid in the Gregorian calendar. * * @param month the month (0-based, meaning 0 for January) * @param day the day of the month * @param year the year * @return <code>true</code> if the date is valid; <code>false</code> * otherwise */ public static boolean isGregorianDate(int month, int day, int year) { if ((month < 0) || (month > 11)) { return false; } int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (month == 1) { int febMax = 28; if (((year % 4) == 0) && ((year % 100) != 0) || ((year % 400) == 0)) { febMax = 29; } if ((day < 1) || (day > febMax)) { return false; } } else if ((day < 1) || (day > months[month])) { return false; } return true; } /** * Returns <code>true</code> if the string is a hexidecimal number. At * present the only requirement is that the string is not <code>null</code>; * it does not actually check the format of the string. * * @param s the string to check * @return <code>true</code> if the string is a hexidecimal number; * <code>false</code> otherwise * @see #isNull(String) */ public static boolean isHex(String s) { if (isNull(s)) { return false; } return true; } /** * Returns <code>true</code> if the string is a valid host name. * * @param name the string to check * @return <code>true</code> if the string is a valid host name; * <code>false</code> otherwise */ public static boolean isHostName(String name) { if (isNull(name)) { return false; } char[] nameCharArray = name.toCharArray(); if ((nameCharArray[0] == CharPool.DASH) || (nameCharArray[0] == CharPool.PERIOD) || (nameCharArray[nameCharArray.length - 1] == CharPool.DASH)) { return false; } for (char c : nameCharArray) { if (!isChar(c) && !isDigit(c) && (c != CharPool.CLOSE_BRACKET) && (c != CharPool.COLON) && (c != CharPool.DASH) && (c != CharPool.OPEN_BRACKET) && (c != CharPool.PERIOD)) { return false; } } return true; } /** * Returns <code>true</code> if the string is an HTML document. The only * requirement is that it contain the opening and closing html tags. * * @param s the string to check * @return <code>true</code> if the string is an HTML document; * <code>false</code> otherwise */ public static boolean isHTML(String s) { if (isNull(s)) { return false; } if ((s.contains("<html>") || s.contains("<HTML>")) && (s.contains("</html>") || s.contains("</HTML>"))) { return true; } return false; } /** * Returns <code>true</code> if the string is a valid IPv4 or IPv6 IP * address. * * @param ipAddress the string to check * @return <code>true</code> if the string is a valid IPv4 or IPv6 IP * address; <code>false</code> otherwise */ public static boolean isIPAddress(String ipAddress) { if (isIPv4Address(ipAddress) || isIPv6Address(ipAddress)) { return true; } return false; } /** * Returns <code>true</code> if the string is a valid IPv4 IP address. * * @param ipAddress the string to check * @return <code>true</code> if the string is a valid IPv4 IP address; * <code>false</code> otherwise */ public static boolean isIPv4Address(String ipAddress) { Matcher matcher = _ipv4AddressPattern.matcher(ipAddress); return matcher.matches(); } /** * Returns <code>true</code> if the string is a valid IPv6 IP address. * * @param ipAddress the string to check * @return <code>true</code> if the string is a valid IPv6 IP address; * <code>false</code> otherwise */ public static boolean isIPv6Address(String ipAddress) { if (isNull(ipAddress)) { return false; } if ((ipAddress.charAt(0) == CharPool.OPEN_BRACKET) && (ipAddress.charAt(ipAddress.length() - 1) == CharPool.CLOSE_BRACKET)) { ipAddress = ipAddress.substring(1, ipAddress.length() - 1); } Matcher matcher = _ipv6AddressPattern.matcher(ipAddress); return matcher.matches(); } /** * Returns <code>true</code> if the date is valid in the Julian calendar. * * @param month the month (0-based, meaning 0 for January) * @param day the day of the month * @param year the year * @return <code>true</code> if the date is valid in the Julian calendar; * <code>false</code> otherwise */ public static boolean isJulianDate(int month, int day, int year) { if ((month < 0) || (month > 11)) { return false; } int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (month == 1) { int febMax = 28; if ((year % 4) == 0) { febMax = 29; } if ((day < 1) || (day > febMax)) { return false; } } else if ((day < 1) || (day > months[month])) { return false; } return true; } /** * Returns <code>true</code> if the string contains a valid number according * to the Luhn algorithm, commonly used to validate credit card numbers. * * @param number the string to check * @return <code>true</code> if the string contains a valid number according * to the Luhn algorithm; <code>false</code> otherwise */ public static boolean isLUHN(String number) { if (number == null) { return false; } number = StringUtil.reverse(number); int total = 0; for (int i = 0; i < number.length(); i++) { int x = 0; if (((i + 1) % 2) == 0) { x = GetterUtil.getInteger(number.substring(i, i + 1)) * 2; if (x >= 10) { String s = String.valueOf(x); x = GetterUtil.getInteger(s.substring(0, 1)) + GetterUtil.getInteger(s.substring(1, 2)); } } else { x = GetterUtil.getInteger(number.substring(i, i + 1)); } total = total + x; } if ((total % 10) == 0) { return true; } else { return false; } } /** * Returns <code>true</code> if the string is a name, meaning it contains * nothing but English letters and spaces. * * @param name the string to check * @return <code>true</code> if the string is a name; <code>false</code> * otherwise */ public static boolean isName(String name) { if (isNull(name)) { return false; } for (char c : name.trim().toCharArray()) { if (!isChar(c) && !Character.isWhitespace(c)) { return false; } } return true; } /** * Returns <code>true</code> if the long number object is not * <code>null</code>, meaning it is neither a <code>null</code> reference or * zero. * * @param l the long number object to check * @return <code>true</code> if the long number object is not * <code>null</code>; <code>false</code> otherwise */ public static boolean isNotNull(Long l) { return !isNull(l); } /** * Returns <code>true</code> if the object is not <code>null</code>, using * the rules from {@link #isNotNull(Long)} or {@link #isNotNull(String)} if * the object is one of these types. * * @param obj the object to check * @return <code>true</code> if the object is not <code>null</code>; * <code>false</code> otherwise */ public static boolean isNotNull(Object obj) { return !isNull(obj); } /** * Returns <code>true</code> if the string is not <code>null</code>, meaning * it is not a <code>null</code> reference, an empty string, whitespace, or * the string "<code>null</code>", with or without leading or trailing * whitespace. * * @param s the string to check * @return <code>true</code> if the string is not <code>null</code>; * <code>false</code> otherwise */ public static boolean isNotNull(String s) { return !isNull(s); } /** * Returns <code>true</code> if the long number object is <code>null</code>, * meaning it is either a <code>null</code> reference or zero. * * @param l the long number object to check * @return <code>true</code> if the long number object is <code>null</code>; * <code>false</code> otherwise */ public static boolean isNull(Long l) { if ((l == null) || (l.longValue() == 0)) { return true; } else { return false; } } /** * Returns <code>true</code> if the object is <code>null</code>, using the * rules from {@link #isNull(Long)} or {@link #isNull(String)} if the object * is one of these types. * * @param obj the object to check * @return <code>true</code> if the object is <code>null</code>; * <code>false</code> otherwise */ public static boolean isNull(Object obj) { if (obj instanceof Long) { return isNull((Long)obj); } else if (obj instanceof String) { return isNull((String)obj); } else if (obj == null) { return true; } else { return false; } } /** * Returns <code>true</code> if the string is <code>null</code>, meaning it * is a <code>null</code> reference, an empty string, whitespace, or the * string "<code>null</code>", with or without leading or trailing * whitespace. * * @param s the string to check * @return <code>true</code> if the string is <code>null</code>; * <code>false</code> otherwise */ public static boolean isNull(String s) { if (s == null) { return true; } int counter = 0; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == CharPool.SPACE) { continue; } else if (counter > 3) { return false; } if (counter == 0) { if (c != CharPool.LOWER_CASE_N) { return false; } } else if (counter == 1) { if (c != CharPool.LOWER_CASE_U) { return false; } } else if ((counter == 2) || (counter == 3)) { if (c != CharPool.LOWER_CASE_L) { return false; } } counter++; } if ((counter == 0) || (counter == 4)) { return true; } return false; } /** * Returns <code>true</code> if the string is a decimal integer number, * meaning it contains nothing but decimal digits. * * @param number the string to check * @return <code>true</code> if the string is a decimal integer number; * <code>false</code> otherwise */ public static boolean isNumber(String number) { if (isNull(number)) { return false; } for (char c : number.toCharArray()) { if (!isDigit(c)) { return false; } } return true; } /** * Returns <code>true</code> if the string is a valid password, meaning it * is at least four characters long and contains only letters and decimal * digits. * * @param password the string to check * @return <code>true</code> if the string is a valid password; * <code>false</code> otherwise */ public static boolean isPassword(String password) { if (isNull(password)) { return false; } if (password.length() < 4) { return false; } for (char c : password.toCharArray()) { if (!isChar(c) && !isDigit(c)) { return false; } } return true; } /** * Returns <code>true</code> if the string is a valid phone number. The only * requirement is that there are decimal digits in the string; length and * format are not checked. * * @param phoneNumber the string to check * @return <code>true</code> if the string is a valid phone number; * <code>false</code> otherwise */ public static boolean isPhoneNumber(String phoneNumber) { return isNumber(StringUtil.extractDigits(phoneNumber)); } public static boolean isUri(String uri) { if (isNotNull(uri)) { try { new URI(uri); return true; } catch (URISyntaxException urise) { } } return false; } /** * Returns <code>true</code> if the string is a valid URL based on the rules * in {@link URL}. * * @param url the string to check * @return <code>true</code> if the string is a valid URL; * <code>false</code> otherwise */ public static boolean isUrl(String url) { return isUrl(url, false); } /** * Returns <code>true</code> if the string is a valid URL based on the rules * in {@link URL}. This method can also validate root relative URLs. * * @param url the string to check * @param acceptRootRelative whether a root relative URL should be accepted * @return <code>true</code> if the string is a valid URL; * <code>false</code> otherwise */ public static boolean isUrl(String url, boolean acceptRootRelative) { if (isNotNull(url)) { if (acceptRootRelative && (url.charAt(0) == '/')) { return true; } if (url.indexOf(CharPool.COLON) == -1) { return false; } try { new URL(url); return true; } catch (MalformedURLException murle) { } } return false; } /** * Returns <code>true</code> if the string is a valid variable name in Java. * * @param variableName the string to check * @return <code>true</code> if the string is a valid variable name in Java; * <code>false</code> otherwise */ public static boolean isVariableName(String variableName) { if (isNull(variableName) || ArrayUtil.contains(_JAVA_KEYWORDS, variableName)) { return false; } Matcher matcher = _variableNamePattern.matcher(variableName); if (matcher.matches()) { return true; } else { return false; } } /** * Returns <code>true</code> if the string is a valid variable term, meaning * it begins with "[$" and ends with "$]". * * @param s the string to check * @return <code>true</code> if the string is a valid variable term; * <code>false</code> otherwise */ public static boolean isVariableTerm(String s) { if (s.startsWith(_VARIABLE_TERM_BEGIN) && s.endsWith(_VARIABLE_TERM_END)) { return true; } else { return false; } } /** * Returns <code>true</code> if the character is whitespace, meaning it is * either the <code>null</code> character '0' or whitespace according to * {@link java.lang.Character#isWhitespace(char)}. * * @param c the character to check * @return <code>true</code> if the character is whitespace; * <code>false</code> otherwise */ public static boolean isWhitespace(char c) { int i = c; if ((i == 0) || Character.isWhitespace(c)) { return true; } else { return false; } } /** * Returns <code>true</code> if the string is an XML document. The only * requirement is that it contain either the xml start tag "<?xml" or the * empty document tag "<root />". * * @param s the string to check * @return <code>true</code> if the string is an XML document; * <code>false</code> otherwise */ public static boolean isXml(String s) { if (isNull(s)) { return false; } else if (s.startsWith(_XML_BEGIN) || s.startsWith(_XML_EMPTY)) { return true; } else { return false; } } private static final String[] _BOOLEANS = {"false", "on", "off", "true"}; private static final int _CHAR_LOWER_CASE_BEGIN = 97; private static final int _CHAR_LOWER_CASE_END = 122; private static final int _CHAR_UPPER_CASE_BEGIN = 65; private static final int _CHAR_UPPER_CASE_END = 90; private static final int _DIGIT_BEGIN = 48; private static final int _DIGIT_END = 57; private static final char[] _EMAIL_ADDRESS_SPECIAL_CHAR = new char[] { '.', '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', '~' }; private static final String[] _JAVA_KEYWORDS = new String[] { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while" }; private static final String _VARIABLE_TERM_BEGIN = "[$"; private static final String _VARIABLE_TERM_END = "$]"; private static final String _XML_BEGIN = "<?xml"; private static final String _XML_EMPTY = "<root />"; private static final Pattern _emailAddressPattern = Pattern.compile( "[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@" + "(?:[a-zA-Z0-9](?:-*[a-zA-Z0-9])?\\.*)+"); private static final Pattern _ipv4AddressPattern; private static final Pattern _ipv6AddressPattern; private static final Pattern _variableNamePattern = Pattern.compile( "[_a-zA-Z]+[_a-zA-Z0-9]*"); static { StringBundler sb = new StringBundler(6); sb.append("^"); sb.append("(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\."); sb.append("(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\."); sb.append("(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\."); sb.append("(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"); sb.append("$"); _ipv4AddressPattern = Pattern.compile(sb.toString()); sb = new StringBundler(28); sb.append("^"); sb.append("\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|"); sb.append("(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|"); sb.append("((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)"); sb.append("(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|"); sb.append("(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:"); sb.append("((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)"); sb.append("(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|"); sb.append("(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|"); sb.append("((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]"); sb.append("?\\d)"); sb.append("(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"); sb.append("(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|"); sb.append("((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|"); sb.append("[1-9]?\\d)"); sb.append("(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"); sb.append("(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|"); sb.append("((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|"); sb.append("[1-9]?\\d)"); sb.append("(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"); sb.append("(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|"); sb.append("((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|"); sb.append("[1-9]?\\d)"); sb.append("(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"); sb.append("(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:"); sb.append("((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\."); sb.append("(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*"); sb.append("$"); _ipv6AddressPattern = Pattern.compile(sb.toString()); } }