001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.kernel.io;
016    
017    import com.liferay.portal.kernel.util.CharPool;
018    
019    import java.io.IOException;
020    import java.io.OutputStream;
021    
022    /**
023     * @author Tina Tian
024     */
025    public class Base64OutputStream extends OutputStream {
026    
027            public Base64OutputStream(OutputStream outputStream) {
028                    _outputStream = outputStream;
029                    _unitBuffer = new byte[3];
030                    _unitBufferIndex = 0;
031                    _outputBuffer = new byte[4];
032            }
033    
034            public void close() throws IOException {
035                    flush();
036    
037                    _outputStream.close();
038            }
039    
040            public void flush() throws IOException {
041                    if (_unitBufferIndex == 1) {
042                            encodeUnit(_unitBuffer[0]);
043                    }
044                    else if (_unitBufferIndex == 2) {
045                            encodeUnit(_unitBuffer[0], _unitBuffer[1]);
046                    }
047    
048                    _unitBufferIndex = 0;
049    
050                    _outputStream.flush();
051            }
052    
053            public void write(byte[] bytes) throws IOException {
054                    write(bytes, 0, bytes.length);
055            }
056    
057            public void write(byte[] bytes, int offset, int length) throws IOException {
058                    if (length <= 0) {
059                            return;
060                    }
061    
062                    while ((_unitBufferIndex != 0) && (length > 0)) {
063                            write(bytes[offset++]);
064    
065                            length--;
066                    }
067    
068                    if (length <= 0) {
069                            return;
070                    }
071    
072                    int bytesLength = length - (length % 3);
073    
074                    length -= bytesLength;
075    
076                    while (bytesLength > 0) {
077                            encodeUnit(bytes[offset], bytes[offset + 1], bytes[offset + 2]);
078    
079                            bytesLength -=3 ;
080                            offset += 3;
081                    }
082    
083                    while (length > 0) {
084                            write(bytes[offset++]);
085    
086                            length--;
087                    }
088            }
089    
090            public void write(int byteValue) throws IOException {
091                    _unitBuffer[_unitBufferIndex++] = (byte)byteValue;
092    
093                    if (_unitBufferIndex == 3) {
094                            encodeUnit(_unitBuffer[0], _unitBuffer[1], _unitBuffer[2]);
095    
096                            _unitBufferIndex = 0;
097                    }
098            }
099    
100            protected void encodeUnit(byte byteValue) throws IOException {
101                    int intValue = byteValue & 0xff;
102    
103                    intValue <<= 4;
104    
105                    _outputBuffer[3] = (byte)CharPool.EQUAL;
106                    _outputBuffer[2] = (byte)CharPool.EQUAL;
107                    _outputBuffer[1] = (byte)getChar(intValue & 0x3f);
108    
109                    intValue >>= 6;
110    
111                    _outputBuffer[0] = (byte)getChar(intValue & 0x3f);
112    
113                    _outputStream.write(_outputBuffer);
114            }
115    
116            protected void encodeUnit(byte byte1, byte byte2) throws IOException {
117                    int intValue = byte1 & 0xff;
118    
119                    intValue <<= 8;
120                    intValue |= byte2 & 0xff;
121                    intValue <<= 2;
122    
123                    _outputBuffer[3] = (byte)CharPool.EQUAL;
124                    _outputBuffer[2] = (byte)getChar(intValue & 0x3f);
125    
126                    intValue >>= 6;
127    
128                    _outputBuffer[1] = (byte)getChar(intValue & 0x3f);
129    
130                    intValue >>= 6;
131    
132                    _outputBuffer[0] = (byte)getChar(intValue & 0x3f);
133    
134                    _outputStream.write(_outputBuffer);
135            }
136    
137            protected void encodeUnit(byte byte1, byte byte2, byte byte3)
138                    throws IOException {
139    
140                    int intVallue = byte1 & 0xff;
141    
142                    intVallue <<= 8;
143                    intVallue |= byte2 & 0xff;
144                    intVallue <<= 8;
145                    intVallue |= byte3 & 0xff;
146    
147                    _outputBuffer[3] = (byte)getChar(intVallue & 0x3f);
148    
149                    intVallue >>= 6;
150    
151                    _outputBuffer[2] = (byte)getChar(intVallue & 0x3f);
152    
153                    intVallue >>= 6;
154    
155                    _outputBuffer[1] = (byte)getChar(intVallue & 0x3f);
156    
157                    intVallue >>= 6;
158    
159                    _outputBuffer[0] = (byte)getChar(intVallue & 0x3f);
160    
161                    _outputStream.write(_outputBuffer);
162            }
163    
164            protected char getChar(int sixbit) {
165                    if (sixbit >= 0 && sixbit <= 25) {
166                            return (char)(65 + sixbit);
167                    }
168    
169                    if (sixbit >= 26 && sixbit <= 51) {
170                            return (char)(97 + (sixbit - 26));
171                    }
172    
173                    if (sixbit >= 52 && sixbit <= 61) {
174                            return (char)(48 + (sixbit - 52));
175                    }
176    
177                    if (sixbit == 62) {
178                            return CharPool.PLUS;
179                    }
180    
181                    if (sixbit != 63) {
182                            return CharPool.QUESTION;
183                    }
184                    else {
185                            return CharPool.SLASH;
186                    }
187            }
188    
189            private byte[] _outputBuffer;
190            private OutputStream _outputStream;
191            private byte[] _unitBuffer;
192            private int _unitBufferIndex;
193    
194    }