/**
* This is basically a state machine implementation of the extract function.
* It uses a DataInputStream instead of a string to avoid the cost of string
* and character encoding
*/
public Event extract(DataInputStream in) throws EventExtractException {
Preconditions.checkNotNull(in);
Mode m = Mode.START;
StringBuilder prio = new StringBuilder();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte b = 0;
long cnt = 0;
try {
while (true) {
b = in.readByte();
cnt++;
switch (m) {
case START:
if (b == '<') {
m = Mode.PRIO;
} else {
m = Mode.ERR;
}
break;
case PRIO:
if (b == '>') {
m = Mode.DATA;
} else {
char ch = (char) b;
if (Character.isDigit(ch)) {
prio.append(ch); // stay in PRIO mode
} else {
m = Mode.ERR;
}
}
break;
case DATA:
if (b == '\n') {
Event e = buildEvent(prio, baos);
return e;
}
baos.write(b);
break;
case ERR:
// read until we get to a \n
if (b == '\n') {
throw new EventExtractException(
"Failed to extract syslog wire entry");
}
// stay in Mode.ERR;
break;
}
}
} catch (EOFException e) {
switch (m) {
case ERR:
// end of stream but was in error state Throw extraction exception
throw new EventExtractException("Failed to extract syslog wire entry");
case DATA:
// end of stream but had data, return it.
return buildEvent(prio, baos);
default:
// if not in error state just return done;
return null;
}
} catch (IOException e) {
throw new EventExtractException("Failed to extract syslog wire entry: "
+ e.getMessage());
}
}