/* * Copyright 2002-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.opentides.util; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; public class StringUtil { private static String zeros = "0000000000"; private static Random random = new Random((new Date()).getTime()); /** * Hide the constructor. */ private StringUtil() { } /** * Checks if a given string is empty or null. * * @param obj * @return */ public static boolean isEmpty(final String obj) { if ((obj==null) || (obj.trim().length()==0)) { return true; } else { return false; } } public static boolean compareNullableStrings(final String str1, final String str2) { if (str1 == null && str2 == null) { return true; } if (str1 == null && str2 != null) { return false; } if (str1 != null && str2 == null) { return false; } return str1.equals(str2); } /** * <p>Replaces all occurrences of a String within another String.</p> * * <p>A {@code null} reference passed to this method is a no-op.</p> * * <p>Copied from Apache Commons StringUtils. </p> * <pre> * StringUtils.replace(null, *, *) = null * StringUtils.replace("", *, *) = "" * StringUtils.replace("any", null, *) = "any" * StringUtils.replace("any", *, null) = "any" * StringUtils.replace("any", "", *) = "any" * StringUtils.replace("aba", "a", null) = "aba" * StringUtils.replace("aba", "a", "") = "b" * StringUtils.replace("aba", "a", "z") = "zbz" * </pre> * * @see #replace(String text, String searchString, String replacement, int max) * @param text text to search and replace in, may be null * @param searchString the String to search for, may be null * @param replacement the String to replace it with, may be null * @return the text with any replacements processed, * {@code null} if null String input */ public static String replace(final String text, final String searchString, final String replacement) { return replace(text, searchString, replacement, -1); } /** * <p>Replaces a String with another String inside a larger String, * for the first {@code max} values of the search String.</p> * * <p>A {@code null} reference passed to this method is a no-op.</p> * * <p>Copied from Apache Commons StringUtils. </p> * <pre> * StringUtils.replace(null, *, *, *) = null * StringUtils.replace("", *, *, *) = "" * StringUtils.replace("any", null, *, *) = "any" * StringUtils.replace("any", *, null, *) = "any" * StringUtils.replace("any", "", *, *) = "any" * StringUtils.replace("any", *, *, 0) = "any" * StringUtils.replace("abaa", "a", null, -1) = "abaa" * StringUtils.replace("abaa", "a", "", -1) = "b" * StringUtils.replace("abaa", "a", "z", 0) = "abaa" * StringUtils.replace("abaa", "a", "z", 1) = "zbaa" * StringUtils.replace("abaa", "a", "z", 2) = "zbza" * StringUtils.replace("abaa", "a", "z", -1) = "zbzz" * </pre> * * @param text text to search and replace in, may be null * @param searchString the String to search for, may be null * @param replacement the String to replace it with, may be null * @param max maximum number of values to replace, or {@code -1} if no maximum * @return the text with any replacements processed, * {@code null} if null String input */ public static String replace(final String text, final String searchString, final String replacement, int max) { if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) { return text; } int start = 0; int end = text.indexOf(searchString, start); if (end == -1) { return text; } final int replLength = searchString.length(); int increase = replacement.length() - replLength; increase = increase < 0 ? 0 : increase; increase *= max < 0 ? 16 : max > 64 ? 64 : max; final StringBuilder buf = new StringBuilder(text.length() + increase); while (end != -1) { buf.append(text.substring(start, end)).append(replacement); start = end + replLength; if (--max == 0) { break; } end = text.indexOf(searchString, start); } buf.append(text.substring(start)); return buf.toString(); } /** * Escapes special characters for HQL. * @param str * @param escapeForLike */ public static String escapeSql(String str, final boolean escapeForLike){ if (str == null) { return null; } else { str = StringUtil.replace(str, "'", "''"); if(escapeForLike) { //escape special characters for LIKE str = StringUtil.replace(str, "\\", "\\\\\\\\"); str = StringUtil.replace(str, "%", "\\%"); str = StringUtil.replace(str, "_", "\\_"); } else { //escape backslash for EQUALS (=) str = StringUtil.replace(str, "\\", "\\\\"); } } return str; } /** * Converts the given string in hex to a byte array. * * For example: * byte[] CDRIVES = convertHexToArray("e04fd020ea3a6910a2d808002b30309d"); * * @param s * @return */ public static byte[] convertHexToArray(final String s) { final int len = s.length(); final byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } return data; } /** * Converts the given number to a fixed length. * Note: max length is 10. * * @param value * @param length * @return */ public static String toFixedString(final int value, final int length) { final String val = Integer.toString(value); final int diff = length-val.length(); if (diff>0) { return (zeros.substring(10-diff)+val); } else { return val; } } /** * Removes HTML tags in an HTML string using regex. * * @param html * @return */ public static String removeHTMLTags(final String html) { return html.replaceAll("<(.*?)>"," ") .replaceAll("\\s+"," "); } /** * Converts the given string to int. * If string is not a number, defValue is used. * * @param str * @param defValue * @return */ public static int convertToInt(final String str, final int defValue) { int value = defValue; try { value = Integer.parseInt(str); } catch (final NumberFormatException nfe) { // do nothing... } return value; } /** * Converts the given string to long. * If string is not a number, defValue is used. * * @param str * @param defValue * @return */ public static long convertToLong(final String str, final long defValue) { long value = defValue; try { value = Long.parseLong(str); } catch (final NumberFormatException nfe) { // do nothing... } return value; } /** * Converts the given string to double. * If string is not a number, defValue is used. * * @param str * @param defValue * @return */ public static double convertToDouble(final String str, final double defValue){ double doub = defValue; try { doub = Double.parseDouble(str); } catch (final NumberFormatException nfe) { // do nothing... } return doub; } public static Float convertToFloat(final String str, final Float defValue) { Float value = null; try { value = Float.parseFloat(str); } catch (final NumberFormatException nfe) { // do nothing... } return value; } /** * generates an alphanumeric string based on specified length. * @param length # of characters to generate * @return random string */ public static String generateRandomString(final int length) { final char[] values = {'a','b','c','d','e','f','g','h','i','j', 'k','l','m','n','o','p','q','r','s','t', 'u','v','w','x','y','z','0','1','2','3', '4','5','6','7','8','9','A','B','C','D', 'E','F','G','H','I','J','K','L','M','N', 'O','P','Q','R','S','T','U','V','W','X', 'Y','Z'}; String out = ""; for (int i=0;i<length;i++) { final int idx=random.nextInt(values.length); out += values[idx]; } return out; } /** * Encrypt password by using SHA-256 algorithm, encryptedPassword length is 32 bits * @param clearTextPassword * @return * @throws NoSuchAlgorithmException * reference http://java.sun.com/j2se/1.4.2/docs/api/java/security/MessageDigest.html */ @SuppressWarnings("restriction") public static String getEncryptedPassword(final String clearTextPassword) throws NoSuchAlgorithmException { // handler for empty string if (StringUtil.isEmpty(clearTextPassword)) { return""; } final MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(clearTextPassword.getBytes()); return new sun.misc.BASE64Encoder().encode(md.digest()); } /** * Encrypts the string along with salt * @param userId * @return * @throws Exception */ @SuppressWarnings("restriction") public static String encrypt(final String userId) { final sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder(); // let's create some dummy salt final byte[] salt = new byte[8]; random.nextBytes(salt); return encoder.encode(salt)+ encoder.encode(userId.getBytes()); } /** * Decrypts the string and removes the salt * @param encryptKey * @return * @throws Exception */ @SuppressWarnings("restriction") public static String decrypt(final String encryptKey) throws Exception { // let's ignore the salt if (!StringUtil.isEmpty(encryptKey) && encryptKey.length() > 12) { final String cipher = encryptKey.substring(12); final sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder(); try { return new String(decoder.decodeBuffer(cipher)); } catch (final IOException e) { throw new Exception( "Failed to perform decryption for key ["+encryptKey+"]",e); } } else { return null; } } /** * Parse a line of text in standard CSV format and returns array of Strings * @param csvLine * @return */ public static List<String> parseCsvLine(final String csvLine) { return StringUtil.parseCsvLine(csvLine, ',', '"', '\\', false); } /** * Parse a line of text in CSV format and returns array of Strings * Implementation of parsing is extracted from open-csv. * http://opencsv.sourceforge.net/ * * @param csvLine * @param separator * @param quotechar * @param escape * @param strictQuotes * @return * @throws IOException */ public static List<String> parseCsvLine(final String csvLine, final char separator, final char quotechar, final char escape, final boolean strictQuotes) { final List<String>tokensOnThisLine = new ArrayList<String>(); StringBuilder sb = new StringBuilder(50); boolean inQuotes = false; for (int i = 0; i < csvLine.length(); i++) { final char c = csvLine.charAt(i); if (c == escape) { final boolean isNextCharEscapable = inQuotes // we are in quotes, therefore there can be escaped quotes in here. && csvLine.length() > (i+1) // there is indeed another character to check. && ( csvLine.charAt(i+1) == quotechar || csvLine.charAt(i+1) == escape); if( isNextCharEscapable ){ sb.append(csvLine.charAt(i+1)); i++; } } else if (c == quotechar) { final boolean isNextCharEscapedQuote = inQuotes // we are in quotes, therefore there can be escaped quotes in here. && csvLine.length() > (i+1) // there is indeed another character to check. && csvLine.charAt(i+1) == quotechar; if( isNextCharEscapedQuote ){ sb.append(csvLine.charAt(i+1)); i++; }else{ inQuotes = !inQuotes; // the tricky case of an embedded quote in the middle: a,bc"d"ef,g if (!strictQuotes) { if(i>2 //not on the beginning of the line && csvLine.charAt(i-1) != separator //not at the beginning of an escape sequence && csvLine.length()>(i+1) && csvLine.charAt(i+1) != separator //not at the end of an escape sequence ){ sb.append(c); } } } } else if (c == separator && !inQuotes) { tokensOnThisLine.add(sb.toString()); sb = new StringBuilder(50); // start work on next token } else { if (!strictQuotes || inQuotes) { sb.append(c); } } } // line is done - check status if (inQuotes) { // _log.warn("Un-terminated quoted field at end of CSV line. \n ["+csvLine+"]"); } if (sb != null) { tokensOnThisLine.add(sb.toString()); } return tokensOnThisLine; } /** * Combines an array of string into one string using the specified separator. * @param separator * @param input * @return */ public static final String explode(final char separator, final String[] input) { if (input==null) { return null; } int count=0; final StringBuilder out = new StringBuilder(); for (final String word:input) { if (count++ > 0) { out.append(separator); } out.append(word); } return out.toString(); } /** * Splits the string with the givek */ public static final String[] splitSafe(String word, String regex) { if (word == null) return null; if (StringUtil.isEmpty(regex)) return new String[] {word}; String[] ret = word.split(regex); if (ret.length==0) return new String[] {word}; else return ret; } }