KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > util > Base64Encoder


1
2 /*
3  * Enhydra Java Application Server Project
4  *
5  * The contents of this file are subject to the Enhydra Public License
6  * Version 1.1 (the "License"); you may not use this file except in
7  * compliance with the License. You may obtain a copy of the License on
8  * the Enhydra web site ( http://www.enhydra.org/ ).
9  *
10  * Software distributed under the License is distributed on an "AS IS"
11  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
12  * the License for the specific terms governing rights and limitations
13  * under the License.
14  *
15  * The Initial Developer of the Enhydra Application Server is Lutris
16  * Technologies, Inc. The Enhydra Application Server and portions created
17  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
18  * All Rights Reserved.
19  *
20  * Contributor(s):
21  *
22  * $Id: Base64Encoder.java,v 1.2 2005/03/24 10:51:25 slobodan Exp $
23  */

24
25
26
27
28 package com.lutris.util;
29 import java.io.ByteArrayOutputStream JavaDoc;
30 import java.io.DataOutputStream JavaDoc;
31 import java.io.IOException JavaDoc;
32 import java.text.CharacterIterator JavaDoc;
33 import java.text.StringCharacterIterator JavaDoc;
34
35 /**
36  * Various conversion methods.
37  * These methods are mostly used to convert internal java data
38  * fields into byte arrays or strings for use over the network.
39  *
40  * @author Mike Ward
41  *
42  */

