/**
* Copyright (c) 2009 - 2011 AppWork UG(haftungsbeschränkt) <e-mail@appwork.org>
*
* This file is part of org.appwork.utils.net
*
* This software is licensed under the Artistic License 2.0,
* see the LICENSE file or http://www.opensource.org/licenses/artistic-license-2.0.php
* for details
*/
package org.appwork.utils.net;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* @author daniel
*
*/
public class Base64OutputStream extends FilterOutputStream {
private static final char[] BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
private final int base64buffer[] = new int[3];
private final byte writebuffer[] = new byte[4];
private int index = 0;
private static final byte PADDING = (byte) '=';
private boolean endFlush = false;
/**
* @param out
*/
public Base64OutputStream(final OutputStream out) {
super(out);
}
@Override
public void flush() throws IOException {
if (this.index == 0 || this.endFlush) {
this.out.flush();
return;
}
if (this.endFlush == false) {
/* a Base64 Stream can only be padded once at the end! */
this.endFlush = true;
this.writebuffer[2] = Base64OutputStream.PADDING;
this.writebuffer[3] = Base64OutputStream.PADDING;
switch (this.index) {
case 1:
this.writebuffer[0] = (byte) Base64OutputStream.BASE64[(this.base64buffer[0] & 0xFC) >> 2];
this.writebuffer[1] = (byte) Base64OutputStream.BASE64[(this.base64buffer[0] & 0x03) << 4];
this.out.write(this.writebuffer);
break;
case 2:
this.writebuffer[0] = (byte) Base64OutputStream.BASE64[(this.base64buffer[0] & 0xFC) >> 2];
this.writebuffer[1] = (byte) Base64OutputStream.BASE64[(this.base64buffer[0] & 0x03) << 4 | (this.base64buffer[1] & 0xF0) >> 4];
this.writebuffer[2] = (byte) Base64OutputStream.BASE64[(this.base64buffer[1] & 0x0F) << 2];
this.out.write(this.writebuffer);
break;
}
}
this.index = 0;
this.out.flush();
}
@Override
public void write(final int b) throws IOException {
/* put byte into base64Buffer */
this.base64buffer[this.index++] = b;
if (this.index == 3) {
/* first 6 bits, &0xFC returns bit 7-2 and >>2 shifts down */
this.writebuffer[0] = (byte) Base64OutputStream.BASE64[(this.base64buffer[0] & 0xFC) >> 2];
/*
* second 6 bits, &0x03 returns bit 1-0 and <<4 shifts up, &0xF0
* returns bit 7-4 and >>4 shifts down
*/
this.writebuffer[1] = (byte) Base64OutputStream.BASE64[(this.base64buffer[0] & 0x03) << 4 | (this.base64buffer[1] & 0xF0) >> 4];
/*
* third 6 bits, &0x0F returns bit 3-0 and <<2 shifts up, &0xC0
* returns bit 7-6 and >>6 shifts down
*/
this.writebuffer[2] = (byte) Base64OutputStream.BASE64[(this.base64buffer[1] & 0x0F) << 2 | (this.base64buffer[2] & 0xC0) >> 6];
/* last 6 bits, 0x3F returns bit 5-0 */
this.writebuffer[3] = (byte) Base64OutputStream.BASE64[this.base64buffer[2] & 0x3F];
this.out.write(this.writebuffer);
this.index = 0;
}
}
}