/**
* Copyright (C) 2010 Orbeon, Inc.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the Free Software Foundation; either version
* 2.1 of the License, or (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
*/
package org.orbeon.oxf.util;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.*;
/**
* This class tries to implement a WriterOutputStream able to handle character encodings correctly.
*/
public class WriterOutputStream extends OutputStream {
private Writer writer; // Writer to write to
private CharsetDecoder decoder;
private ByteBuffer inputBuffer;
private CharBuffer outputBuffer;
private char[] outputBufferArray;
public WriterOutputStream(Writer writer) throws IOException, UnsupportedCharsetException {
this.writer = writer;
this.inputBuffer = ByteBuffer.allocateDirect(1024);
this.outputBufferArray = new char[1024];
this.outputBuffer = CharBuffer.wrap(outputBufferArray);
}
public void setCharset(String charset) {
this.decoder = Charset.forName(charset).newDecoder().reset();
}
public void write(byte[] buf, int off, int len) throws IOException {
int remaining = len;
while (remaining > 0) {
if (remaining > inputBuffer.remaining()) {
remaining -= inputBuffer.remaining();
inputBuffer.put(buf, off, inputBuffer.remaining());
} else {
inputBuffer.put(buf, off, remaining);
remaining = 0;
}
decode();
}
}
public void write(int b) throws IOException {
writer.flush();
inputBuffer.put((byte) b);
if (!(inputBuffer.remaining() > 0))
decode();
}
private void decode() throws IOException {
CoderResult result;
inputBuffer.flip();
do {
result = decoder.decode(inputBuffer, outputBuffer, false);
writer.write(outputBufferArray, 0, outputBuffer.position());
outputBuffer.clear();
} while (!result.isUnderflow());
inputBuffer.compact();
}
public void flush() throws IOException {
decode();
writer.flush();
}
public void close() throws IOException {
flush();
writer.close();
}
}