001: /*
002: * ====================================================================
003: *
004: * XFLOW - Process Management System
005: * Copyright (C) 2003 Rob Tan
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * 1. Redistributions of source code must retain the above copyright
013: * notice, this list of conditions, and the following disclaimer.
014: *
015: * 2. Redistributions in binary form must reproduce the above copyright
016: * notice, this list of conditions, and the disclaimer that follows
017: * these conditions in the documentation and/or other materials
018: * provided with the distribution.
019: *
020: * 3. The name "XFlow" must not be used to endorse or promote products
021: * derived from this software without prior written permission. For
022: * written permission, please contact rcktan@yahoo.com
023: *
024: * 4. Products derived from this software may not be called "XFlow", nor
025: * may "XFlow" appear in their name, without prior written permission
026: * from the XFlow Project Management (rcktan@yahoo.com)
027: *
028: * In addition, we request (but do not require) that you include in the
029: * end-user documentation provided with the redistribution and/or in the
030: * software itself an acknowledgement equivalent to the following:
031: * "This product includes software developed by the
032: * XFlow Project (http://xflow.sourceforge.net/)."
033: * Alternatively, the acknowledgment may be graphical using the logos
034: * available at http://xflow.sourceforge.net/
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL THE XFLOW AUTHORS OR THE PROJECT
040: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: *
049: * ====================================================================
050: * This software consists of voluntary contributions made by many
051: * individuals on behalf of the XFlow Project and was originally
052: * created by Rob Tan (rcktan@yahoo.com)
053: * For more information on the XFlow Project, please see:
054: * <http://xflow.sourceforge.net/>.
055: * ====================================================================
056: */
057: package xflow.util;
058:
059: import java.io.*;
060: import java.util.*;
061:
062: public class HexUtil {
063:
064: /**
065: * <p>The nibbles' hexadecimal values. A nibble is a half byte.</p>
066: */
067: protected static final byte hexval[] = { (byte) '0', (byte) '1',
068: (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6',
069: (byte) '7', (byte) '8', (byte) '9', (byte) 'A', (byte) 'B',
070: (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F' };
071:
072: /**
073: * <p>Converts a string into its hexadecimal notation.</p>
074: *
075: * <p><strong>FIXME:</strong> If this method is called frequently,
076: * it should directly implement the algorithm in the called method
077: * in order to avoid creating a string instance.</p>
078: */
079: public static String hexEncode(final String s) {
080: return hexEncode(s.getBytes());
081: }
082:
083: /**
084: * <p>Converts a byte array into its hexadecimal notation.</p>
085: */
086: public static String hexEncode(final byte[] s) {
087: return hexEncode(s, 0, s.length);
088: }
089:
090: /**
091: * <p>Converts a part of a byte array into its hexadecimal
092: * notation.</p>
093: */
094: public static String hexEncode(final byte[] s, final int offset,
095: final int length) {
096: StringBuffer b = new StringBuffer(length * 2);
097: for (int i = offset; i < offset + length; i++) {
098: int c = s[i];
099: b.append((char) hexval[(c & 0xF0) >> 4]);
100: b.append((char) hexval[(c & 0x0F) >> 0]);
101: }
102: return b.toString();
103: }
104:
105: /**
106: * <p>Converts a single byte into its hexadecimal notation.</p>
107: */
108: public static String hexEncode(final byte b) {
109: StringBuffer sb = new StringBuffer(2);
110: sb.append((char) hexval[(b & 0xF0) >> 4]);
111: sb.append((char) hexval[(b & 0x0F) >> 0]);
112: return sb.toString();
113: }
114:
115: /**
116: * <p>Converts a short value (16-bit) into its hexadecimal
117: * notation.</p>
118: */
119: public static String hexEncode(final short s) {
120: StringBuffer sb = new StringBuffer(4);
121: sb.append((char) hexval[(s & 0xF000) >> 12]);
122: sb.append((char) hexval[(s & 0x0F00) >> 8]);
123: sb.append((char) hexval[(s & 0x00F0) >> 4]);
124: sb.append((char) hexval[(s & 0x000F) >> 0]);
125: return sb.toString();
126: }
127:
128: /**
129: * <p>Converts an int value (32-bit) into its hexadecimal
130: * notation.</p>
131: */
132: public static String hexEncode(final int i) {
133: StringBuffer sb = new StringBuffer(8);
134: sb.append((char) hexval[(i & 0xF0000000) >> 28]);
135: sb.append((char) hexval[(i & 0x0F000000) >> 24]);
136: sb.append((char) hexval[(i & 0x00F00000) >> 20]);
137: sb.append((char) hexval[(i & 0x000F0000) >> 16]);
138: sb.append((char) hexval[(i & 0x0000F000) >> 12]);
139: sb.append((char) hexval[(i & 0x00000F00) >> 8]);
140: sb.append((char) hexval[(i & 0x000000F0) >> 4]);
141: sb.append((char) hexval[(i & 0x0000000F) >> 0]);
142: return sb.toString();
143: }
144:
145: /**
146: * <p>Converts a long value (64-bit) into its hexadecimal
147: * notation.</p>
148: */
149: public static String hexEncode(final long l) {
150: StringBuffer sb = new StringBuffer(16);
151: sb.append(hexEncode((int) (l & 0xFFFFFFFF00000000L) >> 32));
152: sb.append(hexEncode((int) (l & 0x00000000FFFFFFFFL) >> 0));
153: return sb.toString();
154: }
155:
156: /**
157: * <p>Decodes the hexadecimal representation of a sequence of
158: * bytes into a byte array. Each character in the string
159: * represents a nibble (half byte) and must be one of the
160: * characters '0'-'9', 'A'-'F' or 'a'-'f'.</p>
161: *
162: * @param s The string to be decoded
163: *
164: * @return The bytes
165: *
166: * @throw IllegalArgumentException if the string does not contain
167: * a valid representation of a byte sequence.
168: */
169: public static byte[] hexDecode(final String s) {
170: final int length = s.length();
171:
172: /* The string to be converted must have an even number of
173: characters. */
174: if (length % 2 == 1)
175: throw new IllegalArgumentException("String has odd length "
176: + length);
177: byte[] b = new byte[length / 2];
178: char[] c = new char[length];
179: s.toUpperCase().getChars(0, length, c, 0);
180: for (int i = 0; i < length; i += 2)
181: b[i / 2] = (byte) (decodeNibble(c[i]) << 4 & 0xF0 | decodeNibble(c[i + 1]) & 0x0F);
182: return b;
183: }
184:
185: /**
186: * <p>Decodes a nibble.</p>
187: *
188: * @param c A character in the range '0'-'9' or 'A'-'F'. Lower
189: * case is not supported here.
190: *
191: * @return The decoded nibble in the range 0-15
192: *
193: * @throws IllegalArgumentException if <em>c</em> is not a
194: * permitted character
195: */
196: protected static byte decodeNibble(final char c) {
197: for (byte i = 0; i < hexval.length; i++)
198: if ((byte) c == hexval[i])
199: return i;
200: throw new IllegalArgumentException("\"" + c + "\""
201: + " does not represent a nibble.");
202: }
203:
204: public static String hexEncodeObject(Object obj) {
205:
206: String valueStr = null;
207:
208: try {
209: byte[] barr = null;
210: ByteArrayOutputStream out = new ByteArrayOutputStream();
211: ObjectOutputStream s = new ObjectOutputStream(out);
212: s.writeObject(obj);
213: s.flush();
214: barr = out.toByteArray();
215: valueStr = hexEncode(barr);
216: } catch (IOException ie) {
217: System.out.println(ie.getMessage());
218: }
219: return valueStr;
220: }
221:
222: public static Object hexDecodeObject(final String bytes) {
223:
224: byte[] barr = hexDecode(bytes);
225: Object obj = null;
226: try {
227: ByteArrayInputStream in = new ByteArrayInputStream(barr);
228: ObjectInputStream sin = new ObjectInputStream(in);
229: obj = sin.readObject();
230: } catch (Exception ie) {
231: System.out.println(ie.getMessage());
232: }
233: return obj;
234: }
235:
236: /**
237: * <p>For testing.</p>
238: */
239: public static void main(final String args[]) throws IOException {
240: final BufferedReader in = new BufferedReader(
241: new InputStreamReader(System.in));
242: String s;
243: do {
244: s = in.readLine();
245: if (s != null) {
246: String bytes = hexEncodeObject(s);
247: System.out.print("Hex encoded (object): ");
248: System.out.println(bytes);
249: System.out.print("Re-decoded (object): ");
250: System.out.println(hexDecodeObject(bytes));
251:
252: /*
253: String bytes = hexEncode(s);
254: System.out.print("Hex encoded (String): ");
255: System.out.println(bytes);
256: System.out.print("Hex encoded (byte[]): ");
257: System.out.println(hexEncode(s.getBytes()));
258: System.out.print("Re-decoded (byte[]): ");
259: System.out.println(new String(hexDecode(bytes)));
260: */
261:
262: }
263: } while (s != null);
264: }
265:
266: }
|