Repository: logging-log4j2
Updated Branches:
  refs/heads/master 956988641 -> e74e8200b


LOG4J2-1981 JsonLayout, XmlLayout and YamlLayout support 0-byte termination of 
log events


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/e74e8200
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/e74e8200
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/e74e8200

Branch: refs/heads/master
Commit: e74e8200b1630fc89118386ae7d4f0e2cb8ddc81
Parents: 9569886
Author: Mikael StÃ¥ldal <[email protected]>
Authored: Wed Jul 19 21:30:34 2017 +0200
Committer: Mikael StÃ¥ldal <[email protected]>
Committed: Wed Jul 19 21:30:34 2017 +0200

----------------------------------------------------------------------
 .../core/layout/AbstractJacksonLayout.java      | 32 +++++++++++++++++
 .../logging/log4j/core/layout/JsonLayout.java   | 37 +++++++++++---------
 .../logging/log4j/core/layout/XmlLayout.java    | 16 +++++----
 .../logging/log4j/core/layout/YamlLayout.java   | 29 ++++++++-------
 .../log4j/core/layout/JsonLayoutTest.java       | 20 +++++++++++
 .../log4j/core/layout/XmlLayoutTest.java        | 20 +++++++++++
 .../log4j/core/layout/YamlLayoutTest.java       | 18 ++++++++++
 src/changes/changes.xml                         |  3 ++
 src/site/xdoc/manual/layouts.xml.vm             | 21 +++++++++--
 9 files changed, 156 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e74e8200/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java
