KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > xml > util > Base64


1 /* ========================================================================
2  * JCommon : a free general purpose class library for the Java(tm) platform
3  * ========================================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jcommon/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * -------------------------------------
28  * AbstractElementDefinitionHandler.java
29  * -------------------------------------
30  * (C)opyright 2003-2005, by Thomas Morgner and Contributors.
31  *
32  * Original Author: Kevin Kelley <kelley@ruralnet.net> -
33  * 30718 Rd. 28, La Junta, CO, 81050 USA.
34  *
35  * $Id: Base64.java,v 1.4 2005/10/18 13:33:53 mungady Exp $
36  *
37  * Changes
38  * -------------------------
39  * 23.09.2003 : Initial version
40  *
41  */

42 package org.jfree.xml.util;
43
44 import java.io.BufferedInputStream JavaDoc;
45 import java.io.BufferedOutputStream JavaDoc;
46 import java.io.BufferedReader JavaDoc;
47 import java.io.BufferedWriter JavaDoc;
48 import java.io.ByteArrayOutputStream JavaDoc;
49 import java.io.CharArrayWriter JavaDoc;
50 import java.io.File JavaDoc;
51 import java.io.FileInputStream JavaDoc;
52 import java.io.FileOutputStream JavaDoc;
53 import java.io.FileReader JavaDoc;
54 import java.io.FileWriter JavaDoc;
55 import java.io.InputStream JavaDoc;
56 import java.io.OutputStream JavaDoc;
57 import java.io.Reader JavaDoc;
58 import java.io.Writer JavaDoc;
59
60 /**
61  * Provides encoding of raw bytes to base64-encoded characters, and
62  * decoding of base64 characters to raw bytes.
63  * date: 06 August 1998
64  * modified: 14 February 2000
65  * modified: 22 September 2000
66  *
67  * @author Kevin Kelley (kelley@ruralnet.net)
68  * @version 1.3
69  */

