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.poi.contrib.poibrowser;
019:
020: import java.io.BufferedReader;
021: import java.io.IOException;
022: import java.io.InputStreamReader;
023:
024: import org.apache.poi.hpsf.ClassID;
025:
026: /**
027: * <p>Provides utility methods for encoding and decoding hexadecimal
028: * data.</p>
029: *
030: * @author Rainer Klute (klute@rainer-klute.de) - with portions from Tomcat
031: * @version $Id: Codec.java 489730 2006-12-22 19:18:16Z bayard $
032: * @since 2002-01-24
033: */
034: public class Codec {
035:
036: /**
037: * <p>The nibbles' hexadecimal values. A nibble is a half byte.</p>
038: */
039: protected static final byte hexval[] = { (byte) '0', (byte) '1',
040: (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6',
041: (byte) '7', (byte) '8', (byte) '9', (byte) 'A', (byte) 'B',
042: (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F' };
043:
044: /**
045: * <p>Converts a string into its hexadecimal notation.</p>
046: */
047: public static String hexEncode(final String s) {
048: return hexEncode(s.getBytes());
049: }
050:
051: /**
052: * <p>Converts a byte array into its hexadecimal notation.</p>
053: */
054: public static String hexEncode(final byte[] s) {
055: return hexEncode(s, 0, s.length);
056: }
057:
058: /**
059: * <p>Converts a part of a byte array into its hexadecimal
060: * notation.</p>
061: */
062: public static String hexEncode(final byte[] s, final int offset,
063: final int length) {
064: StringBuffer b = new StringBuffer(length * 2);
065: for (int i = offset; i < offset + length; i++) {
066: int c = s[i];
067: b.append((char) hexval[(c & 0xF0) >> 4]);
068: b.append((char) hexval[(c & 0x0F) >> 0]);
069: }
070: return b.toString();
071: }
072:
073: /**
074: * <p>Converts a single byte into its hexadecimal notation.</p>
075: */
076: public static String hexEncode(final byte b) {
077: StringBuffer sb = new StringBuffer(2);
078: sb.append((char) hexval[(b & 0xF0) >> 4]);
079: sb.append((char) hexval[(b & 0x0F) >> 0]);
080: return sb.toString();
081: }
082:
083: /**
084: * <p>Converts a short value (16-bit) into its hexadecimal
085: * notation.</p>
086: */
087: public static String hexEncode(final short s) {
088: StringBuffer sb = new StringBuffer(4);
089: sb.append((char) hexval[(s & 0xF000) >> 12]);
090: sb.append((char) hexval[(s & 0x0F00) >> 8]);
091: sb.append((char) hexval[(s & 0x00F0) >> 4]);
092: sb.append((char) hexval[(s & 0x000F) >> 0]);
093: return sb.toString();
094: }
095:
096: /**
097: * <p>Converts an int value (32-bit) into its hexadecimal
098: * notation.</p>
099: */
100: public static String hexEncode(final int i) {
101: StringBuffer sb = new StringBuffer(8);
102: sb.append((char) hexval[(i & 0xF0000000) >> 28]);
103: sb.append((char) hexval[(i & 0x0F000000) >> 24]);
104: sb.append((char) hexval[(i & 0x00F00000) >> 20]);
105: sb.append((char) hexval[(i & 0x000F0000) >> 16]);
106: sb.append((char) hexval[(i & 0x0000F000) >> 12]);
107: sb.append((char) hexval[(i & 0x00000F00) >> 8]);
108: sb.append((char) hexval[(i & 0x000000F0) >> 4]);
109: sb.append((char) hexval[(i & 0x0000000F) >> 0]);
110: return sb.toString();
111: }
112:
113: /**
114: * <p>Converts a long value (64-bit) into its hexadecimal
115: * notation.</p>
116: */
117: public static String hexEncode(final long l) {
118: StringBuffer sb = new StringBuffer(16);
119: sb.append(hexEncode((int) (l & 0xFFFFFFFF00000000L) >> 32));
120: sb.append(hexEncode((int) (l & 0x00000000FFFFFFFFL) >> 0));
121: return sb.toString();
122: }
123:
124: /**
125: * <p>Converts a class ID into its hexadecimal notation.</p>
126: */
127: public static String hexEncode(final ClassID classID) {
128: return hexEncode(classID.getBytes());
129: }
130:
131: /**
132: * <p>Decodes the hexadecimal representation of a sequence of
133: * bytes into a byte array. Each character in the string
134: * represents a nibble (half byte) and must be one of the
135: * characters '0'-'9', 'A'-'F' or 'a'-'f'.</p>
136: *
137: * @param s The string to be decoded
138: *
139: * @return The bytes
140: *
141: * @throws IllegalArgumentException if the string does not contain
142: * a valid representation of a byte sequence.
143: */
144: public static byte[] hexDecode(final String s) {
145: final int length = s.length();
146:
147: /* The string to be converted must have an even number of
148: characters. */
149: if (length % 2 == 1)
150: throw new IllegalArgumentException("String has odd length "
151: + length);
152: byte[] b = new byte[length / 2];
153: char[] c = new char[length];
154: s.toUpperCase().getChars(0, length, c, 0);
155: for (int i = 0; i < length; i += 2)
156: b[i / 2] = (byte) (decodeNibble(c[i]) << 4 & 0xF0 | decodeNibble(c[i + 1]) & 0x0F);
157: return b;
158: }
159:
160: /**
161: * <p>Decodes a nibble.</p>
162: *
163: * @param c A character in the range '0'-'9' or 'A'-'F'. Lower
164: * case is not supported here.
165: *
166: * @return The decoded nibble in the range 0-15
167: *
168: * @throws IllegalArgumentException if <em>c</em> is not a
169: * permitted character
170: */
171: protected static byte decodeNibble(final char c) {
172: for (byte i = 0; i < hexval.length; i++)
173: if ((byte) c == hexval[i])
174: return i;
175: throw new IllegalArgumentException("\"" + c + "\""
176: + " does not represent a nibble.");
177: }
178:
179: /**
180: * <p>For testing.</p>
181: */
182: public static void main(final String args[]) throws IOException {
183: final BufferedReader in = new BufferedReader(
184: new InputStreamReader(System.in));
185: String s;
186: do {
187: s = in.readLine();
188: if (s != null) {
189: String bytes = hexEncode(s);
190: System.out.print("Hex encoded (String): ");
191: System.out.println(bytes);
192: System.out.print("Hex encoded (byte[]): ");
193: System.out.println(hexEncode(s.getBytes()));
194: System.out.print("Re-decoded (byte[]): ");
195: System.out.println(new String(hexDecode(bytes)));
196: }
197: } while (s != null);
198: }
199:
200: }
|