index 7115df8..989c922 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java
@@ -59,6 +59,9 @@ abstract class AbstractJacksonLayout extends 
AbstractStringLayout {
         @PluginBuilderAttribute
         private boolean stacktraceAsString = false;
 
+        @PluginBuilderAttribute
+        private boolean includeNullDelimiter = false;
+
         protected String toStringOrNull(final byte[] header) {
             return header == null ? null : new String(header, 
Charset.defaultCharset());
         }
@@ -95,6 +98,8 @@ abstract class AbstractJacksonLayout extends 
AbstractStringLayout {
             return stacktraceAsString;
         }
 
+        public boolean isIncludeNullDelimiter() { return includeNullDelimiter; 
}
+
         public B setEventEol(final boolean eventEol) {
             this.eventEol = eventEol;
             return asBuilder();
@@ -130,25 +135,49 @@ abstract class AbstractJacksonLayout extends 
AbstractStringLayout {
             return asBuilder();
         }
 
+        /**
+         * Whether to format the stacktrace as a string, and not a nested 
object (optional, defaults to false).
+         *
+         * @return this builder
+         */
         public B setStacktraceAsString(boolean stacktraceAsString) {
             this.stacktraceAsString = stacktraceAsString;
             return asBuilder();
         }
+
+        /**
+         * Whether to include NULL byte as delimiter after each event 
(optional, default to false).
+         *
+         * @return this builder
+         */
+        public B setIncludeNullDelimiter(final boolean includeNullDelimiter) {
+            this.includeNullDelimiter = includeNullDelimiter;
+            return asBuilder();
+        }
     }
 
     protected final String eol;
     protected final ObjectWriter objectWriter;
     protected final boolean compact;
     protected final boolean complete;
+    protected final boolean includeNullDelimiter;
 
+    @Deprecated
     protected AbstractJacksonLayout(final Configuration config, final 
ObjectWriter objectWriter, final Charset charset,
             final boolean compact, final boolean complete, final boolean 
eventEol, final Serializer headerSerializer,
             final Serializer footerSerializer) {
+        this(config, objectWriter, charset, compact, complete, eventEol, 
headerSerializer, footerSerializer, false);
+    }
+
+    protected AbstractJacksonLayout(final Configuration config, final 
ObjectWriter objectWriter, final Charset charset,
+            final boolean compact, final boolean complete, final boolean 
eventEol, final Serializer headerSerializer,
+            final Serializer footerSerializer, final boolean 
includeNullDelimiter) {
         super(config, charset, headerSerializer, footerSerializer);
         this.objectWriter = objectWriter;
         this.compact = compact;
         this.complete = complete;
         this.eol = compact && !eventEol ? COMPACT_EOL : DEFAULT_EOL;
+        this.includeNullDelimiter = includeNullDelimiter;
     }
 
     /**
@@ -183,6 +212,9 @@ abstract class AbstractJacksonLayout extends 
AbstractStringLayout {
             throws JsonGenerationException, JsonMappingException, IOException {
         objectWriter.writeValue(writer, convertMutableToLog4jEvent(event));
         writer.write(eol);
+        if (includeNullDelimiter) {
+            writer.write('\0');
+        }
         markEvent();
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e74e8200/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java
index bbe2c9c..6fcc13d 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java
@@ -29,10 +29,8 @@ import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.DefaultConfiguration;
 import org.apache.logging.log4j.core.config.Node;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
-import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
 
 /**
  * Appends a series of JSON events as strings serialized as bytes.
@@ -84,8 +82,9 @@ public final class JsonLayout extends AbstractJacksonLayout {
             final boolean encodeThreadContextAsList = isProperties() && 
propertiesAsList;
             final String headerPattern = toStringOrNull(getHeader());
             final String footerPattern = toStringOrNull(getFooter());
-            return new JsonLayout(getConfiguration(), isLocationInfo(), 
isProperties(), encodeThreadContextAsList, isComplete(),
-                    isCompact(), getEventEol(), headerPattern, footerPattern, 
getCharset(), isIncludeStacktrace(), isStacktraceAsString());
+            return new JsonLayout(getConfiguration(), isLocationInfo(), 
isProperties(), encodeThreadContextAsList,
+                    isComplete(), isCompact(), getEventEol(), headerPattern, 
footerPattern, getCharset(),
+                    isIncludeStacktrace(), isStacktraceAsString(), 
isIncludeNullDelimiter());
         }
 
         public boolean isPropertiesAsList() {
@@ -107,21 +106,25 @@ public final class JsonLayout extends 
AbstractJacksonLayout {
             final boolean complete, final boolean compact, final boolean 
eventEol, final String headerPattern,
             final String footerPattern, final Charset charset, final boolean 
includeStacktrace) {
         super(config, new JacksonFactory.JSON(encodeThreadContextAsList, 
includeStacktrace, false).newWriter(
-            locationInfo, properties, compact),
-            charset, compact, complete, eventEol,
-            
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
-            
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build());
+                locationInfo, properties, compact),
+                charset, compact, complete, eventEol,
+                
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
+                
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
+                false);
     }
 
     private JsonLayout(final Configuration config, final boolean locationInfo, 
final boolean properties,
-            final boolean encodeThreadContextAsList,
-            final boolean complete, final boolean compact, final boolean 
eventEol, final String headerPattern,
-            final String footerPattern, final Charset charset, final boolean 
includeStacktrace, final boolean stacktraceAsString) {
+                       final boolean encodeThreadContextAsList,
+                       final boolean complete, final boolean compact, final 
boolean eventEol,
+                       final String headerPattern,final String footerPattern, 
final Charset charset,
+                       final boolean includeStacktrace,final boolean 
stacktraceAsString,
+                       final boolean includeNullDelimiter) {
         super(config, new JacksonFactory.JSON(encodeThreadContextAsList, 
includeStacktrace, stacktraceAsString).newWriter(
-            locationInfo, properties, compact),
-            charset, compact, complete, eventEol,
-            
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
-            
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build());
+                locationInfo, properties, compact),
+                charset, compact, complete, eventEol,
+                
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
+                
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
+                includeNullDelimiter);
     }
 
     /**
@@ -225,7 +228,7 @@ public final class JsonLayout extends AbstractJacksonLayout 
{
             final boolean includeStacktrace) {
         final boolean encodeThreadContextAsList = properties && 
propertiesAsList;
         return new JsonLayout(config, locationInfo, properties, 
encodeThreadContextAsList, complete, compact, eventEol,
-                headerPattern, footerPattern, charset, includeStacktrace, 
false);
+                headerPattern, footerPattern, charset, includeStacktrace, 
false, false);
     }
 
     @PluginBuilderFactory
@@ -240,7 +243,7 @@ public final class JsonLayout extends AbstractJacksonLayout 
{
      */
     public static JsonLayout createDefaultLayout() {
         return new JsonLayout(new DefaultConfiguration(), false, false, false, 
false, false, false,
-                DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, 
false);
+                DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, 
false, false);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e74e8200/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java
index c744acf..1e42649 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java
@@ -25,7 +25,6 @@ import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.Node;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
 import org.apache.logging.log4j.core.jackson.XmlConstants;
 
@@ -69,7 +68,8 @@ public final class XmlLayout extends AbstractJacksonLayout {
         @Override
         public XmlLayout build() {
             return new XmlLayout(getConfiguration(), isLocationInfo(), 
isProperties(), isComplete(),
-                isCompact(), getCharset(), isIncludeStacktrace(), 
isStacktraceAsString());
+                    isCompact(), getCharset(), isIncludeStacktrace(), 
isStacktraceAsString(),
+                    isIncludeNullDelimiter());
         }
     }
 