43 public class Base64Encoder {
44
45     /**
46      * The BASE64 encoding standard's 6-bit alphabet, from RFC 1521,
47      * plus the padding character at the end.
48      */

49     private static final char[] Base64Chars = {
50     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
51     'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
52     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
53     'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
54     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
55     'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
56     'w', 'x', 'y', 'z', '0', '1', '2', '3',
57     '4', '5', '6', '7', '8', '9', '+', '/',
58         '='
59     };
60
61     /**
62      * Encoding alphabet for session keys. Contains only chars that
63      * are safe to use in cookies, URLs and file names. Same as BASE64
64      * except the last two chars and the padding char
65      */

66     private static final
67     char[] SessionKeyChars =
68     {
69     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
70     'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
71     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
72     'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
73     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
74     'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
75     'w', 'x', 'y', 'z', '0', '1', '2', '3',
76     '4', '5', '6', '7', '8', '9', '_', '-',
77         '.'
78     };
79
80     /**
81      * Performs RFC1521 style Base64 encoding of arbitrary binary data.
82      * The output is a java String containing the Base64 characters
83      * representing the binary data. Be aware that this string is in
84      * Unicode form, and should be converted to UTF8 with the usual java
85      * conversion routines before it is sent over a network. The output
86      * string is guaranteed to only contain characters that are a single
87      * byte in UTF8 format. Also be aware that this routine leaves it to
88      * the caller to break the string into 70 byte lines as per RFC1521.
89      *
90      * @param bytes The array of bytes to convert to Base64 encoding.
91      * @return An string containing the specified bytes in Base64
92      * encoded form.
93      */

94     public static final String JavaDoc toBase64String(byte[] bytes) {
95         return toBase64String(bytes, Base64Chars);
96     }
97
98     /**
99      * The encoding is more or less Base 64, but instead of '+'
100      * and '/' as defined in RFC1521, the characters '_' and
101      * '-' are used because they are safe in URLs and file names.
102      *
103      * @param bytes The array of bytes to convert to Base64SessionKey
104      * encoding.
105      * @return An string containing the specified bytes in Base64
106      * encoded form.
107      */

108     public static final String JavaDoc toBase64SessionKeyString(byte[] bytes) {
109         return toBase64String(bytes, SessionKeyChars);
110     }
111     
112     /**
113      * Performs encoding of arbitrary binary data based on a 6 bit
114      * alphabet. The output is a java String containing the encoded
115      * characters representing the binary data. Be aware that this
116      * string is in Unicode form, and should be converted to UTF8 with
117      * the usual java conversion routines before it is sent over a
118      * network. The alphabet passed in via <code>chars</code> is used
119      * without further checks, it's the callers responsibility to set
120      * it to something meaningful.
121      *
122      * @param bytes The array of bytes to convert to Base64 encoding.
123      * @param chars The alphabet used in encoding. Must contain
124      * exactly 65 characters: A 6 bit alphabet plus one
125      * padding char at position 65.
126      * @return An string containing the specified bytes in Base64
127      * encoded form.
128      */

129     private static final String JavaDoc toBase64String(byte[] bytes, char[] chars) {
130     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
131     int len = bytes.length, i=0, ival;
132     while (len >= 3) {
133         ival = ((int)bytes[i++] + 256) & 0xff;
134         ival <<= 8;
135         ival += ((int)bytes[i++] + 256) & 0xff;
136         ival <<= 8;
137         ival += ((int)bytes[i++] + 256) & 0xff;
138         len -= 3;
139         sb.append(chars[(ival >> 18) & 63]);
140         sb.append(chars[(ival >> 12) & 63]);
141         sb.append(chars[(ival >> 6) & 63]);
142         sb.append(chars[ival & 63]);
143     }
144     switch (len) {
145         case 0: // No pads needed.
146
break;
147         case 1: // Two more output bytes and two pads.
148
ival = ((int)bytes[i++] + 256) & 0xff;
149         ival <<= 16;
150         sb.append(chars[(ival >> 18) & 63]);
151         sb.append(chars[(ival >> 12) & 63]);
152         sb.append(chars[64]);
153         sb.append(chars[64]);
154         break;
155         case 2: // Three more output bytes and one pad.
156
ival = ((int)bytes[i++] + 256) & 0xff;
157         ival <<= 8;
158         ival += ((int)bytes[i] + 256) & 0xff;
159         ival <<= 8;
160         sb.append(chars[(ival >> 18) & 63]);
161         sb.append(chars[(ival >> 12) & 63]);
162         sb.append(chars[(ival >> 6) & 63]);
163         sb.append(chars[64]);
164         break;
165     }
166     return new String JavaDoc(sb);
167     }
168     
169     /**
170      * Performs RFC1521 style Base64 decoding of Base64 encoded data.
171      * The output is a byte array containing the decoded binary data.
172      * The input is expected to be a normal Unicode String object.
173      *
174      * @param s The Base64 encoded string to decode into binary data.
175      * @return An array of bytes containing the decoded data.
176      */

177     public static final byte[] fromBase64String(String JavaDoc s) {
178     try {
179         StringCharacterIterator JavaDoc iter = new StringCharacterIterator JavaDoc(s);
180         ByteArrayOutputStream JavaDoc bytestr = new ByteArrayOutputStream JavaDoc();
181         DataOutputStream JavaDoc outstr = new DataOutputStream JavaDoc(bytestr);
182         char c;
183         int d, i, group;
184         int[] bgroup = new int[4];
185         decode: for (i=0, group=0, c = iter.first();
186              c != CharacterIterator.DONE;
187              c = iter.next())
188         {
189         switch (c) {
190             case 'A': d = 0; break; case 'B': d = 1; break;
191             case 'C': d = 2; break; case 'D': d = 3; break;
192             case 'E': d = 4; break; case 'F': d = 5; break;
193             case 'G': d = 6; break; case 'H': d = 7; break;
194             case 'I': d = 8; break; case 'J': d = 9; break;
195             case 'K': d = 10; break; case 'L': d = 11; break;
196             case 'M': d = 12; break; case 'N': d = 13; break;
197             case 'O': d = 14; break; case 'P': d = 15; break;
198             case 'Q': d = 16; break; case 'R': d = 17; break;
199             case 'S': d = 18; break; case 'T': d = 19; break;
200             case 'U': d = 20; break; case 'V': d = 21; break;
201             case 'W': d = 22; break; case 'X': d = 23; break;
202             case 'Y': d = 24; break; case 'Z': d = 25; break;
203             case 'a': d = 26; break; case 'b': d = 27; break;
204             case 'c': d = 28; break; case 'd': d = 29; break;
205             case 'e': d = 30; break; case 'f': d = 31; break;
206             case 'g': d = 32; break; case 'h': d = 33; break;
207             case 'i': d = 34; break; case 'j': d = 35; break;
208             case 'k': d = 36; break; case 'l': d = 37; break;
209             case 'm': d = 38; break; case 'n': d = 39; break;
210             case 'o': d = 40; break; case 'p': d = 41; break;
211             case 'q': d = 42; break; case 'r': d = 43; break;
212             case 's': d = 44; break; case 't': d = 45; break;
213             case 'u': d = 46; break; case 'v': d = 47; break;
214             case 'w': d = 48; break; case 'x': d = 49; break;
215             case 'y': d = 50; break; case 'z': d = 51; break;
216             case '0': d = 52; break; case '1': d = 53; break;
217             case '2': d = 54; break; case '3': d = 55; break;
218             case '4': d = 56; break; case '5': d = 57; break;
219             case '6': d = 58; break; case '7': d = 59; break;
220             case '8': d = 60; break; case '9': d = 61; break;
221             case '+': d = 62; break; case '/': d = 63; break;
222             case '_': d = 62; break; case '-': d = 63; break;
223             default:
224             // Any character not in Base64 alphabet is treated
225
// as end of data. This includes the '=' (pad) char.
226
break decode; // Skip illegal characters.
227
}
228         bgroup[i++] = d;
229         if (i >= 4) {
230             i = 0;
231             group = ((bgroup[0] & 63) << 18)+((bgroup[1] & 63) << 12)+
232                 ((bgroup[2] & 63) << 6) + (bgroup[3] & 63);
233             outstr.writeByte(((group >> 16) & 255));
234             outstr.writeByte(((group >> 8) & 255));
235             outstr.writeByte(group & 255);
236         }
237         }
238         // Handle the case of remaining characters and
239
// pad handling. If input is not a multiple of 4
240
// in length, then '=' pads are assumed.
241
switch (i) {
242         case 2:
243             // One output byte from two input bytes.
244
group = ((bgroup[0] & 63) << 18)+((bgroup[1] & 63) << 12);
245             outstr.writeByte(((group >> 16) & 255));
246             break;
247         case 3:
248             // Two output bytes from three input bytes.
249
group = ((bgroup[0] & 63) << 18)+((bgroup[1] & 63) << 12)+
250                 ((bgroup[2] & 63) << 6);
251             outstr.writeByte(((group >> 16) & 255));
252             outstr.writeByte(((group >> 8) & 255));
253             break;
254         default:
255             // Any other case, including correct 0, is treated as
256
// end of data.
257
break;
258         }
259         outstr.flush();
260         return bytestr.toByteArray();
261     }
262     catch (IOException JavaDoc e) {} // Won't happen. Return null if it does.
263
return null;
264     }
265 }
266
267
Popular Tags