/*
* $Id$
* $URL$
*/
package org.subethamail.common.io;
import java.io.IOException;
import java.io.InputStream;
/**
* This is an InputStream wrapper which takes notice when a
* threshold (number of bytes) is about to be read. This can
* be used to limit input data, swap readers, etc.
*
* @author Jeff Schnitzer
*/
abstract public class ThresholdingInputStream extends InputStream
{
/** */
protected InputStream input;
/** Max number of bytes to read */
int threshold;
/** Number of bytes read so far */
int countRead = 0;
/**
*/
public ThresholdingInputStream(InputStream base, int thresholdBytes)
{
this.input = base;
this.threshold = thresholdBytes;
}
/* (non-Javadoc)
* @see java.io.InputStream#available()
*/
@Override
public int available() throws IOException
{
return this.input.available();
}
/* (non-Javadoc)
* @see java.io.InputStream#close()
*/
@Override
public void close() throws IOException
{
this.input.close();
}
/* (non-Javadoc)
* @see java.io.InputStream#mark(int)
*/
@Override
public void mark(int readlimit)
{
this.input.mark(readlimit);
}
/* (non-Javadoc)
* @see java.io.InputStream#markSupported()
*/
@Override
public boolean markSupported()
{
return this.input.markSupported();
}
/* (non-Javadoc)
* @see java.io.InputStream#read()
*/
@Override
public int read() throws IOException
{
this.checkThreshold(1);
int result = this.input.read();
this.countRead++;
return result;
}
/* (non-Javadoc)
* @see java.io.InputStream#read(byte[], int, int)
*/
@Override
public int read(byte[] b, int off, int len) throws IOException
{
this.checkThreshold(len);
int result = this.input.read(b, off, len);
if (result > 0)
this.countRead += result;
return result;
}
/* (non-Javadoc)
* @see java.io.InputStream#read(byte[])
*/
@Override
public int read(byte[] b) throws IOException
{
this.checkThreshold(b.length);
int result = this.input.read(b);
if (result > 0)
this.countRead += result;
return result;
}
/* (non-Javadoc)
* @see java.io.InputStream#reset()
*/
@Override
public void reset() throws IOException
{
this.input.reset();
this.countRead = 0;
}
/* (non-Javadoc)
* @see java.io.InputStream#skip(long)
*/
@Override
public long skip(long n) throws IOException
{
return this.input.skip(n);
}
/**
* Checks whether reading count bytes would cross the limit.
*/
protected void checkThreshold(int count) throws IOException
{
int predicted = this.countRead + count;
if (predicted > this.threshold)
this.thresholdReached(this.countRead, predicted);
}
/**
* @return the current threshold value.
*/
public int getThreshold()
{
return this.threshold;
}
/**
* Called when the threshold is about to be exceeded. This isn't
* exact; it's called whenever a read would occur that would
* cross the amount.
*
* @param current is the current number of bytes that have been read
* @param predicted is the total number after the read completes
*/
abstract protected void thresholdReached(int current, int predicted) throws IOException;
}