001: /*
002: * Enhydra Java Application Server Project
003: *
004: * The contents of this file are subject to the Enhydra Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License on
007: * the Enhydra web site ( http://www.enhydra.org/ ).
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
011: * the License for the specific terms governing rights and limitations
012: * under the License.
013: *
014: * The Initial Developer of the Enhydra Application Server is Lutris
015: * Technologies, Inc. The Enhydra Application Server and portions created
016: * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
017: * All Rights Reserved.
018: *
019: * Contributor(s):
020: *
021: * $Id: Convert.java,v 1.2 2006-06-15 13:47:00 sinisa Exp $
022: */
023:
024: package com.lutris.util;
025:
026: import java.io.ByteArrayOutputStream;
027: import java.io.DataOutputStream;
028: import java.io.IOException;
029: import java.text.CharacterIterator;
030: import java.text.StringCharacterIterator;
031:
032: /**
033: * Various conversion methods.
034: * These methods are mostly used to convert internal java data
035: * fields into byte arrays or strings for use over the network
036: * or in 8 bit ASCII fields.
037: *
038: * @deprecated Use HexEncoder or Base64Encoder.
039: * @see HexEncoder
040: * @see Base64Encoder
041: *
042: */
043: public class Convert {
044: /**
045: * Hexadecimal characters corresponding to each half byte value.
046: */
047: private static final char[] HexChars = { '0', '1', '2', '3', '4',
048: '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
049:
050: /**
051: * The BASE64 encoding standard's 6-bit alphabet, from RFC 1521,
052: * plus the padding character at the end.
053: */
054: private static final char[] Base64Chars = { 'A', 'B', 'C', 'D',
055: 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
056: 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
057: 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
058: 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
059: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
060: '=' };
061:
062: /**
063: * Converts a long integer to an unsigned hexadecimal String. Treats
064: * the integer as an unsigned 64 bit value and left-pads with the
065: * pad character of the caller's choice.
066: *
067: * @param value The long integer to convert to a hexadecimal string.
068: * @param len The total padded length of the string. If the number
069: * is larger than the padded length, then this length
070: * of the string will be the length of the number.
071: * @param pad The character to use for padding.
072: * @return Unsigned hexadecimal numeric string representing
073: * the specified value.
074: */
075: public static final String toHexString(long value, int len, char pad) {
076: StringBuffer sb = new StringBuffer(Long.toHexString(value));
077: int npad = len - sb.length();
078: while (npad-- > 0)
079: sb.insert(0, pad);
080: return new String(sb);
081: }
082:
083: /**
084: * Converts an arbitrary array of bytes to ASCII hexadecimal string
085: * form, with two hex characters corresponding to each byte. The
086: * length of the resultant string in characters will be twice the
087: * length of the specified array of bytes.
088: *
089: * @param bytes The array of bytes to convert to ASCII hex form.
090: * @return An ASCII hexadecimal numeric string representing the
091: * specified array of bytes.
092: */
093: public static final String toHexString(byte[] bytes) {
094: StringBuffer sb = new StringBuffer();
095: int i;
096: for (i = 0; i < bytes.length; i++) {
097: sb.append(HexChars[(bytes[i] >> 4) & 0xf]);
098: sb.append(HexChars[bytes[i] & 0xf]);
099: }
100: return new String(sb);
101: }
102:
103: /**
104: * Performs RFC1521 style Base64 encoding of arbitrary binary data.
105: * The output is a java String containing the Base64 characters representing
106: * the binary data. Be aware that this string is in Unicode form, and
107: * should be converted to UTF8 with the usual java conversion routines
108: * before it is sent over a network. The output string is guaranteed
109: * to only contain characters that are a single byte in UTF8 format.
110: * Also be aware that this routine leaves it to the caller to break
111: * the string into 70 byte lines as per RFC1521.
112: *
113: * @param bytes The array of bytes to convert to Base64 encoding.
114: * @return An string containing the specified bytes in Base64
115: * encoded form.
116: */
117: public static final String toBase64String(byte[] bytes) {
118: return toBase64String(bytes, Base64Chars);
119: }
120:
121: /**
122: * Performs encoding of arbitrary binary data based on a 6 bit
123: * alphabet. The output is a java String containing the encoded
124: * characters representing the binary data. Be aware that this
125: * string is in Unicode form, and should be converted to UTF8 with
126: * the usual java conversion routines before it is sent over a
127: * network. The alphabet passed in via <code>chars</code> is used
128: * without further checks, it's the callers responsibility to set
129: * it to something meaningful.
130: *
131: * @param bytes The array of bytes to convert to Base64 encoding.
132: * @param chars The alphabet used in encoding. Must contain
133: * exactly 65 characters: A 6 bit alphabet plus one
134: * padding char at position 65.
135: * @return An string containing the specified bytes in Base64
136: * encoded form.
137: */
138: public static final String toBase64String(byte[] bytes, char[] chars) {
139: StringBuffer sb = new StringBuffer();
140: int len = bytes.length, i = 0, ival;
141: while (len >= 3) {
142: ival = ((int) bytes[i++] + 256) & 0xff;
143: ival <<= 8;
144: ival += ((int) bytes[i++] + 256) & 0xff;
145: ival <<= 8;
146: ival += ((int) bytes[i++] + 256) & 0xff;
147: len -= 3;
148: sb.append(chars[(ival >> 18) & 63]);
149: sb.append(chars[(ival >> 12) & 63]);
150: sb.append(chars[(ival >> 6) & 63]);
151: sb.append(chars[ival & 63]);
152: }
153: switch (len) {
154: case 0: // No pads needed.
155: break;
156: case 1: // Two more output bytes and two pads.
157: ival = ((int) bytes[i++] + 256) & 0xff;
158: ival <<= 16;
159: sb.append(chars[(ival >> 18) & 63]);
160: sb.append(chars[(ival >> 12) & 63]);
161: sb.append(chars[64]);
162: sb.append(chars[64]);
163: break;
164: case 2: // Three more output bytes and one pad.
165: ival = ((int) bytes[i++] + 256) & 0xff;
166: ival <<= 8;
167: ival += ((int) bytes[i] + 256) & 0xff;
168: ival <<= 8;
169: sb.append(chars[(ival >> 18) & 63]);
170: sb.append(chars[(ival >> 12) & 63]);
171: sb.append(chars[(ival >> 6) & 63]);
172: sb.append(chars[64]);
173: break;
174: }
175: return new String(sb);
176: }
177:
178: /**
179: * Performs RFC1521 style Base64 decoding of Base64 encoded data.
180: * The output is a byte array containing the decoded binary data.
181: * The input is expected to be a normal Unicode String object.
182: *
183: * @param s The Base64 encoded string to decode into binary data.
184: * @return An array of bytes containing the decoded data.
185: */
186: public static final byte[] fromBase64String(String s) {
187: try {
188: StringCharacterIterator iter = new StringCharacterIterator(
189: s);
190: ByteArrayOutputStream bytestr = new ByteArrayOutputStream();
191: DataOutputStream outstr = new DataOutputStream(bytestr);
192: char c;
193: int d, i, group;
194: int[] bgroup = new int[4];
195: decode: for (i = 0, group = 0, c = iter.first(); c != CharacterIterator.DONE; c = iter
196: .next()) {
197: switch (c) {
198: case 'A':
199: d = 0;
200: break;
201: case 'B':
202: d = 1;
203: break;
204: case 'C':
205: d = 2;
206: break;
207: case 'D':
208: d = 3;
209: break;
210: case 'E':
211: d = 4;
212: break;
213: case 'F':
214: d = 5;
215: break;
216: case 'G':
217: d = 6;
218: break;
219: case 'H':
220: d = 7;
221: break;
222: case 'I':
223: d = 8;
224: break;
225: case 'J':
226: d = 9;
227: break;
228: case 'K':
229: d = 10;
230: break;
231: case 'L':
232: d = 11;
233: break;
234: case 'M':
235: d = 12;
236: break;
237: case 'N':
238: d = 13;
239: break;
240: case 'O':
241: d = 14;
242: break;
243: case 'P':
244: d = 15;
245: break;
246: case 'Q':
247: d = 16;
248: break;
249: case 'R':
250: d = 17;
251: break;
252: case 'S':
253: d = 18;
254: break;
255: case 'T':
256: d = 19;
257: break;
258: case 'U':
259: d = 20;
260: break;
261: case 'V':
262: d = 21;
263: break;
264: case 'W':
265: d = 22;
266: break;
267: case 'X':
268: d = 23;
269: break;
270: case 'Y':
271: d = 24;
272: break;
273: case 'Z':
274: d = 25;
275: break;
276: case 'a':
277: d = 26;
278: break;
279: case 'b':
280: d = 27;
281: break;
282: case 'c':
283: d = 28;
284: break;
285: case 'd':
286: d = 29;
287: break;
288: case 'e':
289: d = 30;
290: break;
291: case 'f':
292: d = 31;
293: break;
294: case 'g':
295: d = 32;
296: break;
297: case 'h':
298: d = 33;
299: break;
300: case 'i':
301: d = 34;
302: break;
303: case 'j':
304: d = 35;
305: break;
306: case 'k':
307: d = 36;
308: break;
309: case 'l':
310: d = 37;
311: break;
312: case 'm':
313: d = 38;
314: break;
315: case 'n':
316: d = 39;
317: break;
318: case 'o':
319: d = 40;
320: break;
321: case 'p':
322: d = 41;
323: break;
324: case 'q':
325: d = 42;
326: break;
327: case 'r':
328: d = 43;
329: break;
330: case 's':
331: d = 44;
332: break;
333: case 't':
334: d = 45;
335: break;
336: case 'u':
337: d = 46;
338: break;
339: case 'v':
340: d = 47;
341: break;
342: case 'w':
343: d = 48;
344: break;
345: case 'x':
346: d = 49;
347: break;
348: case 'y':
349: d = 50;
350: break;
351: case 'z':
352: d = 51;
353: break;
354: case '0':
355: d = 52;
356: break;
357: case '1':
358: d = 53;
359: break;
360: case '2':
361: d = 54;
362: break;
363: case '3':
364: d = 55;
365: break;
366: case '4':
367: d = 56;
368: break;
369: case '5':
370: d = 57;
371: break;
372: case '6':
373: d = 58;
374: break;
375: case '7':
376: d = 59;
377: break;
378: case '8':
379: d = 60;
380: break;
381: case '9':
382: d = 61;
383: break;
384: case '+':
385: d = 62;
386: break;
387: case '/':
388: d = 63;
389: break;
390: default:
391: // Any character not in Base64 alphabet is treated
392: // as end of data. This includes the '=' (pad) char.
393: break decode; // Skip illegal characters.
394: }
395: bgroup[i++] = d;
396: if (i >= 4) {
397: i = 0;
398: group = ((bgroup[0] & 63) << 18)
399: + ((bgroup[1] & 63) << 12)
400: + ((bgroup[2] & 63) << 6)
401: + (bgroup[3] & 63);
402: outstr.writeByte(((group >> 16) & 255));
403: outstr.writeByte(((group >> 8) & 255));
404: outstr.writeByte(group & 255);
405: }
406: }
407: // Handle the case of remaining characters and
408: // pad handling. If input is not a multiple of 4
409: // in length, then '=' pads are assumed.
410: switch (i) {
411: case 2:
412: // One output byte from two input bytes.
413: group = ((bgroup[0] & 63) << 18)
414: + ((bgroup[1] & 63) << 12);
415: outstr.writeByte(((group >> 16) & 255));
416: break;
417: case 3:
418: // Two output bytes from three input bytes.
419: group = ((bgroup[0] & 63) << 18)
420: + ((bgroup[1] & 63) << 12)
421: + ((bgroup[2] & 63) << 6);
422: outstr.writeByte(((group >> 16) & 255));
423: outstr.writeByte(((group >> 8) & 255));
424: break;
425: default:
426: // Any other case, including correct 0, is treated as
427: // end of data.
428: break;
429: }
430: outstr.flush();
431: return bytestr.toByteArray();
432: } catch (IOException e) {
433: } // Won't happen. Return null if it does.
434: return null;
435: }
436: }
|