Source Code Cross Referenced for Base64.java in  » Profiler » JMeasurement » de » mcs » utils » codecs » 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 » Profiler » JMeasurement » de.mcs.utils.codecs 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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