FileDocCategorySizeDatePackage
BASE64EncoderStream.javaAPI DocGlassfish v2 API10530Mon May 14 15:28:46 BST 2007com.sun.mail.util

BASE64EncoderStream

public class BASE64EncoderStream extends FilterOutputStream
This class implements a BASE64 encoder. It is implemented as a FilterOutputStream, so one can just wrap this class around any output stream and write bytes into this filter. The encoding is done as the bytes are written out.
author
John Mani
author
Bill Shannon

Fields Summary
private byte[]
buffer
private int
bufsize
private byte[]
outbuf
private int
count
private int
bytesPerLine
private int
lineLimit
private boolean
noCRLF
private static byte[]
newline
private static final char[]
pem_array
This array maps the characters to their 6 bit values
Constructors Summary
public BASE64EncoderStream(OutputStream out, int bytesPerLine)
Create a BASE64 encoder that encodes the specified output stream.

param
out the output stream
param
bytesPerLine number of bytes per line. The encoder inserts a CRLF sequence after the specified number of bytes, unless bytesPerLine is Integer.MAX_VALUE, in which case no CRLF is inserted. bytesPerLine is rounded down to a multiple of 4.


                                      			        			     			        			          
         
	super(out);
	buffer = new byte[3];
	if (bytesPerLine == Integer.MAX_VALUE || bytesPerLine < 4) {
	    noCRLF = true;
	    bytesPerLine = 76;
	}
	bytesPerLine = (bytesPerLine / 4) * 4;	// Rounded down to 4n
	this.bytesPerLine = bytesPerLine;	// save it
        lineLimit = bytesPerLine / 4 * 3;

	if (noCRLF) {
	    outbuf = new byte[bytesPerLine];
	} else {
	    outbuf = new byte[bytesPerLine + 2];
	    outbuf[bytesPerLine] = (byte)'\r";
	    outbuf[bytesPerLine + 1] = (byte)'\n";
	}
    
public BASE64EncoderStream(OutputStream out)
Create a BASE64 encoder that encodes the specified input stream. Inserts the CRLF sequence after outputting 76 bytes.

param
out the output stream

	this(out, 76);	
    
Methods Summary
public synchronized voidclose()
Forces any buffered output bytes to be encoded out to the stream and closes this output stream

	flush();
	if (count > 0 && !noCRLF) {
	    out.write(newline);
	    out.flush();
	}
	out.close();
    
private static byte[]encode(byte[] inbuf, int off, int size, byte[] outbuf)
Internal use only version of encode. Allow specifying which part of the input buffer to encode. If outbuf is non-null, it's used as is. Otherwise, a new output buffer is allocated.

	if (outbuf == null)
	    outbuf = new byte[encodedSize(size)];
	int inpos, outpos;
	int val;
	for (inpos = off, outpos = 0; size >= 3; size -= 3, outpos += 4) {
	    val = inbuf[inpos++] & 0xff;
	    val <<= 8;
	    val |= inbuf[inpos++] & 0xff;
	    val <<= 8;
	    val |= inbuf[inpos++] & 0xff;
	    outbuf[outpos+3] = (byte)pem_array[val & 0x3f];
	    val >>= 6;
	    outbuf[outpos+2] = (byte)pem_array[val & 0x3f];
	    val >>= 6;
	    outbuf[outpos+1] = (byte)pem_array[val & 0x3f];
	    val >>= 6;
	    outbuf[outpos+0] = (byte)pem_array[val & 0x3f];
	}
	// done with groups of three, finish up any odd bytes left
	if (size == 1) {
	    val = inbuf[inpos++] & 0xff;
	    val <<= 4;
	    outbuf[outpos+3] = (byte)'=";	// pad character;
	    outbuf[outpos+2] = (byte)'=";	// pad character;
	    outbuf[outpos+1] = (byte)pem_array[val & 0x3f];
	    val >>= 6;
	    outbuf[outpos+0] = (byte)pem_array[val & 0x3f];
	} else if (size == 2) {
	    val = inbuf[inpos++] & 0xff;
	    val <<= 8;
	    val |= inbuf[inpos++] & 0xff;
	    val <<= 2;
	    outbuf[outpos+3] = (byte)'=";	// pad character;
	    outbuf[outpos+2] = (byte)pem_array[val & 0x3f];
	    val >>= 6;
	    outbuf[outpos+1] = (byte)pem_array[val & 0x3f];
	    val >>= 6;
	    outbuf[outpos+0] = (byte)pem_array[val & 0x3f];
	}
	return outbuf;
    