70 public class Base64 {
71
72   private Base64 ()
73   {
74   }
75
76     /**
77      * returns an array of base64-encoded characters to represent the
78      * passed data array.
79      *
80      * @param data the array of bytes to encode
81      * @return base64-coded character array.
82      */

83     public static char[] encode(final byte[] data) {
84         final char[] out = new char[((data.length + 2) / 3) * 4];
85
86         //
87
// 3 bytes encode to 4 chars. Output is always an even
88
// multiple of 4 characters.
89
//
90
for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {
91             boolean quad = false;
92             boolean trip = false;
93
94             int val = (0xFF & data[i]);
95             val <<= 8;
96             if ((i + 1) < data.length) {
97                 val |= (0xFF & data[i + 1]);
98                 trip = true;
99             }
100             val <<= 8;
101             if ((i + 2) < data.length) {
102                 val |= (0xFF & data[i + 2]);
103                 quad = true;
104             }
105             out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
106             val >>= 6;
107             out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
108             val >>= 6;
109             out[index + 1] = alphabet[val & 0x3F];
110             val >>= 6;
111             out[index + 0] = alphabet[val & 0x3F];
112         }
113         return out;
114     }
115
116     /**
117      * Decodes a BASE-64 encoded stream to recover the original
118      * data. White space before and after will be trimmed away,
119      * but no other manipulation of the input will be performed.
120      *
121      * As of version 1.2 this method will properly handle input
122      * containing junk characters (newlines and the like) rather
123      * than throwing an error. It does this by pre-parsing the
124      * input and generating from that a count of VALID input
125      * characters.
126      *
127      * @param data the character data.
128      *
129      * @return The decoded data.
130      */

131     public static byte[] decode(final char[] data) {
132         // as our input could contain non-BASE64 data (newlines,
133
// whitespace of any sort, whatever) we must first adjust
134
// our count of USABLE data so that...
135
// (a) we don't misallocate the output array, and
136
// (b) think that we miscalculated our data length
137
// just because of extraneous throw-away junk
138

139         int tempLen = data.length;
140         for (int ix = 0; ix < data.length; ix++) {
141             if ((data[ix] > 255) || codes[data[ix]] < 0) {
142                 --tempLen; // ignore non-valid chars and padding
143
}
144         }
145         // calculate required length:
146
// -- 3 bytes for every 4 valid base64 chars
147
// -- plus 2 bytes if there are 3 extra base64 chars,
148
// or plus 1 byte if there are 2 extra.
149

150         int len = (tempLen / 4) * 3;
151         if ((tempLen % 4) == 3) {
152             len += 2;
153         }
154         if ((tempLen % 4) == 2) {
155             len += 1;
156         }
157
158         final byte[] out = new byte[len];
159
160
161         int shift = 0; // # of excess bits stored in accum
162
int accum = 0; // excess bits
163
int index = 0;
164
165         // we now go through the entire array (NOT using the 'tempLen' value)
166
for (int ix = 0; ix < data.length; ix++) {
167             final int value = (data[ix] > 255) ? -1 : codes[data[ix]];
168
169             if (value >= 0) { // skip over non-code
170
accum <<= 6; // bits shift up by 6 each time thru
171
shift += 6; // loop, with new bits being put in
172
accum |= value; // at the bottom.
173
if (shift >= 8) { // whenever there are 8 or more shifted in,
174
shift -= 8; // write them out (from the top, leaving any
175
out[index++] = // excess at the bottom for next iteration.
176
(byte) ((accum >> shift) & 0xff);
177                 }
178             }
179             // we will also have skipped processing a padding null byte ('=') here;
180
// these are used ONLY for padding to an even length and do not legally
181
// occur as encoded data. for this reason we can ignore the fact that
182
// no index++ operation occurs in that special case: the out[] array is
183
// initialized to all-zero bytes to start with and that works to our
184
// advantage in this combination.
185
}
186
187         // if there is STILL something wrong we just have to throw up now!
188
if (index != out.length) {
189             throw new Error JavaDoc("Miscalculated data length (wrote "
190                 + index + " instead of " + out.length + ")");
191         }
192
193         return out;
194     }
195
196
197     //
198
// code characters for values 0..63
199
//
200
private static char[] alphabet =
201         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();
202
203     //
204
// lookup table for converting base64 characters to value in range 0..63
205
//
206
private static byte[] codes = new byte[256];
207
208     static {
209         for (int i = 0; i < 256; i++) {
210             codes[i] = -1;
211         }
212         for (int i = 'A'; i <= 'Z'; i++) {
213             codes[i] = (byte) (i - 'A');
214         }
215         for (int i = 'a'; i <= 'z'; i++) {
216             codes[i] = (byte) (26 + i - 'a');
217         }
218         for (int i = '0'; i <= '9'; i++) {
219             codes[i] = (byte) (52 + i - '0');
220         }
221         codes['+'] = 62;
222         codes['/'] = 63;
223     }
224
225
226
227
228     ///////////////////////////////////////////////////
229
// remainder (main method and helper functions) is
230
// for testing purposes only, feel free to clip it.
231
///////////////////////////////////////////////////
232

233     /**
234      * Entry point.
235      *
236      * @param args the command line arguments.
237      */

238     public static void main(final String JavaDoc[] args) {
239         boolean decode = false;
240
241         if (args.length == 0) {
242             System.out.println("usage: java Base64 [-d[ecode]] filename");
243             System.exit(0);
244         }
245         for (int i = 0; i < args.length; i++) {
246             if ("-decode".equalsIgnoreCase(args[i])) {
247                 decode = true;
248             }
249             else if ("-d".equalsIgnoreCase(args[i])) {
250                 decode = true;
251             }
252         }
253
254         final String JavaDoc filename = args[args.length - 1];
255         final File JavaDoc file = new File JavaDoc(filename);
256         if (!file.exists()) {
257             System.out.println("Error: file '" + filename + "' doesn't exist!");
258             System.exit(0);
259         }
260
261         if (decode) {
262             final char[] encoded = readChars(file);
263             final byte[] decoded = decode(encoded);
264             writeBytes(file, decoded);
265         }
266         else {
267             final byte[] decoded = readBytes(file);
268             final char[] encoded = encode(decoded);
269             writeChars(file, encoded);
270         }
271     }
272
273     private static byte[] readBytes(final File JavaDoc file) {
274         final ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
275         try {
276             final InputStream JavaDoc fis = new FileInputStream JavaDoc(file);
277             final InputStream JavaDoc is = new BufferedInputStream JavaDoc(fis);
278
279             int count;
280             final byte[] buf = new byte[16384];
281             while ((count = is.read(buf)) != -1) {
282                 if (count > 0) {
283                     baos.write(buf, 0, count);
284                 }
285             }
286             is.close();
287         }
288         catch (Exception JavaDoc e) {
289             e.printStackTrace();
290         }
291
292         return baos.toByteArray();
293     }
294
295     private static char[] readChars(final File JavaDoc file) {
296         final CharArrayWriter JavaDoc caw = new CharArrayWriter JavaDoc();
297         try {
298             final Reader JavaDoc fr = new FileReader JavaDoc(file);
299             final Reader JavaDoc in = new BufferedReader JavaDoc(fr);
300             int count;
301             final char[] buf = new char[16384];
302             while ((count = in.read(buf)) != -1) {
303                 if (count > 0) {
304                     caw.write(buf, 0, count);
305                 }
306             }
307             in.close();
308         }
309         catch (Exception JavaDoc e) {
310             e.printStackTrace();
311         }
312
313         return caw.toCharArray();
314     }
315
316     private static void writeBytes(final File JavaDoc file, final byte[] data) {
317         try {
318             final OutputStream JavaDoc fos = new FileOutputStream JavaDoc(file);
319             final OutputStream JavaDoc os = new BufferedOutputStream JavaDoc(fos);
320             os.write(data);
321             os.close();
322         }
323         catch (Exception JavaDoc e) {
324             e.printStackTrace();
325         }
326     }
327
328     private static void writeChars(final File JavaDoc file, final char[] data) {
329         try {
330             final Writer JavaDoc fos = new FileWriter JavaDoc(file);
331             final Writer JavaDoc os = new BufferedWriter JavaDoc(fos);
332             os.write(data);
333             os.close();
334         }
335         catch (Exception JavaDoc e) {
336             e.printStackTrace();
337         }
338     }
339     ///////////////////////////////////////////////////
340
// end of test code.
341
///////////////////////////////////////////////////
342

343 }
344
Popular Tags