package com.voxeo.moho.common.util;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
/**
* A collection of String utilities.
*/
public final class StringUtils {
/** An empty string constant */
public static final String EMPTY = "";
public static final String SINGLE_QUOTE = "\'";
public static final String DOUBLE_QUOTE = "\"";
/** Millisecond conversion constants */
private static final long MSEC = 1;
private static final long SECS = 1000;
private static final long MINS = 60 * 1000;
private static final long HOUR = 60 * 60 * 1000;
private static final char SLASH_CHAR = '/';
private static final char BACKSLASH_CHAR = '\\';
private static final String FILE_SEPARATOR = File.separator;
private static final String PATH_SEPARATOR = File.pathSeparator;
private static final String FILE_SEPARATOR_ALIAS = "/";
private static final String PATH_SEPARATOR_ALIAS = ":";
private static final int NORMAL = 0;
private static final int SEEN_DOLLAR = 1;
private static final int IN_BRACKET = 2;
public static String[] addStringToArray(final String[] array, final String str) {
if (Checker.isEmpty(array)) {
return new String[] {str};
}
final String[] newArr = new String[array.length + 1];
System.arraycopy(array, 0, newArr, 0, array.length);
newArr[array.length] = str;
return newArr;
}
public static String[] concatenateStringArrays(final String[] array1, final String[] array2) {
if (Checker.isEmpty(array1)) {
return array2;
}
if (Checker.isEmpty(array2)) {
return array1;
}
final String[] newArr = new String[array1.length + array2.length];
System.arraycopy(array1, 0, newArr, 0, array1.length);
System.arraycopy(array2, 0, newArr, array1.length, array2.length);
return newArr;
}
public static String[] mergeStringArrays(final String[] array1, final String[] array2) {
if (Checker.isEmpty(array1)) {
return array2;
}
if (Checker.isEmpty(array2)) {
return array1;
}
final List<String> result = new ArrayList<String>();
result.addAll(Arrays.asList(array1));
for (int i = 0; i < array2.length; ++i) {
final String str = array2[i];
if (!result.contains(str)) {
result.add(str);
}
}
return toStringArray(result);
}
public static String[] removeDuplicateStrings(final String[] array) {
if (Checker.isEmpty(array)) {
return array;
}
final Set<String> set = new TreeSet<String>();
for (int i = 0; i < array.length; ++i) {
set.add(array[i]);
}
return toStringArray(set);
}
public static String[] sortStringArray(final String[] array) {
if (Checker.isEmpty(array)) {
return new String[0];
}
Arrays.sort(array);
return array;
}
public static boolean isUpperCase(final String s) {
if (Checker.isEmpty(s)) {
return false;
}
for (int i = 0; i < s.length(); i++) {
if (Character.isLowerCase(s.charAt(i))) {
return false;
}
}
return true;
}
public static String capitalize(final String str) {
return changeFirstCharacterCase(str, true);
}
public static String uncapitalize(final String str) {
return changeFirstCharacterCase(str, false);
}
private static String changeFirstCharacterCase(final String str, final boolean capitalize) {
if (str == null || str.length() == 0) {
return str;
}
final StringBuffer buf = new StringBuffer(str.length());
if (capitalize) {
buf.append(Character.toUpperCase(str.charAt(0)));
}
else {
buf.append(Character.toLowerCase(str.charAt(0)));
}
buf.append(str.substring(1));
return buf.toString();
}
public static int select(final String line, final int index) {
try {
final int i = Integer.parseInt(line);
if (i >= 0 && i < index) {
return i;
}
else {
return -1;
}
}
catch (final Exception e) {
return -1;
}
}
// ///////////////////////////////////////////////////////////////////////
// Substitution Methods //
// ///////////////////////////////////////////////////////////////////////
/**
* Substitute sub-strings in side of a string.
*
* @param buff
* Stirng buffer to use for substitution (buffer is not reset)
* @param from
* String to substitute from
* @param to
* String to substitute to
* @param string
* String to look for from in
* @return Substituted string
*/
public static String subst(final StringBuffer buff, final String from, final String to, final String string) {
int begin = 0, end = 0;
while ((end = string.indexOf(from, end)) != -1) {
// append the first part of the string
buff.append(string.substring(begin, end));
// append the replaced string
buff.append(to);
// update positions
begin = end + from.length();
end = begin;
}
// append the rest of the string
buff.append(string.substring(begin, string.length()));
return buff.toString();
}
/**
* Substitute sub-strings in side of a string.
*
* @param from
* String to substitute from
* @param to
* String to substitute to
* @param string
* String to look for from in
* @return Substituted string
*/
public static String subst(final String from, final String to, final String string) {
return subst(new StringBuffer(), from, to, string);
}
/**
* Substitute sub-strings in side of a string.
*
* @param buff
* String buffer to use for substitution (buffer is not reset)
* @param string
* String to subst mappings in
* @param map
* Map of from->to strings
* @param beginToken
* Beginning token
* @param endToken
* Ending token
* @return Substituted string
*/
public static String subst(final StringBuffer buff, final String string, final Map map, final String beginToken,
final String endToken) {
int begin = 0, rangeEnd = 0;
Range range;
while ((range = rangeOf(beginToken, endToken, string, rangeEnd)) != null) {
// append the first part of the string
buff.append(string.substring(begin, range.begin));
// Get the string to replace from the map
final String key = string.substring(range.begin + beginToken.length(), range.end);
Object value = map.get(key);
// if mapping does not exist then use empty;
if (value == null) {
value = EMPTY;
}
// append the replaced string
buff.append(value);
// update positions
begin = range.end + endToken.length();
rangeEnd = begin;
}
// append the rest of the string
buff.append(string.substring(begin, string.length()));
return buff.toString();
}
/**
* Substitute sub-strings in side of a string.
*
* @param string
* String to subst mappings in
* @param map
* Map of from->to strings
* @param beginToken
* Beginning token
* @param endToken
* Ending token
* @return Substituted string
*/
public static String subst(final String string, final Map map, final String beginToken, final String endToken) {
return subst(new StringBuffer(), string, map, beginToken, endToken);
}
/**
* Substitute index identifiers with the replacement value from the given
* array for the corresponding index.
*
* @param buff
* The string buffer used for the substitution (buffer is not reset).
* @param string
* String substitution format.
* @param replace
* Array of strings whose values will be used as replacements in the
* given string when a token with their index is found.
* @param token
* The character token to specify the start of an index reference.
* @return Substituted string.
*/
public static String subst(final StringBuffer buff, final String string, final String replace[], final char token) {
final int i = string.length();
for (int j = 0; j >= 0 && j < i; j++) {
final char c = string.charAt(j);
// if the char is the token, then get the index
if (c == token) {
// if we aren't at the end of the string, get the index
if (j != i) {
final int k = Character.digit(string.charAt(j + 1), 10);
if (k == -1) {
buff.append(string.charAt(j + 1));
}
else if (k < replace.length) {
buff.append(replace[k]);
}
j++;
}
}
else {
buff.append(c);
}
}
return buff.toString();
}
/**
* Substitute index identifiers with the replacement value from the given
* array for the corresponding index.
*
* @param string
* String substitution format.
* @param replace
* Array of strings whose values will be used as replacements in the
* given string when a token with their index is found.
* @param token
* The character token to specify the start of an index reference.
* @return Substituted string.
*/
public static String subst(final String string, final String replace[], final char token) {
return subst(new StringBuffer(), string, replace, token);
}
/**
* Substitute index identifiers (with <code>%</code> for the index token) with
* the replacement value from the given array for the corresponding index.
*
* @param string
* String substitution format.
* @param replace
* Array of strings whose values will be used as replacements in the
* given string when a token with their index is found.
* @return Substituted string.
*/
public static String subst(final String string, final String replace[]) {
return subst(new StringBuffer(), string, replace, '%');
}
// ///////////////////////////////////////////////////////////////////////
// Range Methods //
// ///////////////////////////////////////////////////////////////////////
/**
* Represents a range between two integers.
*/
public static class Range {
/** The beginning of the range. */
public int begin;
/** The end of the range. */
public int end;
/**
* Construct a new range.
*
* @param begin
* The beginning of the range.
* @param end
* The end of the range.
*/
public Range(final int begin, final int end) {
this.begin = begin;
this.end = end;
}
/**
* Default constructor.
*/
public Range() {
}
}
/**
* Return the range from a begining token to an ending token.
*
* @param beginToken
* String to indicate begining of range.
* @param endToken
* String to indicate ending of range.
* @param string
* String to look for range in.
* @param fromIndex
* Beginning index.
* @return (begin index, end index) or <i>null</i>.
*/
public static Range rangeOf(final String beginToken, final String endToken, final String string, final int fromIndex) {
final int begin = string.indexOf(beginToken, fromIndex);
if (begin != -1) {
final int end = string.indexOf(endToken, begin + 1);
if (end != -1) {
return new Range(begin, end);
}
}
return null;
}
/**
* Return the range from a begining token to an ending token.
*
* @param beginToken
* String to indicate begining of range.
* @param endToken
* String to indicate ending of range.
* @param string
* String to look for range in.
* @return (begin index, end index) or <i>null</i>.
*/
public static Range rangeOf(final String beginToken, final String endToken, final String string) {
return rangeOf(beginToken, endToken, string, 0);
}
public static String[] split(final String string, final String delim, final int limit) {
// get the count of delim in string, if count is > limit
// then use limit for count. The number of delimiters is less by one
// than the number of elements, so add one to count.
int count = count(string, delim) + 1;
if (limit > 0 && count > limit) {
count = limit;
}
final String strings[] = new String[count];
int begin = 0;
for (int i = 0; i < count; i++) {
// get the next index of delim
int end = string.indexOf(delim, begin);
// if the end index is -1 or if this is the last element
// then use the string's length for the end index
if (end == -1 || i + 1 == count) {
end = string.length();
}
// if end is 0, then the first element is empty
if (end == 0) {
strings[i] = EMPTY;
}
else {
strings[i] = string.substring(begin, end);
}
// update the begining index
begin = end + 1;
}
return strings;
}
public static String[] split(final String string, final String delim) {
return split(string, delim, -1);
}
public static List<String> splitToList(final String string, final String delim, final int limit) {
// get the count of delim in string, if count is > limit
// then use limit for count. The number of delimiters is less by one
// than the number of elements, so add one to count.
int count = count(string, delim) + 1;
if (limit > 0 && count > limit) {
count = limit;
}
final List<String> strings = new ArrayList<String>(count);
int begin = 0;
for (int i = 0; i < count; i++) {
// get the next index of delim
int end = string.indexOf(delim, begin);
// if the end index is -1 or if this is the last element
// then use the string's length for the end index
if (end == -1 || i + 1 == count) {
end = string.length();
}
// if end is 0, then the first element is empty
if (end == 0) {
strings.add(EMPTY);
}
else {
strings.add(string.substring(begin, end));
}
// update the begining index
begin = end + 1;
}
return strings;
}
public static List<String> splitToList(final String string, final String delim) {
return splitToList(string, delim, -1);
}
// ///////////////////////////////////////////////////////////////////////
// Joining/Concatenation Methods //
// ///////////////////////////////////////////////////////////////////////
/**
* Join an array of strings into one delimited string.
*
* @param buff
* String buffered used for join (buffer is not reset).
* @param array
* Array of objects to join as strings.
* @param delim
* Delimiter to join strings with or <i>null</i>.
* @return Joined string.
*/
public static String join(final StringBuffer buff, final Object array[], final String delim) {
final boolean haveDelim = delim != null;
for (int i = 0; i < array.length; i++) {
if (array[i] != null) {
buff.append(array[i]);
}
// if this is the last element then don't append delim
if (haveDelim && i + 1 < array.length) {
buff.append(delim);
}
}
return buff.toString();
}
/**
* Join an array of strings into one delimited string.
*
* @param array
* Array of objects to join as strings.
* @param delim
* Delimiter to join strings with or <i>null</i>.
* @return Joined string.
*/
public static String join(final Object array[], final String delim) {
return join(new StringBuffer(), array, delim);
}
/**
* Convert and join an array of objects into one string.
*
* @param array
* Array of objects to join as strings.
* @return Converted and joined objects.
*/
public static String join(final Object array[]) {
return join(array, null);
}
/**
* Convert and join an array of bytes into one string.
*
* @param array
* Array of objects to join as strings.
* @return Converted and joined objects.
*/
public static String join(final byte array[]) {
final Byte bytes[] = new Byte[array.length];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = new Byte(array[i]);
}
return join(bytes, null);
}
/**
* Return a string composed of the given array.
*
* @param buff
* Buffer used to construct string value (not reset).
* @param array
* Array of objects.
* @param prefix
* String prefix.
* @param separator
* Element sepearator.
* @param suffix
* String suffix.
* @return String in the format of: prefix + n ( + separator + n+i)* + suffix.
*/
public static String join(final StringBuffer buff, final Object[] array, final String prefix, final String separator,
final String suffix) {
buff.append(prefix);
join(buff, array, separator);
buff.append(suffix);
return buff.toString();
}
/**
* Return a string composed of the given array.
*
* @param array
* Array of objects.
* @param prefix
* String prefix.
* @param separator
* Element sepearator.
* @param suffix
* String suffix.
* @return String in the format of: prefix + n ( + separator + n+i)* + suffix.
*/
public static String join(final Object[] array, final String prefix, final String separator, final String suffix) {
return join(new StringBuffer(), array, prefix, separator, suffix);
}
// ///////////////////////////////////////////////////////////////////////
// Counting Methods //
// ///////////////////////////////////////////////////////////////////////
/**
* Count the number of instances of substring within a string.
*
* @param string
* String to look for substring in.
* @param substring
* Sub-string to look for.
* @return Count of substrings in string.
*/
public static int count(final String string, final String substring) {
int count = 0;
int idx = 0;
while ((idx = string.indexOf(substring, idx)) != -1) {
idx++;
count++;
}
return count;
}
/**
* Count the number of instances of character within a string.
*
* @param string
* String to look for substring in.
* @param c
* Character to look for.
* @return Count of substrings in string.
*/
public static int count(final String string, final char c) {
return count(string, String.valueOf(c));
}
// ///////////////////////////////////////////////////////////////////////
// Padding Methods //
// ///////////////////////////////////////////////////////////////////////
/**
* Return a string padded with the given string for the given count.
*
* @param buff
* String buffer used for padding (buffer is not reset).
* @param string
* Pad element.
* @param count
* Pad count.
* @return Padded string.
*/
public static String pad(final StringBuffer buff, final String string, final int count) {
for (int i = 0; i < count; i++) {
buff.append(string);
}
return buff.toString();
}
/**
* Return a string padded with the given string for the given count.
*
* @param string
* Pad element.
* @param count
* Pad count.
* @return Padded string.
*/
public static String pad(final String string, final int count) {
return pad(new StringBuffer(), string, count);
}
/**
* Return a string padded with the given string value of an object for the
* given count.
*
* @param obj
* Object to convert to a string.
* @param count
* Pad count.
* @return Padded string.
*/
public static String pad(final Object obj, final int count) {
return pad(new StringBuffer(), String.valueOf(obj), count);
}
// ///////////////////////////////////////////////////////////////////////
// Misc Methods //
// ///////////////////////////////////////////////////////////////////////
/**
* <p>
* Compare two strings.
* <p>
* Both or one of them may be null.
*
* @return true if object equals or intern ==, else false.
*/
public static boolean compare(final String me, final String you) {
// If both null or intern equals
if (me == you) {
return true;
}
// if me null and you are not
if (me == null && you != null) {
return false;
}
// me will not be null, test for equality
return me.equals(you);
}
/**
* Check if the given string is empty.
*
* @param string
* String to check
* @return True if string is empty
*/
public static boolean isEmpty(final String string) {
if (string == null || string.trim().length() == 0 || string.equals(EMPTY)) {
return true;
}
return false;
}
/**
* Return the <i>nth</i> index of the given token occurring in the given
* string.
*
* @param string
* String to search.
* @param token
* Token to match.
* @param index
* <i>Nth</i> index.
* @return Index of <i>nth</i> item or -1.
*/
public static int nthIndexOf(final String string, final String token, final int index) {
int j = 0;
for (int i = 0; i < index; i++) {
j = string.indexOf(token, j + 1);
if (j == -1) {
break;
}
}
return j;
}
/**
* Parses a time period into a long. Translates possible [msec|sec|min|h]
* suffixes For example: "1" -> 1 (msec) "1msec -> 1 (msec) "1sec" -> 1000
* (msecs) "1min" -> 60000 (msecs) "1h" -> 3600000 (msecs) Accepts negative
* periods, e.g. "-1"
*
* @param period
* the stringfied time period
* @return the parsed time period as long
* @throws NumberFormatException
*/
public static long parseTimePeriod(final String period) {
try {
String s = period.toLowerCase();
long factor;
// look for suffix
if (s.endsWith("msec")) {
s = s.substring(0, s.lastIndexOf("msec"));
factor = MSEC;
}
else if (s.endsWith("sec")) {
s = s.substring(0, s.lastIndexOf("sec"));
factor = SECS;
}
else if (s.endsWith("min")) {
s = s.substring(0, s.lastIndexOf("min"));
factor = MINS;
}
else if (s.endsWith("h")) {
s = s.substring(0, s.lastIndexOf("h"));
factor = HOUR;
}
else {
factor = 1;
}
return Long.parseLong(s) * factor;
}
catch (final RuntimeException e) {
// thrown in addition when period is 'null'
throw new NumberFormatException("For input time period: '" + period + "'");
}
}
/**
* Same like parseTimePeriod(), but guards for negative entries.
*
* @param period
* the stringfied time period
* @return the parsed time period as long
* @throws NumberFormatException
*/
public static long parsePositiveTimePeriod(final String period) {
final long retval = parseTimePeriod(period);
if (retval < 0) {
throw new NumberFormatException("Negative input time period: '" + period + "'");
}
return retval;
}
public static String[] trim(final String[] strings) {
for (int i = 0; i < strings.length; i++) {
strings[i] = strings[i].trim();
}
return strings;
}
public static String trim(final String str) {
if (isEmpty(str)) {
return str;
}
final StringBuffer buf = new StringBuffer(str);
while (buf.length() > 0 && Character.isWhitespace(buf.charAt(0))) {
buf.deleteCharAt(0);
}
while (buf.length() > 0 && Character.isWhitespace(buf.charAt(buf.length() - 1))) {
buf.deleteCharAt(buf.length() - 1);
}
return buf.toString();
}
public static String trimLeading(final String s) {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != ' ' && s.charAt(i) != '\t') {
return s.substring(i);
}
}
return "";
}
public static String trimLeading(final String s, final String prefix) {
if (s.startsWith(prefix)) {
return s.substring(prefix.length());
}
return s;
}
public static String trimTrailing(final String str) {
if (isEmpty(str)) {
return str;
}
final StringBuffer buf = new StringBuffer(str);
while (buf.length() > 0 && Character.isWhitespace(buf.charAt(buf.length() - 1))) {
buf.deleteCharAt(buf.length() - 1);
}
return buf.toString();
}
public static String trimLeadingCharacter(final String str, final char leadingCharacter) {
if (isEmpty(str)) {
return str;
}
final StringBuffer buf = new StringBuffer(str);
while (buf.length() > 0 && buf.charAt(0) == leadingCharacter) {
buf.deleteCharAt(0);
}
return buf.toString();
}
public static String trimTrailingCharacter(final String str, final char trailingCharacter) {
if (isEmpty(str)) {
return str;
}
final StringBuffer buf = new StringBuffer(str);
while (buf.length() > 0 && buf.charAt(buf.length() - 1) == trailingCharacter) {
buf.deleteCharAt(buf.length() - 1);
}
return buf.toString();
}
public static String[] trimArrayElements(final String[] array) {
if (Checker.isEmpty(array)) {
return new String[0];
}
final String[] result = new String[array.length];
for (int i = 0; i < array.length; ++i) {
final String element = array[i];
result[i] = element != null ? element.trim() : null;
}
return result;
}
public static String removeWhiteSpace(final String s) {
String retn = null;
if (s != null) {
final int len = s.length();
final StringBuffer sbuf = new StringBuffer(len);
for (int i = 0; i < len; i++) {
final char c = s.charAt(i);
if (!Character.isWhitespace(c)) {
sbuf.append(c);
}
}
retn = sbuf.toString();
}
return retn;
}
public static StringBuffer stringSubstitution(final String argStr, final Map vars, final boolean isLenient) {
final StringBuffer argBuf = new StringBuffer();
if (argStr == null || argStr.length() == 0) {
return argBuf;
}
if (vars == null || vars.size() == 0) {
return argBuf.append(argStr);
}
final int argStrLength = argStr.length();
for (int cIdx = 0; cIdx < argStrLength;) {
char ch = argStr.charAt(cIdx);
char del = ' ';
switch (ch) {
case '$':
final StringBuffer nameBuf = new StringBuffer();
del = argStr.charAt(cIdx + 1);
if (del == '{') {
cIdx++;
for (++cIdx; cIdx < argStr.length(); ++cIdx) {
ch = argStr.charAt(cIdx);
if (ch == '_' || ch == '.' || ch == '-' || ch == '+' || Character.isLetterOrDigit(ch)) {
nameBuf.append(ch);
}
else {
break;
}
}
if (nameBuf.length() > 0) {
final Object temp = vars.get(nameBuf.toString());
final String value = temp != null ? temp.toString() : null;
if (value != null) {
argBuf.append(value);
}
else {
if (isLenient) {
// just append the unresolved variable declaration
argBuf.append("${").append(nameBuf.toString()).append("}");
}
else {
// complain that no variable was found
throw new RuntimeException("No value found for : " + nameBuf);
}
}
del = argStr.charAt(cIdx);
if (del != '}') {
throw new RuntimeException("Delimiter not found for : " + nameBuf);
}
}
cIdx++;
}
else {
argBuf.append(ch);
++cIdx;
}
break;
default:
argBuf.append(ch);
++cIdx;
break;
}
}
return argBuf;
}
public static String fixFileSeparatorChar(final String arg) {
return arg.replace(SLASH_CHAR, File.separatorChar).replace(BACKSLASH_CHAR, File.separatorChar);
}
public static String processQuotedString(final String quoted) {
final StringBuffer buf = new StringBuffer();
final int len = quoted.length();
for (int index = 1; index <= len - 2; index++) {
final char c = quoted.charAt(index);
if (c != '\\') {
buf.append(c);
}
}
return buf.toString();
}
public static String quote(final String str) {
return str != null ? "'" + str + "'" : null;
}
public static String unqualify(final String qualifiedName) {
return unqualify(qualifiedName, '.');
}
public static String unqualify(final String qualifiedName, final char separator) {
return qualifiedName.substring(qualifiedName.lastIndexOf(separator) + 1);
}
public static boolean startsWithIgnoreCase(final String str, final String prefix) {
if (str == null || prefix == null) {
return false;
}
if (str.startsWith(prefix)) {
return true;
}
if (str.length() < prefix.length()) {
return false;
}
final String lcStr = str.substring(0, prefix.length()).toLowerCase();
final String lcPrefix = prefix.toLowerCase();
return lcStr.equals(lcPrefix);
}
public static boolean endsWithIgnoreCase(final String str, final String suffix) {
if (str == null || suffix == null) {
return false;
}
if (str.endsWith(suffix)) {
return true;
}
if (str.length() < suffix.length()) {
return false;
}
final String lcStr = str.substring(str.length() - suffix.length()).toLowerCase();
final String lcSuffix = suffix.toLowerCase();
return lcStr.equals(lcSuffix);
}
public static boolean containsWithIgnoreCase(final String base, final String string) {
return base.toLowerCase().contains(string.toLowerCase());
}
public static boolean containsWhitespace(final String str) {
if (isEmpty(str)) {
return false;
}
final int strLen = str.length();
for (int i = 0; i < strLen; ++i) {
if (Character.isWhitespace(str.charAt(i))) {
return true;
}
}
return false;
}
public static String replace(final String inString, final String oldPattern, final String newPattern) {
if (isEmpty(inString) || isEmpty(oldPattern) || newPattern == null) {
return inString;
}
final StringBuffer sbuf = new StringBuffer();
int pos = 0;
int index = inString.indexOf(oldPattern);
final int patLen = oldPattern.length();
while (index >= 0) {
sbuf.append(inString.substring(pos, index));
sbuf.append(newPattern);
pos = index + patLen;
index = inString.indexOf(oldPattern, pos);
}
sbuf.append(inString.substring(pos));
return sbuf.toString();
}
public static String delete(final String inString, final String pattern) {
return replace(inString, pattern, "");
}
public static String replaceProperties(final String string) {
return replaceProperties(string, (Properties) null);
}
public static String replaceProperties(final String string, final Properties props) {
if (string == null) {
return string;
}
final char[] chars = string.toCharArray();
final StringBuffer buffer = new StringBuffer();
boolean properties = false;
int state = NORMAL;
int start = 0;
for (int i = 0; i < chars.length; ++i) {
final char c = chars[i];
// Dollar sign outside brackets
if (c == '$' && state != IN_BRACKET) {
state = SEEN_DOLLAR;
}
else if (c == '{' && state == SEEN_DOLLAR) {
buffer.append(string.substring(start, i - 1));
state = IN_BRACKET;
start = i - 1;
}
// No open bracket after dollar
else if (state == SEEN_DOLLAR) {
state = NORMAL;
}
else if (c == '}' && state == IN_BRACKET) {
// No content
if (start + 2 == i) {
buffer.append("${}"); // REVIEW: Correct?
}
else { // Collect the system property
String value = null;
final String key = string.substring(start + 2, i);
// check for alias
if (FILE_SEPARATOR_ALIAS.equals(key)) {
value = FILE_SEPARATOR;
}
else if (PATH_SEPARATOR_ALIAS.equals(key)) {
value = PATH_SEPARATOR;
}
else {
// check from the properties
if (props != null) {
value = props.getProperty(key);
}
else {
value = System.getProperty(key);
}
if (value == null) {
// Check for a default value ${key:default}
final int colon = key.indexOf(':');
if (colon > 0) {
final String realKey = key.substring(0, colon);
if (props != null) {
value = props.getProperty(realKey);
}
else {
value = System.getProperty(realKey);
}
if (value == null) {
// Check for a composite key, "key1,key2"
value = resolveCompositeKey(realKey, props);
// Not a composite key either, use the specified default
if (value == null) {
value = key.substring(colon + 1);
}
}
}
else {
// No default, check for a composite key, "key1,key2"
value = resolveCompositeKey(key, props);
}
}
}
if (value != null) {
properties = true;
buffer.append(value);
}
}
start = i + 1;
state = NORMAL;
}
}
// No properties
if (properties == false) {
return string;
}
// Collect the trailing characters
if (start != chars.length) {
buffer.append(string.substring(start, chars.length));
}
// Done
return buffer.toString();
}
public static String replaceProperties(final String string, final Map<String, Object> props) {
if (string == null) {
return string;
}
final char[] chars = string.toCharArray();
final StringBuffer buffer = new StringBuffer();
boolean properties = false;
int state = NORMAL;
int start = 0;
for (int i = 0; i < chars.length; ++i) {
final char c = chars[i];
// Dollar sign outside brackets
if (c == '$' && state != IN_BRACKET) {
state = SEEN_DOLLAR;
}
else if (c == '{' && state == SEEN_DOLLAR) {
buffer.append(string.substring(start, i - 1));
state = IN_BRACKET;
start = i - 1;
}
// No open bracket after dollar
else if (state == SEEN_DOLLAR) {
state = NORMAL;
}
else if (c == '}' && state == IN_BRACKET) {
// No content
if (start + 2 == i) {
buffer.append("${}"); // REVIEW: Correct?
}
else { // Collect the system property
String value = null;
final String key = string.substring(start + 2, i);
// check for alias
if (FILE_SEPARATOR_ALIAS.equals(key)) {
value = FILE_SEPARATOR;
}
else if (PATH_SEPARATOR_ALIAS.equals(key)) {
value = PATH_SEPARATOR;
}
else {
// check from the properties
if (props != null) {
Object o = props.get(key);
if (o instanceof Callable) {
try {
o = ((Callable) o).call();
}
catch (final Exception e) {
;
}
}
if (o != null) {
value = String.valueOf(o);
}
}
else {
value = System.getProperty(key);
}
if (value == null) {
// Check for a default value ${key:default}
final int colon = key.indexOf(':');
if (colon > 0) {
final String realKey = key.substring(0, colon);
if (props != null) {
Object o = props.get(realKey);
if (o instanceof Callable) {
try {
o = ((Callable) o).call();
}
catch (final Exception e) {
;
}
}
if (o != null) {
value = String.valueOf(o);
}
}
else {
value = System.getProperty(realKey);
}
if (value == null) {
value = resolveCompositeKey(realKey, props);
if (value == null) {
value = key.substring(colon + 1);
}
}
}
else {
// No default, check for a composite key, "key1,key2"
value = resolveCompositeKey(key, props);
}
}
}
if (value != null) {
properties = true;
buffer.append(value);
}
}
start = i + 1;
state = NORMAL;
}
}
// No properties
if (properties == false) {
return string;
}
// Collect the trailing characters
if (start != chars.length) {
buffer.append(string.substring(start, chars.length));
}
// Done
return buffer.toString();
}
private static String resolveCompositeKey(final String key, final Properties props) {
String value = null;
// Look for the comma
final int comma = key.indexOf(',');
if (comma > -1) {
// If we have a first part, try resolve it
if (comma > 0) {
// Check the first part
final String key1 = key.substring(0, comma);
if (props != null) {
value = props.getProperty(key1);
}
else {
value = System.getProperty(key1);
}
}
// Check the second part, if there is one and first lookup failed
if (value == null && comma < key.length() - 1) {
final String key2 = key.substring(comma + 1);
if (props != null) {
value = props.getProperty(key2);
}
else {
value = System.getProperty(key2);
}
}
}
// Return whatever we've found or null
return value;
}
private static String resolveCompositeKey(final String key, final Map<String, Object> props) {
String value = null;
// Look for the comma
final int comma = key.indexOf(',');
if (comma > -1) {
// If we have a first part, try resolve it
if (comma > 0) {
// Check the first part
final String key1 = key.substring(0, comma);
if (props != null) {
Object o = props.get(key1);
if (o instanceof Callable) {
try {
o = ((Callable) o).call();
}
catch (final Exception e) {
;
}
}
if (o != null) {
value = String.valueOf(o);
}
}
else {
value = System.getProperty(key1);
}
}
// Check the second part, if there is one and first lookup failed
if (value == null && comma < key.length() - 1) {
final String key2 = key.substring(comma + 1);
if (props != null) {
Object o = props.get(key2);
if (o instanceof Callable) {
try {
o = ((Callable) o).call();
}
catch (final Exception e) {
;
}
}
if (o != null) {
value = String.valueOf(o);
}
}
else {
value = System.getProperty(key2);
}
}
}
// Return whatever we've found or null
return value;
}
public static boolean toBoolean(final String s) {
return "true".equalsIgnoreCase(s) || "1".equalsIgnoreCase(s) || "on".equalsIgnoreCase(s)
|| "enable".equalsIgnoreCase(s) || "yes".equalsIgnoreCase(s);
}
public static URL toURL(String urlspec, final String relativePrefix) throws MalformedURLException {
urlspec = urlspec.trim();
URL url;
try {
url = new URL(urlspec);
if (url.getProtocol().equals("file")) {
url = makeURLFromFilespec(url.getFile(), relativePrefix);
}
}
catch (final Exception e) {
// make sure we have a absolute & canonical file url
try {
url = makeURLFromFilespec(urlspec, relativePrefix);
}
catch (final IOException n) {
//
// jason: or should we rethrow e?
//
throw new MalformedURLException(n.toString());
}
}
return url;
}
public static URI toURI(String urispec, final String relativePrefix) throws URISyntaxException {
urispec = urispec.trim();
URI uri;
if (urispec.startsWith("file:")) {
uri = makeURIFromFilespec(urispec.substring(5), relativePrefix);
}
else {
uri = new URI(urispec);
}
return uri;
}
public static URL toURL(final String urlspec) throws MalformedURLException {
return toURL(urlspec, null);
}
/**
* @param urispec
* @return
* @throws MalformedURLException
*/
public static URI toURI(final String urispec) throws URISyntaxException {
return toURI(urispec, null);
}
@SuppressWarnings("deprecation")
private static URL makeURLFromFilespec(final String filespec, final String relativePrefix) throws IOException {
// make sure the file is absolute & canonical file url
File file = new File(filespec);
// if we have a prefix and the file is not abs then prepend
if (relativePrefix != null && !file.isAbsolute()) {
file = new File(relativePrefix, filespec);
}
// make sure it is canonical (no ../ and such)
file = file.getCanonicalFile();
return file.toURL();
}
private static URI makeURIFromFilespec(final String filespec, final String relativePrefix) {
// make sure the file is absolute & canonical file url
File file = new File(filespec);
// if we have a prefix and the file is not abs then prepend
if (relativePrefix != null && !file.isAbsolute()) {
file = new File(relativePrefix, filespec);
}
return file.toURI();
}
public static Properties toProperties(final String[] array, final String delimiter) {
if (Checker.isEmpty(array)) {
return new Properties();
}
final Properties result = new Properties();
for (int i = 0; i < array.length; ++i) {
final String element = array[i];
final String[] splittedElement = split(element, delimiter);
if (splittedElement == null) {
continue;
}
result.setProperty(splittedElement[0].trim(), splittedElement[1].trim());
}
return result;
}
public static String format(final String message, final Object... args) {
try {
for (int i = 0; i < args.length; i++) {
final Object o = args[i];
if (o != null && o.getClass().isArray()) {
args[i] = Arrays.asList((Object[]) o);
}
}
return String.format(message, args);
}
catch (final Exception e) {
final String error = buildExceptionMessage(message, e, args);
return error;
}
}
private static String buildExceptionMessage(final String message, final Exception e, final Object... args) {
String error = "Could not format message with format string: {" + message + "}, args: {";
final boolean useComma = false;
for (final Object arg : args) {
if (useComma) {
error += ", ";
}
error += "{" + (arg != null ? arg : "null") + "}";
}
return error;
}
public static byte[] toBytes(final String s) {
try {
return s.getBytes(LanguageUtils.DEFAULT_ENCODING);
}
catch (final UnsupportedEncodingException e) {
return s.getBytes();
}
}
public static String toString(final Object input) {
return toString(input, null);
}
public static String toString(final Object input, final String separator) {
final StringBuffer buffer = new StringBuffer();
if (input instanceof Collection) {
final Collection col = (Collection) input;
for (final Iterator it = col.iterator(); it.hasNext();) {
final Object o = it.next();
buffer.append("{").append(toString(o, separator)).append("}").append(separator == null ? "," : separator);
}
if (buffer.length() > 0) {
buffer.deleteCharAt(buffer.length() - 1);
}
}
else if (input instanceof Map) {
final Map map = (Map) input;
for (final Iterator it = map.keySet().iterator(); it.hasNext();) {
final Object key = it.next();
final Object value = map.get(key);
buffer.append(toString(key, separator)).append("=").append("{").append(toString(value, separator)).append("}")
.append(separator == null ? "," : separator);
}
if (buffer.length() > 0) {
buffer.deleteCharAt(buffer.length() - 1);
}
}
else if (input != null && input.getClass().isArray()) {
final Object[] array = (Object[]) input;
buffer.append(toString(Arrays.asList(array), separator));
}
else if (input instanceof InetSocketAddress) {
buffer.append(NetworkUtils.hostportizeAddress((InetAddress) input));
}
else if (input instanceof LazyInetSocketAddress) {
buffer.append(((LazyInetSocketAddress) input).hostportize());
}
else if (input instanceof InetAddress) {
buffer.append(NetworkUtils.translateAddress((InetAddress) input));
}
else {
buffer.append(String.valueOf(input));
}
return buffer.toString();
}
public static String[] toStringArray(final Collection<?> collection) {
if (collection == null) {
return null;
}
final String[] retval = new String[collection.size()];
int i = 0;
for (final Object o : collection) {
retval[i] = String.valueOf(o);
i = i + 1;
}
return retval;
}
}