Source Code Cross Referenced for Base64.java in  » Groupware » LibreSource » org » libresource » so6 » core » engine » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Groupware » LibreSource » org.libresource.so6.core.engine.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * LibreSource
0003:         * Copyright (C) 2004-2008 Artenum SARL / INRIA
0004:         * http://www.libresource.org - contact@artenum.com
0005:         *
0006:         * This file is part of the LibreSource software, 
0007:         * which can be used and distributed under license conditions.
0008:         * The license conditions are provided in the LICENSE.TXT file 
0009:         * at the root path of the packaging that enclose this file. 
0010:         * More information can be found at 
0011:         * - http://dev.libresource.org/home/license
0012:         *
0013:         * Initial authors :
0014:         *
0015:         * Guillaume Bort / INRIA
0016:         * Francois Charoy / Universite Nancy 2
0017:         * Julien Forest / Artenum
0018:         * Claude Godart / Universite Henry Poincare
0019:         * Florent Jouille / INRIA
0020:         * Sebastien Jourdain / INRIA / Artenum
0021:         * Yves Lerumeur / Artenum
0022:         * Pascal Molli / Universite Henry Poincare
0023:         * Gerald Oster / INRIA
0024:         * Mariarosa Penzi / Artenum
0025:         * Gerard Sookahet / Artenum
0026:         * Raphael Tani / INRIA
0027:         *
0028:         * Contributors :
0029:         *
0030:         * Stephane Bagnier / Artenum
0031:         * Amadou Dia / Artenum-IUP Blois
0032:         * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0033:         */package org.libresource.so6.core.engine.util;
0034:
0035:        /**
0036:         * Encodes and decodes to and from Base64 notation.
0037:         *
0038:         * <p>
0039:         * Change Log:
0040:         * </p>
0041:         * <ul>
0042:         * <li>v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on
0043:         * systems with other encodings (like EBCDIC).</li>
0044:         * <li>v2.0.1 - Fixed an error when decoding a single byte, that is, when the
0045:         * encoded data was a single byte.</li>
0046:         * <li>v2.0 - I got rid of methods that used booleans to set options. Now
0047:         * everything is more consolidated and cleaner. The code now detects when data
0048:         * that's being decoded is gzip-compressed and will decompress it automatically.
0049:         * Generally things are cleaner. You'll probably have to change some method
0050:         * calls that you were making to support the new options format (<tt>int</tt>
0051:         * s that you "OR" together).</li>
0052:         * <li>v1.5.1 - Fixed bug when decompressing and decoding to a byte[] using
0053:         * <tt>decode( String s, boolean gzipCompressed )</tt>. Added the ability to
0054:         * "suspend" encoding in the Output Stream so you can turn on and off the
0055:         * encoding if you need to embed base64 data in an otherwise "normal" stream
0056:         * (like an XML file).</li>
0057:         * <li>v1.5 - Output stream pases on flush() command but doesn't do anything
0058:         * itself. This helps when using GZIP streams. Added the ability to
0059:         * GZip-compress objects before encoding them.</li>
0060:         * <li>v1.4 - Added helper methods to read/write files.</li>
0061:         * <li>v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.</li>
0062:         * <li>v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input
0063:         * stream where last buffer being read, if not completely full, was not
0064:         * returned.</li>
0065:         * <li>v1.3.4 - Fixed when "improperly padded stream" error was thrown at the
0066:         * wrong time.</li>
0067:         * <li>v1.3.3 - Fixed I/O streams which were totally messed up.</li>
0068:         * </ul>
0069:         *
0070:         * <p>
0071:         * I am placing this code in the Public Domain. Do with it as you will. This
0072:         * software comes with no guarantees or warranties but with plenty of
0073:         * well-wishing instead! Please visit <a
0074:         * href="http://iharder.net/xmlizable">http://iharder.net/base64 </a>
0075:         * periodically to check for updates or to contribute improvements.
0076:         * </p>
0077:         *
0078:         * @author Robert Harder
0079:         * @author rob@iharder.net
0080:         * @version 2.0
0081:         */
0082:        public class Base64 {
0083:            /* ******** P U B L I C F I E L D S ******** */
0084:
0085:            /** No options specified. Value is zero. */
0086:            public final static int NO_OPTIONS = 0;
0087:
0088:            /** Specify encoding. */
0089:            public final static int ENCODE = 1;
0090:
0091:            /** Specify decoding. */
0092:            public final static int DECODE = 0;
0093:
0094:            /** Specify that data should be gzip-compressed. */
0095:            public final static int GZIP = 2;
0096:
0097:            /** Don't break lines when encoding (violates strict Base64 specification) */
0098:            public final static int DONT_BREAK_LINES = 8;
0099:
0100:            /* ******** P R I V A T E F I E L D S ******** */
0101:
0102:            /** Maximum line length (76) of Base64 output. */
0103:            private final static int MAX_LINE_LENGTH = 76;
0104:
0105:            /** The equals sign (=) as a byte. */
0106:            private final static byte EQUALS_SIGN = (byte) '=';
0107:
0108:            /** The new line character (\n) as a byte. */
0109:            private final static byte NEW_LINE = (byte) '\n';
0110:
0111:            /** Preferred encoding. */
0112:            private final static String PREFERRED_ENCODING = "UTF-8";
0113:
0114:            /** The 64 valid Base64 values. */
0115:            private final static byte[] ALPHABET;
0116:            private final static byte[] _NATIVE_ALPHABET = /* May be something funny like EBCDIC */{
0117:                    (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E',
0118:                    (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J',
0119:                    (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O',
0120:                    (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T',
0121:                    (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y',
0122:                    (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd',
0123:                    (byte) 'e', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i',
0124:                    (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n',
0125:                    (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's',
0126:                    (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x',
0127:                    (byte) 'y', (byte) 'z', (byte) '0', (byte) '1', (byte) '2',
0128:                    (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
0129:                    (byte) '8', (byte) '9', (byte) '+', (byte) '/' };
0130:
0131:            /** Determine which ALPHABET to use. */
0132:            static {
0133:                byte[] __bytes;
0134:
0135:                try {
0136:                    __bytes = new String(
0137:                            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
0138:                            .getBytes(PREFERRED_ENCODING);
0139:                } // end try
0140:                catch (java.io.UnsupportedEncodingException use) {
0141:                    __bytes = _NATIVE_ALPHABET; // Fall back to native encoding
0142:                } // end catch
0143:
0144:                ALPHABET = __bytes;
0145:            } // end static
0146:
0147:            /**
0148:             * Translates a Base64 value to either its 6-bit reconstruction value or a
0149:             * negative number indicating some other meaning.
0150:             */
0151:            private final static byte[] DECODABET = { -9, -9, -9, -9, -9, -9,
0152:                    -9, -9, -9, // Decimal 0 - 8
0153:                    -5, -5, // Whitespace: Tab and Linefeed
0154:                    -9, -9, // Decimal 11 - 12
0155:                    -5, // Whitespace: Carriage Return
0156:                    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 -
0157:                    // 26
0158:                    -9, -9, -9, -9, -9, // Decimal 27 - 31
0159:                    -5, // Whitespace: Space
0160:                    -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
0161:                    62, // Plus sign at decimal 43
0162:                    -9, -9, -9, // Decimal 44 - 46
0163:                    63, // Slash at decimal 47
0164:                    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
0165:                    -9, -9, -9, // Decimal 58 - 60
0166:                    -1, // Equals sign at decimal 61
0167:                    -9, -9, -9, // Decimal 62 - 64
0168:                    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through
0169:                    // 'N'
0170:                    14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O'
0171:                    // through 'Z'
0172:                    -9, -9, -9, -9, -9, -9, // Decimal 91 - 96
0173:                    26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a'
0174:                    // through 'm'
0175:                    39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n'
0176:                    // through 'z'
0177:                    -9, -9, -9, -9 // Decimal 123 - 126
0178:            /*
0179:             * ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 127 - 139
0180:             * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
0181:             * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
0182:             * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
0183:             * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
0184:             * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
0185:             * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
0186:             * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
0187:             * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
0188:             * -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255
0189:             */
0190:            };
0191:            private final static byte BAD_ENCODING = -9; // Indicates error in encoding
0192:            private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in
0193:            // encoding
0194:            private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in
0195:
0196:            // encoding
0197:
0198:            /** Defeats instantiation. */
0199:            private Base64() {
0200:            }
0201:
0202:            /* ******** E N C O D I N G M E T H O D S ******** */
0203:
0204:            /**
0205:             * Encodes the first three bytes of array <var>threeBytes </var> and returns
0206:             * a four-byte array in Base64 notation.
0207:             *
0208:             * @param threeBytes
0209:             *            the array to convert
0210:             * @return four byte array in Base64 notation.
0211:             * @since 1.3
0212:             */
0213:            private static byte[] encode3to4(byte[] threeBytes) {
0214:                return encode3to4(threeBytes, 3);
0215:            } // end encodeToBytes
0216:
0217:            /**
0218:             * Encodes up to the first three bytes of array <var>threeBytes </var> and
0219:             * returns a four-byte array in Base64 notation. The actual number of
0220:             * significant bytes in your array is given by <var>numSigBytes </var>. The
0221:             * array <var>threeBytes </var> needs only be as big as <var>numSigBytes
0222:             * </var>.
0223:             *
0224:             * @param threeBytes
0225:             *            the array to convert
0226:             * @param numSigBytes
0227:             *            the number of significant bytes in your array
0228:             * @return four byte array in Base64 notation.
0229:             * @since 1.3
0230:             */
0231:            private static byte[] encode3to4(byte[] threeBytes, int numSigBytes) {
0232:                byte[] dest = new byte[4];
0233:                encode3to4(threeBytes, 0, numSigBytes, dest, 0);
0234:
0235:                return dest;
0236:            }
0237:
0238:            /**
0239:             * Encodes up to the first three bytes of array <var>threeBytes </var> and
0240:             * returns a four-byte array in Base64 notation. The actual number of
0241:             * significant bytes in your array is given by <var>numSigBytes </var>. The
0242:             * array <var>threeBytes </var> needs only be as big as <var>numSigBytes
0243:             * </var>. Code can reuse a byte array by passing a four-byte array as
0244:             * <var>b4 </var>.
0245:             *
0246:             * @param b4
0247:             *            A reusable byte array to reduce array instantiation
0248:             * @param threeBytes
0249:             *            the array to convert
0250:             * @param numSigBytes
0251:             *            the number of significant bytes in your array
0252:             * @return four byte array in Base64 notation.
0253:             * @since 1.5.1
0254:             */
0255:            private static byte[] encode3to4(byte[] b4, byte[] threeBytes,
0256:                    int numSigBytes) {
0257:                encode3to4(threeBytes, 0, numSigBytes, b4, 0);
0258:
0259:                return b4;
0260:            } // end encode3to4
0261:
0262:            /**
0263:             * Encodes up to three bytes of the array <var>source </var> and writes the
0264:             * resulting four Base64 bytes to <var>destination </var>. The source and
0265:             * destination arrays can be manipulated anywhere along their length by
0266:             * specifying <var>srcOffset </var> and <var>destOffset </var>. This method
0267:             * does not check to make sure your arrays are large enough to accomodate
0268:             * <var>srcOffset </var>+ 3 for the <var>source </var> array or
0269:             * <var>destOffset </var>+ 4 for the <var>destination </var> array. The
0270:             * actual number of significant bytes in your array is given by
0271:             * <var>numSigBytes </var>.
0272:             *
0273:             * @param source
0274:             *            the array to convert
0275:             * @param srcOffset
0276:             *            the index where conversion begins
0277:             * @param numSigBytes
0278:             *            the number of significant bytes in your array
0279:             * @param destination
0280:             *            the array to hold the conversion
0281:             * @param destOffset
0282:             *            the index where output will be put
0283:             * @return the <var>destination </var> array
0284:             * @since 1.3
0285:             */
0286:            private static byte[] encode3to4(byte[] source, int srcOffset,
0287:                    int numSigBytes, byte[] destination, int destOffset) {
0288:                //           1 2 3
0289:                // 01234567890123456789012345678901 Bit position
0290:                // --------000000001111111122222222 Array position from threeBytes
0291:                // --------| || || || | Six bit groups to index ALPHABET
0292:                //          >>18 >>12 >> 6 >> 0 Right shift necessary
0293:                //                0x3f 0x3f 0x3f Additional AND
0294:                // Create buffer with zero-padding if there are only one or two
0295:                // significant bytes passed in the array.
0296:                // We have to shift left 24 in order to flush out the 1's that appear
0297:                // when Java treats a value as negative that is cast from a byte to an
0298:                // int.
0299:                int inBuff = ((numSigBytes > 0) ? ((source[srcOffset] << 24) >>> 8)
0300:                        : 0)
0301:                        | ((numSigBytes > 1) ? ((source[srcOffset + 1] << 24) >>> 16)
0302:                                : 0)
0303:                        | ((numSigBytes > 2) ? ((source[srcOffset + 2] << 24) >>> 24)
0304:                                : 0);
0305:
0306:                switch (numSigBytes) {
0307:                case 3:
0308:                    destination[destOffset] = ALPHABET[(inBuff >>> 18)];
0309:                    destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
0310:                    destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
0311:                    destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];
0312:
0313:                    return destination;
0314:
0315:                case 2:
0316:                    destination[destOffset] = ALPHABET[(inBuff >>> 18)];
0317:                    destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
0318:                    destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
0319:                    destination[destOffset + 3] = EQUALS_SIGN;
0320:
0321:                    return destination;
0322:
0323:                case 1:
0324:                    destination[destOffset] = ALPHABET[(inBuff >>> 18)];
0325:                    destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
0326:                    destination[destOffset + 2] = EQUALS_SIGN;
0327:                    destination[destOffset + 3] = EQUALS_SIGN;
0328:
0329:                    return destination;
0330:
0331:                default:
0332:                    return destination;
0333:                } // end switch
0334:            } // end encode3to4
0335:
0336:            /**
0337:             * Serializes an object and returns the Base64-encoded version of that
0338:             * serialized object. If the object cannot be serialized or there is another
0339:             * error, the method will return <tt>null</tt>. The object is not
0340:             * GZip-compressed before being encoded.
0341:             *
0342:             * @param serializableObject
0343:             *            The object to encode
0344:             * @return The Base64-encoded object
0345:             * @since 1.4
0346:             */
0347:            public static String encodeObject(
0348:                    java.io.Serializable serializableObject) {
0349:                return encodeObject(serializableObject, NO_OPTIONS);
0350:            } // end encodeObject
0351:
0352:            /**
0353:             * Serializes an object and returns the Base64-encoded version of that
0354:             * serialized object. If the object cannot be serialized or there is another
0355:             * error, the method will return <tt>null</tt>.
0356:             * <p>
0357:             * Valid options:
0358:             *
0359:             * <pre>
0360:             *
0361:             *    GZIP: gzip-compresses object before encoding it.
0362:             *    DONT_BREAK_LINES: don't break lines at 76 characters
0363:             *      &lt;i&gt;Note: Technically, this makes your encoding non-compliant.&lt;/i&gt;
0364:             *
0365:             * </pre>
0366:             *
0367:             * <p>
0368:             * Example: <code>encodeObject( myObj, Base64.GZIP )</code> or
0369:             * <p>
0370:             * Example:
0371:             * <code>encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
0372:             *
0373:             * @param serializableObject
0374:             *            The object to encode
0375:             * @options Specified options
0376:             * @return The Base64-encoded object
0377:             * @see Base64#GZIP
0378:             * @see Base64#DONT_BREAK_LINES
0379:             * @since 2.0
0380:             */
0381:            public static String encodeObject(
0382:                    java.io.Serializable serializableObject, int options) {
0383:                // Streams
0384:                java.io.ByteArrayOutputStream baos = null;
0385:                java.io.OutputStream b64os = null;
0386:                java.io.ObjectOutputStream oos = null;
0387:                java.util.zip.GZIPOutputStream gzos = null;
0388:
0389:                // Isolate options
0390:                int gzip = (options & GZIP);
0391:                int dontBreakLines = (options & DONT_BREAK_LINES);
0392:
0393:                try {
0394:                    // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
0395:                    baos = new java.io.ByteArrayOutputStream();
0396:                    b64os = new Base64.OutputStream(baos, ENCODE
0397:                            | dontBreakLines);
0398:
0399:                    // GZip?
0400:                    if (gzip == GZIP) {
0401:                        gzos = new java.util.zip.GZIPOutputStream(b64os);
0402:                        oos = new java.io.ObjectOutputStream(gzos);
0403:                    } // end if: gzip
0404:                    else {
0405:                        oos = new java.io.ObjectOutputStream(b64os);
0406:                    }
0407:
0408:                    oos.writeObject(serializableObject);
0409:                } // end try
0410:                catch (java.io.IOException e) {
0411:                    e.printStackTrace();
0412:
0413:                    return null;
0414:                } // end catch
0415:                finally {
0416:                    try {
0417:                        oos.close();
0418:                    } catch (Exception e) {
0419:                    }
0420:
0421:                    try {
0422:                        gzos.close();
0423:                    } catch (Exception e) {
0424:                    }
0425:
0426:                    try {
0427:                        b64os.close();
0428:                    } catch (Exception e) {
0429:                    }
0430:
0431:                    try {
0432:                        baos.close();
0433:                    } catch (Exception e) {
0434:                    }
0435:                } // end finally
0436:
0437:                // Return value according to relevant encoding.
0438:                try {
0439:                    return new String(baos.toByteArray(), PREFERRED_ENCODING);
0440:                } // end try
0441:                catch (java.io.UnsupportedEncodingException uue) {
0442:                    return new String(baos.toByteArray());
0443:                } // end catch
0444:            } // end encode
0445:
0446:            /**
0447:             * Encodes a byte array into Base64 notation. Does not GZip-compress data.
0448:             *
0449:             * @param source
0450:             *            The data to convert
0451:             * @since 1.4
0452:             */
0453:            public static String encodeBytes(byte[] source) {
0454:                return encodeBytes(source, 0, source.length, NO_OPTIONS);
0455:            } // end encodeBytes
0456:
0457:            /**
0458:             * Encodes a byte array into Base64 notation.
0459:             * <p>
0460:             * Valid options:
0461:             *
0462:             * <pre>
0463:             *
0464:             *    GZIP: gzip-compresses object before encoding it.
0465:             *    DONT_BREAK_LINES: don't break lines at 76 characters
0466:             *      &lt;i&gt;Note: Technically, this makes your encoding non-compliant.&lt;/i&gt;
0467:             *
0468:             * </pre>
0469:             *
0470:             * <p>
0471:             * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
0472:             * <p>
0473:             * Example:
0474:             * <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
0475:             *
0476:             *
0477:             * @param source
0478:             *            The data to convert
0479:             * @param options
0480:             *            Specified options
0481:             * @see Base64#GZIP
0482:             * @see Base64#DONT_BREAK_LINES
0483:             * @since 2.0
0484:             */
0485:            public static String encodeBytes(byte[] source, int options) {
0486:                return encodeBytes(source, 0, source.length, options);
0487:            } // end encodeBytes
0488:
0489:            /**
0490:             * Encodes a byte array into Base64 notation. Does not GZip-compress data.
0491:             *
0492:             * @param source
0493:             *            The data to convert
0494:             * @param off
0495:             *            Offset in array where conversion should begin
0496:             * @param len
0497:             *            Length of data to convert
0498:             * @since 1.4
0499:             */
0500:            public static String encodeBytes(byte[] source, int off, int len) {
0501:                return encodeBytes(source, off, len, NO_OPTIONS);
0502:            } // end encodeBytes
0503:
0504:            /**
0505:             * Encodes a byte array into Base64 notation.
0506:             * <p>
0507:             * Valid options:
0508:             *
0509:             * <pre>
0510:             *
0511:             *    GZIP: gzip-compresses object before encoding it.
0512:             *    DONT_BREAK_LINES: don't break lines at 76 characters
0513:             *      &lt;i&gt;Note: Technically, this makes your encoding non-compliant.&lt;/i&gt;
0514:             *
0515:             * </pre>
0516:             *
0517:             * <p>
0518:             * Example: <code>encodeBytes( myData, Base64.GZIP )</code> or
0519:             * <p>
0520:             * Example:
0521:             * <code>encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )</code>
0522:             *
0523:             *
0524:             * @param source
0525:             *            The data to convert
0526:             * @param off
0527:             *            Offset in array where conversion should begin
0528:             * @param len
0529:             *            Length of data to convert
0530:             * @param breakLines
0531:             *            Break lines at 80 characters or less.
0532:             * @param options
0533:             *            Specified options
0534:             * @see Base64#GZIP
0535:             * @see Base64#DONT_BREAK_LINES
0536:             * @since 2.0
0537:             */
0538:            public static String encodeBytes(byte[] source, int off, int len,
0539:                    int options) {
0540:                // Isolate options
0541:                int dontBreakLines = (options & DONT_BREAK_LINES);
0542:                int gzip = (options & GZIP);
0543:
0544:                // Compress?
0545:                if (gzip == GZIP) {
0546:                    java.io.ByteArrayOutputStream baos = null;
0547:                    java.util.zip.GZIPOutputStream gzos = null;
0548:                    Base64.OutputStream b64os = null;
0549:
0550:                    try {
0551:                        // GZip -> Base64 -> ByteArray
0552:                        baos = new java.io.ByteArrayOutputStream();
0553:                        b64os = new Base64.OutputStream(baos, ENCODE
0554:                                | dontBreakLines);
0555:                        gzos = new java.util.zip.GZIPOutputStream(b64os);
0556:                        gzos.write(source, off, len);
0557:                        gzos.close();
0558:                    } // end try
0559:                    catch (java.io.IOException e) {
0560:                        e.printStackTrace();
0561:
0562:                        return null;
0563:                    } // end catch
0564:                    finally {
0565:                        try {
0566:                            gzos.close();
0567:                        } catch (Exception e) {
0568:                        }
0569:
0570:                        try {
0571:                            b64os.close();
0572:                        } catch (Exception e) {
0573:                        }
0574:
0575:                        try {
0576:                            baos.close();
0577:                        } catch (Exception e) {
0578:                        }
0579:                    } // end finally
0580:
0581:                    // Return value according to relevant encoding.
0582:                    try {
0583:                        return new String(baos.toByteArray(),
0584:                                PREFERRED_ENCODING);
0585:                    } // end try
0586:                    catch (java.io.UnsupportedEncodingException uue) {
0587:                        return new String(baos.toByteArray());
0588:                    } // end catch
0589:                } // end if: compress
0590:
0591:                // Else, don't compress. Better not to use streams at all then.
0592:                else {
0593:                    // Convert option to boolean in way that code likes it.
0594:                    boolean breakLines = dontBreakLines == 0;
0595:                    int len43 = (len * 4) / 3;
0596:                    byte[] outBuff = new byte[(len43) // Main 4:3
0597:                            + (((len % 3) > 0) ? 4 : 0) // Account for padding
0598:                            + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New
0599:                    // lines
0600:
0601:                    int d = 0;
0602:                    int e = 0;
0603:                    int len2 = len - 2;
0604:                    int lineLength = 0;
0605:
0606:                    for (; d < len2; d += 3, e += 4) {
0607:                        encode3to4(source, d + off, 3, outBuff, e);
0608:                        lineLength += 4;
0609:
0610:                        if (breakLines && (lineLength == MAX_LINE_LENGTH)) {
0611:                            outBuff[e + 4] = NEW_LINE;
0612:                            e++;
0613:                            lineLength = 0;
0614:                        } // end if: end of line
0615:                    } // en dfor: each piece of array
0616:
0617:                    if (d < len) {
0618:                        encode3to4(source, d + off, len - d, outBuff, e);
0619:                        e += 4;
0620:                    } // end if: some padding needed
0621:
0622:                    // Return value according to relevant encoding.
0623:                    try {
0624:                        return new String(outBuff, 0, e, PREFERRED_ENCODING);
0625:                    } // end try
0626:                    catch (java.io.UnsupportedEncodingException uue) {
0627:                        return new String(outBuff, 0, e);
0628:                    } // end catch
0629:                } // end else: don't compress
0630:            } // end encodeBytes
0631:
0632:            /* ******** D E C O D I N G M E T H O D S ******** */
0633:
0634:            /**
0635:             * Decodes the first four bytes of array <var>fourBytes </var> and returns
0636:             * an array up to three bytes long with the decoded values.
0637:             *
0638:             * @param fourBytes
0639:             *            the array with Base64 content
0640:             * @return array with decoded values
0641:             * @since 1.3
0642:             */
0643:            private static byte[] decode4to3(byte[] fourBytes) {
0644:                byte[] outBuff1 = new byte[3];
0645:                int count = decode4to3(fourBytes, 0, outBuff1, 0);
0646:                byte[] outBuff2 = new byte[count];
0647:
0648:                for (int i = 0; i < count; i++)
0649:                    outBuff2[i] = outBuff1[i];
0650:
0651:                return outBuff2;
0652:            }
0653:
0654:            /**
0655:             * Decodes four bytes from array <var>source </var> and writes the resulting
0656:             * bytes (up to three of them) to <var>destination </var>. The source and
0657:             * destination arrays can be manipulated anywhere along their length by
0658:             * specifying <var>srcOffset </var> and <var>destOffset </var>. This method
0659:             * does not check to make sure your arrays are large enough to accomodate
0660:             * <var>srcOffset </var>+ 4 for the <var>source </var> array or
0661:             * <var>destOffset </var>+ 3 for the <var>destination </var> array. This
0662:             * method returns the actual number of bytes that were converted from the
0663:             * Base64 encoding.
0664:             *
0665:             *
0666:             * @param source
0667:             *            the array to convert
0668:             * @param srcOffset
0669:             *            the index where conversion begins
0670:             * @param destination
0671:             *            the array to hold the conversion
0672:             * @param destOffset
0673:             *            the index where output will be put
0674:             * @return the number of decoded bytes converted
0675:             * @since 1.3
0676:             */
0677:            private static int decode4to3(byte[] source, int srcOffset,
0678:                    byte[] destination, int destOffset) {
0679:                // Example: Dk==
0680:                if (source[srcOffset + 2] == EQUALS_SIGN) {
0681:                    // Two ways to do the same thing. Don't know which way I like best.
0682:                    //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6
0683:                    // )
0684:                    //              | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );
0685:                    int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
0686:                            | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12);
0687:                    destination[destOffset] = (byte) (outBuff >>> 16);
0688:
0689:                    return 1;
0690:                }
0691:                // Example: DkL=
0692:                else if (source[srcOffset + 3] == EQUALS_SIGN) {
0693:                    // Two ways to do the same thing. Don't know which way I like best.
0694:                    //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6
0695:                    // )
0696:                    //              | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
0697:                    //              | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );
0698:                    int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
0699:                            | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
0700:                            | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6);
0701:                    destination[destOffset] = (byte) (outBuff >>> 16);
0702:                    destination[destOffset + 1] = (byte) (outBuff >>> 8);
0703:
0704:                    return 2;
0705:                }
0706:                // Example: DkLE
0707:                else {
0708:                    try {
0709:                        // Two ways to do the same thing. Don't know which way I like
0710:                        // best.
0711:                        //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 )
0712:                        // >>> 6 )
0713:                        //              | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
0714:                        //              | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
0715:                        //              | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
0716:                        int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
0717:                                | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
0718:                                | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6)
0719:                                | (DECODABET[source[srcOffset + 3]] & 0xFF);
0720:                        destination[destOffset] = (byte) (outBuff >> 16);
0721:                        destination[destOffset + 1] = (byte) (outBuff >> 8);
0722:                        destination[destOffset + 2] = (byte) (outBuff);
0723:
0724:                        return 3;
0725:                    } catch (Exception e) {
0726:                        System.out.println("" + source[srcOffset] + ": "
0727:                                + (DECODABET[source[srcOffset]]));
0728:                        System.out.println("" + source[srcOffset + 1] + ": "
0729:                                + (DECODABET[source[srcOffset + 1]]));
0730:                        System.out.println("" + source[srcOffset + 2] + ": "
0731:                                + (DECODABET[source[srcOffset + 2]]));
0732:                        System.out.println("" + source[srcOffset + 3] + ": "
0733:                                + (DECODABET[source[srcOffset + 3]]));
0734:
0735:                        return -1;
0736:                    } //e nd catch
0737:                }
0738:            } // end decodeToBytes
0739:
0740:            /**
0741:             * Very low-level access to decoding ASCII characters in the form of a byte
0742:             * array. Does not support automatically gunzipping or any other "fancy"
0743:             * features.
0744:             *
0745:             * @param source
0746:             *            The Base64 encoded data
0747:             * @param off
0748:             *            The offset of where to begin decoding
0749:             * @param len
0750:             *            The length of characters to decode
0751:             * @return decoded data
0752:             * @since 1.3
0753:             */
0754:            public static byte[] decode(byte[] source, int off, int len) {
0755:                int len34 = (len * 3) / 4;
0756:                byte[] outBuff = new byte[len34]; // Upper limit on size of output
0757:                int outBuffPosn = 0;
0758:                byte[] b4 = new byte[4];
0759:                int b4Posn = 0;
0760:                int i = 0;
0761:                byte sbiCrop = 0;
0762:                byte sbiDecode = 0;
0763:
0764:                for (i = off; i < (off + len); i++) {
0765:                    sbiCrop = (byte) (source[i] & 0x7f); // Only the low seven bits
0766:                    sbiDecode = DECODABET[sbiCrop];
0767:
0768:                    if (sbiDecode >= WHITE_SPACE_ENC) // White space, Equals sign or
0769:                    // better
0770:                    {
0771:                        if (sbiDecode >= EQUALS_SIGN_ENC) {
0772:                            b4[b4Posn++] = sbiCrop;
0773:
0774:                            if (b4Posn > 3) {
0775:                                outBuffPosn += decode4to3(b4, 0, outBuff,
0776:                                        outBuffPosn);
0777:                                b4Posn = 0;
0778:
0779:                                // If that was the equals sign, break out of 'for' loop
0780:                                if (sbiCrop == EQUALS_SIGN) {
0781:                                    break;
0782:                                }
0783:                            } // end if: quartet built
0784:                        } // end if: equals sign or better
0785:                    } // end if: white space, equals sign or better
0786:                    else {
0787:                        System.err.println("Bad Base64 input character at " + i
0788:                                + ": " + source[i] + "(decimal)");
0789:
0790:                        return null;
0791:                    } // end else:
0792:                } // each input character
0793:
0794:                byte[] out = new byte[outBuffPosn];
0795:                System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
0796:
0797:                return out;
0798:            } // end decode
0799:
0800:            /**
0801:             * Decodes data from Base64 notation, automatically detecting
0802:             * gzip-compressed data and decompressing it.
0803:             *
0804:             * @param s
0805:             *            the string to decode
0806:             * @return the decoded data
0807:             * @since 1.4
0808:             */
0809:            public static byte[] decode(String s) {
0810:                byte[] bytes;
0811:
0812:                try {
0813:                    bytes = s.getBytes(PREFERRED_ENCODING);
0814:                } // end try
0815:                catch (java.io.UnsupportedEncodingException uee) {
0816:                    bytes = s.getBytes();
0817:                } // end catch
0818:
0819:                //</change>
0820:                // Decode
0821:                bytes = decode(bytes, 0, bytes.length);
0822:
0823:                // Check to see if it's gzip-compressed
0824:                // GZIP Magic Two-Byte Number: 0x8b1f (35615)
0825:                if (bytes.length >= 2) {
0826:                    int head = ((int) bytes[0] & 0xff)
0827:                            | ((bytes[1] << 8) & 0xff00);
0828:
0829:                    if ((bytes != null) && // In case decoding returned null
0830:                            (bytes.length >= 4) && // Don't want to get
0831:
0832:                            // ArrayIndexOutOfBounds exception
0833:                            (java.util.zip.GZIPInputStream.GZIP_MAGIC == head)) {
0834:                        java.io.ByteArrayInputStream bais = null;
0835:                        java.util.zip.GZIPInputStream gzis = null;
0836:                        java.io.ByteArrayOutputStream baos = null;
0837:                        byte[] buffer = new byte[2048];
0838:                        int length = 0;
0839:
0840:                        try {
0841:                            baos = new java.io.ByteArrayOutputStream();
0842:                            bais = new java.io.ByteArrayInputStream(bytes);
0843:                            gzis = new java.util.zip.GZIPInputStream(bais);
0844:
0845:                            while ((length = gzis.read(buffer)) >= 0) {
0846:                                baos.write(buffer, 0, length);
0847:                            } // end while: reading input
0848:
0849:                            // No error? Get new bytes.
0850:                            bytes = baos.toByteArray();
0851:                        } // end try
0852:                        catch (java.io.IOException e) {
0853:                            // Just return originally-decoded bytes
0854:                        } // end catch
0855:                        finally {
0856:                            try {
0857:                                baos.close();
0858:                            } catch (Exception e) {
0859:                            }
0860:
0861:                            try {
0862:                                gzis.close();
0863:                            } catch (Exception e) {
0864:                            }
0865:
0866:                            try {
0867:                                bais.close();
0868:                            } catch (Exception e) {
0869:                            }
0870:                        } // end finally
0871:                    } // end if: gzipped
0872:                } // end if: bytes.length >= 2
0873:
0874:                return bytes;
0875:            } // end decode
0876:
0877:            /**
0878:             * Attempts to decode Base64 data and deserialize a Java Object within.
0879:             * Returns <tt>null</tt> if there was an error.
0880:             *
0881:             * @param encodedObject
0882:             *            The Base64 data to decode
0883:             * @return The decoded and deserialized object
0884:             * @since 1.5
0885:             */
0886:            public static Object decodeToObject(String encodedObject) {
0887:                // Decode and gunzip if necessary
0888:                byte[] objBytes = decode(encodedObject);
0889:                java.io.ByteArrayInputStream bais = null;
0890:                java.io.ObjectInputStream ois = null;
0891:                Object obj = null;
0892:
0893:                try {
0894:                    bais = new java.io.ByteArrayInputStream(objBytes);
0895:                    ois = new java.io.ObjectInputStream(bais);
0896:                    obj = ois.readObject();
0897:                } // end try
0898:                catch (java.io.IOException e) {
0899:                    e.printStackTrace();
0900:                    obj = null;
0901:                } // end catch
0902:                catch (java.lang.ClassNotFoundException e) {
0903:                    e.printStackTrace();
0904:                    obj = null;
0905:                } // end catch
0906:                finally {
0907:                    try {
0908:                        bais.close();
0909:                    } catch (Exception e) {
0910:                    }
0911:
0912:                    try {
0913:                        ois.close();
0914:                    } catch (Exception e) {
0915:                    }
0916:                } // end finally
0917:
0918:                return obj;
0919:            } // end decodeObject
0920:
0921:            /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */
0922:
0923:            /**
0924:             * A {@link Base64#InputStream}will read data from another
0925:             * {@link java.io.InputStream}, given in the constructor, and encode/decode
0926:             * to/from Base64 notation on the fly.
0927:             *
0928:             * @see Base64
0929:             * @see java.io.FilterInputStream
0930:             * @since 1.3
0931:             */
0932:            public static class InputStream extends java.io.FilterInputStream {
0933:                private int options; // Options specified
0934:                private boolean encode; // Encoding or decoding
0935:                private int position; // Current position in the buffer
0936:                private byte[] buffer; // Small buffer holding converted data
0937:                private int bufferLength; // Length of buffer (3 or 4)
0938:                private int numSigBytes; // Number of meaningful bytes in the buffer
0939:                private int lineLength;
0940:                private boolean breakLines; // Break lines at less than 80 characters
0941:
0942:                /**
0943:                 * Constructs a {@link Base64#InputStream}in DECODE mode.
0944:                 *
0945:                 * @param in
0946:                 *            the {@link java.io.InputStream}from which to read data.
0947:                 * @since 1.3
0948:                 */
0949:                public InputStream(java.io.InputStream in) {
0950:                    this (in, DECODE);
0951:                } // end constructor
0952:
0953:                /**
0954:                 * Constructs a {@link Base64#InputStream}in either ENCODE or DECODE
0955:                 * mode.
0956:                 * <p>
0957:                 * Valid options:
0958:                 *
0959:                 * <pre>
0960:                 *
0961:                 *    ENCODE or DECODE: Encode or Decode as data is read.
0962:                 *    DONT_BREAK_LINES: don't break lines at 76 characters
0963:                 *      (only meaningful when encoding)
0964:                 *      &lt;i&gt;Note: Technically, this makes your encoding non-compliant.&lt;/i&gt;
0965:                 *
0966:                 * </pre>
0967:                 *
0968:                 * <p>
0969:                 * Example: <code>new Base64.InputStream( in, Base64.DECODE )</code>
0970:                 *
0971:                 *
0972:                 * @param in
0973:                 *            the {@link java.io.InputStream}from which to read data.
0974:                 * @param options
0975:                 *            Specified options
0976:                 * @see Base64#ENCODE
0977:                 * @see Base64#DECODE
0978:                 * @see Base64#DONT_BREAK_LINES
0979:                 * @since 2.0
0980:                 */
0981:                public InputStream(java.io.InputStream in, int options) {
0982:                    super (in);
0983:                    this .options = options;
0984:                    this .breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
0985:                    this .encode = (options & ENCODE) == ENCODE;
0986:                    this .bufferLength = encode ? 4 : 3;
0987:                    this .buffer = new byte[bufferLength];
0988:                    this .position = -1;
0989:                    this .lineLength = 0;
0990:                } // end constructor
0991:
0992:                /**
0993:                 * Reads enough of the input stream to convert to/from Base64 and
0994:                 * returns the next byte.
0995:                 *
0996:                 * @return next byte
0997:                 * @since 1.3
0998:                 */
0999:                public int read() throws java.io.IOException {
1000:                    // Do we need to get data?
1001:                    if (position < 0) {
1002:                        if (encode) {
1003:                            byte[] b3 = new byte[3];
1004:                            int numBinaryBytes = 0;
1005:
1006:                            for (int i = 0; i < 3; i++) {
1007:                                try {
1008:                                    int b = in.read();
1009:
1010:                                    // If end of stream, b is -1.
1011:                                    if (b >= 0) {
1012:                                        b3[i] = (byte) b;
1013:                                        numBinaryBytes++;
1014:                                    } // end if: not end of stream
1015:                                } // end try: read
1016:                                catch (java.io.IOException e) {
1017:                                    // Only a problem if we got no data at all.
1018:                                    if (i == 0) {
1019:                                        throw e;
1020:                                    }
1021:                                } // end catch
1022:                            } // end for: each needed input byte
1023:
1024:                            if (numBinaryBytes > 0) {
1025:                                encode3to4(b3, 0, numBinaryBytes, buffer, 0);
1026:                                position = 0;
1027:                                numSigBytes = 4;
1028:                            } // end if: got data
1029:                            else {
1030:                                return -1;
1031:                            } // end else
1032:                        } // end if: encoding
1033:
1034:                        // Else decoding
1035:                        else {
1036:                            byte[] b4 = new byte[4];
1037:                            int i = 0;
1038:
1039:                            for (i = 0; i < 4; i++) {
1040:                                // Read four "meaningful" bytes:
1041:                                int b = 0;
1042:
1043:                                do {
1044:                                    b = in.read();
1045:                                } while ((b >= 0)
1046:                                        && (DECODABET[b & 0x7f] <= WHITE_SPACE_ENC));
1047:
1048:                                if (b < 0) {
1049:                                    break; // Reads a -1 if end of stream
1050:                                }
1051:
1052:                                b4[i] = (byte) b;
1053:                            } // end for: each needed input byte
1054:
1055:                            if (i == 4) {
1056:                                numSigBytes = decode4to3(b4, 0, buffer, 0);
1057:                                position = 0;
1058:                            } // end if: got four characters
1059:                            else if (i == 0) {
1060:                                return -1;
1061:                            } // end else if: also padded correctly
1062:                            else {
1063:                                // Must have broken out from above.
1064:                                throw new java.io.IOException(
1065:                                        "Improperly padded Base64 input.");
1066:                            } // end
1067:                        } // end else: decode
1068:                    } // end else: get data
1069:
1070:                    // Got data?
1071:                    if (position >= 0) {
1072:                        // End of relevant data?
1073:                        if ( /* !encode && */
1074:                        position >= numSigBytes) {
1075:                            return -1;
1076:                        }
1077:
1078:                        if (encode && breakLines
1079:                                && (lineLength >= MAX_LINE_LENGTH)) {
1080:                            lineLength = 0;
1081:
1082:                            return '\n';
1083:                        } // end if
1084:                        else {
1085:                            lineLength++; // This isn't important when decoding
1086:
1087:                            // but throwing an extra "if" seems
1088:                            // just as wasteful.
1089:                            int b = buffer[position++];
1090:
1091:                            if (position >= bufferLength) {
1092:                                position = -1;
1093:                            }
1094:
1095:                            return b & 0xFF; // This is how you "cast" a byte that's
1096:
1097:                            // intended to be unsigned.
1098:                        } // end else
1099:                    } // end if: position >= 0
1100:
1101:                    // Else error
1102:                    else {
1103:                        // When JDK1.4 is more accepted, use an assertion here.
1104:                        throw new java.io.IOException(
1105:                                "Error in Base64 code reading stream.");
1106:                    } // end else
1107:                } // end read
1108:
1109:                /**
1110:                 * Calls {@link #read}repeatedly until the end of stream is reached or
1111:                 * <var>len </var> bytes are read. Returns number of bytes read into
1112:                 * array or -1 if end of stream is encountered.
1113:                 *
1114:                 * @param dest
1115:                 *            array to hold values
1116:                 * @param off
1117:                 *            offset for array
1118:                 * @param len
1119:                 *            max number of bytes to read into array
1120:                 * @return bytes read into array or -1 if end of stream is encountered.
1121:                 * @since 1.3
1122:                 */
1123:                public int read(byte[] dest, int off, int len)
1124:                        throws java.io.IOException {
1125:                    int i;
1126:                    int b;
1127:
1128:                    for (i = 0; i < len; i++) {
1129:                        b = read();
1130:
1131:                        //if( b < 0 && i == 0 )
1132:                        //    return -1;
1133:                        if (b >= 0) {
1134:                            dest[off + i] = (byte) b;
1135:                        } else if (i == 0) {
1136:                            return -1;
1137:                        } else {
1138:                            break; // Out of 'for' loop
1139:                        }
1140:                    } // end for: each byte read
1141:
1142:                    return i;
1143:                } // end read
1144:            } // end inner class InputStream
1145:
1146:            /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */
1147:
1148:            /**
1149:             * A {@link Base64#OutputStream}will write data to another
1150:             * {@link java.io.OutputStream}, given in the constructor, and
1151:             * encode/decode to/from Base64 notation on the fly.
1152:             *
1153:             * @see Base64
1154:             * @see java.io.FilterOutputStream
1155:             * @since 1.3
1156:             */
1157:            public static class OutputStream extends java.io.FilterOutputStream {
1158:                private int options;
1159:                private boolean encode;
1160:                private int position;
1161:                private byte[] buffer;
1162:                private int bufferLength;
1163:                private int lineLength;
1164:                private boolean breakLines;
1165:                private byte[] b4; // Scratch used in a few places
1166:                private boolean suspendEncoding;
1167:
1168:                /**
1169:                 * Constructs a {@link Base64#OutputStream}in ENCODE mode.
1170:                 *
1171:                 * @param out
1172:                 *            the {@link java.io.OutputStream}to which data will be
1173:                 *            written.
1174:                 * @since 1.3
1175:                 */
1176:                public OutputStream(java.io.OutputStream out) {
1177:                    this (out, ENCODE);
1178:                } // end constructor
1179:
1180:                /**
1181:                 * Constructs a {@link Base64#OutputStream}in either ENCODE or DECODE
1182:                 * mode.
1183:                 * <p>
1184:                 * Valid options:
1185:                 *
1186:                 * <pre>
1187:                 *
1188:                 *    ENCODE or DECODE: Encode or Decode as data is read.
1189:                 *    DONT_BREAK_LINES: don't break lines at 76 characters
1190:                 *      (only meaningful when encoding)
1191:                 *      &lt;i&gt;Note: Technically, this makes your encoding non-compliant.&lt;/i&gt;
1192:                 *
1193:                 * </pre>
1194:                 *
1195:                 * <p>
1196:                 * Example: <code>new Base64.OutputStream( out, Base64.ENCODE )</code>
1197:                 *
1198:                 * @param out
1199:                 *            the {@link java.io.OutputStream}to which data will be
1200:                 *            written.
1201:                 * @param options
1202:                 *            Specified options.
1203:                 * @see Base64#ENCODE
1204:                 * @see Base64#DECODE
1205:                 * @see Base64#DONT_BREAK_LINES
1206:                 * @since 1.3
1207:                 */
1208:                public OutputStream(java.io.OutputStream out, int options) {
1209:                    super (out);
1210:                    this .options = options;
1211:                    this .breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
1212:                    this .encode = (options & ENCODE) == ENCODE;
1213:                    this .bufferLength = encode ? 3 : 4;
1214:                    this .buffer = new byte[bufferLength];
1215:                    this .position = 0;
1216:                    this .lineLength = 0;
1217:                    this .suspendEncoding = false;
1218:                    this .b4 = new byte[4];
1219:                } // end constructor
1220:
1221:                /**
1222:                 * Writes the byte to the output stream after converting to/from Base64
1223:                 * notation. When encoding, bytes are buffered three at a time before
1224:                 * the output stream actually gets a write() call. When decoding, bytes
1225:                 * are buffered four at a time.
1226:                 *
1227:                 * @param theByte
1228:                 *            the byte to write
1229:                 * @since 1.3
1230:                 */
1231:                public void write(int theByte) throws java.io.IOException {
1232:                    // Encoding suspended?
1233:                    if (suspendEncoding) {
1234:                        super .out.write(theByte);
1235:
1236:                        return;
1237:                    } // end if: supsended
1238:
1239:                    // Encode?
1240:                    if (encode) {
1241:                        buffer[position++] = (byte) theByte;
1242:
1243:                        if (position >= bufferLength) // Enough to encode.
1244:                        {
1245:                            out.write(encode3to4(b4, buffer, bufferLength));
1246:                            lineLength += 4;
1247:
1248:                            if (breakLines && (lineLength >= MAX_LINE_LENGTH)) {
1249:                                out.write(NEW_LINE);
1250:                                lineLength = 0;
1251:                            } // end if: end of line
1252:
1253:                            position = 0;
1254:                        } // end if: enough to output
1255:                    } // end if: encoding
1256:
1257:                    // Else, Decoding
1258:                    else {
1259:                        // Meaningful Base64 character?
1260:                        if (DECODABET[theByte & 0x7f] > WHITE_SPACE_ENC) {
1261:                            buffer[position++] = (byte) theByte;
1262:
1263:                            if (position >= bufferLength) // Enough to output.
1264:                            {
1265:                                int len = Base64.decode4to3(buffer, 0, b4, 0);
1266:                                out.write(b4, 0, len);
1267:
1268:                                //out.write( Base64.decode4to3( buffer ) );
1269:                                position = 0;
1270:                            } // end if: enough to output
1271:                        } // end if: meaningful base64 character
1272:                        else if (DECODABET[theByte & 0x7f] != WHITE_SPACE_ENC) {
1273:                            throw new java.io.IOException(
1274:                                    "Invalid character in Base64 data.");
1275:                        } // end else: not white space either
1276:                    } // end else: decoding
1277:                } // end write
1278:
1279:                /**
1280:                 * Calls {@link #write}repeatedly until <var>len </var> bytes are
1281:                 * written.
1282:                 *
1283:                 * @param theBytes
1284:                 *            array from which to read bytes
1285:                 * @param off
1286:                 *            offset for array
1287:                 * @param len
1288:                 *            max number of bytes to read into array
1289:                 * @since 1.3
1290:                 */
1291:                public void write(byte[] theBytes, int off, int len)
1292:                        throws java.io.IOException {
1293:                    // Encoding suspended?
1294:                    if (suspendEncoding) {
1295:                        super .out.write(theBytes, off, len);
1296:
1297:                        return;
1298:                    } // end if: supsended
1299:
1300:                    for (int i = 0; i < len; i++) {
1301:                        write(theBytes[off + i]);
1302:                    } // end for: each byte written
1303:                } // end write
1304:
1305:                /**
1306:                 * Method added by PHIL. [Thanks, PHIL. -Rob] This pads the buffer
1307:                 * without closing the stream.
1308:                 */
1309:                public void flushBase64() throws java.io.IOException {
1310:                    if (position > 0) {
1311:                        if (encode) {
1312:                            out.write(encode3to4(b4, buffer, position));
1313:                            position = 0;
1314:                        } // end if: encoding
1315:                        else {
1316:                            throw new java.io.IOException(
1317:                                    "Base64 input not properly padded.");
1318:                        } // end else: decoding
1319:                    } // end if: buffer partially full
1320:                } // end flush
1321:
1322:                /**
1323:                 * Flushes and closes (I think, in the superclass) the stream.
1324:                 *
1325:                 * @since 1.3
1326:                 */
1327:                public void close() throws java.io.IOException {
1328:                    // 1. Ensure that pending characters are written
1329:                    flushBase64();
1330:
1331:                    // 2. Actually close the stream
1332:                    // Base class both flushes and closes.
1333:                    super .close();
1334:                    buffer = null;
1335:                    out = null;
1336:                } // end close
1337:
1338:                /**
1339:                 * Suspends encoding of the stream. May be helpful if you need to embed
1340:                 * a piece of base640-encoded data in a stream.
1341:                 *
1342:                 * @since 1.5.1
1343:                 */
1344:                public void suspendEncoding() throws java.io.IOException {
1345:                    flushBase64();
1346:                    this .suspendEncoding = true;
1347:                } // end suspendEncoding
1348:
1349:                /**
1350:                 * Resumes encoding of the stream. May be helpful if you need to embed a
1351:                 * piece of base640-encoded data in a stream.
1352:                 *
1353:                 * @since 1.5.1
1354:                 */
1355:                public void resumeEncoding() {
1356:                    this .suspendEncoding = false;
1357:                } // end resumeEncoding
1358:            } // end inner class OutputStream
1359:        } // end class Base64
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.