KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > prefs > Base64


1 /*
2  * @(#)Base64.java 1.5 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.util.prefs;
9
10 /**
11  * Static methods for translating Base64 encoded strings to byte arrays
12  * and vice-versa.
13  *
14  * @author Josh Bloch
15  * @version 1.5, 12/19/03
16  * @see Preferences
17  * @since 1.4
18  */

19 class Base64 {
20     /**
21      * Translates the specified byte array into a Base64 string as per
22      * Preferences.put(byte[]).
23      */

24     static String JavaDoc byteArrayToBase64(byte[] a) {
25         return byteArrayToBase64(a, false);
26     }
27
28     /**
29      * Translates the specified byte array into an "aternate representation"
30      * Base64 string. This non-standard variant uses an alphabet that does
31      * not contain the uppercase alphabetic characters, which makes it
32      * suitable for use in situations where case-folding occurs.
33      */

34     static String JavaDoc byteArrayToAltBase64(byte[] a) {
35         return byteArrayToBase64(a, true);
36     }
37
38     private static String JavaDoc byteArrayToBase64(byte[] a, boolean alternate) {
39         int aLen = a.length;
40         int numFullGroups = aLen/3;
41         int numBytesInPartialGroup = aLen - 3*numFullGroups;
42         int resultLen = 4*((aLen + 2)/3);
43         StringBuffer JavaDoc result = new StringBuffer JavaDoc(resultLen);
44         char[] intToAlpha = (alternate ? intToAltBase64 : intToBase64);
45
46         // Translate all full groups from byte array elements to Base64
47
int inCursor = 0;
48         for (int i=0; i<numFullGroups; i++) {
49             int byte0 = a[inCursor++] & 0xff;
50             int byte1 = a[inCursor++] & 0xff;
51             int byte2 = a[inCursor++] & 0xff;
52             result.append(intToAlpha[byte0 >> 2]);
53             result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
54             result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
55             result.append(intToAlpha[byte2 & 0x3f]);
56         }
57
58         // Translate partial group if present
59
if (numBytesInPartialGroup != 0) {
60             int byte0 = a[inCursor++] & 0xff;
61             result.append(intToAlpha[byte0 >> 2]);
62             if (numBytesInPartialGroup == 1) {
63                 result.append(intToAlpha[(byte0 << 4) & 0x3f]);
64                 result.append("==");
65             } else {
66                 // assert numBytesInPartialGroup == 2;
67
int byte1 = a[inCursor++] & 0xff;
68                 result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
69                 result.append(intToAlpha[(byte1 << 2)&0x3f]);
70                 result.append('=');
71             }
72         }
73         // assert inCursor == a.length;
74
// assert result.length() == resultLen;
75
return result.toString();
76     }
77
78     /**
79      * This array is a lookup table that translates 6-bit positive integer
80      * index values into their "Base64 Alphabet" equivalents as specified
81      * in Table 1 of RFC 2045.
82      */

83     private static final char intToBase64[] = {
84         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
85         'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
86         'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
87         'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
88         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
89     };
90
91     /**
92      * This array is a lookup table that translates 6-bit positive integer
93      * index values into their "Alternate Base64 Alphabet" equivalents.
94      * This is NOT the real Base64 Alphabet as per in Table 1 of RFC 2045.
95      * This alternate alphabet does not use the capital letters. It is
96      * designed for use in environments where "case folding" occurs.
97      */

98     private static final char intToAltBase64[] = {
99         '!', '"', '#', '$', '%', '&', '\'', '(', ')', ',', '-', '.', ':',
100         ';', '<', '>', '@', '[', ']', '^', '`', '_', '{', '|', '}', '~',
101         'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
102         'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
103         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '?'
104     };
105
106     /**
107      * Translates the specified Base64 string (as per Preferences.get(byte[]))
108      * into a byte array.
109      *
110      * @throw IllegalArgumentException if <tt>s</tt> is not a valid Base64
111      * string.
112      */

113     static byte[] base64ToByteArray(String JavaDoc s) {
114         return base64ToByteArray(s, false);
115     }
116
117     /**
118      * Translates the specified "aternate representation" Base64 string
119      * into a byte array.
120      *
121      * @throw IllegalArgumentException or ArrayOutOfBoundsException
122      * if <tt>s</tt> is not a valid alternate representation
123      * Base64 string.
124      */

125     static byte[] altBase64ToByteArray(String JavaDoc s) {
126         return base64ToByteArray(s, true);
127     }
128
129     private static byte[] base64ToByteArray(String JavaDoc s, boolean alternate) {
130         byte[] alphaToInt = (alternate ? altBase64ToInt : base64ToInt);
131         int sLen = s.length();
132         int numGroups = sLen/4;
133         if (4*numGroups != sLen)
134             throw new IllegalArgumentException JavaDoc(
135                 "String length must be a multiple of four.");
136         int missingBytesInLastGroup = 0;
137         int numFullGroups = numGroups;
138         if (sLen != 0) {
139             if (s.charAt(sLen-1) == '=') {
140                 missingBytesInLastGroup++;
141                 numFullGroups--;
142             }
143             if (s.charAt(sLen-2) == '=')
144                 missingBytesInLastGroup++;
145         }
146         byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
147
148         // Translate all full groups from base64 to byte array elements
149
int inCursor = 0, outCursor = 0;
150         for (int i=0; i<numFullGroups; i++) {
151             int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
152             int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
153             int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
154             int ch3 = base64toInt(s.charAt(inCursor++), alphaToInt);
155             result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
156             result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
157             result[outCursor++] = (byte) ((ch2 << 6) | ch3);
158         }
159
160         // Translate partial group, if present
161
if (missingBytesInLastGroup != 0) {
162             int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
163             int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
164             result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
165
166             if (missingBytesInLastGroup == 1) {
167                 int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
168                 result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
169             }
170         }
171         // assert inCursor == s.length()-missingBytesInLastGroup;
172
// assert outCursor == result.length;
173
return result;
174     }
175
176     /**
177      * Translates the specified character, which is assumed to be in the
178      * "Base 64 Alphabet" into its equivalent 6-bit positive integer.
179      *
180      * @throw IllegalArgumentException or ArrayOutOfBoundsException if
181      * c is not in the Base64 Alphabet.
182      */

183     private static int base64toInt(char c, byte[] alphaToInt) {
184         int result = alphaToInt[c];
185         if (result < 0)
186             throw new IllegalArgumentException JavaDoc("Illegal character " + c);
187         return result;
188     }
189
190     /**
191      * This array is a lookup table that translates unicode characters
192      * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
193      * into their 6-bit positive integer equivalents. Characters that
194      * are not in the Base64 alphabet but fall within the bounds of the
195      * array are translated to -1.
196      */

197     private static final byte base64ToInt[] = {
198         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
199         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
200         -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
201         55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
202         5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
203         24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
204         35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
205     };
206
207     /**
208      * This array is the analogue of base64ToInt, but for the nonstandard
209      * variant that avoids the use of uppercase alphabetic characters.
210      */

211     private static final byte altBase64ToInt[] = {
212         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
213         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
214         2, 3, 4, 5, 6, 7, 8, -1, 62, 9, 10, 11, -1 , 52, 53, 54, 55, 56, 57,
215         58, 59, 60, 61, 12, 13, 14, -1, 15, 63, 16, -1, -1, -1, -1, -1, -1,
216         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
217         -1, -1, -1, 17, -1, 18, 19, 21, 20, 26, 27, 28, 29, 30, 31, 32, 33,
218         34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
219         51, 22, 23, 24, 25
220     };
221     
222     public static void main(String JavaDoc args[]) {
223         int numRuns = Integer.parseInt(args[0]);
224         int numBytes = Integer.parseInt(args[1]);
225         java.util.Random JavaDoc rnd = new java.util.Random JavaDoc();
226         for (int i=0; i<numRuns; i++) {
227             for (int j=0; j<numBytes; j++) {
228                 byte[] arr = new byte[j];
229                 for (int k=0; k<j; k++)
230                     arr[k] = (byte)rnd.nextInt();
231
232                 String JavaDoc s = byteArrayToBase64(arr);
233                 byte [] b = base64ToByteArray(s);
234                 if (!java.util.Arrays.equals(arr, b))
235                     System.out.println("Dismal failure!");
236
237                 s = byteArrayToAltBase64(arr);
238                 b = altBase64ToByteArray(s);
239                 if (!java.util.Arrays.equals(arr, b))
240                     System.out.println("Alternate dismal failure!");
241             }
242         }
243     }
244 }
245
Popular Tags