@@ -79,14 +79,15 @@ public final class XmlLayout extends AbstractJacksonLayout {
     @Deprecated
     protected XmlLayout(final boolean locationInfo, final boolean properties, 
final boolean complete,
                         final boolean compact, final Charset charset, final 
boolean includeStacktrace) {
-        this(null, locationInfo, properties, complete, compact, charset, 
includeStacktrace, false);
+        this(null, locationInfo, properties, complete, compact, charset, 
includeStacktrace, false, false);
     }
 
     private XmlLayout(final Configuration config, final boolean locationInfo, 
final boolean properties,
                       final boolean complete, final boolean compact, final 
Charset charset,
-                      final boolean includeStacktrace, final boolean 
stacktraceAsString) {
+                      final boolean includeStacktrace, final boolean 
stacktraceAsString,
+                      final boolean includeNullDelimiter) {
         super(config, new JacksonFactory.XML(includeStacktrace, 
stacktraceAsString).newWriter(
-            locationInfo, properties, compact), charset, compact, complete, 
false, null, null);
+            locationInfo, properties, compact), charset, compact, complete, 
false, null, null, includeNullDelimiter);
     }
 
     /**
@@ -177,7 +178,8 @@ public final class XmlLayout extends AbstractJacksonLayout {
             final boolean compact,
             final Charset charset,
             final boolean includeStacktrace) {
-        return new XmlLayout(null, locationInfo, properties, complete, 
compact, charset, includeStacktrace, false);
+        return new XmlLayout(null, locationInfo, properties, complete, 
compact, charset, includeStacktrace, false,
+                false);
     }
 
     @PluginBuilderFactory
@@ -191,6 +193,6 @@ public final class XmlLayout extends AbstractJacksonLayout {
      * @return an XML Layout.
      */
     public static XmlLayout createDefaultLayout() {
-        return new XmlLayout(null, false, false, false, false, 
StandardCharsets.UTF_8, true, false);
+        return new XmlLayout(null, false, false, false, false, 
StandardCharsets.UTF_8, true, false, false);
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e74e8200/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
index 8a5994e..221819d 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
@@ -26,9 +26,7 @@ import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.DefaultConfiguration;
 import org.apache.logging.log4j.core.config.Node;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
-import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
 import org.apache.logging.log4j.util.Strings;
 
 /**
@@ -62,7 +60,8 @@ public final class YamlLayout extends AbstractJacksonLayout {
             final String headerPattern = toStringOrNull(getHeader());
             final String footerPattern = toStringOrNull(getFooter());
             return new YamlLayout(getConfiguration(), isLocationInfo(), 
isProperties(), isComplete(),
-                isCompact(), getEventEol(), headerPattern, footerPattern, 
getCharset(), isIncludeStacktrace(), isStacktraceAsString());
+                    isCompact(), getEventEol(), headerPattern, footerPattern, 
getCharset(),
+                    isIncludeStacktrace(), isStacktraceAsString(), 
isIncludeNullDelimiter());
         }
     }
 
@@ -74,18 +73,22 @@ public final class YamlLayout extends AbstractJacksonLayout 
{
             final boolean complete, final boolean compact, final boolean 
eventEol, final String headerPattern,
             final String footerPattern, final Charset charset, final boolean 
includeStacktrace) {
         super(config, new JacksonFactory.YAML(includeStacktrace, 
false).newWriter(locationInfo, properties, compact), charset, compact,
-            complete, eventEol,
-            
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
-            
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build());
+                complete, eventEol,
+                
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
+                
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
+                false);
     }
 
     private YamlLayout(final Configuration config, final boolean locationInfo, 
final boolean properties,
-            final boolean complete, final boolean compact, final boolean 
eventEol, final String headerPattern,
-            final String footerPattern, final Charset charset, final boolean 
includeStacktrace, final boolean stacktraceAsString) {
+                       final boolean complete, final boolean compact, final 
boolean eventEol,
+                       final String headerPattern, final String footerPattern, 
final Charset charset,
+                       final boolean includeStacktrace, final boolean 
stacktraceAsString,
+                       final boolean includeNullDelimiter) {
         super(config, new JacksonFactory.YAML(includeStacktrace, 
stacktraceAsString).newWriter(locationInfo, properties, compact), charset, 
compact,
-            complete, eventEol,
-            
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
-            
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build());
+                complete, eventEol,
+                
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
+                
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
+                includeNullDelimiter);
     }
 
     /**
@@ -173,7 +176,7 @@ public final class YamlLayout extends AbstractJacksonLayout 
{
             final Charset charset,
             final boolean includeStacktrace) {
         return new YamlLayout(config, locationInfo, properties, false, false, 
true, headerPattern, footerPattern,
-                charset, includeStacktrace, false);
+                charset, includeStacktrace, false, false);
     }
 
     @PluginBuilderFactory
@@ -188,6 +191,6 @@ public final class YamlLayout extends AbstractJacksonLayout 
{
      */
     public static AbstractJacksonLayout createDefaultLayout() {
         return new YamlLayout(new DefaultConfiguration(), false, false, false, 
false, false, DEFAULT_HEADER,
-                DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false);
+                DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false);
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e74e8200/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java
index 6016a31..82c9eea 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java
@@ -394,6 +394,26 @@ public class JsonLayoutTest {
         return layout.toSerializable(expected);
     }
 
+    @Test
+    public void testIncludeNullDelimiterTrue() throws Exception {
+        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
+                .setCompact(true)
+                .setIncludeNullDelimiter(true)
+                .build();
+        final String str = 
layout.toSerializable(LogEventFixtures.createLogEvent());
+        assertTrue(str.endsWith("\0"));
+    }
+
+    @Test
+    public void testIncludeNullDelimiterFalse() throws Exception {
+        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
+                .setCompact(true)
+                .setIncludeNullDelimiter(false)
+                .build();
+        final String str = 
layout.toSerializable(LogEventFixtures.createLogEvent());
+        assertFalse(str.endsWith("\0"));
+    }
+    
     private String toPropertySeparator(final boolean compact) {
         return compact ? ":" : " : ";
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e74e8200/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/XmlLayoutTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/XmlLayoutTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/XmlLayoutTest.java
index bbfec57..4701b17 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/XmlLayoutTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/XmlLayoutTest.java
@@ -342,4 +342,24 @@ public class XmlLayoutTest {
         // @formatter:off
         return layout.toSerializable(expected);
     }
+
+    @Test
+    public void testIncludeNullDelimiterTrue() throws Exception {
+        final AbstractJacksonLayout layout = XmlLayout.newBuilder()
+                .setCompact(true)
+                .setIncludeNullDelimiter(true)
+                .build();
+        final String str = 
layout.toSerializable(LogEventFixtures.createLogEvent());
+        assertTrue(str.endsWith("\0"));
+    }
+
+    @Test
+    public void testIncludeNullDelimiterFalse() throws Exception {
+        final AbstractJacksonLayout layout = XmlLayout.newBuilder()
+                .setCompact(true)
+                .setIncludeNullDelimiter(false)
+                .build();
+        final String str = 
layout.toSerializable(LogEventFixtures.createLogEvent());
+        assertFalse(str.endsWith("\0"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e74e8200/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java
index a634488..3531237 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java
@@ -337,6 +337,24 @@ public class YamlLayoutTest {
         return layout.toSerializable(expected);
     }
 
+    @Test
+    public void testIncludeNullDelimiterTrue() throws Exception {
+        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
+                .setIncludeNullDelimiter(true)
+                .build();
+        final String str = 
layout.toSerializable(LogEventFixtures.createLogEvent());
+        assertTrue(str.endsWith("\0"));
+    }
+
+    @Test
+    public void testIncludeNullDelimiterFalse() throws Exception {
+        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
+                .setIncludeNullDelimiter(false)
+                .build();
+        final String str = 
layout.toSerializable(LogEventFixtures.createLogEvent());
+        assertFalse(str.endsWith("\0"));
+    }
+
     private String toPropertySeparator(final boolean compact, final boolean 
value) {
         return value ? ": " : ":";
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e74e8200/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 762e66a..36343d1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,9 @@
          - "remove" - Removed
     -->
     <release version="2.9.0" date="2017-MM-DD" description="GA Release 2.9.0">
+      <action issue="LOG4J2-1981" dev="mikes" type="add">
+        JsonLayout, XmlLayout and YamlLayout support 0-byte termination of log 
events.
+      </action>
       <action issue="LOG4J2-1864" dev="mattsicker" type="add" due-to="Matthias 
Kappeller">
         Support capped collections for MongoDb appender.
       </action>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e74e8200/src/site/xdoc/manual/layouts.xml.vm
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/layouts.xml.vm 
b/src/site/xdoc/manual/layouts.xml.vm
index d7eaa6b..06e93dd 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -452,7 +452,12 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3);
             <tr>
               <td>stacktraceAsString</td>
               <td>boolean</td>
-              <td>Whether to format the stackstrace as a string, and not a 
nested object (optional, defaults to false).</td>
+              <td>Whether to format the stacktrace as a string, and not a 
nested object (optional, defaults to false).</td>
+            </tr>
+            <tr>
+              <td>includeNullDelimiter</td>
+              <td>boolean</td>
+              <td>Whether to include NULL byte as delimiter after each event 
(optional, default to false).</td>
             </tr>
             <caption align="top">JsonLayout Parameters</caption>
           </table>
@@ -2186,7 +2191,12 @@ at 
org.apache.logging.log4j.core.pattern.ExtendedThrowableTest.testException(Ext
             <tr>
               <td>stacktraceAsString</td>
               <td>boolean</td>
-              <td>Whether to format the stackstrace as a string, and not a 
nested object (optional, defaults to false).</td>
+              <td>Whether to format the stacktrace as a string, and not a 
nested object (optional, defaults to false).</td>
+            </tr>
+            <tr>
+              <td>includeNullDelimiter</td>
+              <td>boolean</td>
+              <td>Whether to include NULL byte as delimiter after each event 
(optional, default to false).</td>
             </tr>
             <caption align="top">XmlLayout Parameters</caption>
           </table>
@@ -2275,7 +2285,12 @@ source:
             <tr>
               <td>stacktraceAsString</td>
               <td>boolean</td>
-              <td>Whether to format the stackstrace as a string, and not a 
nested object (optional, defaults to false).</td>
+              <td>Whether to format the stacktrace as a string, and not a 
nested object (optional, defaults to false).</td>
+            </tr>
+            <tr>
+              <td>includeNullDelimiter</td>
+              <td>boolean</td>
+              <td>Whether to include NULL byte as delimiter after each event 
(optional, default to false).</td>
             </tr>
             <caption align="top">YamlLayout Parameters</caption>
           </table>

Reply via email to