mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

matthew_swift
28.47.2010 f2160f4bd1c8ac67e5a86a6710d431e8932877f9
sdk/src/com/sun/opends/sdk/util/StaticUtils.java
@@ -29,7 +29,8 @@
import static com.sun.opends.sdk.messages.Messages.*;
import static com.sun.opends.sdk.messages.Messages.ERR_HEX_DECODE_INVALID_CHARACTER;
import static com.sun.opends.sdk.messages.Messages.ERR_HEX_DECODE_INVALID_LENGTH;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
@@ -49,8 +50,10 @@
 */
public final class StaticUtils
{
  public static final Logger DEBUG_LOG = Logger
      .getLogger("org.opends.sdk");
  /**
   * The debug logger which should be used by the SDK.
   */
  public static final Logger DEBUG_LOG = Logger.getLogger("org.opends.sdk");
  /**
   * The end-of-line character for this platform.
@@ -67,16 +70,14 @@
  /**
   * Retrieves a string representation of the provided byte in
   * hexadecimal.
   * Retrieves a string representation of the provided byte in hexadecimal.
   *
   * @param b
   *          The byte for which to retrieve the hexadecimal string
   *          representation.
   * @return The string representation of the provided byte in
   *         hexadecimal.
   * @return The string representation of the provided byte in hexadecimal.
   */
  public static String byteToHex(byte b)
  public static String byteToHex(final byte b)
  {
    switch (b & 0xFF)
    {
@@ -600,13 +601,544 @@
  /**
   * Attempts to compress the data in the provided source array into the
   * given destination array. If the compressed data will fit into the
   * destination array, then this method will return the number of bytes
   * of compressed data in the array. Otherwise, it will return -1 to
   * indicate that the compression was not successful. Note that if -1
   * is returned, then the data in the destination array should be
   * considered invalid.
   * Retrieves a string representation of the provided byte in hexadecimal.
   *
   * @param b
   *          The byte for which to retrieve the hexadecimal string
   *          representation.
   * @return The string representation of the provided byte in hexadecimal using
   *         lowercase characters.
   */
  public static String byteToLowerHex(final byte b)
  {
    switch (b & 0xFF)
    {
    case 0x00:
      return "00";
    case 0x01:
      return "01";
    case 0x02:
      return "02";
    case 0x03:
      return "03";
    case 0x04:
      return "04";
    case 0x05:
      return "05";
    case 0x06:
      return "06";
    case 0x07:
      return "07";
    case 0x08:
      return "08";
    case 0x09:
      return "09";
    case 0x0A:
      return "0a";
    case 0x0B:
      return "0b";
    case 0x0C:
      return "0c";
    case 0x0D:
      return "0d";
    case 0x0E:
      return "0e";
    case 0x0F:
      return "0f";
    case 0x10:
      return "10";
    case 0x11:
      return "11";
    case 0x12:
      return "12";
    case 0x13:
      return "13";
    case 0x14:
      return "14";
    case 0x15:
      return "15";
    case 0x16:
      return "16";
    case 0x17:
      return "17";
    case 0x18:
      return "18";
    case 0x19:
      return "19";
    case 0x1A:
      return "1a";
    case 0x1B:
      return "1b";
    case 0x1C:
      return "1c";
    case 0x1D:
      return "1d";
    case 0x1E:
      return "1e";
    case 0x1F:
      return "1f";
    case 0x20:
      return "20";
    case 0x21:
      return "21";
    case 0x22:
      return "22";
    case 0x23:
      return "23";
    case 0x24:
      return "24";
    case 0x25:
      return "25";
    case 0x26:
      return "26";
    case 0x27:
      return "27";
    case 0x28:
      return "28";
    case 0x29:
      return "29";
    case 0x2A:
      return "2a";
    case 0x2B:
      return "2b";
    case 0x2C:
      return "2c";
    case 0x2D:
      return "2d";
    case 0x2E:
      return "2e";
    case 0x2F:
      return "2f";
    case 0x30:
      return "30";
    case 0x31:
      return "31";
    case 0x32:
      return "32";
    case 0x33:
      return "33";
    case 0x34:
      return "34";
    case 0x35:
      return "35";
    case 0x36:
      return "36";
    case 0x37:
      return "37";
    case 0x38:
      return "38";
    case 0x39:
      return "39";
    case 0x3A:
      return "3a";
    case 0x3B:
      return "3b";
    case 0x3C:
      return "3c";
    case 0x3D:
      return "3d";
    case 0x3E:
      return "3e";
    case 0x3F:
      return "3f";
    case 0x40:
      return "40";
    case 0x41:
      return "41";
    case 0x42:
      return "42";
    case 0x43:
      return "43";
    case 0x44:
      return "44";
    case 0x45:
      return "45";
    case 0x46:
      return "46";
    case 0x47:
      return "47";
    case 0x48:
      return "48";
    case 0x49:
      return "49";
    case 0x4A:
      return "4a";
    case 0x4B:
      return "4b";
    case 0x4C:
      return "4c";
    case 0x4D:
      return "4d";
    case 0x4E:
      return "4e";
    case 0x4F:
      return "4f";
    case 0x50:
      return "50";
    case 0x51:
      return "51";
    case 0x52:
      return "52";
    case 0x53:
      return "53";
    case 0x54:
      return "54";
    case 0x55:
      return "55";
    case 0x56:
      return "56";
    case 0x57:
      return "57";
    case 0x58:
      return "58";
    case 0x59:
      return "59";
    case 0x5A:
      return "5a";
    case 0x5B:
      return "5b";
    case 0x5C:
      return "5c";
    case 0x5D:
      return "5d";
    case 0x5E:
      return "5e";
    case 0x5F:
      return "5f";
    case 0x60:
      return "60";
    case 0x61:
      return "61";
    case 0x62:
      return "62";
    case 0x63:
      return "63";
    case 0x64:
      return "64";
    case 0x65:
      return "65";
    case 0x66:
      return "66";
    case 0x67:
      return "67";
    case 0x68:
      return "68";
    case 0x69:
      return "69";
    case 0x6A:
      return "6a";
    case 0x6B:
      return "6b";
    case 0x6C:
      return "6c";
    case 0x6D:
      return "6d";
    case 0x6E:
      return "6e";
    case 0x6F:
      return "6f";
    case 0x70:
      return "70";
    case 0x71:
      return "71";
    case 0x72:
      return "72";
    case 0x73:
      return "73";
    case 0x74:
      return "74";
    case 0x75:
      return "75";
    case 0x76:
      return "76";
    case 0x77:
      return "77";
    case 0x78:
      return "78";
    case 0x79:
      return "79";
    case 0x7A:
      return "7a";
    case 0x7B:
      return "7b";
    case 0x7C:
      return "7c";
    case 0x7D:
      return "7d";
    case 0x7E:
      return "7e";
    case 0x7F:
      return "7f";
    case 0x80:
      return "80";
    case 0x81:
      return "81";
    case 0x82:
      return "82";
    case 0x83:
      return "83";
    case 0x84:
      return "84";
    case 0x85:
      return "85";
    case 0x86:
      return "86";
    case 0x87:
      return "87";
    case 0x88:
      return "88";
    case 0x89:
      return "89";
    case 0x8A:
      return "8a";
    case 0x8B:
      return "8b";
    case 0x8C:
      return "8c";
    case 0x8D:
      return "8d";
    case 0x8E:
      return "8e";
    case 0x8F:
      return "8f";
    case 0x90:
      return "90";
    case 0x91:
      return "91";
    case 0x92:
      return "92";
    case 0x93:
      return "93";
    case 0x94:
      return "94";
    case 0x95:
      return "95";
    case 0x96:
      return "96";
    case 0x97:
      return "97";
    case 0x98:
      return "98";
    case 0x99:
      return "99";
    case 0x9A:
      return "9a";
    case 0x9B:
      return "9b";
    case 0x9C:
      return "9c";
    case 0x9D:
      return "9d";
    case 0x9E:
      return "9e";
    case 0x9F:
      return "9f";
    case 0xA0:
      return "a0";
    case 0xA1:
      return "a1";
    case 0xA2:
      return "a2";
    case 0xA3:
      return "a3";
    case 0xA4:
      return "a4";
    case 0xA5:
      return "a5";
    case 0xA6:
      return "a6";
    case 0xA7:
      return "a7";
    case 0xA8:
      return "a8";
    case 0xA9:
      return "a9";
    case 0xAA:
      return "aa";
    case 0xAB:
      return "ab";
    case 0xAC:
      return "ac";
    case 0xAD:
      return "ad";
    case 0xAE:
      return "ae";
    case 0xAF:
      return "af";
    case 0xB0:
      return "b0";
    case 0xB1:
      return "b1";
    case 0xB2:
      return "b2";
    case 0xB3:
      return "b3";
    case 0xB4:
      return "b4";
    case 0xB5:
      return "b5";
    case 0xB6:
      return "b6";
    case 0xB7:
      return "b7";
    case 0xB8:
      return "b8";
    case 0xB9:
      return "b9";
    case 0xBA:
      return "ba";
    case 0xBB:
      return "bb";
    case 0xBC:
      return "bc";
    case 0xBD:
      return "bd";
    case 0xBE:
      return "be";
    case 0xBF:
      return "bf";
    case 0xC0:
      return "c0";
    case 0xC1:
      return "c1";
    case 0xC2:
      return "c2";
    case 0xC3:
      return "c3";
    case 0xC4:
      return "c4";
    case 0xC5:
      return "c5";
    case 0xC6:
      return "c6";
    case 0xC7:
      return "c7";
    case 0xC8:
      return "c8";
    case 0xC9:
      return "c9";
    case 0xCA:
      return "ca";
    case 0xCB:
      return "cb";
    case 0xCC:
      return "cc";
    case 0xCD:
      return "cd";
    case 0xCE:
      return "ce";
    case 0xCF:
      return "cf";
    case 0xD0:
      return "d0";
    case 0xD1:
      return "d1";
    case 0xD2:
      return "d2";
    case 0xD3:
      return "d3";
    case 0xD4:
      return "d4";
    case 0xD5:
      return "d5";
    case 0xD6:
      return "d6";
    case 0xD7:
      return "d7";
    case 0xD8:
      return "d8";
    case 0xD9:
      return "d9";
    case 0xDA:
      return "da";
    case 0xDB:
      return "db";
    case 0xDC:
      return "dc";
    case 0xDD:
      return "dd";
    case 0xDE:
      return "de";
    case 0xDF:
      return "df";
    case 0xE0:
      return "e0";
    case 0xE1:
      return "e1";
    case 0xE2:
      return "e2";
    case 0xE3:
      return "e3";
    case 0xE4:
      return "e4";
    case 0xE5:
      return "e5";
    case 0xE6:
      return "e6";
    case 0xE7:
      return "e7";
    case 0xE8:
      return "e8";
    case 0xE9:
      return "e9";
    case 0xEA:
      return "ea";
    case 0xEB:
      return "eb";
    case 0xEC:
      return "ec";
    case 0xED:
      return "ed";
    case 0xEE:
      return "ee";
    case 0xEF:
      return "ef";
    case 0xF0:
      return "f0";
    case 0xF1:
      return "f1";
    case 0xF2:
      return "f2";
    case 0xF3:
      return "f3";
    case 0xF4:
      return "f4";
    case 0xF5:
      return "f5";
    case 0xF6:
      return "f6";
    case 0xF7:
      return "f7";
    case 0xF8:
      return "f8";
    case 0xF9:
      return "f9";
    case 0xFA:
      return "fa";
    case 0xFB:
      return "fb";
    case 0xFC:
      return "fc";
    case 0xFD:
      return "fd";
    case 0xFE:
      return "fe";
    case 0xFF:
      return "ff";
    default:
      return "??";
    }
  }
  /**
   * Attempts to compress the data in the provided source array into the given
   * destination array. If the compressed data will fit into the destination
   * array, then this method will return the number of bytes of compressed data
   * in the array. Otherwise, it will return -1 to indicate that the compression
   * was not successful. Note that if -1 is returned, then the data in the
   * destination array should be considered invalid.
   *
   * @param src
   *          The array containing the raw data to compress.
@@ -615,8 +1147,7 @@
   * @param srcLen
   *          The maximum number of source data bytes to compress.
   * @param dst
   *          The array into which the compressed data should be
   *          written.
   *          The array into which the compressed data should be written.
   * @param dstOff
   *          The start offset of the compressed data.
   * @param dstLen
@@ -624,8 +1155,8 @@
   * @return The number of bytes of compressed data, or -1 if it was not
   *         possible to actually compress the data.
   */
  public static int compress(byte[] src, int srcOff, int srcLen,
      byte[] dst, int dstOff, int dstLen)
  public static int compress(final byte[] src, final int srcOff,
      final int srcLen, final byte[] dst, final int dstOff, final int dstLen)
  {
    final Deflater deflater = new Deflater();
    try
@@ -633,8 +1164,7 @@
      deflater.setInput(src, srcOff, srcLen);
      deflater.finish();
      final int compressedLength = deflater
          .deflate(dst, dstOff, dstLen);
      final int compressedLength = deflater.deflate(dst, dstOff, dstLen);
      if (deflater.finished())
      {
        return compressedLength;
@@ -653,26 +1183,26 @@
  /**
   * Attempts to compress the data in the provided byte sequence into
   * the provided byte string builder. Note that if compression was not
   * successful, then the byte string builder will be left unchanged.
   * Attempts to compress the data in the provided byte sequence into the
   * provided byte string builder. Note that if compression was not successful,
   * then the byte string builder will be left unchanged.
   *
   * @param input
   *          The source data to be compressed.
   * @param output
   *          The destination buffer to which the compressed data will
   *          be appended.
   *          The destination buffer to which the compressed data will be
   *          appended.
   * @return <code>true</code> if compression was successful or
   *         <code>false</code> otherwise.
   */
  public static boolean compress(ByteSequence input,
      ByteStringBuilder output)
  public static boolean compress(final ByteSequence input,
      final ByteStringBuilder output)
  {
    byte[] inputBytes = input.toByteArray();
    byte[] outputBytes = new byte[inputBytes.length];
    final byte[] inputBytes = input.toByteArray();
    final byte[] outputBytes = new byte[inputBytes.length];
    final int compressedSize = compress(inputBytes, 0,
        inputBytes.length, outputBytes, 0, outputBytes.length);
    final int compressedSize = compress(inputBytes, 0, inputBytes.length,
        outputBytes, 0, outputBytes.length);
    if (compressedSize != -1)
    {
@@ -691,138 +1221,19 @@
  public static ByteString evaluateEscapes(SubstringReader reader,
      char[] escapeChars, boolean trim) throws DecodeException
  {
    return evaluateEscapes(reader, escapeChars, escapeChars, trim);
  }
  public static ByteString evaluateEscapes(SubstringReader reader,
      char[] escapeChars, char[] delimiterChars, boolean trim)
      throws DecodeException
  {
    int length = 0;
    int lengthWithoutSpace = 0;
    char c;
    ByteStringBuilder valueBuffer = null;
    if (trim)
    {
      reader.skipWhitespaces();
    }
    reader.mark();
    while (reader.remaining() > 0)
    {
      c = reader.read();
      if (c == 0x5C) // The backslash character
      {
        if (valueBuffer == null)
        {
          valueBuffer = new ByteStringBuilder();
        }
        valueBuffer.append(reader.read(length));
        valueBuffer.append(evaluateEscapedChar(reader, escapeChars));
        reader.mark();
        length = lengthWithoutSpace = 0;
      }
      if (delimiterChars != null)
      {
        for (final char delimiterChar : delimiterChars)
        {
          if (c == delimiterChar)
          {
            reader.reset();
            if (valueBuffer != null)
            {
              if (trim)
              {
                valueBuffer.append(reader.read(lengthWithoutSpace));
              }
              else
              {
                valueBuffer.append(reader.read(length));
              }
              return valueBuffer.toByteString();
            }
            else
            {
              if (trim)
              {
                if (lengthWithoutSpace > 0)
                {
                  return ByteString.valueOf(reader
                      .read(lengthWithoutSpace));
                }
                return ByteString.empty();
              }
              if (length > 0)
              {
                return ByteString.valueOf(reader.read(length));
              }
              return ByteString.empty();
            }
          }
        }
      }
      length++;
      if (c != ' ')
      {
        lengthWithoutSpace = length;
      }
      else
      {
        lengthWithoutSpace++;
      }
    }
    reader.reset();
    if (valueBuffer != null)
    {
      if (trim)
      {
        valueBuffer.append(reader.read(lengthWithoutSpace));
      }
      else
      {
        valueBuffer.append(reader.read(length));
      }
      return valueBuffer.toByteString();
    }
    else
    {
      if (trim)
      {
        if (lengthWithoutSpace > 0)
        {
          return ByteString.valueOf(reader.read(lengthWithoutSpace));
        }
        return ByteString.empty();
      }
      if (length > 0)
      {
        return ByteString.valueOf(reader.read(length));
      }
      return ByteString.empty();
    }
  }
  /**
   * Returns a string containing provided date formatted using the
   * generalized time syntax.
   * Returns a string containing provided date formatted using the generalized
   * time syntax.
   *
   * @param date
   *          The date to be formated.
   * @return The string containing provided date formatted using the
   *         generalized time syntax.
   * @return The string containing provided date formatted using the generalized
   *         time syntax.
   * @throws NullPointerException
   *           If {@code date} was {@code null}.
   */
  public static String formatAsGeneralizedTime(Date date)
  public static String formatAsGeneralizedTime(final Date date)
      throws NullPointerException
  {
    return formatAsGeneralizedTime(date.getTime());
  }
@@ -830,17 +1241,18 @@
  /**
   * Returns a string containing provided date formatted using the
   * generalized time syntax.
   * Returns a string containing provided date formatted using the generalized
   * time syntax.
   *
   * @param date
   *          The date to be formated.
   * @return The string containing provided date formatted using the
   *         generalized time syntax.
   * @return The string containing provided date formatted using the generalized
   *         time syntax.
   * @throws IllegalArgumentException
   *           If {@code date} was invalid.
   */
  public static String formatAsGeneralizedTime(long date)
  public static String formatAsGeneralizedTime(final long date)
      throws IllegalArgumentException
  {
    // Generalized time has the format yyyyMMddHHmmss.SSS'Z'
@@ -849,8 +1261,7 @@
    final StringBuilder sb = new StringBuilder(19);
    final GregorianCalendar calendar = new GregorianCalendar(
        TIME_ZONE_UTC_OBJ);
    final GregorianCalendar calendar = new GregorianCalendar(TIME_ZONE_UTC_OBJ);
    calendar.setLenient(false);
    calendar.setTimeInMillis(date);
@@ -860,8 +1271,7 @@
    {
      final IllegalArgumentException e = new IllegalArgumentException(
          "Year cannot be < 0:" + n);
      StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax", "format",
          e);
      StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax", "format", e);
      throw e;
    }
    else if (n < 10)
@@ -940,16 +1350,16 @@
  /**
   * Construct a byte array containing the UTF-8 encoding of the
   * provided string. This is significantly faster than calling
   * Construct a byte array containing the UTF-8 encoding of the provided
   * string. This is significantly faster than calling
   * {@link String#getBytes(String)} for ASCII strings.
   *
   * @param s
   *          The string to convert to a UTF-8 byte array.
   * @return Returns a byte array containing the UTF-8 encoding of the
   *         provided string.
   * @return Returns a byte array containing the UTF-8 encoding of the provided
   *         string.
   */
  public static byte[] getBytes(String s)
  public static byte[] getBytes(final String s)
  {
    if (s == null)
    {
@@ -984,20 +1394,17 @@
  /**
   * Retrieves the best human-readable message for the provided
   * exception. For exceptions defined in the OpenDS project, it will
   * attempt to use the message (combining it with the message ID if
   * available). For some exceptions that use encapsulation (e.g.,
   * InvocationTargetException), it will be unwrapped and the cause will
   * be treated. For all others, the
   * Retrieves the best human-readable message for the provided exception. For
   * exceptions defined in the OpenDS project, it will attempt to use the
   * message (combining it with the message ID if available). For some
   * exceptions that use encapsulation (e.g., InvocationTargetException), it
   * will be unwrapped and the cause will be treated. For all others, the
   *
   * @param t
   *          The {@code Throwable} object for which to retrieve the
   *          message.
   * @return The human-readable message generated for the provided
   *         exception.
   *          The {@code Throwable} object for which to retrieve the message.
   * @return The human-readable message generated for the provided exception.
   */
  public static LocalizableMessage getExceptionMessage(Throwable t)
  public static LocalizableMessage getExceptionMessage(final Throwable t)
  {
    if (t instanceof LocalizableException)
    {
@@ -1016,8 +1423,7 @@
      message.append(")");
      return message.toMessage();
    }
    else if (t instanceof InvocationTargetException
        && t.getCause() != null)
    else if (t instanceof InvocationTargetException && t.getCause() != null)
    {
      return getExceptionMessage(t.getCause());
    }
@@ -1074,13 +1480,13 @@
   *
   * @param hexString
   *          The hexadecimal string to convert to a byte array.
   * @return The byte array containing the binary representation of the
   *         provided hex string.
   * @return The byte array containing the binary representation of the provided
   *         hex string.
   * @throws java.text.ParseException
   *           If the provided string contains invalid hexadecimal
   *           digits or does not contain an even number of digits.
   *           If the provided string contains invalid hexadecimal digits or
   *           does not contain an even number of digits.
   */
  public static byte[] hexStringToByteArray(String hexString)
  public static byte[] hexStringToByteArray(final String hexString)
      throws ParseException
  {
    int length;
@@ -1089,7 +1495,7 @@
      return new byte[0];
    }
    if (length % 2 == 1)
    if (length % 2 != 0)
    {
      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_LENGTH
          .get(hexString);
@@ -1116,13 +1522,14 @@
   *          The first hexadecimal character.
   * @param c2
   *          The second hexadecimal character.
   * @return The byte containing the binary representation of the
   *         provided hex characters.
   * @return The byte containing the binary representation of the provided hex
   *         characters.
   * @throws ParseException
   *           If the provided string contains invalid hexadecimal
   *           digits or does not contain an even number of digits.
   *           If the provided string contains invalid hexadecimal digits or
   *           does not contain an even number of digits.
   */
  public static byte hexToByte(char c1, char c2) throws ParseException
  public static byte hexToByte(final char c1, final char c2)
      throws ParseException
  {
    byte b;
    switch (c1)
@@ -1182,8 +1589,8 @@
      b = (byte) 0xF0;
      break;
    default:
      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER
          .get(new String(new char[] { c1, c2 }), c1);
      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER.get(
          new String(new char[] { c1, c2 }), c1);
      throw new ParseException(message.toString(), 0);
    }
@@ -1244,8 +1651,8 @@
      b |= 0x0F;
      break;
    default:
      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER
          .get(new String(new char[] { c1, c2 }), c1);
      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER.get(
          new String(new char[] { c1, c2 }), c1);
      throw new ParseException(message.toString(), 0);
    }
@@ -1255,16 +1662,15 @@
  /**
   * Indicates whether the provided character is an ASCII alphabetic
   * character.
   * Indicates whether the provided character is an ASCII alphabetic character.
   *
   * @param c
   *          The character for which to make the determination.
   * @return <CODE>true</CODE> if the provided value is an uppercase or
   *         lowercase ASCII alphabetic character, or <CODE>false</CODE>
   *         if it is not.
   *         lowercase ASCII alphabetic character, or <CODE>false</CODE> if it
   *         is not.
   */
  public static boolean isAlpha(char c)
  public static boolean isAlpha(final char c)
  {
    final ASCIICharProp cp = ASCIICharProp.valueOf(c);
    return cp != null ? cp.isLetter() : false;
@@ -1277,10 +1683,10 @@
   *
   * @param c
   *          The character for which to make the determination.
   * @return <CODE>true</CODE> if the provided character represents a
   *         numeric digit, or <CODE>false</CODE> if not.
   * @return <CODE>true</CODE> if the provided character represents a numeric
   *         digit, or <CODE>false</CODE> if not.
   */
  public static boolean isDigit(char c)
  public static boolean isDigit(final char c)
  {
    final ASCIICharProp cp = ASCIICharProp.valueOf(c);
    return cp != null ? cp.isDigit() : false;
@@ -1296,7 +1702,7 @@
   * @return <CODE>true</CODE> if the provided character represents a
   *         hexadecimal digit, or <CODE>false</CODE> if not.
   */
  public static boolean isHexDigit(char c)
  public static boolean isHexDigit(final char c)
  {
    final ASCIICharProp cp = ASCIICharProp.valueOf(c);
    return cp != null ? cp.isHexDigit() : false;
@@ -1305,16 +1711,15 @@
  /**
   * Returns a string representation of the contents of the provided
   * byte sequence using hexadecimal characters and a space between each
   * byte.
   * Returns a string representation of the contents of the provided byte
   * sequence using hexadecimal characters and a space between each byte.
   *
   * @param bytes
   *          The byte sequence.
   * @return A string representation of the contents of the provided
   *         byte sequence using hexadecimal characters.
   * @return A string representation of the contents of the provided byte
   *         sequence using hexadecimal characters.
   */
  public static String toHex(ByteSequence bytes)
  public static String toHex(final ByteSequence bytes)
  {
    return toHex(bytes, new StringBuilder((bytes.length() - 1) * 3 + 2))
        .toString();
@@ -1323,19 +1728,19 @@
  /**
   * Appends the string representation of the contents of the provided
   * byte sequence to a string builder using hexadecimal characters and
   * a space between each byte.
   * Appends the string representation of the contents of the provided byte
   * sequence to a string builder using hexadecimal characters and a space
   * between each byte.
   *
   * @param bytes
   *          The byte sequence.
   * @param builder
   *          The string builder to which the hexadecimal representation
   *          of {@code bytes} should be appended.
   *          The string builder to which the hexadecimal representation of
   *          {@code bytes} should be appended.
   * @return The string builder.
   */
  public static StringBuilder toHex(ByteSequence bytes,
      StringBuilder builder)
  public static StringBuilder toHex(final ByteSequence bytes,
      final StringBuilder builder)
  {
    final int length = bytes.length();
    builder.ensureCapacity(builder.length() + (length - 1) * 3 + 2);
@@ -1351,24 +1756,23 @@
  /**
   * Appends a string representation of the data in the provided byte
   * sequence to the given string builder using the specified indent.
   * Appends a string representation of the data in the provided byte sequence
   * to the given string builder using the specified indent.
   * <p>
   * The data will be formatted with sixteen hex bytes in a row followed
   * by the ASCII representation, then wrapping to a new line as
   * necessary. The state of the byte buffer is not changed.
   * The data will be formatted with sixteen hex bytes in a row followed by the
   * ASCII representation, then wrapping to a new line as necessary. The state
   * of the byte buffer is not changed.
   *
   * @param bytes
   *          The byte sequence.
   * @param builder
   *          The string builder to which the information is to be
   *          appended.
   *          The string builder to which the information is to be appended.
   * @param indent
   *          The number of spaces to indent the output.
   * @return The string builder.
   */
  public static StringBuilder toHexPlusAscii(ByteSequence bytes,
      StringBuilder builder, int indent)
  public static StringBuilder toHexPlusAscii(final ByteSequence bytes,
      final StringBuilder builder, final int indent)
  {
    final StringBuilder indentBuf = new StringBuilder(indent);
    for (int i = 0; i < indent; i++)
@@ -1455,23 +1859,23 @@
  /**
   * Appends a lowercase string representation of the contents of the
   * given byte array to the provided buffer. This implementation
   * presumes that the provided string will contain only ASCII
   * characters and is optimized for that case. However, if a non-ASCII
   * character is encountered it will fall back on a more expensive
   * algorithm that will work properly for non-ASCII characters.
   * Appends a lowercase string representation of the contents of the given byte
   * array to the provided buffer. This implementation presumes that the
   * provided string will contain only ASCII characters and is optimized for
   * that case. However, if a non-ASCII character is encountered it will fall
   * back on a more expensive algorithm that will work properly for non-ASCII
   * characters.
   *
   * @param b
   *          The byte array for which to obtain the lowercase string
   *          representation.
   * @param builder
   *          The buffer to which the lowercase form of the string
   *          should be appended.
   *          The buffer to which the lowercase form of the string should be
   *          appended.
   * @return The updated {@code StringBuilder}.
   */
  public static StringBuilder toLowerCase(ByteSequence b,
      StringBuilder builder)
  public static StringBuilder toLowerCase(final ByteSequence b,
      final StringBuilder builder)
  {
    Validator.ensureNotNull(b, builder);
@@ -1504,18 +1908,16 @@
  /**
   * Retrieves a lower-case representation of the given string. This
   * implementation presumes that the provided string will contain only
   * ASCII characters and is optimized for that case. However, if a
   * non-ASCII character is encountered it will fall back on a more
   * expensive algorithm that will work properly for non-ASCII
   * characters.
   * implementation presumes that the provided string will contain only ASCII
   * characters and is optimized for that case. However, if a non-ASCII
   * character is encountered it will fall back on a more expensive algorithm
   * that will work properly for non-ASCII characters.
   *
   * @param s
   *          The string for which to obtain the lower-case
   *          representation.
   *          The string for which to obtain the lower-case representation.
   * @return The lower-case representation of the given string.
   */
  public static String toLowerCase(String s)
  public static String toLowerCase(final String s)
  {
    Validator.ensureNotNull(s);
@@ -1532,7 +1934,10 @@
    while (i < length)
    {
      cp = ASCIICharProp.valueOf(s.charAt(i));
      if (cp == null || cp.isUpperCase()) break;
      if (cp == null || cp.isUpperCase())
      {
        break;
      }
      i++;
    }
@@ -1554,7 +1959,10 @@
      while (i < length)
      {
        cp = ASCIICharProp.valueOf(s.charAt(i));
        if (cp == null) break;
        if (cp == null)
        {
          break;
        }
        builder.append(cp.toLowerCase());
        i++;
      }
@@ -1571,23 +1979,21 @@
  /**
   * Appends a lower-case representation of the given string to the
   * provided buffer. This implementation presumes that the provided
   * string will contain only ASCII characters and is optimized for that
   * case. However, if a non-ASCII character is encountered it will fall
   * back on a more expensive algorithm that will work properly for
   * non-ASCII characters.
   * Appends a lower-case representation of the given string to the provided
   * buffer. This implementation presumes that the provided string will contain
   * only ASCII characters and is optimized for that case. However, if a
   * non-ASCII character is encountered it will fall back on a more expensive
   * algorithm that will work properly for non-ASCII characters.
   *
   * @param s
   *          The string for which to obtain the lower-case
   *          representation.
   *          The string for which to obtain the lower-case representation.
   * @param builder
   *          The {@code StringBuilder} to which the lower-case form of
   *          the string should be appended.
   *          The {@code StringBuilder} to which the lower-case form of the
   *          string should be appended.
   * @return The updated {@code StringBuilder}.
   */
  public static StringBuilder toLowerCase(String s,
      StringBuilder builder)
  public static StringBuilder toLowerCase(final String s,
      final StringBuilder builder)
  {
    Validator.ensureNotNull(s, builder);
@@ -1618,16 +2024,15 @@
  /**
   * Attempts to uncompress the data in the provided source array into
   * the given destination array. If the uncompressed data will fit into
   * the given destination array, then this method will return the
   * number of bytes of uncompressed data written into the destination
   * buffer. Otherwise, it will return a negative value to indicate that
   * the destination buffer was not large enough. The absolute value of
   * that negative return value will indicate the buffer size required
   * to fully decompress the data. Note that if a negative value is
   * returned, then the data in the destination array should be
   * considered invalid.
   * Attempts to uncompress the data in the provided source array into the given
   * destination array. If the uncompressed data will fit into the given
   * destination array, then this method will return the number of bytes of
   * uncompressed data written into the destination buffer. Otherwise, it will
   * return a negative value to indicate that the destination buffer was not
   * large enough. The absolute value of that negative return value will
   * indicate the buffer size required to fully decompress the data. Note that
   * if a negative value is returned, then the data in the destination array
   * should be considered invalid.
   *
   * @param src
   *          The array containing the raw data to compress.
@@ -1636,31 +2041,28 @@
   * @param srcLen
   *          The maximum number of source data bytes to compress.
   * @param dst
   *          The array into which the compressed data should be
   *          written.
   *          The array into which the compressed data should be written.
   * @param dstOff
   *          The start offset of the compressed data.
   * @param dstLen
   *          The maximum number of bytes of compressed data.
   * @return A positive value containing the number of bytes of
   *         uncompressed data written into the destination buffer, or a
   *         negative value whose absolute value is the size of the
   *         destination buffer required to fully decompress the
   *         provided data.
   * @return A positive value containing the number of bytes of uncompressed
   *         data written into the destination buffer, or a negative value whose
   *         absolute value is the size of the destination buffer required to
   *         fully decompress the provided data.
   * @throws java.util.zip.DataFormatException
   *           If a problem occurs while attempting to uncompress the
   *           data.
   *           If a problem occurs while attempting to uncompress the data.
   */
  public static int uncompress(byte[] src, int srcOff, int srcLen,
      byte[] dst, int dstOff, int dstLen) throws DataFormatException
  public static int uncompress(final byte[] src, final int srcOff,
      final int srcLen, final byte[] dst, final int dstOff, final int dstLen)
      throws DataFormatException
  {
    final Inflater inflater = new Inflater();
    try
    {
      inflater.setInput(src, srcOff, srcLen);
      final int decompressedLength = inflater.inflate(dst, dstOff,
          dstLen);
      final int decompressedLength = inflater.inflate(dst, dstOff, dstLen);
      if (inflater.finished())
      {
        return decompressedLength;
@@ -1686,31 +2088,29 @@
  /**
   * Attempts to uncompress the data in the provided byte sequence into
   * the provided byte string builder. Note that if uncompression was
   * not successful, then the data in the destination buffer should be
   * considered invalid.
   * Attempts to uncompress the data in the provided byte sequence into the
   * provided byte string builder. Note that if uncompression was not
   * successful, then the data in the destination buffer should be considered
   * invalid.
   *
   * @param input
   *          The source data to be uncompressed.
   * @param output
   *          The destination buffer to which the uncompressed data will
   *          be appended.
   *          The destination buffer to which the uncompressed data will be
   *          appended.
   * @param uncompressedSize
   *          The uncompressed size of the data if known or 0 otherwise.
   * @return <code>true</code> if decompression was successful or
   *         <code>false</code> otherwise.
   * @throws java.util.zip.DataFormatException
   *           If a problem occurs while attempting to uncompress the
   *           data.
   *           If a problem occurs while attempting to uncompress the data.
   */
  public static boolean uncompress(ByteSequence input,
      ByteStringBuilder output, int uncompressedSize)
  public static boolean uncompress(final ByteSequence input,
      final ByteStringBuilder output, final int uncompressedSize)
      throws DataFormatException
  {
    byte[] inputBytes = input.toByteArray();
    byte[] outputBytes = new byte[uncompressedSize > 0 ? uncompressedSize
        : 0];
    final byte[] inputBytes = input.toByteArray();
    byte[] outputBytes = new byte[uncompressedSize > 0 ? uncompressedSize : 0];
    int decompressResult = uncompress(inputBytes, 0, inputBytes.length,
        outputBytes, 0, outputBytes.length);
@@ -1740,13 +2140,11 @@
   * Retrieves the printable ASCII representation of the provided byte.
   *
   * @param b
   *          The byte for which to retrieve the printable ASCII
   *          representation.
   * @return The printable ASCII representation of the provided byte, or
   *         a space if the provided byte does not have printable ASCII
   *         representation.
   *          The byte for which to retrieve the printable ASCII representation.
   * @return The printable ASCII representation of the provided byte, or a space
   *         if the provided byte does not have printable ASCII representation.
   */
  private static char byteToASCII(byte b)
  private static char byteToASCII(final byte b)
  {
    if (b >= 32 && b <= 126)
    {
@@ -1758,164 +2156,6 @@
  private static char evaluateEscapedChar(SubstringReader reader,
      char[] escapeChars) throws DecodeException
  {
    final char c1 = reader.read();
    byte b;
    switch (c1)
    {
    case '0':
      b = 0x00;
      break;
    case '1':
      b = 0x10;
      break;
    case '2':
      b = 0x20;
      break;
    case '3':
      b = 0x30;
      break;
    case '4':
      b = 0x40;
      break;
    case '5':
      b = 0x50;
      break;
    case '6':
      b = 0x60;
      break;
    case '7':
      b = 0x70;
      break;
    case '8':
      b = (byte) 0x80;
      break;
    case '9':
      b = (byte) 0x90;
      break;
    case 'A':
    case 'a':
      b = (byte) 0xA0;
      break;
    case 'B':
    case 'b':
      b = (byte) 0xB0;
      break;
    case 'C':
    case 'c':
      b = (byte) 0xC0;
      break;
    case 'D':
    case 'd':
      b = (byte) 0xD0;
      break;
    case 'E':
    case 'e':
      b = (byte) 0xE0;
      break;
    case 'F':
    case 'f':
      b = (byte) 0xF0;
      break;
    default:
      if (c1 == 0x5C)
      {
        return c1;
      }
      if (escapeChars != null)
      {
        for (final char escapeChar : escapeChars)
        {
          if (c1 == escapeChar)
          {
            return c1;
          }
        }
      }
      final LocalizableMessage message = ERR_INVALID_ESCAPE_CHAR.get(
          reader.getString(), c1);
      throw DecodeException.error(message);
    }
    // The two positions must be the hex characters that
    // comprise the escaped value.
    if (reader.remaining() == 0)
    {
      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_LENGTH
          .get(reader.getString());
      throw DecodeException.error(message);
    }
    final char c2 = reader.read();
    switch (c2)
    {
    case '0':
      // No action required.
      break;
    case '1':
      b |= 0x01;
      break;
    case '2':
      b |= 0x02;
      break;
    case '3':
      b |= 0x03;
      break;
    case '4':
      b |= 0x04;
      break;
    case '5':
      b |= 0x05;
      break;
    case '6':
      b |= 0x06;
      break;
    case '7':
      b |= 0x07;
      break;
    case '8':
      b |= 0x08;
      break;
    case '9':
      b |= 0x09;
      break;
    case 'A':
    case 'a':
      b |= 0x0A;
      break;
    case 'B':
    case 'b':
      b |= 0x0B;
      break;
    case 'C':
    case 'c':
      b |= 0x0C;
      break;
    case 'D':
    case 'd':
      b |= 0x0D;
      break;
    case 'E':
    case 'e':
      b |= 0x0E;
      break;
    case 'F':
    case 'f':
      b |= 0x0F;
      break;
    default:
      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER
          .get(new String(new char[] { c1, c2 }), c1);
      throw DecodeException.error(message);
    }
    return (char) b;
  }
  // Prevent instantiation.
  private StaticUtils()
  {