blob: 08413132e83454b53ea2f9c1df7d09fba094dfa5 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE.txt file distributed with this work for
// additional information regarding copyright ownership. The ASF licenses this
// file to you under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
package org.apache.oodt.commons.io;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.oodt.commons.util.Base64;
/** An output stream that encodes its data into RFC-1512 base 64 format.
*
* Wrap this input stream around another output stream, and all the bytes will be
* converted into their base-64 format when you write to it.
*
* @author Kelly
*/
public class Base64EncodingOutputStream extends FilterOutputStream {
/** Construct a base-64 encoding output stream.
*
* @param outputStream The output stream to which to write.
*/
public Base64EncodingOutputStream(OutputStream outputStream) {
super(outputStream);
}
/** Write a byte of data.
*
* The byte will be encoded into base-64 format on the output.
*
* @param b The byte.
* @throws IOException If an I/O error occurs.
*/
public void write(int b) throws IOException {
if (buffer == null)
throw new IOException("Can't write onto a closed stream");
buffer[index++] = (byte) b;
if (index == buffer.length) shipout();
}
/** Write a bunch of bytes.
*
* The given array of bytes will be encoded into base-64 on the output.
*
* @param b The array to write.
* @param offset Where in the data to start writing.
* @param length How many bytes to write.
* @throws IOException If an I/O error occurs.
*/
public void write(byte[] b, int offset, int length) throws IOException {
if (b == null) throw new IllegalArgumentException("Can't write a null array");
if (offset < 0 || offset >= b.length)
throw new IndexOutOfBoundsException("Can't get bytes at " + offset + " in array with indexes 0.."
+ (b.length - 1));
if (length < 0) throw new IllegalArgumentException("Can't write a negative amount of bytes");
if (offset + length > b.length)
throw new IndexOutOfBoundsException("Can't get bytes beyond edge of array");
if (buffer == null)
throw new IOException("Can't write onto a closed stream");
while (length > 0) {
int avail = buffer.length - index;
int amount = avail < length? avail : length;
System.arraycopy(b, offset, buffer, index, amount);
index += amount;
offset += amount;
length -= amount;
if (index == buffer.length) shipout();
}
}
/** Flush the stream.
*
* This causes any buffered bytes to be encoded and shipped out to the underlying
* stream, which is also flushed.
*
* @throws IOException If an I/O error occurs.
*/
public void flush() throws IOException {
if (buffer == null)
throw new IOException("Can't flush a closed stream");
shipout();
out.flush();
}
/** Close the stream.
*
* This writes out any unflushed data in base-64 format and closes the underlying
* stream.
*
* @throws IOException If an I/O error occurs.
*/
public void close() throws IOException {
if (buffer == null)
throw new IOException("Can't close an already closed stream");
flush();
out.close();
out = null;
buffer = null;
}
/** Ship out a bunch of buffered data in base-64 format.
*
* This resets the index of the next byte to insert back to zero.
*
* @throws IOException If an I/O error occurs.
*/
private void shipout() throws IOException {
byte[] encoded = Base64.encode(buffer, 0, index);
out.write(encoded);
index = 0;
}
/** Size of the output data buffer. Must be a multiple of 3.
*/
private static final int BUFFER_SIZE = 300;
/** Buffer for output data.
*/
private byte[] buffer = new byte[BUFFER_SIZE];
/** Where we are in the buffer.
*/
private int index = 0;
}