/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2010-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.netmgt.syslogd;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opennms.core.utils.LogUtils;
public class Rfc5424SyslogParser extends SyslogParser {
// <PRI>VERSION TIMESTAMP HOST APP PROC MSGID STRUCTURED MSG
private static final Pattern m_rfc5424Pattern = Pattern.compile("^<(\\d{1,3})>(\\d{0,2}?) (\\S+T\\S+) (\\S*) (\\S*) (\\d+|-) (\\S*) ((?:\\[.*?\\])*|-)(?: (?:BOM)?(.*?))?$", Pattern.MULTILINE);
private static final Pattern m_dateWithOffset = Pattern.compile("^(.*[\\-\\+]\\d\\d):?(\\d\\d)$");
protected Rfc5424SyslogParser(final String text) {
super(text);
}
public static SyslogParser getParser(final String text) {
return new Rfc5424SyslogParser(text);
}
protected Pattern getPattern() {
return m_rfc5424Pattern;
}
public SyslogMessage parse() throws SyslogParserException {
if (!this.find()) {
if (traceEnabled()) {
LogUtils.tracef(this, "'%s' did not match '%s'", m_rfc5424Pattern, getText());
}
return null;
}
final Matcher matcher = getMatcher();
final SyslogMessage message = new SyslogMessage();
try {
final int priorityField = Integer.parseInt(matcher.group(1));
message.setFacility(SyslogFacility.getFacilityForCode(priorityField));
message.setSeverity(SyslogSeverity.getSeverityForCode(priorityField));
} catch (final NumberFormatException e) {
LogUtils.debugf(this, e, "Unable to parse priority field '%s'", matcher.group(1));
}
if (matcher.group(2).length() != 0) {
try {
int version = Integer.parseInt(matcher.group(2));
message.setVersion(version);
} catch (NumberFormatException e) {
LogUtils.debugf(this, e, "Unable to parse version (%s) as a number.", matcher.group(2));
}
}
if (!matcher.group(3).equals("-")) {
message.setDate(parseDate(matcher.group(3)));
}
if (!matcher.group(4).equals("-")) {
message.setHostName(matcher.group(4));
}
if (!matcher.group(5).equals("-")) {
message.setProcessName(matcher.group(5));
}
if (!matcher.group(6).equals("-")) {
try {
message.setProcessId(Integer.parseInt(matcher.group(6)));
} catch (final NumberFormatException e) {
LogUtils.debugf(this, e, "Unable to parse process ID '%s' as a number.", matcher.group(6));
}
}
if (!matcher.group(7).equals("-")) {
message.setMessageID(matcher.group(7));
}
final String messageText = matcher.group(9);
if (messageText != null && messageText.length() != 0) {
message.setMessage(messageText.trim());
}
return message;
}
@Override
protected Date parseDate(final String dateString) {
if (dateString.endsWith("Z")) {
try {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
df.setTimeZone(TimeZone.getTimeZone("GMT"));
return df.parse(dateString);
} catch (final Exception e) {
// try again with optional decimals
try {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'", Locale.ROOT);
df.setLenient(true);
df.setTimeZone(TimeZone.getTimeZone("GMT"));
return df.parse(dateString);
} catch (final Exception pe) {
LogUtils.debugf(this, pe, "Unable to parse date string '%s'.", dateString);
}
}
} else {
final Matcher matcher = m_dateWithOffset.matcher(dateString);
final String newString;
if (matcher.find()) {
newString = matcher.group(1) + matcher.group(2);
} else {
final String first = dateString.substring(0, dateString.lastIndexOf('-'));
final String last = dateString.substring(dateString.lastIndexOf('-'));
newString = first + last.replace(":", "");
}
try {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ROOT);
return df.parse(newString);
} catch (final Exception e) {
// try again with optional decimals
try {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ", Locale.ROOT);
df.setLenient(true);
return df.parse(newString);
} catch (final Exception pe) {
LogUtils.debugf(this, pe, "Unable to parse date string '%s'.", newString);
}
}
}
return null;
}
}