LineLoggingBuffer.java
package com.icegreen.greenmail.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* Buffers and logs when detecting CR-LF.
* <p>
* <ul>
* <li>Wraps long lines</li>
* <li>Escapes non-ASCII-printable chars</li>
* </ul>
*/
public class LineLoggingBuffer {
private final ByteArrayOutputStream buf = new ByteArrayOutputStream();
private final String linePrefix;
protected final Logger log = LoggerFactory.getLogger(getClass());
protected static final byte[] WRAP = "[WRAP]".getBytes(StandardCharsets.US_ASCII);
/**
* Creates new buffer using given line prefix.
*
* @param linePrefix prefix for each line printed, eg "S:" or "C:"
*/
public LineLoggingBuffer(String linePrefix) {
this.linePrefix = linePrefix;
}
/**
* Appends and escapes value.
*
* @param b value
*/
public void append(int b) {
if (b > 0) {
if (b == '\n') {
buf.write('\\');
buf.write('n');
} else if (b == '\r') {
buf.write('\\');
buf.write('r');
} else if (b == '\t') {
buf.write('\\');
buf.write('t');
} else if (b < ' ') { // Non-printable ASCII
buf.write('^');
buf.write('@' + b);
} else {
buf.write(b);
}
}
// Print when encountering negative (-1) value -or- new line -or- reaching max line length
if (b < 0 || b == '\n' || isLineLengthExceeded()) {
logLine();
}
}
/**
* Triggers log output of current buffer (if any) and resets back to empty buffer.
*/
public void logLine() {
if (buf.size() > 0) {
try {
if (isLineLengthExceeded()) { // Signal wrapping
buf.write(WRAP);
}
if(log.isDebugEnabled()) {
String line = buf.toString(StandardCharsets.UTF_8.name());
log.debug("{}{}", linePrefix, line);
}
buf.reset();
} catch (IOException e) {
throw new IllegalStateException("Can not log output stream", e);
}
}
}
protected boolean isLineLengthExceeded() {
return buf.size() > 128;
}
}