/*
* Copyright 2013 Chris Pheby
*
* Licensed 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.jadira.lang.io.buffered;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Provides the basic structure for implementing BufferedOutputStreams. Subclasses typically differ in terms of how they provide the buffer.
* Some of the functionality needs to be effectively reproduced from BufferedOutputStream - such methods reference the equivalents in that class.
*/
public abstract class AbstractBufferedOutputStream extends FilterOutputStream {
/** The default buffer size in bytes */
public static int DEFAULT_BUFFER_SIZE = 8192;
private int count;
/**
* A BufferedOutputStream where the buffer is provided by a byte array. Use this class as an alternative to {@link java.io.BufferedOutputStream}
* @param out OutputStream to be decorated
*/
public AbstractBufferedOutputStream(OutputStream out) {
this(out, DEFAULT_BUFFER_SIZE);
}
/**
* Creates a new instance with the given buffer size in bytes.
* @param out OutputStream to be decorated
* @param size The size of the buffer in bytes
* @see java.io.BufferedOutputStream#BufferedOutputStream(OutputStream, int)
*/
public AbstractBufferedOutputStream(OutputStream out, int size) {
super(out);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size may not be less than or equal to zero");
}
}
private void flushBuffer() throws IOException {
if (count > 0) {
out.write(bytes(), 0, count);
count = 0;
}
}
/**
* @see java.io.BufferedOutputStream#write(int)
*/
public void write(int b) throws IOException {
if (count >= limit()) {
flushBuffer();
}
put((byte) b);
}
/**
* @see java.io.BufferedOutputStream#write(byte[], int, int)
*/
public void write(byte b[], int off, int len) throws IOException {
if (len >= limit()) {
flushBuffer();
out.write(b, off, len);
return;
}
if (len > limit() - count) {
flushBuffer();
}
put(count, b, off, len);
count += len;
}
/**
* @see java.io.BufferedOutputStream#flush
*/
public void flush() throws IOException {
flushBuffer();
out.flush();
}
@Override
public void close() throws IOException {
try {
super.close();
} finally {
clean();
}
}
/**
* Return the bytes in the buffer as a byte array
* @return The bytes
*/
protected abstract byte[] bytes();
/**
* Put a single byte into the buffer
* @param b The byte
*/
protected abstract void put(byte b);
/**
* Puts bytes into the buffer
* @param count The number of bytes already written into the buffer
* @param b The byte array with the bytes to put
* @param off Offset to write from in the bytes, b
* @param len The number of bytes to write
*/
protected abstract void put(int count, byte[] b, int off, int len);
/**
* Returns the limit of the buffer
* @return The limit
*/
protected abstract int limit();
/**
* Performs any necessary cleaning of the buffer and releasing of resources.
*/
protected abstract void clean();
}