package com.hwlcn.ldap.util;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.UUID;
import com.hwlcn.HwlcnException;
import com.hwlcn.core.annotation.ThreadSafety;
import com.hwlcn.ldap.ldap.sdk.Control;
import static com.hwlcn.ldap.util.Debug.*;
import static com.hwlcn.ldap.util.UtilityMessages.*;
import static com.hwlcn.ldap.util.Validator.*;
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
public final class StaticUtils
{
public static final byte[] NO_BYTES = new byte[0];
public static final Control[] NO_CONTROLS = new Control[0];
public static final String[] NO_STRINGS = new String[0];
public static final String EOL = System.getProperty("line.separator");
public static final byte[] EOL_BYTES = getBytes(EOL);
private static final ThreadLocal<SimpleDateFormat> dateFormatters =
new ThreadLocal<SimpleDateFormat>();
private StaticUtils()
{
}
public static byte[] getBytes(final String s)
{
final int length;
if ((s == null) || ((length = s.length()) == 0))
{
return NO_BYTES;
}
final byte[] b = new byte[length];
for (int i=0; i < length; i++)
{
final char c = s.charAt(i);
if (c <= 0x7F)
{
b[i] = (byte) (c & 0x7F);
}
else
{
try
{
return s.getBytes("UTF-8");
}
catch (Exception e)
{
debugException(e);
return s.getBytes();
}
}
}
return b;
}
public static boolean isASCIIString(final byte[] b)
{
for (final byte by : b)
{
if ((by & 0x80) == 0x80)
{
return false;
}
}
return true;
}
public static boolean isPrintableString(final byte[] b)
{
for (final byte by : b)
{
if ((by & 0x80) == 0x80)
{
return false;
}
if (((by >= 'a') && (by <= 'z')) ||
((by >= 'A') && (by <= 'Z')) ||
((by >= '0') && (by <= '9')))
{
continue;
}
switch (by)
{
case '\'':
case '(':
case ')':
case '+':
case ',':
case '-':
case '.':
case '=':
case '/':
case ':':
case '?':
case ' ':
continue;
default:
return false;
}
}
return true;
}
public static String toUTF8String(final byte[] b)
{
try
{
return new String(b, "UTF-8");
}
catch (Exception e)
{
debugException(e);
return new String(b);
}
}
public static String toUTF8String(final byte[] b, final int offset,
final int length)
{
try
{
return new String(b, offset, length, "UTF-8");
}
catch (Exception e)
{
debugException(e);
return new String(b, offset, length);
}
}
public static String toInitialLowerCase(final String s)
{
if ((s == null) || (s.length() == 0))
{
return s;
}
else if (s.length() == 1)
{
return toLowerCase(s);
}
else
{
final char c = s.charAt(0);
if (((c >= 'A') && (c <= 'Z')) || (c < ' ') || (c > '~'))
{
final StringBuilder b = new StringBuilder(s);
b.setCharAt(0, Character.toLowerCase(c));
return b.toString();
}
else
{
return s;
}
}
}
public static String toLowerCase(final String s)
{
if (s == null)
{
return null;
}
final int length = s.length();
final char[] charArray = s.toCharArray();
for (int i=0; i < length; i++)
{
switch (charArray[i])
{
case 'A':
charArray[i] = 'a';
break;
case 'B':
charArray[i] = 'b';
break;
case 'C':
charArray[i] = 'c';
break;
case 'D':
charArray[i] = 'd';
break;
case 'E':
charArray[i] = 'e';
break;
case 'F':
charArray[i] = 'f';
break;
case 'G':
charArray[i] = 'g';
break;
case 'H':
charArray[i] = 'h';
break;
case 'I':
charArray[i] = 'i';
break;
case 'J':
charArray[i] = 'j';
break;
case 'K':
charArray[i] = 'k';
break;
case 'L':
charArray[i] = 'l';
break;
case 'M':
charArray[i] = 'm';
break;
case 'N':
charArray[i] = 'n';
break;
case 'O':
charArray[i] = 'o';
break;
case 'P':
charArray[i] = 'p';
break;
case 'Q':
charArray[i] = 'q';
break;
case 'R':
charArray[i] = 'r';
break;
case 'S':
charArray[i] = 's';
break;
case 'T':
charArray[i] = 't';
break;
case 'U':
charArray[i] = 'u';
break;
case 'V':
charArray[i] = 'v';
break;
case 'W':
charArray[i] = 'w';
break;
case 'X':
charArray[i] = 'x';
break;
case 'Y':
charArray[i] = 'y';
break;
case 'Z':
charArray[i] = 'z';
break;
default:
if (charArray[i] > 0x7F)
{
return s.toLowerCase();
}
break;
}
}
return new String(charArray);
}
public static boolean isHex(final char c)
{
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'a':
case 'A':
case 'b':
case 'B':
case 'c':
case 'C':
case 'd':
case 'D':
case 'e':
case 'E':
case 'f':
case 'F':
return true;
default:
return false;
}
}
public static String toHex(final byte b)
{
final StringBuilder buffer = new StringBuilder(2);
toHex(b, buffer);
return buffer.toString();
}
public static void toHex(final byte b, final StringBuilder buffer)
{
switch (b & 0xF0)
{
case 0x00:
buffer.append('0');
break;
case 0x10:
buffer.append('1');
break;
case 0x20:
buffer.append('2');
break;
case 0x30:
buffer.append('3');
break;
case 0x40:
buffer.append('4');
break;
case 0x50:
buffer.append('5');
break;
case 0x60:
buffer.append('6');
break;
case 0x70:
buffer.append('7');
break;
case 0x80:
buffer.append('8');
break;
case 0x90:
buffer.append('9');
break;
case 0xA0:
buffer.append('a');
break;
case 0xB0:
buffer.append('b');
break;
case 0xC0:
buffer.append('c');
break;
case 0xD0:
buffer.append('d');
break;
case 0xE0:
buffer.append('e');
break;
case 0xF0:
buffer.append('f');
break;
}
switch (b & 0x0F)
{
case 0x00:
buffer.append('0');
break;
case 0x01:
buffer.append('1');
break;
case 0x02:
buffer.append('2');
break;
case 0x03:
buffer.append('3');
break;
case 0x04:
buffer.append('4');
break;
case 0x05:
buffer.append('5');
break;
case 0x06:
buffer.append('6');
break;
case 0x07:
buffer.append('7');
break;
case 0x08:
buffer.append('8');
break;
case 0x09:
buffer.append('9');
break;
case 0x0A:
buffer.append('a');
break;
case 0x0B:
buffer.append('b');
break;
case 0x0C:
buffer.append('c');
break;
case 0x0D:
buffer.append('d');
break;
case 0x0E:
buffer.append('e');
break;
case 0x0F:
buffer.append('f');
break;
}
}
public static String toHex(final byte[] b)
{
ensureNotNull(b);
final StringBuilder buffer = new StringBuilder(2 * b.length);
toHex(b, buffer);
return buffer.toString();
}
public static void toHex(final byte[] b, final StringBuilder buffer)
{
toHex(b, null, buffer);
}
public static void toHex(final byte[] b, final String delimiter,
final StringBuilder buffer)
{
boolean first = true;
for (final byte bt : b)
{
if (first)
{
first = false;
}
else if (delimiter != null)
{
buffer.append(delimiter);
}
toHex(bt, buffer);
}
}
public static String toHexPlusASCII(final byte[] array, final int indent)
{
final StringBuilder buffer = new StringBuilder();
toHexPlusASCII(array, indent, buffer);
return buffer.toString();
}
public static void toHexPlusASCII(final byte[] array, final int indent,
final StringBuilder buffer)
{
if ((array == null) || (array.length == 0))
{
return;
}
for (int i=0; i < indent; i++)
{
buffer.append(' ');
}
int pos = 0;
int startPos = 0;
while (pos < array.length)
{
toHex(array[pos++], buffer);
buffer.append(' ');
if ((pos % 16) == 0)
{
buffer.append(" ");
for (int i=startPos; i < pos; i++)
{
if ((array[i] < ' ') || (array[i] > '~'))
{
buffer.append(' ');
}
else
{
buffer.append((char) array[i]);
}
}
buffer.append(EOL);
startPos = pos;
if (pos < array.length)
{
for (int i=0; i < indent; i++)
{
buffer.append(' ');
}
}
}
}
if ((array.length % 16) != 0)
{
final int missingBytes = (16 - (array.length % 16));
if (missingBytes > 0)
{
for (int i=0; i < missingBytes; i++)
{
buffer.append(" ");
}
buffer.append(" ");
for (int i=startPos; i < array.length; i++)
{
if ((array[i] < ' ') || (array[i] > '~'))
{
buffer.append(' ');
}
else
{
buffer.append((char) array[i]);
}
}
buffer.append(EOL);
}
}
}
public static void hexEncode(final char c, final StringBuilder buffer)
{
final byte[] charBytes;
if (c <= 0x7F)
{
charBytes = new byte[] { (byte) (c & 0x7F) };
}
else
{
charBytes = getBytes(String.valueOf(c));
}
for (final byte b : charBytes)
{
buffer.append('\\');
toHex(b, buffer);
}
}
public static String getStackTrace(final Throwable t)
{
final StringBuilder buffer = new StringBuilder();
getStackTrace(t, buffer);
return buffer.toString();
}
public static void getStackTrace(final Throwable t,
final StringBuilder buffer)
{
buffer.append(getUnqualifiedClassName(t.getClass()));
buffer.append('(');
final String message = t.getMessage();
if (message != null)
{
buffer.append("message='");
buffer.append(message);
buffer.append("', ");
}
buffer.append("trace='");
getStackTrace(t.getStackTrace(), buffer);
buffer.append('\'');
final Throwable cause = t.getCause();
if (cause != null)
{
buffer.append(", cause=");
getStackTrace(cause, buffer);
}
buffer.append(", revision=");
buffer.append(')');
}
public static String getStackTrace(final StackTraceElement[] elements)
{
final StringBuilder buffer = new StringBuilder();
getStackTrace(elements, buffer);
return buffer.toString();
}
public static void getStackTrace(final StackTraceElement[] elements,
final StringBuilder buffer)
{
for (int i=0; i < elements.length; i++)
{
if (i > 0)
{
buffer.append(" / ");
}
buffer.append(elements[i].getMethodName());
buffer.append('(');
buffer.append(elements[i].getFileName());
final int lineNumber = elements[i].getLineNumber();
if (lineNumber > 0)
{
buffer.append(':');
buffer.append(lineNumber);
}
buffer.append(')');
}
}
public static String getExceptionMessage(final Throwable t)
{
if (t == null)
{
return ERR_NO_EXCEPTION.get();
}
final StringBuilder buffer = new StringBuilder();
if (t instanceof LDAPSDKException)
{
buffer.append(((LDAPSDKException) t).getExceptionMessage());
}
else if (t instanceof HwlcnException)
{
buffer.append(((HwlcnException) t).getExceptionMessage());
}
if ((t instanceof RuntimeException) || (t instanceof Error))
{
return getStackTrace(t);
}
else
{
buffer.append(String.valueOf(t));
}
final Throwable cause = t.getCause();
if (cause != null)
{
buffer.append(" caused by ");
buffer.append(getExceptionMessage(cause));
}
return buffer.toString();
}
public static String getUnqualifiedClassName(final Class<?> c)
{
final String className = c.getName();
final int lastPeriodPos = className.lastIndexOf('.');
if (lastPeriodPos > 0)
{
return className.substring(lastPeriodPos+1);
}
else
{
return className;
}
}
public static String encodeGeneralizedTime(final Date d)
{
SimpleDateFormat dateFormat = dateFormatters.get();
if (dateFormat == null)
{
dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
dateFormatters.set(dateFormat);
}
return dateFormat.format(d);
}
public static Date decodeGeneralizedTime(final String t)
throws ParseException
{
ensureNotNull(t);
int tzPos;
final TimeZone tz;
if (t.endsWith("Z"))
{
tz = TimeZone.getTimeZone("UTC");
tzPos = t.length() - 1;
}
else
{
tzPos = t.lastIndexOf('-');
if (tzPos < 0)
{
tzPos = t.lastIndexOf('+');
if (tzPos < 0)
{
throw new ParseException(ERR_GENTIME_DECODE_CANNOT_PARSE_TZ.get(t),
0);
}
}
tz = TimeZone.getTimeZone("GMT" + t.substring(tzPos));
if (tz.getRawOffset() == 0)
{
if (! (t.endsWith("+0000") || t.endsWith("-0000")))
{
throw new ParseException(ERR_GENTIME_DECODE_CANNOT_PARSE_TZ.get(t),
tzPos);
}
}
}
final String subSecFormatStr;
final String trimmedTimestamp;
int periodPos = t.lastIndexOf('.', tzPos);
if (periodPos > 0)
{
final int subSecondLength = tzPos - periodPos - 1;
switch (subSecondLength)
{
case 0:
subSecFormatStr = "";
trimmedTimestamp = t.substring(0, periodPos);
break;
case 1:
subSecFormatStr = ".SSS";
trimmedTimestamp = t.substring(0, (periodPos+2)) + "00";
break;
case 2:
subSecFormatStr = ".SSS";
trimmedTimestamp = t.substring(0, (periodPos+3)) + '0';
break;
default:
subSecFormatStr = ".SSS";
trimmedTimestamp = t.substring(0, periodPos+4);
break;
}
}
else
{
subSecFormatStr = "";
periodPos = tzPos;
trimmedTimestamp = t.substring(0, tzPos);
}
final String formatStr;
switch (periodPos)
{
case 10:
formatStr = "yyyyMMddHH" + subSecFormatStr;
break;
case 12:
formatStr = "yyyyMMddHHmm" + subSecFormatStr;
break;
case 14:
formatStr = "yyyyMMddHHmmss" + subSecFormatStr;
break;
default:
throw new ParseException(ERR_GENTIME_CANNOT_PARSE_INVALID_LENGTH.get(t),
periodPos);
}
final SimpleDateFormat dateFormat = new SimpleDateFormat(formatStr);
dateFormat.setTimeZone(tz);
dateFormat.setLenient(false);
return dateFormat.parse(trimmedTimestamp);
}
public static String trimLeading(final String s)
{
ensureNotNull(s);
int nonSpacePos = 0;
final int length = s.length();
while ((nonSpacePos < length) && (s.charAt(nonSpacePos) == ' '))
{
nonSpacePos++;
}
if (nonSpacePos == 0)
{
return s;
}
else if (nonSpacePos >= length)
{
return "";
}
else
{
return s.substring(nonSpacePos, length);
}
}
public static String trimTrailing(final String s)
{
ensureNotNull(s);
final int lastPos = s.length() - 1;
int nonSpacePos = lastPos;
while ((nonSpacePos >= 0) && (s.charAt(nonSpacePos) == ' '))
{
nonSpacePos--;
}
if (nonSpacePos < 0)
{
return "";
}
else if (nonSpacePos == lastPos)
{
return s;
}
else
{
return s.substring(0, (nonSpacePos+1));
}
}
public static List<String> wrapLine(final String line, final int maxWidth)
{
final int breakPos = line.indexOf('\n');
if (breakPos >= 0)
{
final ArrayList<String> lineList = new ArrayList<String>(10);
final StringTokenizer tokenizer = new StringTokenizer(line, "\r\n");
while (tokenizer.hasMoreTokens())
{
lineList.addAll(wrapLine(tokenizer.nextToken(), maxWidth));
}
return lineList;
}
final int length = line.length();
if ((maxWidth <= 0) || (length < maxWidth))
{
return Arrays.asList(line);
}
int wrapPos = maxWidth;
int lastWrapPos = 0;
final ArrayList<String> lineList = new ArrayList<String>(5);
while (true)
{
final int spacePos = line.lastIndexOf(' ', wrapPos);
if (spacePos > lastWrapPos)
{
final String s = trimTrailing(line.substring(lastWrapPos, spacePos));
if (s.length() > 0)
{
lineList.add(s);
}
wrapPos = spacePos;
}
else
{
lineList.add(line.substring(lastWrapPos, wrapPos));
}
while ((wrapPos < length) && (line.charAt(wrapPos) == ' '))
{
wrapPos++;
}
lastWrapPos = wrapPos;
wrapPos += maxWidth;
if (wrapPos >= length)
{
if (lastWrapPos >= length)
{
break;
}
else
{
final String s = trimTrailing(line.substring(lastWrapPos));
if (s.length() > 0)
{
lineList.add(s);
}
break;
}
}
}
return lineList;
}
public static String cleanExampleCommandLineArgument(final String s)
{
return ExampleCommandLineArgument.getCleanArgument(s).getLocalForm();
}
public static String concatenateStrings(final String... a)
{
return concatenateStrings(null, null, " ", null, null, a);
}
public static String concatenateStrings(final List<String> l)
{
return concatenateStrings(null, null, " ", null, null, l);
}
public static String concatenateStrings(final String beforeList,
final String beforeElement,
final String betweenElements,
final String afterElement,
final String afterList,
final String... a)
{
return concatenateStrings(beforeList, beforeElement, betweenElements,
afterElement, afterList, Arrays.asList(a));
}
public static String concatenateStrings(final String beforeList,
final String beforeElement,
final String betweenElements,
final String afterElement,
final String afterList,
final List<String> l)
{
ensureNotNull(l);
final StringBuilder buffer = new StringBuilder();
if (beforeList != null)
{
buffer.append(beforeList);
}
final Iterator<String> iterator = l.iterator();
while (iterator.hasNext())
{
if (beforeElement != null)
{
buffer.append(beforeElement);
}
buffer.append(iterator.next());
if (afterElement != null)
{
buffer.append(afterElement);
}
if ((betweenElements != null) && iterator.hasNext())
{
buffer.append(betweenElements);
}
}
if (afterList != null)
{
buffer.append(afterList);
}
return buffer.toString();
}
public static String secondsToHumanReadableDuration(final long s)
{
return millisToHumanReadableDuration(s * 1000L);
}
public static String millisToHumanReadableDuration(final long m)
{
final StringBuilder buffer = new StringBuilder();
long numMillis = m;
final long numDays = numMillis / 86400000L;
if (numDays > 0)
{
numMillis -= (numDays * 86400000L);
if (numDays == 1)
{
buffer.append(INFO_NUM_DAYS_SINGULAR.get(numDays));
}
else
{
buffer.append(INFO_NUM_DAYS_PLURAL.get(numDays));
}
}
final long numHours = numMillis / 3600000L;
if (numHours > 0)
{
numMillis -= (numHours * 3600000L);
if (buffer.length() > 0)
{
buffer.append(", ");
}
if (numHours == 1)
{
buffer.append(INFO_NUM_HOURS_SINGULAR.get(numHours));
}
else
{
buffer.append(INFO_NUM_HOURS_PLURAL.get(numHours));
}
}
final long numMinutes = numMillis / 60000L;
if (numMinutes > 0)
{
numMillis -= (numMinutes * 60000L);
if (buffer.length() > 0)
{
buffer.append(", ");
}
if (numMinutes == 1)
{
buffer.append(INFO_NUM_MINUTES_SINGULAR.get(numMinutes));
}
else
{
buffer.append(INFO_NUM_MINUTES_PLURAL.get(numMinutes));
}
}
if (numMillis == 1000)
{
if (buffer.length() > 0)
{
buffer.append(", ");
}
buffer.append(INFO_NUM_SECONDS_SINGULAR.get(1));
}
else if ((numMillis > 0) || (buffer.length() == 0))
{
if (buffer.length() > 0)
{
buffer.append(", ");
}
final long numSeconds = numMillis / 1000L;
numMillis -= (numSeconds * 1000L);
if ((numMillis % 1000L) != 0L)
{
final double numSecondsDouble = numSeconds + (numMillis / 1000.0);
final DecimalFormat decimalFormat = new DecimalFormat("0.000");
buffer.append(INFO_NUM_SECONDS_WITH_DECIMAL.get(
decimalFormat.format(numSecondsDouble)));
}
else
{
buffer.append(INFO_NUM_SECONDS_PLURAL.get(numSeconds));
}
}
return buffer.toString();
}
public static long nanosToMillis(final long nanos)
{
return Math.max(0L, Math.round(nanos / 1000000.0d));
}
public static long millisToNanos(final long millis)
{
return Math.max(0L, (millis * 1000000L));
}
public static boolean isNumericOID(final String s)
{
boolean digitRequired = true;
boolean periodFound = false;
for (final char c : s.toCharArray())
{
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
digitRequired = false;
break;
case '.':
if (digitRequired)
{
return false;
}
else
{
digitRequired = true;
}
periodFound = true;
break;
default:
return false;
}
}
return (periodFound && (! digitRequired));
}
public static String capitalize(final String s)
{
if (s == null)
{
return null;
}
switch (s.length())
{
case 0:
return s;
case 1:
return s.toUpperCase();
default:
final char c = s.charAt(0);
if (Character.isUpperCase(c))
{
return s;
}
else
{
return Character.toUpperCase(c) + s.substring(1);
}
}
}
public static byte[] encodeUUID(final UUID uuid)
{
final byte[] b = new byte[16];
final long mostSignificantBits = uuid.getMostSignificantBits();
b[0] = (byte) ((mostSignificantBits >> 56) & 0xFF);
b[1] = (byte) ((mostSignificantBits >> 48) & 0xFF);
b[2] = (byte) ((mostSignificantBits >> 40) & 0xFF);
b[3] = (byte) ((mostSignificantBits >> 32) & 0xFF);
b[4] = (byte) ((mostSignificantBits >> 24) & 0xFF);
b[5] = (byte) ((mostSignificantBits >> 16) & 0xFF);
b[6] = (byte) ((mostSignificantBits >> 8) & 0xFF);
b[7] = (byte) (mostSignificantBits & 0xFF);
final long leastSignificantBits = uuid.getLeastSignificantBits();
b[8] = (byte) ((leastSignificantBits >> 56) & 0xFF);
b[9] = (byte) ((leastSignificantBits >> 48) & 0xFF);
b[10] = (byte) ((leastSignificantBits >> 40) & 0xFF);
b[11] = (byte) ((leastSignificantBits >> 32) & 0xFF);
b[12] = (byte) ((leastSignificantBits >> 24) & 0xFF);
b[13] = (byte) ((leastSignificantBits >> 16) & 0xFF);
b[14] = (byte) ((leastSignificantBits >> 8) & 0xFF);
b[15] = (byte) (leastSignificantBits & 0xFF);
return b;
}
public static UUID decodeUUID(final byte[] b)
throws ParseException
{
if (b.length != 16)
{
throw new ParseException(ERR_DECODE_UUID_INVALID_LENGTH.get(toHex(b)), 0);
}
long mostSignificantBits = 0L;
for (int i=0; i < 8; i++)
{
mostSignificantBits = (mostSignificantBits << 8) | (b[i] & 0xFF);
}
long leastSignificantBits = 0L;
for (int i=8; i < 16; i++)
{
leastSignificantBits = (leastSignificantBits << 8) | (b[i] & 0xFF);
}
return new UUID(mostSignificantBits, leastSignificantBits);
}
public static boolean isWindows()
{
final String osName = toLowerCase(System.getProperty("os.name"));
return ((osName != null) && osName.contains("windows"));
}
public static List<String> toArgumentList(final String s)
throws ParseException
{
if ((s == null) || (s.length() == 0))
{
return Collections.emptyList();
}
int quoteStartPos = -1;
boolean inEscape = false;
final ArrayList<String> argList = new ArrayList<String>();
final StringBuilder currentArg = new StringBuilder();
for (int i=0; i < s.length(); i++)
{
final char c = s.charAt(i);
if (inEscape)
{
currentArg.append(c);
inEscape = false;
continue;
}
if (c == '\\')
{
inEscape = true;
}
else if (c == '"')
{
if (quoteStartPos >= 0)
{
quoteStartPos = -1;
}
else
{
quoteStartPos = i;
}
}
else if (c == ' ')
{
if (quoteStartPos >= 0)
{
currentArg.append(c);
}
else if (currentArg.length() > 0)
{
argList.add(currentArg.toString());
currentArg.setLength(0);
}
}
else
{
currentArg.append(c);
}
}
if (s.endsWith("\\") && (! s.endsWith("\\\\")))
{
throw new ParseException(ERR_ARG_STRING_DANGLING_BACKSLASH.get(),
(s.length() - 1));
}
if (quoteStartPos >= 0)
{
throw new ParseException(ERR_ARG_STRING_UNMATCHED_QUOTE.get(
quoteStartPos), quoteStartPos);
}
if (currentArg.length() > 0)
{
argList.add(currentArg.toString());
}
return Collections.unmodifiableList(argList);
}
public static <T> List<T> toList(final T[] array)
{
if (array == null)
{
return null;
}
final ArrayList<T> l = new ArrayList<T>(array.length);
l.addAll(Arrays.asList(array));
return l;
}
public static <T> List<T> toNonNullList(final T[] array)
{
if (array == null)
{
return new ArrayList<T>(0);
}
final ArrayList<T> l = new ArrayList<T>(array.length);
l.addAll(Arrays.asList(array));
return l;
}
public static boolean bothNullOrEqual(final Object o1, final Object o2)
{
if (o1 == null)
{
return (o2 == null);
}
else if (o2 == null)
{
return false;
}
return o1.equals(o2);
}
public static boolean bothNullOrEqualIgnoreCase(final String s1,
final String s2)
{
if (s1 == null)
{
return (s2 == null);
}
else if (s2 == null)
{
return false;
}
return s1.equalsIgnoreCase(s2);
}
public static boolean stringsEqualIgnoreCaseOrderIndependent(
final String[] a1, final String[] a2)
{
if (a1 == null)
{
return (a2 == null);
}
else if (a2 == null)
{
return false;
}
if (a1.length != a2.length)
{
return false;
}
if (a1.length == 1)
{
return (a1[0].equalsIgnoreCase(a2[0]));
}
final HashSet<String> s1 = new HashSet<String>(a1.length);
for (final String s : a1)
{
s1.add(toLowerCase(s));
}
final HashSet<String> s2 = new HashSet<String>(a2.length);
for (final String s : a2)
{
s2.add(toLowerCase(s));
}
return s1.equals(s2);
}
public static <T> boolean arraysEqualOrderIndependent(final T[] a1,
final T[] a2)
{
if (a1 == null)
{
return (a2 == null);
}
else if (a2 == null)
{
return false;
}
if (a1.length != a2.length)
{
return false;
}
if (a1.length == 1)
{
return (a1[0].equals(a2[0]));
}
final HashSet<T> s1 = new HashSet<T>(Arrays.asList(a1));
final HashSet<T> s2 = new HashSet<T>(Arrays.asList(a2));
return s1.equals(s2);
}
}