Source Code Cross Referenced for Base64.java in  » Web-Services » restlet-1.0.8 » com » noelios » restlet » 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 » Web Services » restlet 1.0.8 » com.noelios.restlet.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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