001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.catalina.util;
019:
020: import java.io.ByteArrayOutputStream;
021:
022: /**
023: * Library of utility methods useful in dealing with converting byte arrays
024: * to and from strings of hexadecimal digits.
025: *
026: * @author Craig R. McClanahan
027: */
028:
029: public final class HexUtils {
030: // Code from Ajp11, from Apache's JServ
031:
032: // Table for HEX to DEC byte translation
033: public static final int[] DEC = { -1, -1, -1, -1, -1, -1, -1, -1,
034: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
035: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
036: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 00, 01, 02, 03, 04,
037: 05, 06, 07, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12,
038: 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
039: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10,
040: 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
041: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
042: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
043: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
044: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
045: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
046: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
047: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
048: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
049: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
050: -1, -1, -1, -1, -1, -1, -1, -1, };
051:
052: /**
053: * The string manager for this package.
054: */
055: private static StringManager sm = StringManager
056: .getManager("org.apache.catalina.util");
057:
058: /**
059: * Convert a String of hexadecimal digits into the corresponding
060: * byte array by encoding each two hexadecimal digits as a byte.
061: *
062: * @param digits Hexadecimal digits representation
063: *
064: * @exception IllegalArgumentException if an invalid hexadecimal digit
065: * is found, or the input string contains an odd number of hexadecimal
066: * digits
067: */
068: public static byte[] convert(String digits) {
069:
070: ByteArrayOutputStream baos = new ByteArrayOutputStream();
071: for (int i = 0; i < digits.length(); i += 2) {
072: char c1 = digits.charAt(i);
073: if ((i + 1) >= digits.length())
074: throw new IllegalArgumentException(sm
075: .getString("hexUtil.odd"));
076: char c2 = digits.charAt(i + 1);
077: byte b = 0;
078: if ((c1 >= '0') && (c1 <= '9'))
079: b += ((c1 - '0') * 16);
080: else if ((c1 >= 'a') && (c1 <= 'f'))
081: b += ((c1 - 'a' + 10) * 16);
082: else if ((c1 >= 'A') && (c1 <= 'F'))
083: b += ((c1 - 'A' + 10) * 16);
084: else
085: throw new IllegalArgumentException(sm
086: .getString("hexUtil.bad"));
087: if ((c2 >= '0') && (c2 <= '9'))
088: b += (c2 - '0');
089: else if ((c2 >= 'a') && (c2 <= 'f'))
090: b += (c2 - 'a' + 10);
091: else if ((c2 >= 'A') && (c2 <= 'F'))
092: b += (c2 - 'A' + 10);
093: else
094: throw new IllegalArgumentException(sm
095: .getString("hexUtil.bad"));
096: baos.write(b);
097: }
098: return (baos.toByteArray());
099:
100: }
101:
102: /**
103: * Convert a byte array into a printable format containing a
104: * String of hexadecimal digit characters (two per byte).
105: *
106: * @param bytes Byte array representation
107: */
108: public static String convert(byte bytes[]) {
109:
110: StringBuffer sb = new StringBuffer(bytes.length * 2);
111: for (int i = 0; i < bytes.length; i++) {
112: sb.append(convertDigit((int) (bytes[i] >> 4)));
113: sb.append(convertDigit((int) (bytes[i] & 0x0f)));
114: }
115: return (sb.toString());
116:
117: }
118:
119: /**
120: * Convert 4 hex digits to an int, and return the number of converted
121: * bytes.
122: *
123: * @param hex Byte array containing exactly four hexadecimal digits
124: *
125: * @exception IllegalArgumentException if an invalid hexadecimal digit
126: * is included
127: */
128: public static int convert2Int(byte[] hex) {
129: // Code from Ajp11, from Apache's JServ
130:
131: // assert b.length==4
132: // assert valid data
133: int len;
134: if (hex.length < 4)
135: return 0;
136: if (DEC[hex[0]] < 0)
137: throw new IllegalArgumentException(sm
138: .getString("hexUtil.bad"));
139: len = DEC[hex[0]];
140: len = len << 4;
141: if (DEC[hex[1]] < 0)
142: throw new IllegalArgumentException(sm
143: .getString("hexUtil.bad"));
144: len += DEC[hex[1]];
145: len = len << 4;
146: if (DEC[hex[2]] < 0)
147: throw new IllegalArgumentException(sm
148: .getString("hexUtil.bad"));
149: len += DEC[hex[2]];
150: len = len << 4;
151: if (DEC[hex[3]] < 0)
152: throw new IllegalArgumentException(sm
153: .getString("hexUtil.bad"));
154: len += DEC[hex[3]];
155: return len;
156: }
157:
158: /**
159: * [Private] Convert the specified value (0 .. 15) to the corresponding
160: * hexadecimal digit.
161: *
162: * @param value Value to be converted
163: */
164: private static char convertDigit(int value) {
165:
166: value &= 0x0f;
167: if (value >= 10)
168: return ((char) (value - 10 + 'a'));
169: else
170: return ((char) (value + '0'));
171:
172: }
173:
174: }
|