private voidencode()
Encode the data stored in buffer. Uses outbuf to store the encoded data before writing.

exception
IOException if an I/O error occurs.


                                 
         
	int osize = encodedSize(bufsize);
	out.write(encode(buffer, 0, bufsize, outbuf), 0, osize);
	// increment count
	count += osize;
	// If writing out this encoded unit caused overflow,
	// start a new line.
	if (count >= bytesPerLine) {
	    if (!noCRLF)
		out.write(newline);
	    count = 0;
	}
    
public static byte[]encode(byte[] inbuf)
Base64 encode a byte array. No line breaks are inserted. This method is suitable for short strings, such as those in the IMAP AUTHENTICATE protocol, but not to encode the entire content of a MIME part.

	if (inbuf.length == 0)
	    return inbuf;
	return encode(inbuf, 0, inbuf.length, null);
    
private static intencodedSize(int size)
Return the corresponding encoded size for the given number of bytes, not including any CRLF.

	return ((size + 2) / 3) * 4;
    
public synchronized voidflush()
Flushes this output stream and forces any buffered output bytes to be encoded out to the stream.

exception
IOException if an I/O error occurs.

	if (bufsize > 0) { // If there's unencoded characters in the buffer ..
	    encode();      // .. encode them
	    bufsize = 0;
	}
	out.flush();
    
public synchronized voidwrite(byte[] b, int off, int len)
Encodes len bytes from the specified byte array starting at offset off to this output stream.

param
b the data.
param
off the start offset in the data.
param
len the number of bytes to write.
exception
IOException if an I/O error occurs.

	int end = off + len;

	// finish off incomplete coding unit
	while (bufsize != 0 && off < end)
	    write(b[off++]);

	// finish off line
	int blen = ((bytesPerLine - count) / 4) * 3;
	if (off + blen < end) {
	    // number of bytes that will be produced in outbuf
	    int outlen = encodedSize(blen);
	    if (!noCRLF) {
		outbuf[outlen++] = (byte)'\r";
		outbuf[outlen++] = (byte)'\n";
	    }
	    out.write(encode(b, off, blen, outbuf), 0, outlen);
	    off += blen;
	    count = 0;
	}

	// do bulk encoding a line at a time.
	for (; off + lineLimit < end; off += lineLimit)
	    out.write(encode(b, off, lineLimit, outbuf));

	// handle remaining partial line
	if (off + 3 < end) {
	    blen = end - off;
	    blen = (blen / 3) * 3;	// round down
	    // number of bytes that will be produced in outbuf
	    int outlen = encodedSize(blen);
	    out.write(encode(b, off, blen, outbuf), 0, outlen);
	    off += blen;
	    count += outlen;
	}

	// start next coding unit
	for (; off < end; off++)
	    write(b[off]);
    
public voidwrite(byte[] b)
Encodes b.length bytes to this output stream.

param
b the data to be written.
exception
IOException if an I/O error occurs.

	write(b, 0, b.length);
    
public synchronized voidwrite(int c)
Encodes the specified byte to this output stream.

param
c the byte.
exception
IOException if an I/O error occurs.

	buffer[bufsize++] = (byte)c;
	if (bufsize == 3) { // Encoding unit = 3 bytes
	    encode();
	    bufsize = 0;
	}