| | |
| | | |
| | | |
| | | |
| | | 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; |
| | |
| | | */ |
| | | 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. |
| | |
| | | |
| | | |
| | | /** |
| | | * 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) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | * @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 |
| | |
| | | * @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 |
| | |
| | | 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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | 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()); |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 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' |
| | | |
| | |
| | | |
| | | 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); |
| | | |
| | |
| | | { |
| | | 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) |
| | |
| | | |
| | | |
| | | /** |
| | | * 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) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * 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) |
| | | { |
| | |
| | | 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()); |
| | | } |
| | |
| | | * |
| | | * @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; |
| | |
| | | return new byte[0]; |
| | | } |
| | | |
| | | if (length % 2 == 1) |
| | | if (length % 2 != 0) |
| | | { |
| | | final LocalizableMessage message = ERR_HEX_DECODE_INVALID_LENGTH |
| | | .get(hexString); |
| | |
| | | * 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) |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | |
| | | * |
| | | * @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; |
| | |
| | | * @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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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(); |
| | |
| | | |
| | | |
| | | /** |
| | | * 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); |
| | |
| | | |
| | | |
| | | /** |
| | | * 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++) |
| | |
| | | |
| | | |
| | | /** |
| | | * 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); |
| | | |
| | |
| | | |
| | | /** |
| | | * 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); |
| | | |
| | |
| | | while (i < length) |
| | | { |
| | | cp = ASCIICharProp.valueOf(s.charAt(i)); |
| | | if (cp == null || cp.isUpperCase()) break; |
| | | if (cp == null || cp.isUpperCase()) |
| | | { |
| | | break; |
| | | } |
| | | i++; |
| | | } |
| | | |
| | |
| | | while (i < length) |
| | | { |
| | | cp = ASCIICharProp.valueOf(s.charAt(i)); |
| | | if (cp == null) break; |
| | | if (cp == null) |
| | | { |
| | | break; |
| | | } |
| | | builder.append(cp.toLowerCase()); |
| | | i++; |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 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); |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | * @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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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); |
| | |
| | | * 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) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | 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() |
| | | { |