Use structured syslog parser from the NessComputing syslog4j fork.
Fixes parsing of structured data values that contain whitespace. This addresses issues from Graylog2/graylog2-server#845. Parser and test code from NessComputing/syslog4j@038caf2.
This commit is contained in:
parent
28a2b817c7
commit
dd8bbcd6be
34
pom.xml
34
pom.xml
@ -73,6 +73,16 @@
|
|||||||
<version>1.5.4</version>
|
<version>1.5.4</version>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>18.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>3.3.2</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>log4j</groupId>
|
<groupId>log4j</groupId>
|
||||||
<artifactId>log4j</artifactId>
|
<artifactId>log4j</artifactId>
|
||||||
@ -91,6 +101,12 @@
|
|||||||
<version>6.8.8</version>
|
<version>6.8.8</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.11</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@ -164,6 +180,24 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.18.1</version>
|
||||||
|
<!-- For running both, junit and testng tests. -->
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.surefire</groupId>
|
||||||
|
<artifactId>surefire-junit4</artifactId>
|
||||||
|
<version>2.18.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.surefire</groupId>
|
||||||
|
<artifactId>surefire-testng</artifactId>
|
||||||
|
<version>2.18.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package org.graylog2.syslog4j.impl;
|
package org.graylog2.syslog4j.impl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.graylog2.syslog4j.SyslogBackLogHandlerIF;
|
import org.graylog2.syslog4j.SyslogBackLogHandlerIF;
|
||||||
import org.graylog2.syslog4j.SyslogConfigIF;
|
import org.graylog2.syslog4j.SyslogConfigIF;
|
||||||
import org.graylog2.syslog4j.SyslogIF;
|
import org.graylog2.syslog4j.SyslogIF;
|
||||||
@ -16,6 +13,9 @@ import org.graylog2.syslog4j.impl.message.structured.StructuredSyslogMessage;
|
|||||||
import org.graylog2.syslog4j.impl.message.structured.StructuredSyslogMessageIF;
|
import org.graylog2.syslog4j.impl.message.structured.StructuredSyslogMessageIF;
|
||||||
import org.graylog2.syslog4j.util.SyslogUtility;
|
import org.graylog2.syslog4j.util.SyslogUtility;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractSyslog provides a base abstract implementation of the SyslogIF.
|
* AbstractSyslog provides a base abstract implementation of the SyslogIF.
|
||||||
* <p/>
|
* <p/>
|
||||||
@ -115,7 +115,7 @@ public abstract class AbstractSyslog implements SyslogIF {
|
|||||||
|
|
||||||
public void log(int level, String message) {
|
public void log(int level, String message) {
|
||||||
if (this.syslogConfig.isUseStructuredData()) {
|
if (this.syslogConfig.isUseStructuredData()) {
|
||||||
StructuredSyslogMessageIF structuredMessage = new StructuredSyslogMessage(null, null, message);
|
StructuredSyslogMessageIF structuredMessage = new StructuredSyslogMessage(null, null, null, message);
|
||||||
|
|
||||||
log(getStructuredMessageProcessor(), level, structuredMessage.createMessage());
|
log(getStructuredMessageProcessor(), level, structuredMessage.createMessage());
|
||||||
|
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
package org.graylog2.syslog4j.impl.message.structured;
|
package org.graylog2.syslog4j.impl.message.structured;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.graylog2.syslog4j.SyslogConstants;
|
||||||
|
import org.graylog2.syslog4j.impl.message.AbstractSyslogMessage;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.graylog2.syslog4j.SyslogConstants;
|
|
||||||
import org.graylog2.syslog4j.impl.message.AbstractSyslogMessage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SyslogStructuredMessage extends AbstractSyslogMessage's ability to provide
|
* SyslogStructuredMessage extends AbstractSyslogMessage's ability to provide
|
||||||
* support for turning POJO (Plain Ol' Java Objects) into Syslog messages. It
|
* support for turning POJO (Plain Ol' Java Objects) into Syslog messages. It
|
||||||
@ -28,26 +31,26 @@ import org.graylog2.syslog4j.impl.message.AbstractSyslogMessage;
|
|||||||
* @version $Id: StructuredSyslogMessage.java,v 1.5 2010/09/11 16:49:24 cvs Exp $
|
* @version $Id: StructuredSyslogMessage.java,v 1.5 2010/09/11 16:49:24 cvs Exp $
|
||||||
*/
|
*/
|
||||||
public class StructuredSyslogMessage extends AbstractSyslogMessage implements StructuredSyslogMessageIF {
|
public class StructuredSyslogMessage extends AbstractSyslogMessage implements StructuredSyslogMessageIF {
|
||||||
private static final long serialVersionUID = 3669887659567965965L;
|
|
||||||
|
|
||||||
private String messageId;
|
private String messageId;
|
||||||
private Map structuredData;
|
private Map<String, Map<String, String>> structuredData;
|
||||||
private String message;
|
private String message;
|
||||||
|
private String procId;
|
||||||
|
|
||||||
private StructuredSyslogMessage() {
|
private StructuredSyslogMessage() {
|
||||||
this.messageId = null;
|
this.messageId = null;
|
||||||
this.message = null;
|
this.message = null;
|
||||||
|
this.procId = null;
|
||||||
this.structuredData = null;
|
this.structuredData = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the {@link StructuredSyslogMessage} using MSGID,
|
* Constructs the {@link StructuredSyslogMessage} using MSGID,
|
||||||
* STRUCTURED-DATA and MSG fields, as described in:
|
* STRUCTURED-DATA and MSG fields, as described in:
|
||||||
* <p/>
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
|
* http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
|
||||||
* </p>
|
* </p>
|
||||||
* <p/>
|
*
|
||||||
* The Map must be a String -> (Map of String -> String), which encompasses
|
* The Map must be a String -> (Map of String -> String), which encompasses
|
||||||
* the STRUCTURED-DATA field described in above document.
|
* the STRUCTURED-DATA field described in above document.
|
||||||
*
|
*
|
||||||
@ -56,45 +59,14 @@ public class StructuredSyslogMessage extends AbstractSyslogMessage implements St
|
|||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
public StructuredSyslogMessage(final String messageId,
|
public StructuredSyslogMessage(final String messageId,
|
||||||
final Map structuredData, final String message) {
|
final String procId,
|
||||||
|
final Map<String, Map<String, String>> structuredData,
|
||||||
|
final String message) {
|
||||||
super();
|
super();
|
||||||
this.messageId = messageId;
|
this.messageId = messageId;
|
||||||
|
this.procId = procId;
|
||||||
this.structuredData = structuredData;
|
this.structuredData = structuredData;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
|
||||||
ensureCorrectMapType();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ensureCorrectMapType() {
|
|
||||||
if (!(getStructuredData() == null)) {
|
|
||||||
Set sdEntrySet = getStructuredData().entrySet();
|
|
||||||
for (Iterator it = sdEntrySet.iterator(); it.hasNext(); ) {
|
|
||||||
Map.Entry sdEntry = (Map.Entry) it.next();
|
|
||||||
if (!(sdEntry.getKey() instanceof String)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Structured data map must be a map of String -> (Map of String,String)");
|
|
||||||
}
|
|
||||||
if (!(sdEntry.getValue() instanceof Map)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Structured data map must be a map of String -> (Map of String,String)");
|
|
||||||
}
|
|
||||||
|
|
||||||
Set entrySet = ((Map) sdEntry.getValue()).entrySet();
|
|
||||||
for (Iterator it2 = entrySet.iterator(); it2.hasNext(); ) {
|
|
||||||
Map.Entry entry = (Map.Entry) it2.next();
|
|
||||||
|
|
||||||
if (!(entry.getKey() instanceof String)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Structured data map must be a map of String -> (Map of String,String)");
|
|
||||||
}
|
|
||||||
if (!(entry.getValue() instanceof String)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Structured data map must be a map of String -> (Map of String,String)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,91 +82,82 @@ public class StructuredSyslogMessage extends AbstractSyslogMessage implements St
|
|||||||
return syslogMessage;
|
return syslogMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deserialize(final String stringMessage) {
|
private void deserialize(final String stringMessage) {
|
||||||
// Check correct format
|
|
||||||
if (stringMessage.indexOf('[') <= 0)
|
|
||||||
throw new IllegalArgumentException("Invalid Syslog string format: "
|
|
||||||
+ stringMessage);
|
|
||||||
|
|
||||||
|
int start = stringMessage.indexOf('[');
|
||||||
|
int end = -1;
|
||||||
|
|
||||||
|
// Check correct format
|
||||||
|
if (start <= 0)
|
||||||
|
throw new IllegalArgumentException("Invalid Syslog string format: " + stringMessage);
|
||||||
|
|
||||||
|
//SYSLOG HEADER
|
||||||
// Divide the string in 2 sections
|
// Divide the string in 2 sections
|
||||||
final String syslogHeader = stringMessage.substring(0, stringMessage
|
final String syslogHeader = stringMessage.substring(0, stringMessage.indexOf('['));
|
||||||
.indexOf('['));
|
|
||||||
String structuredDataString = stringMessage.substring(stringMessage
|
|
||||||
.indexOf('['), stringMessage.lastIndexOf(']') + 1);
|
|
||||||
|
|
||||||
if ((stringMessage.lastIndexOf(']') + 2) <= stringMessage.length())
|
|
||||||
this.message = stringMessage.substring(stringMessage.lastIndexOf(']') + 2);
|
|
||||||
|
|
||||||
else {
|
|
||||||
this.message = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split into tokens
|
// Split into tokens
|
||||||
final String[] tokens = syslogHeader.split(" ");
|
final String[] tokens = syslogHeader.split(" ");
|
||||||
|
|
||||||
// Check number of tokens must be 1 -- rest of the header should already
|
// Check number of tokens must be 1 -- rest of the header should already
|
||||||
// be stripped
|
// be stripped
|
||||||
if (tokens.length != 1) {
|
if (tokens.length != 1) {
|
||||||
throw new IllegalArgumentException("Invalid Syslog string format: "
|
throw new IllegalArgumentException("Invalid Syslog string format: " + stringMessage);
|
||||||
+ stringMessage);
|
}
|
||||||
|
this.messageId = SyslogConstants.STRUCTURED_DATA_NILVALUE.equals(tokens[0]) ? null : tokens[0];
|
||||||
|
|
||||||
|
//STRUCTURED_DATA
|
||||||
|
if (stringMessage.contains(SyslogConstants.STRUCTURED_DATA_EMPTY_VALUE)){
|
||||||
|
this.structuredData = Collections.emptyMap();
|
||||||
|
end=stringMessage.indexOf(SyslogConstants.STRUCTURED_DATA_EMPTY_VALUE)+4;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
final Map<String, Map<String, String>> structuredDataMap = Maps.newHashMap();
|
||||||
|
|
||||||
|
while(start < stringMessage.length() && matchChar(stringMessage, start, '[') == start) {
|
||||||
|
Preconditions.checkArgument(stringMessage.charAt(start) == '[', "Invalid structured data in syslog message '%s'", stringMessage);
|
||||||
|
end = matchChar(stringMessage, start, ']');
|
||||||
|
Preconditions.checkArgument(end != -1 && stringMessage.charAt(end) == ']', "Invalid structured data in syslog message '%s'", stringMessage);
|
||||||
|
|
||||||
|
String key = null;
|
||||||
|
Map<String, String> keyMap = Maps.newHashMap();
|
||||||
|
while (start < end) {
|
||||||
|
if (key == null) {
|
||||||
|
final int keyEnd = matchChar(stringMessage, ++start, ']', ' '); // Key can be terminated by a space (then more fields to follow) or a ]
|
||||||
|
key = stringMessage.substring(start, keyEnd);
|
||||||
|
start = keyEnd; // start either points after the end (then the while terminates) or at the first char of the first field.
|
||||||
|
} else {
|
||||||
|
Preconditions.checkArgument(start < stringMessage.length() && stringMessage.charAt(start) == ' ', "Invalid structured data in syslog message '%s'", stringMessage);
|
||||||
|
start = start + 1; // Start points at the space behind either the key or the previous value
|
||||||
|
Preconditions.checkArgument(key != null, "Invalid structured data in syslog message '%s'", stringMessage);
|
||||||
|
final int equalsIndex = stringMessage.indexOf('=', start); // Equals terminates the field name.
|
||||||
|
Preconditions.checkArgument(equalsIndex != -1, "Invalid structured data in syslog message '%s'", stringMessage);
|
||||||
|
Preconditions.checkArgument(stringMessage.charAt(equalsIndex + 1) == '"', "Invalid structured data in syslog message '%s'", stringMessage);
|
||||||
|
|
||||||
|
// Look for the end of the value. It needs to be terminated by "
|
||||||
|
final int valueEnd = matchChar(stringMessage, equalsIndex + 2, '"');
|
||||||
|
Preconditions.checkArgument(valueEnd != -1 && stringMessage.charAt(valueEnd) == '"', "Invalid structured data in syslog message '%s'", stringMessage);
|
||||||
|
|
||||||
|
keyMap.put(stringMessage.substring(start, equalsIndex), unescape(stringMessage.substring(equalsIndex + 2, valueEnd)));
|
||||||
|
start = valueEnd + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start++;
|
||||||
|
structuredDataMap.put(key, keyMap);
|
||||||
|
}
|
||||||
|
this.structuredData = structuredDataMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.messageId = SyslogConstants.STRUCTURED_DATA_NILVALUE.equals(tokens[0]) ? null
|
//MESSAGE
|
||||||
: tokens[0];
|
if ((end + 2) <= stringMessage.length()){
|
||||||
|
this.message = stringMessage.substring(end + 2);
|
||||||
this.structuredData = new HashMap();
|
} else {
|
||||||
if (!SyslogConstants.STRUCTURED_DATA_EMPTY_VALUE.equals(structuredDataString)) {
|
this.message = "";
|
||||||
while (!"".equals(structuredDataString)) {
|
|
||||||
if (!structuredDataString.startsWith("[")
|
|
||||||
|| structuredDataString.indexOf(']') == -1) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Invalid structured data format in Syslog message: "
|
|
||||||
+ stringMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String structuredDataIteration = structuredDataString
|
|
||||||
.substring(1, structuredDataString.indexOf(']'));
|
|
||||||
|
|
||||||
final Map iterMap = new HashMap();
|
|
||||||
|
|
||||||
final String[] params = structuredDataIteration.split(" ");
|
|
||||||
|
|
||||||
for (int i = 1; i < params.length; i++) {
|
|
||||||
final String[] paramIter = params[i].split("=");
|
|
||||||
if (paramIter.length != 2) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Invalid structured data format in Syslog message: "
|
|
||||||
+ stringMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!paramIter[1].startsWith("\"")
|
|
||||||
|| !paramIter[1].endsWith("\"")) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Invalid structured data format in Syslog message: "
|
|
||||||
+ stringMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterMap.put(paramIter[0], paramIter[1].substring(1,
|
|
||||||
paramIter[1].length() - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.structuredData.put(params[0], iterMap);
|
|
||||||
|
|
||||||
if (structuredDataString.indexOf(']') != structuredDataString
|
|
||||||
.lastIndexOf(']')) {
|
|
||||||
structuredDataString = structuredDataString
|
|
||||||
.substring(structuredDataString.indexOf(']') + 1);
|
|
||||||
} else {
|
|
||||||
structuredDataString = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the MSGID field of the structured message format, as described
|
* Returns the MSGID field of the structured message format, as described
|
||||||
* in:
|
* in:
|
||||||
* <p/>
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
|
* http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
|
||||||
* </p>
|
* </p>
|
||||||
@ -208,20 +171,20 @@ public class StructuredSyslogMessage extends AbstractSyslogMessage implements St
|
|||||||
/**
|
/**
|
||||||
* Returns the structured data map. The Map is a String -> (Map of String ->
|
* Returns the structured data map. The Map is a String -> (Map of String ->
|
||||||
* String), which encompasses the STRUCTURED-DATA field, as described in:
|
* String), which encompasses the STRUCTURED-DATA field, as described in:
|
||||||
* <p/>
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
|
* http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @return Returns a Map object containing structured data.
|
* @return Returns a Map object containing structured data.
|
||||||
*/
|
*/
|
||||||
public Map getStructuredData() {
|
public Map<String, Map<String, String>> getStructuredData() {
|
||||||
return this.structuredData;
|
return this.structuredData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the MSG field of the structured message format, as described in:
|
* Returns the MSG field of the structured message format, as described in:
|
||||||
* <p/>
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
|
* http://tools.ietf.org/html/draft-ietf-syslog-protocol-23#section-6
|
||||||
* </p>
|
* </p>
|
||||||
@ -232,10 +195,15 @@ public class StructuredSyslogMessage extends AbstractSyslogMessage implements St
|
|||||||
return this.message;
|
return this.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getProcId()
|
||||||
|
{
|
||||||
|
return procId;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @seeorg.productivity.java.syslog4j.impl.message.AbstractSyslogMessage#
|
* @see com.nesscomputing.syslog4j.impl.message.AbstractSyslogMessage#
|
||||||
* createMessage()
|
* createMessage()
|
||||||
*/
|
*/
|
||||||
public String createMessage() {
|
public String createMessage() {
|
||||||
@ -259,40 +227,31 @@ public class StructuredSyslogMessage extends AbstractSyslogMessage implements St
|
|||||||
// structured data present
|
// structured data present
|
||||||
sb.append(SyslogConstants.STRUCTURED_DATA_EMPTY_VALUE);
|
sb.append(SyslogConstants.STRUCTURED_DATA_EMPTY_VALUE);
|
||||||
} else {
|
} else {
|
||||||
Set sdEntrySet = getStructuredData().entrySet();
|
Set<Map.Entry<String, Map<String, String>>> sdEntrySet = getStructuredData().entrySet();
|
||||||
for (Iterator it = sdEntrySet.iterator(); it.hasNext(); ) {
|
for (Iterator<Map.Entry<String, Map<String, String>>> it = sdEntrySet.iterator(); it.hasNext();) {
|
||||||
final Map.Entry sdElement = (Map.Entry) it.next();
|
final Map.Entry<String, Map<String, String>> sdElement = it.next();
|
||||||
final String sdId = (String) sdElement.getKey();
|
final String sdId = sdElement.getKey();
|
||||||
|
|
||||||
if (sdId == null || sdId.length() == 0
|
if (StringUtils.isBlank(sdId) || !StructuredSyslogMessage.checkIsPrintable(sdId)) {
|
||||||
|| !StructuredSyslogMessage.checkIsPrintable(sdId)) {
|
throw new IllegalArgumentException("Illegal structured data id: " + sdId);
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Illegal structured data id: " + sdId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.append('[').append(sdId);
|
sb.append('[').append(sdId);
|
||||||
|
|
||||||
final Map sdParams = (Map) sdElement.getValue();
|
final Map<String, String> sdParams = sdElement.getValue();
|
||||||
|
|
||||||
if (sdParams != null) {
|
if (sdParams != null) {
|
||||||
Set entrySet = sdParams.entrySet();
|
Set<Map.Entry<String, String>> entrySet = sdParams.entrySet();
|
||||||
for (Iterator it2 = entrySet.iterator(); it2.hasNext(); ) {
|
for (Iterator<Map.Entry<String, String>> it2 = entrySet.iterator(); it2.hasNext();) {
|
||||||
Map.Entry entry = (Map.Entry) it2.next();
|
Map.Entry<String, String> entry = it2.next();
|
||||||
final String paramName = (String) entry.getKey();
|
final String paramName = entry.getKey();
|
||||||
final String paramValue = (String) entry.getValue();
|
final String paramValue = entry.getValue();
|
||||||
|
|
||||||
if (paramName == null
|
if (StringUtils.isBlank(paramName) || !StructuredSyslogMessage.checkIsPrintable(paramName))
|
||||||
|| paramName.length() == 0
|
throw new IllegalArgumentException("Illegal structured data parameter name: " + paramName);
|
||||||
|| !StructuredSyslogMessage
|
|
||||||
.checkIsPrintable(paramName))
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Illegal structured data parameter name: "
|
|
||||||
+ paramName);
|
|
||||||
|
|
||||||
if (paramValue == null)
|
if (paramValue == null)
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException("Null structured data parameter value for parameter name: " + paramName);
|
||||||
"Null structured data parameter value for parameter name: "
|
|
||||||
+ paramName);
|
|
||||||
|
|
||||||
sb.append(' ');
|
sb.append(' ');
|
||||||
sb.append(paramName);
|
sb.append(paramName);
|
||||||
@ -306,7 +265,7 @@ public class StructuredSyslogMessage extends AbstractSyslogMessage implements St
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getMessage() != null && getMessage().length() != 0) {
|
if (!StringUtils.isEmpty(getMessage())) {
|
||||||
sb.append(' ');
|
sb.append(' ');
|
||||||
sb.append(StructuredSyslogMessage.nilProtect(getMessage()));
|
sb.append(StructuredSyslogMessage.nilProtect(getMessage()));
|
||||||
}
|
}
|
||||||
@ -342,13 +301,55 @@ public class StructuredSyslogMessage extends AbstractSyslogMessage implements St
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String nilProtect(final String value) {
|
public static String nilProtect(final String value) {
|
||||||
if (value == null || value.trim().length() == 0) {
|
if (StringUtils.isBlank(value)) {
|
||||||
return SyslogConstants.STRUCTURED_DATA_NILVALUE;
|
return SyslogConstants.STRUCTURED_DATA_NILVALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int matchChar(final String data, final int start, final char ... matchChars)
|
||||||
|
{
|
||||||
|
int ptr = start;
|
||||||
|
for(;;) {
|
||||||
|
if (ptr >= data.length()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.charAt(ptr) == '\\') {
|
||||||
|
ptr++;
|
||||||
|
ptr++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr >= data.length()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < matchChars.length; i++) {
|
||||||
|
if (data.charAt(ptr) == matchChars[i]) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String unescape(final String str)
|
||||||
|
{
|
||||||
|
if (str.indexOf('\\') == -1) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
if (str.charAt(i) == '\\') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sb.append(str.charAt(i));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
|
@ -146,7 +146,7 @@ public class StructuredSyslogServerEvent extends SyslogServerEvent {
|
|||||||
// throw new SyslogRuntimeException(
|
// throw new SyslogRuntimeException(
|
||||||
// "Message received is not a valid structured message: "
|
// "Message received is not a valid structured message: "
|
||||||
// + getMessage(), e);
|
// + getMessage(), e);
|
||||||
return new StructuredSyslogMessage(null, null, getMessage());
|
return new StructuredSyslogMessage(null, null, null, getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* (C) Copyright 2008-2011 syslog4j.org
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the GNU Lesser General Public License
|
||||||
|
* (LGPL) version 2.1 which accompanies this distribution, and is available at
|
||||||
|
* http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*/
|
||||||
|
package org.graylog2.syslog4j.server.impl.structured;
|
||||||
|
|
||||||
|
import org.graylog2.syslog4j.impl.message.structured.StructuredSyslogMessage;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestMatchChar
|
||||||
|
{
|
||||||
|
@Test
|
||||||
|
public void testMatchChar() throws Exception
|
||||||
|
{
|
||||||
|
Assert.assertEquals(2, StructuredSyslogMessage.matchChar("hello", 0, 'l'));
|
||||||
|
Assert.assertEquals(2, StructuredSyslogMessage.matchChar("hello", 2, 'l'));
|
||||||
|
Assert.assertEquals(3, StructuredSyslogMessage.matchChar("hello", 3, 'l'));
|
||||||
|
Assert.assertEquals(-1, StructuredSyslogMessage.matchChar("hello", 4, 'l'));
|
||||||
|
Assert.assertEquals(-1, StructuredSyslogMessage.matchChar("hello", 10, 'l'));
|
||||||
|
|
||||||
|
Assert.assertEquals(2, StructuredSyslogMessage.matchChar("\\ll", 0, 'l'));
|
||||||
|
Assert.assertEquals(-1, StructuredSyslogMessage.matchChar("\\l\\l", 0, 'l'));
|
||||||
|
Assert.assertEquals(-1, StructuredSyslogMessage.matchChar("\\", 0, 'x'));
|
||||||
|
Assert.assertEquals(-1, StructuredSyslogMessage.matchChar("foo\\", 0, 'x'));
|
||||||
|
|
||||||
|
Assert.assertEquals(-1, StructuredSyslogMessage.matchChar("this\\\"is\\ a\\ test.", 0, ' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,260 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* (C) Copyright 2008-2011 syslog4j.org
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the GNU Lesser General Public License
|
||||||
|
* (LGPL) version 2.1 which accompanies this distribution, and is available at
|
||||||
|
* http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*/
|
||||||
|
package org.graylog2.syslog4j.test.message.structured;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Cleversafe open-source code header - Version 1.2 - February 15, 2008
|
||||||
|
//
|
||||||
|
// Cleversafe Dispersed Storage(TM) is software for secure, private and
|
||||||
|
// reliable storage of the world's data using information dispersal.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2005-2008 Cleversafe, Inc.
|
||||||
|
//
|
||||||
|
// This program 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 2
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program 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 this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
// USA.
|
||||||
|
//
|
||||||
|
// Contact Information: Cleversafe, 224 North Desplaines Street, Suite 500
|
||||||
|
// Chicago IL 60661
|
||||||
|
// email licensing@cleversafe.org
|
||||||
|
//
|
||||||
|
// END-OF-HEADER
|
||||||
|
// -----------------------
|
||||||
|
// @author: mmotwani
|
||||||
|
//
|
||||||
|
// Date: Jul 15, 2009
|
||||||
|
// ---------------------
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import org.graylog2.syslog4j.impl.message.structured.StructuredSyslogMessage;
|
||||||
|
import org.graylog2.syslog4j.server.impl.event.structured.StructuredSyslogServerEvent;
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class StructuredSyslogMessageTest extends TestCase
|
||||||
|
{
|
||||||
|
public void testFromString1()
|
||||||
|
{
|
||||||
|
final String messageStr = "msgId1 [0@0] my message!!";
|
||||||
|
|
||||||
|
final StructuredSyslogMessage message = StructuredSyslogMessage.fromString(messageStr);
|
||||||
|
|
||||||
|
assertEquals("msgId1 [0@0] my message!!",message.toString());
|
||||||
|
assertEquals(-108931075,message.hashCode());
|
||||||
|
|
||||||
|
assertEquals("my message!!", message.getMessage());
|
||||||
|
assertEquals("msgId1", message.getMessageId());
|
||||||
|
assertTrue(message.getStructuredData().size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testFromString1a()
|
||||||
|
{
|
||||||
|
final String messageStr = "msgId1 [type a=\"[xx\\] xx\"] [first] my message!!";
|
||||||
|
|
||||||
|
final StructuredSyslogMessage message = StructuredSyslogMessage.fromString(messageStr);
|
||||||
|
|
||||||
|
assertEquals("msgId1 [type a=\"[xx\\] xx\"] [first] my message!!",message.toString());
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals("[first] my message!!", message.getMessage());
|
||||||
|
assertEquals("msgId1", message.getMessageId());
|
||||||
|
assertEquals("[xx] xx", (message.getStructuredData().get("type")).get("a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFromString1b()
|
||||||
|
{
|
||||||
|
final String messageStr = "msgId1 [type a=\"[xx\\] xx\"] my [second] message!!";
|
||||||
|
|
||||||
|
final StructuredSyslogMessage message = StructuredSyslogMessage.fromString(messageStr);
|
||||||
|
|
||||||
|
assertEquals("msgId1 [type a=\"[xx\\] xx\"] my [second] message!!",message.toString());
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals("my [second] message!!", message.getMessage());
|
||||||
|
assertEquals("msgId1", message.getMessageId());
|
||||||
|
assertEquals("[xx] xx", (message.getStructuredData().get("type")).get("a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFromString1c()
|
||||||
|
{
|
||||||
|
final String messageStr = "msgId1 [type a=\"[xx\\] xx\"][value b=\"c\"] my message!! [last]";
|
||||||
|
|
||||||
|
final StructuredSyslogMessage message = StructuredSyslogMessage.fromString(messageStr);
|
||||||
|
|
||||||
|
assertEquals("my message!! [last]", message.getMessage());
|
||||||
|
assertEquals("msgId1", message.getMessageId());
|
||||||
|
assertEquals("[xx] xx", (message.getStructuredData().get("type")).get("a"));
|
||||||
|
assertEquals("c", (message.getStructuredData().get("value")).get("b"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFromString2()
|
||||||
|
{
|
||||||
|
final String messageStr = "msgId1 [invalid SD] my message!!";
|
||||||
|
|
||||||
|
try {
|
||||||
|
StructuredSyslogMessage.fromString(messageStr);
|
||||||
|
fail();
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFromString3()
|
||||||
|
{
|
||||||
|
final String messageStr = "msgId1 [data1 a=b] my message!!";
|
||||||
|
|
||||||
|
try {
|
||||||
|
StructuredSyslogMessage.fromString(messageStr);
|
||||||
|
fail();
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFromString4()
|
||||||
|
{
|
||||||
|
final String messageStr = "msgId1 [data1 a=\"b] my message!!";
|
||||||
|
|
||||||
|
try {
|
||||||
|
StructuredSyslogMessage.fromString(messageStr);
|
||||||
|
fail();
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFromString5()
|
||||||
|
{
|
||||||
|
final String messageStr = "msgId1 [data1 a=b\"] my message!!";
|
||||||
|
|
||||||
|
try {
|
||||||
|
StructuredSyslogMessage.fromString(messageStr);
|
||||||
|
fail();
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFromString6()
|
||||||
|
{
|
||||||
|
final String messageStr = "msgId1 [data1 a=\"b\"] my message!!";
|
||||||
|
|
||||||
|
final StructuredSyslogMessage message = StructuredSyslogMessage.fromString(messageStr);
|
||||||
|
|
||||||
|
assertEquals("my message!!", message.getMessage());
|
||||||
|
assertEquals("msgId1", message.getMessageId());
|
||||||
|
assertTrue(message.getStructuredData().size() == 1);
|
||||||
|
assertTrue((message.getStructuredData().get("data1")).size() == 1);
|
||||||
|
assertEquals("b", (message.getStructuredData().get("data1")).get("a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFromString7()
|
||||||
|
{
|
||||||
|
final String messageStr =
|
||||||
|
"msgId1 [data1 a=\"b\"][data2 a=\"b\" x1=\"c1\" n2=\"f5\"] my message!!";
|
||||||
|
|
||||||
|
final StructuredSyslogMessage message = StructuredSyslogMessage.fromString(messageStr);
|
||||||
|
|
||||||
|
assertEquals("my message!!", message.getMessage());
|
||||||
|
assertEquals("msgId1", message.getMessageId());
|
||||||
|
assertTrue(message.getStructuredData().size() == 2);
|
||||||
|
assertTrue((message.getStructuredData().get("data1")).size() == 1);
|
||||||
|
assertTrue((message.getStructuredData().get("data2")).size() == 3);
|
||||||
|
assertEquals("b", (message.getStructuredData().get("data1")).get("a"));
|
||||||
|
assertEquals("b", (message.getStructuredData().get("data2")).get("a"));
|
||||||
|
assertEquals("c1", (message.getStructuredData().get("data2")).get("x1"));
|
||||||
|
assertEquals("f5", (message.getStructuredData().get("data2")).get("n2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateMessage1()
|
||||||
|
{
|
||||||
|
final StructuredSyslogMessage message = new StructuredSyslogMessage("msgId", null, null, null);
|
||||||
|
assertEquals("msgId [0@0]", message.createMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateMessage2()
|
||||||
|
{
|
||||||
|
final StructuredSyslogMessage message =
|
||||||
|
new StructuredSyslogMessage("msgId", null, null, "my message");
|
||||||
|
assertEquals("msgId [0@0] my message", message.createMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateMessage3()
|
||||||
|
{
|
||||||
|
final StructuredSyslogMessage message =
|
||||||
|
new StructuredSyslogMessage("msgId", null, Maps.<String, Map<String, String>>newHashMap(), "my message");
|
||||||
|
assertEquals("msgId [0@0] my message", message.createMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateMessage4()
|
||||||
|
{
|
||||||
|
final Map<String, Map<String, String>> map = Maps.newHashMap();
|
||||||
|
final StructuredSyslogMessage message =
|
||||||
|
new StructuredSyslogMessage("msgId", null, map, "my message");
|
||||||
|
assertEquals("msgId [0@0] my message", message.createMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMessageWithNulls() throws Exception
|
||||||
|
{
|
||||||
|
final String message = "<134>1 2012-07-25T21:32:08.887+00:00 some-server.some.domain noprog qtp583592918-80437 95d42b22c48e4eadb59e61a182c102d4 [l@2 si=\"some-server-s4\" sc=\"/a/b-c/d\" ip=\"1.2.3.4\" m=\"GET\" u=\"http://1.2.3.4:8081/path/PATH:12345/path\" q=\"source=SERVICE\" rc=\"200\" t=\"12\"][co@2 auth-cookie=\"jskldjskldjasskljlaskjas\"][rs@2 some-header=\"4054630f-8d31-457c-b1ff-2f2b465d69ef\"] nomsg";
|
||||||
|
final StructuredSyslogServerEvent ev = new StructuredSyslogServerEvent(message, InetAddress.getLocalHost());
|
||||||
|
final StructuredSyslogMessage msg = ev.getStructuredMessage();
|
||||||
|
Assert.assertEquals("95d42b22c48e4eadb59e61a182c102d4", msg.getMessageId());
|
||||||
|
Assert.assertNotNull(msg.getStructuredData());
|
||||||
|
Assert.assertNotNull(msg.getStructuredData().get("l@2"));
|
||||||
|
Assert.assertEquals("/a/b-c/d", msg.getStructuredData().get("l@2").get("sc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMessageWithEmptyStruct() throws Exception
|
||||||
|
{
|
||||||
|
final String message = "<134>1 2012-07-25T21:32:08.887+00:00 some-server.some.domain noprog qtp583592918-80437 95d42b22c48e4eadb59e61a182c102d4 [l@2][a@3 a=\"b\\\"c\"]";
|
||||||
|
final StructuredSyslogServerEvent ev = new StructuredSyslogServerEvent(message, InetAddress.getLocalHost());
|
||||||
|
final StructuredSyslogMessage msg = ev.getStructuredMessage();
|
||||||
|
Assert.assertEquals("95d42b22c48e4eadb59e61a182c102d4", msg.getMessageId());
|
||||||
|
Assert.assertNotNull(msg.getStructuredData());
|
||||||
|
Assert.assertNotNull(msg.getStructuredData().get("l@2"));
|
||||||
|
Assert.assertNotNull(msg.getStructuredData().get("a@3"));
|
||||||
|
Assert.assertEquals("b\"c", msg.getStructuredData().get("a@3").get("a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMessageWithSpace() throws Exception
|
||||||
|
{
|
||||||
|
final String message = "<134>1 2012-07-25T21:32:08.887+00:00 some-server.some.domain noprog qtp583592918-80437 95d42b22c48e4eadb59e61a182c102d4 [rh@12345 xxx=\"hell0 7|133454|00022f444ad7fe10ef5d0d536ae879f1\"]'";
|
||||||
|
final StructuredSyslogServerEvent ev = new StructuredSyslogServerEvent(message, InetAddress.getLocalHost());
|
||||||
|
final StructuredSyslogMessage msg = ev.getStructuredMessage();
|
||||||
|
Assert.assertNotNull(msg.getStructuredData().get("rh@12345"));
|
||||||
|
Assert.assertEquals("hell0 7|133454|00022f444ad7fe10ef5d0d536ae879f1", msg.getStructuredData().get("rh@12345").get("xxx"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user