LoggingInputStream.java
package emissary.util.io;
import org.slf4j.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
/**
* This InputStream wraps another InputStream and logs all methods calls.
*/
public class LoggingInputStream extends InputStream {
/**
* The InputStream that is being wrapped.
*/
private final InputStream inputStream;
/**
* The prefix added to the log statement.
*/
private final String prefix;
/**
* The logger to be used for logging.
*/
private final Logger logger;
/**
* Determines whether a stack trace should also be logged.
*/
private final boolean logStackTrace;
/**
* Constructs a InputStream that wraps another InputStream and logs all methods calls.
*
* @param inputStream to be wrapped.
* @param prefix added to the log statement.
* @param logger to be used for logging.
* @param logStackTrace determines whether a stack trace should also be logged.
*/
public LoggingInputStream(final InputStream inputStream, final String prefix, final Logger logger,
final boolean logStackTrace) {
this.inputStream = inputStream;
this.prefix = prefix;
this.logger = logger;
this.logStackTrace = logStackTrace;
log("{} : created : lST={}", prefix, logStackTrace);
}
@Override
public int read() throws IOException {
final int r = inputStream.read();
log("{} : read-0 : r={}", prefix, r);
return r;
}
@Override
public int read(final byte[] b) throws IOException {
final int r = inputStream.read(b);
log("{} : read-1 : r={}", prefix, r);
return r;
}
@Override
public int read(final byte[] b, final int off, final int len) throws IOException {
final int r = inputStream.read(b, off, len);
log("{} : read-3 : off={} len={} : r={}", prefix, off, len, r);
return r;
}
@Override
public long skip(final long n) throws IOException {
final long r = inputStream.skip(n);
log("{} : skip : n={} : r={}", prefix, n, r);
return r;
}
@Override
public int available() throws IOException {
final int r = inputStream.available();
log("{} : available : r={}", prefix, r);
return r;
}
@Override
public void close() throws IOException {
log("{} : close", prefix);
inputStream.close();
}
@Override
public synchronized void mark(final int readlimit) {
log("{} : mark : rl={}", prefix, readlimit);
inputStream.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
log("{} : reset", prefix);
inputStream.reset();
}
@Override
public boolean markSupported() {
final boolean r = inputStream.markSupported();
log("{} : markSupported : r={}", prefix, r);
return r;
}
private void log(final String format, final Object... arguments) {
if (logStackTrace) {
final Object[] newArguments = Arrays.copyOf(arguments, arguments.length + 1);
// "Throwable" is used since this class should only be used during development.
newArguments[newArguments.length - 1] = new Throwable("DEBUG");
logger.info(format, newArguments);
} else {
logger.info(format, arguments);
}
}
}