//
// Copyright (c) 2011 Linkeos.
//
// This file is part of Elveos.org.
// Elveos.org is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 3 of the License, or (at your
// option) any later version.
//
// Elveos.org is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
// You should have received a copy of the GNU General Public License along
// with Elveos.org. If not, see http://www.gnu.org/licenses/.
//
package com.bloatit.framework.xcgiserver.mime;
import java.io.IOException;
import java.io.OutputStream;
import com.bloatit.framework.xcgiserver.mime.decoders.MimeDecoder;
/**
* <p>
* An output stream that will decode text (using MimeDecoder) before it is
* written.
* </p>
*/
public class DecodingOuputStream extends OutputStream {
private static final int DEFAULT_BUFFER_MULTIPLY = 1024;
private final MimeDecoder codec;
private final OutputStream output;
private final int bufferSize;
private final byte[] buffer;
private int bufferIndex;
/**
* <p>
* Creates a new DecodingOutputStream with a default buffer size.
* </p>
*
* @param output The stream used to write the decoded text
* @param codec The codec used to decode the text
*/
public DecodingOuputStream(final OutputStream output, final MimeDecoder codec) {
this(output, codec, DEFAULT_BUFFER_MULTIPLY);
}
/**
* <p>
* Creates a new DecodingOutputStream with a given buffer size.
* </p>
*
* @param output The stream used to write the decoded text
* @param codec The codec used to decode the text
* @param bufferMultiply The multiplicator used to compute the buffer size.
* To find the real bufferSize, you need to do
* <code> {@link MimeDecoder#decodeStep()}</code>*
* <code>bufferMultiply</code>
*/
private DecodingOuputStream(final OutputStream output, final MimeDecoder codec, final int bufferMultiply) {
super();
this.output = output;
this.codec = codec;
this.bufferSize = bufferMultiply;
buffer = new byte[bufferMultiply * codec.decodeStep()];
}
@Override
public void close() throws IOException {
flush();
output.close();
}
@Override
public void flush() throws IOException {
output.write(codec.decode(buffer, 0, bufferIndex));
bufferIndex = 0;
output.flush();
}
@Override
public void write(final byte[] b, final int off, final int len) throws IOException {
for (int i = off; i < len; i++) {
write(b[i]);
}
}
@Override
public void write(final byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(final int b) throws IOException {
write((byte) b);
}
/**
* <p>
* Writes one byte to the stream.
* </p>
* <p>
* This method has the same result as calling the {@link #write(int)}
* method, except it will result in VERY slightly less overehead so should
* be prefered ...
* </p>
*
* @param b the byte to write
* @throws IOException when an IO error occurs
*/
private void write(final byte b) throws IOException {
if (bufferIndex >= bufferSize) {
output.write(codec.decode(buffer, 0, bufferIndex));
bufferIndex = 0;
}
buffer[bufferIndex++] = b;
}
}