You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2018/02/20 02:09:18 UTC

[01/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Repository: logging-log4j2
Updated Branches:
  refs/heads/master ec3c623a8 -> 0eb5212e4


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/LevelMixInTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/LevelMixInTest.java b/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/LevelMixInTest.java
new file mode 100644
index 0000000..0cdcb36
--- /dev/null
+++ b/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/LevelMixInTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.categories.Layouts;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
+
+/**
+ * Tests {@link LevelMixIn}.
+ */
+@Category(Layouts.Json.class)
+public abstract class LevelMixInTest {
+
+    static class Fixture {
+        @JsonProperty
+        private final Level level = Level.DEBUG;
+
+        @Override
+        public boolean equals(final Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            final Fixture other = (Fixture) obj;
+            if (this.level == null) {
+                if (other.level != null) {
+                    return false;
+                }
+            } else if (!this.level.equals(other.level)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((this.level == null) ? 0 : this.level.hashCode());
+            return result;
+        }
+    }
+    private ObjectMapper log4jObjectMapper;
+
+    private ObjectReader reader;
+
+    private ObjectWriter writer;
+
+    protected abstract ObjectMapper newObjectMapper();
+
+    @Before
+    public void setUp() {
+        log4jObjectMapper = newObjectMapper();
+        writer = log4jObjectMapper.writer();
+        reader = log4jObjectMapper.readerFor(Level.class);
+    }
+
+    @Test
+    public void testContainer() throws IOException {
+        final Fixture expected = new Fixture();
+        final String str = writer.writeValueAsString(expected);
+        Assert.assertTrue(str.contains("DEBUG"));
+        final ObjectReader fixtureReader = log4jObjectMapper.readerFor(Fixture.class);
+        final Fixture actual = fixtureReader.readValue(str);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testNameOnly() throws IOException {
+        final Level expected = Level.getLevel("DEBUG");
+        final String str = writer.writeValueAsString(expected);
+        Assert.assertTrue(str.contains("DEBUG"));
+        final Level actual = reader.readValue(str);
+        Assert.assertEquals(expected, actual);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/ThrowableProxyJacksonTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/ThrowableProxyJacksonTest.java b/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/ThrowableProxyJacksonTest.java
new file mode 100644
index 0000000..ee07711
--- /dev/null
+++ b/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/ThrowableProxyJacksonTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ *
+ */
+public class ThrowableProxyJacksonTest {
+
+    static class Fixture {
+        @JsonProperty
+        ThrowableProxy proxy = new ThrowableProxy(new IOException("test"));
+    }
+
+    protected void testIoContainer(final ObjectMapper objectMapper) throws IOException {
+        final Fixture expected = new Fixture();
+        final String s = objectMapper.writeValueAsString(expected);
+        final Fixture actual = objectMapper.readValue(s, Fixture.class);
+        assertEquals(expected.proxy.getName(), actual.proxy.getName());
+        assertEquals(expected.proxy.getMessage(), actual.proxy.getMessage());
+        assertEquals(expected.proxy.getLocalizedMessage(), actual.proxy.getLocalizedMessage());
+        assertEquals(expected.proxy.getCommonElementCount(), actual.proxy.getCommonElementCount());
+        assertArrayEquals(expected.proxy.getExtendedStackTrace(), actual.proxy.getExtendedStackTrace());
+        assertEquals(expected.proxy, actual.proxy);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 2c8f327..ff8c1b9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1341,6 +1341,10 @@
     <module>log4j-api</module>
     <module>log4j-core-java9</module>
     <module>log4j-core</module>
+    <module>log4j-layout-jackson</module>
+    <module>log4j-layout-jackson-json</module>
+    <module>log4j-layout-jackson-xml</module>
+    <module>log4j-layout-jackson-yaml</module>
     <module>log4j-core-its</module>
     <module>log4j-1.2-api</module>
     <module>log4j-slf4j-impl</module>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d3f9420..edb22bc 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -61,6 +61,9 @@
       <action issue="LOG4J2-2244" dev="ggregory" type="update" due-to="Gary Gregory">
         org.apache.logging.log4j.core.lookup.EnvironmentLookup may throw NPE.
       </action>      
+      <action issue="LOG4J2-2237" dev="ggregory" type="update" due-to="Gary Gregory">
+        Move Jackson-based layouts to their own modules: JSON, XML, and YAML.
+      </action>      
     </release>
     <release version="2.11.0" date="2018-xx-xx" description="GA Release 2.11.0">
       <action issue="LOG4J2-2254" dev="rgoers" type="fix">


[04/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParser.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParser.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParser.java
new file mode 100644
index 0000000..32776a2
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParser.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml.parser;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.parser.AbstractJacksonLogEventParser;
+import org.apache.logging.log4j.jackson.xml.Log4jXmlObjectMapper;
+
+/**
+ * Parses the output from XmlLayout layout into instances of {@link LogEvent}.
+ */
+public class XmlLogEventParser extends AbstractJacksonLogEventParser {
+
+    public XmlLogEventParser() {
+        super(new Log4jXmlObjectMapper());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/site/manual/index.md
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/site/manual/index.md b/log4j-layout-jackson-xml/src/site/manual/index.md
new file mode 100644
index 0000000..216fe05
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/site/manual/index.md
@@ -0,0 +1,33 @@
+<!-- vim: set syn=markdown : -->
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+# Apache Log4j Layout for Jackson XML module
+
+As of Log4j 3.0.0, the layout based on Jackson XML has moved from the existing module logj-core to the new modules log4j-layout-jackson-xml.
+
+## Requirements
+
+This module was introduced in Log4j 2.11.0 and requires Jackson.
+
+Some features may require optional
+[dependencies](../runtime-dependencies.html). These dependencies are specified in the
+documentation for those features.
+
+Some Log4j features require external dependencies.
+See the [Dependency Tree](dependencies.html#Dependency_Tree)
+for the exact list of JAR files needed for these features.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/site/site.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/site/site.xml b/log4j-layout-jackson-xml/src/site/site.xml
new file mode 100644
index 0000000..6d4cddc
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/site/site.xml
@@ -0,0 +1,52 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project name="Log4j Core"
+         xmlns="http://maven.apache.org/DECORATION/1.4.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
+  <body>
+    <links>
+      <item name="Apache" href="http://www.apache.org/" />
+      <item name="Logging Services" href="http://logging.apache.org/"/>
+      <item name="Log4j" href="../index.html"/>
+    </links>
+
+    <!-- Component-specific reports -->
+    <menu ref="reports"/>
+
+	<!-- Overall Project Info -->
+    <menu name="Log4j Project Information" img="icon-info-sign">
+      <item name="Dependencies" href="../dependencies.html" />
+      <item name="Dependency Convergence" href="../dependency-convergence.html" />
+      <item name="Dependency Management" href="../dependency-management.html" />
+      <item name="Project Team" href="../team-list.html" />
+      <item name="Mailing Lists" href="../mail-lists.html" />
+      <item name="Issue Tracking" href="../issue-tracking.html" />
+      <item name="Project License" href="../license.html" />
+      <item name="Source Repository" href="../source-repository.html" />
+      <item name="Project Summary" href="../project-summary.html" />
+    </menu>
+
+    <menu name="Log4j Project Reports" img="icon-cog">
+      <item name="Changes Report" href="../changes-report.html" />
+      <item name="JIRA Report" href="../jira-report.html" />
+      <item name="Surefire Report" href="../surefire-report.html" />
+      <item name="RAT Report" href="../rat-report.html" />
+    </menu>
+  </body>
+</project>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/LevelMixInXmlTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/LevelMixInXmlTest.java b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/LevelMixInXmlTest.java
new file mode 100644
index 0000000..36e8532
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/LevelMixInXmlTest.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.jackson.LevelMixInTest;
+import org.junit.Ignore;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Ignore("Fails for #testNameOnly()")
+@Category(Layouts.Xml.class)
+public class LevelMixInXmlTest extends LevelMixInTest {
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jXmlObjectMapper();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/MarkerMixInXmlTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/MarkerMixInXmlTest.java b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/MarkerMixInXmlTest.java
new file mode 100644
index 0000000..b909453
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/MarkerMixInXmlTest.java
@@ -0,0 +1,34 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache license, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the license for the specific language governing permissions and
+* limitations under the license.
+*/
+
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.jackson.AbstractMarkerMixInTest;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Category(Layouts.Xml.class)
+public class MarkerMixInXmlTest extends AbstractMarkerMixInTest {
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jXmlObjectMapper(true, false);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/StackTraceElementXmlMixInTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/StackTraceElementXmlMixInTest.java b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/StackTraceElementXmlMixInTest.java
new file mode 100644
index 0000000..1d45672
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/StackTraceElementXmlMixInTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.jackson.Log4jStackTraceElementDeserializer;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+@Category(Layouts.Json.class)
+public class StackTraceElementXmlMixInTest {
+
+    protected String aposToQuotes(final String json) {
+        return json.replace("'", "\"");
+    }
+
+    private void roundtrip(final ObjectMapper mapper)
+            throws JsonProcessingException, IOException, JsonParseException, JsonMappingException {
+        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java",
+                123);
+        final String s = mapper.writeValueAsString(expected);
+        final StackTraceElement actual = mapper.readValue(s, StackTraceElement.class);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testFromJsonWithLog4jModule() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        final boolean encodeThreadContextAsList = false;
+        final Log4jXmlModule module = new Log4jXmlModule(true, false);
+        module.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
+        mapper.registerModule(module);
+        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java",
+                123);
+        final String s = this
+                .aposToQuotes("{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':123}");
+        final StackTraceElement actual = mapper.readValue(s, StackTraceElement.class);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testFromJsonWithSimpleModule() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        final SimpleModule module = new SimpleModule();
+        module.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
+        mapper.registerModule(module);
+        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java",
+                123);
+        final String s = this
+                .aposToQuotes("{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':123}");
+        final StackTraceElement actual = mapper.readValue(s, StackTraceElement.class);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testLog4jXmlObjectMapper() throws Exception {
+        this.roundtrip(new Log4jXmlObjectMapper());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/ConcurrentLoggingWithXmlLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/ConcurrentLoggingWithXmlLayoutTest.java b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/ConcurrentLoggingWithXmlLayoutTest.java
new file mode 100644
index 0000000..afbff8a
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/ConcurrentLoggingWithXmlLayoutTest.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml.layout;
+
+import static org.hamcrest.CoreMatchers.endsWith;
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertThat;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.junit.AfterClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+/**
+ * Like the test for LOG4J2-1769.
+ */
+public class ConcurrentLoggingWithXmlLayoutTest {
+
+    private class LoggingThread extends Thread {
+        private final Set<Thread> threads;
+        private final Logger log;
+
+        LoggingThread(final Set<Thread> threads, final Logger log) {
+            this.threads = threads;
+            this.log = log;
+        }
+
+        @Override
+        public void run() {
+            log.info(threads.size());
+            try {
+                for (int i = 0; i < 64; i++) {
+                    log.info("First message.");
+                    log.info("Second message.");
+                }
+            } finally {
+                threads.remove(this);
+            }
+        }
+    }
+
+    @ClassRule
+    public static LoggerContextRule context = new LoggerContextRule("log4j2-xml-layout.xml");
+
+    private static final String PATH = "target/test-xml-layout.log";
+
+    @AfterClass
+    public static void after() {
+        new File(PATH).delete();
+    }
+
+    @Test
+    public void testConcurrentLogging() throws Throwable {
+        final Logger log = context.getLogger(ConcurrentLoggingWithXmlLayoutTest.class);
+        final Set<Thread> threads = Collections.synchronizedSet(new HashSet<Thread>());
+        final List<Throwable> thrown = Collections.synchronizedList(new ArrayList<Throwable>());
+
+        for (int x = 0; x < Runtime.getRuntime().availableProcessors() * 2; x++) {
+            final Thread t = new LoggingThread(threads, log);
+            threads.add(t);
+
+            // Appender is configured with ignoreExceptions="false";
+            // any exceptions are propagated to the caller, so we can catch them here.
+            t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+                @Override
+                public void uncaughtException(final Thread t, final Throwable e) {
+                    thrown.add(e);
+                }
+            });
+            t.start();
+        }
+
+        while (!threads.isEmpty()) {
+            log.info("not done going to sleep...");
+            Thread.sleep(10);
+        }
+
+        // if any error occurred, fail this test
+        if (!thrown.isEmpty()) {
+            throw thrown.get(0);
+        }
+
+        // simple test to ensure content is not corrupted
+        if (new File(PATH).exists()) {
+            final List<String> lines = Files.readAllLines(new File(PATH).toPath(), Charset.defaultCharset());
+            for (final String line : lines) {
+                assertThat(line, startsWith("<Event "));
+                assertThat(line, endsWith("</Event>"));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/ThrowableProxyXmlTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/ThrowableProxyXmlTest.java b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/ThrowableProxyXmlTest.java
new file mode 100644
index 0000000..7fb9177
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/ThrowableProxyXmlTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.xml.layout;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.jackson.ThrowableProxyJacksonTest;
+import org.apache.logging.log4j.jackson.xml.Log4jXmlObjectMapper;
+import org.junit.Test;
+
+public class ThrowableProxyXmlTest extends ThrowableProxyJacksonTest {
+
+    @Test
+    public void testIoContainerAsXml() throws IOException {
+        testIoContainer(new Log4jXmlObjectMapper());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayoutTest.java b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayoutTest.java
new file mode 100644
index 0000000..5323163
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayoutTest.java
@@ -0,0 +1,440 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml.layout;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.BasicConfigurationFactory;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.layout.LogEventFixtures;
+import org.apache.logging.log4j.core.lookup.JavaLookup;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.apache.logging.log4j.jackson.AbstractJacksonLayout;
+import org.apache.logging.log4j.jackson.XmlConstants;
+import org.apache.logging.log4j.jackson.xml.AbstractLogEventXmlMixIn;
+import org.apache.logging.log4j.jackson.xml.Log4jXmlObjectMapper;
+import org.apache.logging.log4j.junit.ThreadContextRule;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.spi.AbstractLogger;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+/**
+ * Tests {@link XmlLayout}.
+ */
+@Category(Layouts.Xml.class)
+public class XmlLayoutTest {
+    private static final int NOT_FOUND = -1;
+    private static final String body = "<Message>empty mdc</Message>";
+    static ConfigurationFactory cf = new BasicConfigurationFactory();
+    private static final String markerTag = "<Marker name=\"EVENT\"/>";
+
+    @AfterClass
+    public static void cleanupClass() {
+        ConfigurationFactory.removeConfigurationFactory(cf);
+    }
+
+    @BeforeClass
+    public static void setupClass() {
+        ConfigurationFactory.setConfigurationFactory(cf);
+        final LoggerContext ctx = LoggerContext.getContext();
+        ctx.reconfigure();
+    }
+
+    @Rule
+    public final ThreadContextRule threadContextRule = new ThreadContextRule();
+
+    LoggerContext ctx = LoggerContext.getContext();
+
+    Logger rootLogger = this.ctx.getRootLogger();
+
+    private void checkAttribute(final String name, final String value, final boolean compact, final String str) {
+        Assert.assertTrue(str, str.contains(name + "=\"" + value + "\""));
+    }
+
+    private void checkAttributeName(final String name, final boolean compact, final String str) {
+        Assert.assertTrue(str, str.contains(name + "=\""));
+    }
+
+    private void checkContains(final String expected, final List<String> list) {
+        for (final String string : list) {
+            final String trimedLine = string.trim();
+            if (trimedLine.contains(expected)) {
+                return;
+            }
+        }
+        Assert.fail("Cannot find " + expected + " in " + list);
+    }
+
+    private void checkContextMapElement(final String key, final String value, final boolean compact, final String str) {
+        // <item key="MDC.A" value="A_Value"/>
+        assertTrue(str, str.contains(String.format("<item key=\"%s\" value=\"%s\"/>", key, value)));
+    }
+
+    private void checkContextStackElement(final String value, final boolean compact, final String str) {
+        // <ContextStackItem>stack_msg1</ContextStackItem>
+        assertTrue(str, str.contains(String.format("<ContextStackItem>%s</ContextStackItem>", value)));
+    }
+
+    private void checkElementName(final String name, final boolean compact, final String str,
+            final boolean withAttributes, final boolean withChildren) {
+        // simple checks, don't try to be too smart here, we're just looking for the names and basic shape.
+        // start
+        final String startStr = withAttributes ? "<" + name + " " : "<" + name + ">";
+        final int startPos = str.indexOf(startStr);
+        Assert.assertTrue(String.format("Missing text '%s' in: %s", startStr, str), startPos >= 0);
+        // end
+        final String endStr = withChildren ? "</" + name + ">" : "/>";
+        final int endPos = str.indexOf(endStr, startPos + startStr.length());
+        Assert.assertTrue(str, endPos >= 0);
+    }
+
+    private void checkElementNameAbsent(final String name, final boolean compact, final String str) {
+        Assert.assertFalse(str.contains("<" + name));
+    }
+
+    private void checkJsonPropertyOrder(final boolean includeContextStack, final boolean includeContextMap,
+            final boolean includeStacktrace, final String str) {
+        final JsonPropertyOrder annotation = AbstractLogEventXmlMixIn.class.getAnnotation(JsonPropertyOrder.class);
+        Assert.assertNotNull(annotation);
+        int previousIndex = 0;
+        String previousName = null;
+        for (final String name : annotation.value()) {
+            final int currentIndex = str.indexOf(name);
+            if (!includeContextStack && XmlConstants.ELT_CONTEXT_STACK.equals(name)) {
+                Assert.assertTrue(String.format("Unexpected element '%s' in: %s", name, str),
+                        currentIndex == NOT_FOUND);
+                break;
+            }
+            if (!includeContextMap && XmlConstants.ELT_CONTEXT_MAP.equals(name)) {
+                Assert.assertTrue(String.format("Unexpected element '%s' in: %s", name, str),
+                        currentIndex == NOT_FOUND);
+                break;
+            }
+            if (!includeStacktrace && XmlConstants.ELT_EXTENDED_STACK_TRACE.equals(name)) {
+                Assert.assertTrue(String.format("Unexpected element '%s' in: %s", name, str),
+                        currentIndex == NOT_FOUND);
+                break;
+            }
+            if (!includeStacktrace && XmlConstants.ELT_EXTENDED_STACK_TRACE_ITEM.equals(name)) {
+                Assert.assertTrue(String.format("Unexpected element '%s' in: %s", name, str),
+                        currentIndex == NOT_FOUND);
+                break;
+            }
+            // TODO
+            // Bug: The method
+            // com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._sortProperties(Map<String,
+            // POJOPropertyBuilder>) messes up the order defined in AbstractXmlLogEventMixIn's JsonPropertyOrder
+            // annotations.
+            // Assert.assertTrue(String.format("name='%s', previousIndex=%,d, previousName='%s', currentIndex=%,d: %s",
+            // name, previousIndex, previousName, currentIndex, str), previousIndex < currentIndex);
+            previousIndex = currentIndex;
+            previousName = name;
+        }
+    }
+
+    private String prepareXMLForStacktraceTests(final boolean stacktraceAsString) {
+        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
+        // @formatter:off
+        final AbstractJacksonLayout layout = XmlLayout.newBuilder()
+                .setCompact(true)
+                .setIncludeStacktrace(true)
+                .setStacktraceAsString(stacktraceAsString)
+                .build();
+        // @formatter:off
+        return layout.toSerializable(expected);
+    }
+
+    @Test
+    public void testAdditionalFields() throws Exception {
+        final AbstractJacksonLayout layout = XmlLayout.newBuilder().setLocationInfo(false).setProperties(false)
+                .setIncludeStacktrace(false)
+                .setAdditionalFields(new KeyValuePair[] { new KeyValuePair("KEY1", "VALUE1"),
+                        new KeyValuePair("KEY2", "${java:runtime}"), })
+                .setCharset(StandardCharsets.UTF_8).setConfiguration(ctx.getConfiguration()).build();
+        final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
+        assertTrue(str, str.contains("<KEY1>VALUE1</KEY1>"));
+        assertTrue(str, str.contains("<KEY2>" + new JavaLookup().getRuntime() + "</KEY2>"));
+    }
+
+    /**
+     * @param includeLocationInfo
+     *            TODO
+     * @param compact
+     * @param includeContextMap
+     *            TODO
+     * @param includeContextStack
+     *            TODO
+     * @throws IOException
+     * @throws JsonParseException
+     * @throws JsonMappingException
+     */
+    private void testAllFeatures(final boolean includeLocationInfo, final boolean compact,
+            final boolean includeContextMap, final boolean includeContextStack, final boolean includeStacktrace)
+            throws IOException, JsonParseException, JsonMappingException {
+        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
+        // @formatter:off
+        final XmlLayout layout = XmlLayout.newBuilder()
+                .setLocationInfo(includeLocationInfo)
+                .setProperties(includeContextMap)
+                .setComplete(false)
+                .setCompact(compact)
+                .setIncludeStacktrace(includeStacktrace)
+                .setCharset(StandardCharsets.UTF_8)
+                .build();
+        final String str = layout.toSerializable(expected);
+        // @formatter:on
+        // System.out.println(str);
+        assertEquals(str, !compact, str.contains("\n"));
+        assertEquals(str, includeLocationInfo, str.contains("Source"));
+        assertEquals(str, includeContextMap, str.contains("ContextMap"));
+        final Log4jLogEvent actual = new Log4jXmlObjectMapper().readValue(str, Log4jLogEvent.class);
+        LogEventFixtures.assertEqualLogEvents(expected, actual, includeLocationInfo, includeContextMap,
+                includeStacktrace);
+        if (includeContextMap) {
+            this.checkContextMapElement("MDC.A", "A_Value", compact, str);
+            this.checkContextMapElement("MDC.B", "B_Value", compact, str);
+        }
+        if (includeContextStack) {
+            this.checkContextStackElement("stack_msg1", compact, str);
+            this.checkContextStackElement("stack_msg2", compact, str);
+        }
+
+        //
+        assertNull(actual.getThrown());
+        // check some attrs
+        assertTrue(str, str.contains("loggerFqcn=\"f.q.c.n\""));
+        assertTrue(str, str.contains("loggerName=\"a.B\""));
+        // make sure short names are used
+        assertTrue(str, str.contains("<Event "));
+        if (includeStacktrace) {
+            assertTrue("Missing \"class=\" in: " + str, str.contains("class="));
+            assertTrue("Missing \"method=\" in: " + str, str.contains("method="));
+            assertTrue("Missing \"file=\" in: " + str, str.contains("file="));
+            assertTrue("Missing \"line=\" in: " + str, str.contains("line="));
+        }
+        //
+        // make sure the names we want are used
+        // this.checkAttributeName("timeMillis", compact, str);
+        this.checkElementName("Instant", compact, str, true, false);
+        this.checkAttributeName("epochSecond", compact, str);
+        this.checkAttributeName("nanoOfSecond", compact, str);
+        this.checkAttributeName("thread", compact, str); // and not threadName
+        this.checkAttributeName("level", compact, str);
+        this.checkAttributeName("loggerName", compact, str);
+        this.checkElementName("Marker", compact, str, true, true);
+        this.checkAttributeName("name", compact, str);
+        this.checkElementName("Parents", compact, str, false, true);
+        this.checkElementName("Message", compact, str, false, true);
+        this.checkElementName("Thrown", compact, str, true, true);
+        this.checkElementName("Cause", compact, str, true, includeStacktrace);
+        this.checkAttributeName("commonElementCount", compact, str);
+        this.checkAttributeName("message", compact, str);
+        this.checkAttributeName("localizedMessage", compact, str);
+        if (includeStacktrace) {
+            this.checkElementName("ExtendedStackTrace", compact, str, false, true);
+            this.checkAttributeName("class", compact, str);
+            this.checkAttributeName("method", compact, str);
+            this.checkAttributeName("file", compact, str);
+            this.checkAttributeName("line", compact, str);
+            this.checkAttributeName("exact", compact, str);
+            this.checkAttributeName("location", compact, str);
+            this.checkAttributeName("version", compact, str);
+        } else {
+            this.checkElementNameAbsent("ExtendedStackTrace", compact, str);
+        }
+        this.checkElementName("Suppressed", compact, str, false, true);
+        this.checkAttributeName("loggerFqcn", compact, str);
+        this.checkAttributeName("endOfBatch", compact, str);
+        if (includeContextMap) {
+            this.checkElementName("ContextMap", compact, str, false, true);
+        } else {
+            this.checkElementNameAbsent("ContextMap", compact, str);
+        }
+        this.checkElementName("ContextStack", compact, str, false, true);
+        if (includeLocationInfo) {
+            this.checkElementName("Source", compact, str, true, false);
+        } else {
+            this.checkElementNameAbsent("Source", compact, str);
+        }
+        // check some attrs
+        this.checkAttribute("loggerFqcn", "f.q.c.n", compact, str);
+        this.checkAttribute("loggerName", "a.B", compact, str);
+        this.checkJsonPropertyOrder(includeContextStack, includeContextMap, includeStacktrace, str);
+    }
+
+    @Test
+    public void testContentType() {
+        final XmlLayout layout = XmlLayout.createDefaultLayout();
+        assertEquals("text/xml; charset=UTF-8", layout.getContentType());
+    }
+
+    @Test
+    public void testDefaultCharset() {
+        final XmlLayout layout = XmlLayout.createDefaultLayout();
+        assertEquals(StandardCharsets.UTF_8, layout.getCharset());
+    }
+
+    @Test
+    public void testExcludeStacktrace() throws Exception {
+        this.testAllFeatures(false, false, false, false, false);
+    }
+
+    @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"));
+    }
+
+    @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 case for MDC conversion pattern.
+     */
+    @Test
+    public void testLayout() throws Exception {
+        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
+        for (final Appender appender : appenders.values()) {
+            this.rootLogger.removeAppender(appender);
+        }
+        // set up appender
+        final XmlLayout layout = XmlLayout.newBuilder().setLocationInfo(true).setProperties(true).setComplete(true)
+                .setCompact(false).setIncludeStacktrace(true).build();
+
+        final ListAppender appender = new ListAppender("List", null, layout, true, false);
+        appender.start();
+
+        // set appender on root and set level to debug
+        this.rootLogger.addAppender(appender);
+        this.rootLogger.setLevel(Level.DEBUG);
+
+        // output starting message
+        this.rootLogger.debug("starting mdc pattern test");
+
+        this.rootLogger.debug("empty mdc");
+
+        ThreadContext.put("key1", "value1");
+        ThreadContext.put("key2", "value2");
+
+        this.rootLogger.debug("filled mdc");
+
+        ThreadContext.remove("key1");
+        ThreadContext.remove("key2");
+
+        this.rootLogger.error("finished mdc pattern test", new NullPointerException("test"));
+
+        final Marker marker = MarkerManager.getMarker("EVENT");
+        this.rootLogger.error(marker, "marker test");
+
+        appender.stop();
+
+        final List<String> list = appender.getMessages();
+
+        final String string = list.get(0);
+        assertTrue("Incorrect header: " + string, string.equals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
+        assertTrue("Incorrect footer", list.get(list.size() - 1).equals("</Events>"));
+        this.checkContains("loggerFqcn=\"" + AbstractLogger.class.getName() + "\"", list);
+        this.checkContains("level=\"DEBUG\"", list);
+        this.checkContains(">starting mdc pattern test</Message>", list);
+        // this.checkContains("<Message>starting mdc pattern test</Message>", list);
+
+        // <Marker xmlns="" _class="org.apache.logging.log4j.MarkerManager..Log4jMarker" name="EVENT"/>
+        this.checkContains("<Marker", list);
+        this.checkContains("name=\"EVENT\"/>", list);
+
+        for (final Appender app : appenders.values()) {
+            this.rootLogger.addAppender(app);
+        }
+    }
+
+    @Test
+    public void testLayoutLoggerName() {
+        final XmlLayout layout = XmlLayout.newBuilder().setLocationInfo(false).setProperties(true).setComplete(true)
+                .setCompact(false).setIncludeStacktrace(true).build();
+
+        final Log4jLogEvent event = Log4jLogEvent.newBuilder() //
+                .setLoggerName("a.B") //
+                .setLoggerFqcn("f.q.c.n") //
+                .setLevel(Level.DEBUG) //
+                .setMessage(new SimpleMessage("M")) //
+                .setThreadName("threadName") //
+                .setTimeMillis(1).build();
+        final String str = layout.toSerializable(event);
+        assertTrue(str, str.contains("loggerName=\"a.B\""));
+    }
+
+    @Test
+    public void testLocationOffCompactOffMdcOff() throws Exception {
+        this.testAllFeatures(false, false, false, false, true);
+    }
+
+    @Test
+    public void testLocationOnCompactOnMdcOn() throws Exception {
+        this.testAllFeatures(true, true, true, true, true);
+    }
+
+    @Test
+    public void testLocationOnCompactOnNdcOn() throws Exception {
+        this.testAllFeatures(false, false, false, true, false);
+    }
+
+    @Test
+    public void testStacktraceAsNonString() throws Exception {
+        final String str = prepareXMLForStacktraceTests(false);
+        assertTrue(str, str.contains("<ExtendedStackTrace><ExtendedStackTraceItem"));
+    }
+
+    @Test
+    public void testStacktraceAsString() throws Exception {
+        final String str = prepareXMLForStacktraceTests(true);
+        assertTrue(str, str.contains("<ExtendedStackTrace>java.lang.NullPointerException"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParserTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParserTest.java b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParserTest.java
new file mode 100644
index 0000000..93e30b5
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/test/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParserTest.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml.parser;
+
+import java.nio.charset.StandardCharsets;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.parser.AbstractLogEventParserTest;
+import org.apache.logging.log4j.core.parser.ParseException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class XmlLogEventParserTest extends AbstractLogEventParserTest {
+
+    private static final String XML = "<Event xmlns=\"http://logging.apache.org/log4j/2.0/events\"\n" +
+            "       timeMillis=\"1493121664118\"\n" +
+            "       level=\"INFO\"\n" +
+            "       loggerName=\"HelloWorld\"\n" +
+            "       endOfBatch=\"false\"\n" +
+            "       thread=\"main\"\n" +
+            "       loggerFqcn=\"org.apache.logging.log4j.spi.AbstractLogger\"\n" +
+            "       threadId=\"1\"\n" +
+            "       threadPriority=\"5\">\n" +
+            "  <Instant epochSecond=\"1493121664\" nanoOfSecond=\"118000000\"/>\n" +
+            "  <Marker name=\"child\">\n" +
+            "    <Parents>\n" +
+            "      <Marker name=\"parent\">\n" +
+            "        <Parents>\n" +
+            "          <Marker name=\"grandparent\"/>\n" +
+            "        </Parents>\n" +
+            "      </Marker>\n" +
+            "    </Parents>\n" +
+            "  </Marker>\n" +
+            "  <Message>Hello, world!</Message>\n" +
+            "  <ContextMap>\n" +
+            "    <item key=\"bar\" value=\"BAR\"/>\n" +
+            "    <item key=\"foo\" value=\"FOO\"/>\n" +
+            "  </ContextMap>\n" +
+            "  <ContextStack>\n" +
+            "    <ContextStackItem>one</ContextStackItem>\n" +
+            "    <ContextStackItem>two</ContextStackItem>\n" +
+            "  </ContextStack>\n" +
+            "  <Source\n" +
+            "      class=\"logtest.Main\"\n" +
+            "      method=\"main\"\n" +
+            "      file=\"Main.java\"\n" +
+            "      line=\"29\"/>\n" +
+            "  <Thrown commonElementCount=\"0\" message=\"error message\" name=\"java.lang.RuntimeException\">\n" +
+            "    <ExtendedStackTrace>\n" +
+            "      <ExtendedStackTraceItem\n" +
+            "          class=\"logtest.Main\"\n" +
+            "          method=\"main\"\n" +
+            "          file=\"Main.java\"\n" +
+            "          line=\"29\"\n" +
+            "          exact=\"true\"\n" +
+            "          location=\"classes/\"\n" +
+            "          version=\"?\"/>\n" +
+            "    </ExtendedStackTrace>\n" +
+            "  </Thrown>\n" +
+            "</Event>";
+
+    private XmlLogEventParser parser;
+
+    @Before
+    public void setup() {
+        parser = new XmlLogEventParser();
+    }
+
+    @Test
+    public void testByteArray() throws ParseException {
+        final LogEvent logEvent = parser.parseFrom(XML.getBytes(StandardCharsets.UTF_8));
+        assertLogEvent(logEvent);
+    }
+
+    @Test
+    public void testByteArrayOffsetLength() throws ParseException {
+        final byte[] bytes = ("abc" + XML + "def").getBytes(StandardCharsets.UTF_8);
+        final LogEvent logEvent = parser.parseFrom(bytes, 3, bytes.length - 6);
+        assertLogEvent(logEvent);
+    }
+
+    @Test
+    public void testEmptyObject() throws ParseException {
+        parser.parseFrom("<Event></Event>");
+    }
+
+    @Test
+    public void testString() throws ParseException {
+        final LogEvent logEvent = parser.parseFrom(XML);
+        assertLogEvent(logEvent);
+    }
+
+    @Test(expected = ParseException.class)
+    public void testStringEmpty() throws ParseException {
+        parser.parseFrom("");
+    }
+
+    @Test
+    public void testStringIgnoreInvalidProperty() throws ParseException {
+        parser.parseFrom("<Event><foo>bar</foo></Event>");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testStringInvalidXml() throws ParseException {
+        parser.parseFrom("foobar");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testStringWrongPropertyType() throws ParseException {
+        parser.parseFrom("<Event><Instant epochSecond=\"bar\">foobar</Instant></Event>");
+    }
+
+    @Test
+    public void testTimeMillisIgnored() throws ParseException {
+        parser.parseFrom("<Event><timeMillis>foobar</timeMillis></Event>");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/test/resources/log4j2-xml-layout.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/test/resources/log4j2-xml-layout.xml b/log4j-layout-jackson-xml/src/test/resources/log4j2-xml-layout.xml
new file mode 100644
index 0000000..f0b1709
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/test/resources/log4j2-xml-layout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<Configuration status="INFO" packages="">
+  <Appenders>
+    <File name="stdout" ignoreExceptions="false" fileName="target/test-xml-layout.log" append="false">
+      <XmlLayout compact="true" eventEol="true" />
+    </File>
+  </Appenders>
+
+  <Loggers>
+    <Root level="INFO">
+      <AppenderRef ref="stdout" />
+    </Root>
+  </Loggers>
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/pom.xml b/log4j-layout-jackson-yaml/pom.xml
new file mode 100644
index 0000000..9df9743
--- /dev/null
+++ b/log4j-layout-jackson-yaml/pom.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ~ Licensed to the Apache Software Foundation (ASF) under one or more ~ contributor license agreements. See the NOTICE 
+  file distributed with ~ this work for additional information regarding copyright ownership. ~ The ASF licenses this file 
+  to You under the Apache License, Version 2.0 ~ (the "License"); you may not use this file except in compliance with ~ the 
+  License. You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable 
+  law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES 
+  OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and 
+  ~ limitations under the License. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>org.apache.logging.log4j</groupId>
+    <artifactId>log4j</artifactId>
+    <version>3.0.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>log4j-layout-jackson-yaml</artifactId>
+  <name>Apache Log4j Layout for Jackson YAML</name>
+  <description>
+    Apache Log4j Layout for Jackson YAML.
+  </description>
+  <properties>
+    <log4jParentDir>${basedir}/..</log4jParentDir>
+    <docLabel>Log4j Layout for Jackson YAML Documentation</docLabel>
+    <projectDir>/log4j-layout-yaml</projectDir>
+    <module.name>org.apache.logging.log4j.jackson.yaml</module.name>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-layout-jackson</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-yaml</artifactId>
+    </dependency>
+    <!-- Test Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <type>test-jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <type>test-jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-layout-jackson</artifactId>
+      <type>test-jar</type>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Fragment-Host>org.apache.logging.log4j.jackson.yaml</Fragment-Host>
+            <Export-Package>*</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-changes-plugin</artifactId>
+        <version>${changes.plugin.version}</version>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>changes-report</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+        <configuration>
+          <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
+          <useJql>true</useJql>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>${checkstyle.plugin.version}</version>
+        <configuration>
+          <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
+          <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
+          <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
+          <enableRulesSummary>false</enableRulesSummary>
+          <propertyExpansion>basedir=${basedir}</propertyExpansion>
+          <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>${javadoc.plugin.version}</version>
+        <configuration>
+          <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
+            Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
+            and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
+          <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating project -->
+          <detectOfflineLinks>false</detectOfflineLinks>
+          <linksource>true</linksource>
+        </configuration>
+        <reportSets>
+          <reportSet>
+            <id>non-aggregate</id>
+            <reports>
+              <report>javadoc</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>${findbugs.plugin.version}</version>
+        <configuration>
+          <fork>true</fork>
+          <jvmArgs>-Duser.language=en</jvmArgs>
+          <threshold>Normal</threshold>
+          <effort>Default</effort>
+          <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jxr-plugin</artifactId>
+        <version>${jxr.plugin.version}</version>
+        <reportSets>
+          <reportSet>
+            <id>non-aggregate</id>
+            <reports>
+              <report>jxr</report>
+            </reports>
+          </reportSet>
+          <reportSet>
+            <id>aggregate</id>
+            <reports>
+              <report>aggregate</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-pmd-plugin</artifactId>
+        <version>${pmd.plugin.version}</version>
+        <configuration>
+          <targetJdk>${maven.compiler.target}</targetJdk>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+</project>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/Log4jYamlModule.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/Log4jYamlModule.java b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/Log4jYamlModule.java
new file mode 100644
index 0000000..8446a9d
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/Log4jYamlModule.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.yaml;
+
+import org.apache.logging.log4j.jackson.SetupContextInitializer;
+import org.apache.logging.log4j.jackson.SimpleModuleInitializer;
+
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+final class Log4jYamlModule extends SimpleModule {
+
+    private static final long serialVersionUID = 1L;
+    private final boolean encodeThreadContextAsList;
+    private final boolean includeStacktrace;
+    private final boolean stacktraceAsString;
+
+    Log4jYamlModule(final boolean encodeThreadContextAsList, final boolean includeStacktrace,
+            final boolean stacktraceAsString) {
+        super(Log4jYamlModule.class.getName(), new Version(2, 0, 0, null, null, null));
+        this.encodeThreadContextAsList = encodeThreadContextAsList;
+        this.includeStacktrace = includeStacktrace;
+        this.stacktraceAsString = stacktraceAsString;
+        // MUST call initialize() here.
+        // Calling this from setupModule is too late!
+        // noinspection ThisEscapedInObjectConstruction
+        new SimpleModuleInitializer().initialize(this, false);
+    }
+
+    @Override
+    public void setupModule(final SetupContext context) {
+        // MUST call super here.
+        super.setupModule(context);
+        if (encodeThreadContextAsList) {
+            new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
+        } else {
+            new YamlSetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/Log4jYamlObjectMapper.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/Log4jYamlObjectMapper.java b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/Log4jYamlObjectMapper.java
new file mode 100644
index 0000000..62c6483
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/Log4jYamlObjectMapper.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.yaml;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
+
+/**
+ * A Jackson {@link ObjectMapper} initialized for Log4j.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class Log4jYamlObjectMapper extends YAMLMapper {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Create a new instance using the {@link Log4jYamlModule}.
+     */
+    public Log4jYamlObjectMapper() {
+        this(false, true, false);
+    }
+
+    /**
+     * Create a new instance using the {@link Log4jYamlModule}.
+     */
+    public Log4jYamlObjectMapper(final boolean encodeThreadContextAsList, final boolean includeStacktrace, final boolean stacktraceAsString) {
+        this.registerModule(new Log4jYamlModule(encodeThreadContextAsList, includeStacktrace, stacktraceAsString));
+        this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/YamlSetupContextInitializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/YamlSetupContextInitializer.java b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/YamlSetupContextInitializer.java
new file mode 100644
index 0000000..67f6fd1
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/YamlSetupContextInitializer.java
@@ -0,0 +1,47 @@
+package org.apache.logging.log4j.jackson.yaml;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.core.time.Instant;
+import org.apache.logging.log4j.jackson.ExtendedStackTraceElementMixIn;
+import org.apache.logging.log4j.jackson.InstantMixIn;
+import org.apache.logging.log4j.jackson.LevelMixIn;
+import org.apache.logging.log4j.jackson.LogEventJsonMixIn;
+import org.apache.logging.log4j.jackson.MarkerMixIn;
+import org.apache.logging.log4j.jackson.StackTraceElementMixIn;
+import org.apache.logging.log4j.jackson.ThrowableProxyMixIn;
+import org.apache.logging.log4j.jackson.ThrowableProxyWithStacktraceAsStringMixIn;
+import org.apache.logging.log4j.jackson.ThrowableProxyWithoutStacktraceMixIn;
+
+import com.fasterxml.jackson.databind.Module.SetupContext;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+/**
+ * Used to set up {@link SetupContext} from different {@link SimpleModule}s.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+class YamlSetupContextInitializer {
+
+    public void setupModule(final SetupContext context, final boolean includeStacktrace,
+            final boolean stacktraceAsString) {
+        // JRE classes: we cannot edit those with Jackson annotations
+        context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class);
+        // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not
+        // depend on Jackson.
+        context.setMixInAnnotations(Marker.class, MarkerMixIn.class);
+        context.setMixInAnnotations(Level.class, LevelMixIn.class);
+        context.setMixInAnnotations(Instant.class, InstantMixIn.class);
+        context.setMixInAnnotations(LogEvent.class, LogEventJsonMixIn.class); // different ThreadContext handling
+        // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
+        context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
+        context.setMixInAnnotations(ThrowableProxy.class, includeStacktrace
+                ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringMixIn.class : ThrowableProxyMixIn.class)
+                : ThrowableProxyWithoutStacktraceMixIn.class);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlConstants.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlConstants.java b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlConstants.java
new file mode 100644
index 0000000..856a201
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlConstants.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.yaml.layout;
+
+public class YamlConstants {
+
+    static final String EVENT = "event";
+    static final String ELT_CAUSE = "cause";
+    static final String ELT_CONTEXT_MAP = "contextMap";
+    static final String ELT_CONTEXT_STACK = "contextStack";
+    static final String ELT_MARKER = "marker";
+    static final String ELT_PARENTS = "parents";
+    static final String ELT_SOURCE = "source";
+    static final String ELT_SUPPRESSED = "suppressed";
+    static final String ELT_THROWN = "thrown";
+    static final String ELT_MESSAGE = "message";
+    static final String ELT_EXTENDED_STACK_TRACE = "extendedStackTrace";
+    static final String ELT_NANO_TIME = "nanoTime";
+    static final String ELT_INSTANT = "instant";
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlJacksonFactory.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlJacksonFactory.java b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlJacksonFactory.java
new file mode 100644
index 0000000..e32041a
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlJacksonFactory.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.yaml.layout;
+
+import org.apache.logging.log4j.jackson.AbstractJacksonFactory;
+import org.apache.logging.log4j.jackson.yaml.Log4jYamlObjectMapper;
+
+import com.fasterxml.jackson.core.PrettyPrinter;
+import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
+import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+class YamlJacksonFactory extends AbstractJacksonFactory {
+
+    public YamlJacksonFactory(final boolean includeStacktrace, final boolean stacktraceAsString) {
+        super(includeStacktrace, stacktraceAsString);
+    }
+
+    @Override
+    protected String getPropertyNameForContextMap() {
+        return YamlConstants.ELT_CONTEXT_MAP;
+    }
+
+    @Override
+    protected String getPropertyNameForNanoTime() {
+        return YamlConstants.ELT_NANO_TIME;
+    }
+
+    @Override
+    protected String getPropertyNameForSource() {
+        return YamlConstants.ELT_SOURCE;
+    }
+
+    @Override
+    protected String getPropertyNameForStackTrace() {
+        return YamlConstants.ELT_EXTENDED_STACK_TRACE;
+    }
+
+    @Override
+    protected PrettyPrinter newCompactPrinter() {
+        return new MinimalPrettyPrinter();
+    }
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jYamlObjectMapper(false, includeStacktrace, stacktraceAsString);
+    }
+
+    @Override
+    protected PrettyPrinter newPrettyPrinter() {
+        return new DefaultPrettyPrinter();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayout.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayout.java b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayout.java
new file mode 100644
index 0000000..418ef9a
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayout.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.yaml.layout;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+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.PluginBuilderFactory;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.apache.logging.log4j.jackson.AbstractJacksonLayout;
+import org.apache.logging.log4j.util.Strings;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonRootName;
+import com.fasterxml.jackson.annotation.JsonUnwrapped;
+
+/**
+ * Appends a series of YAML events as strings serialized as bytes.
+ *
+ * <h3>Encoding</h3>
+ * <p>
+ * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise
+ * events containing non ASCII characters could result in corrupted log files.
+ * </p>
+ * <h3>Additional Fields</h3>
+ * <p>
+ * This property allows addition of custom fields into generated JSON.
+ * {@code <YamlLayout><KeyValuePair key="foo" value="bar"/></YamlLayout>} inserts {@code foo: "bar"} directly into YAML
+ * output. Supports Lookup expressions.
+ * </p>
+ */
+@Plugin(name = "YamlLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
+public final class YamlLayout extends AbstractJacksonLayout {
+
+    public static class Builder<B extends Builder<B>> extends AbstractJacksonLayout.Builder<B>
+            implements org.apache.logging.log4j.core.util.Builder<YamlLayout> {
+
+        public Builder() {
+            super();
+            setCharset(StandardCharsets.UTF_8);
+        }
+
+        @Override
+        public YamlLayout build() {
+            final String headerPattern = toStringOrNull(getHeader());
+            final String footerPattern = toStringOrNull(getFooter());
+            return new YamlLayout(getConfiguration(), isLocationInfo(), isProperties(), isComplete(), isCompact(),
+                    getEventEol(), headerPattern, footerPattern, getCharset(), isIncludeStacktrace(),
+                    isStacktraceAsString(), isIncludeNullDelimiter(), getAdditionalFields());
+        }
+    }
+
+    @JsonRootName(YamlConstants.EVENT)
+    public static class YamlLogEventWithAdditionalFields extends LogEventWithAdditionalFields {
+
+        public YamlLogEventWithAdditionalFields(final Object logEvent, final Map<String, String> additionalFields) {
+            super(logEvent, additionalFields);
+        }
+
+        @Override
+        @JsonAnyGetter
+        public Map<String, String> getAdditionalFields() {
+            return super.getAdditionalFields();
+        }
+
+        @Override
+        @JsonUnwrapped
+        public Object getLogEvent() {
+            return super.getLogEvent();
+        }
+
+    }
+
+    private static final String DEFAULT_FOOTER = Strings.EMPTY;
+
+    private static final String DEFAULT_HEADER = Strings.EMPTY;
+
+    static final String CONTENT_TYPE = "application/yaml";
+
+    /**
+     * Creates a YAML Layout using the default settings. Useful for testing.
+     *
+     * @return A YAML Layout.
+     */
+    public static AbstractJacksonLayout createDefaultLayout() {
+        return new YamlLayout(new DefaultConfiguration(), false, false, false, false, false, DEFAULT_HEADER,
+                DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, null);
+    }
+
+    /**
+     * Creates a YAML Layout.
+     *
+     * @param config
+     *            The plugin configuration.
+     * @param locationInfo
+     *            If "true", includes the location information in the generated YAML.
+     * @param properties
+     *            If "true", includes the thread context map in the generated YAML.
+     * @param headerPattern
+     *            The header pattern, defaults to {@code ""} if null.
+     * @param footerPattern
+     *            The header pattern, defaults to {@code ""} if null.
+     * @param charset
+     *            The character set to use, if {@code null}, uses "UTF-8".
+     * @param includeStacktrace
+     *            If "true", includes the stacktrace of any Throwable in the generated YAML, defaults to "true".
+     * @return A YAML Layout.
+     *
+     * @deprecated Use {@link #newBuilder()} instead
+     */
+    @Deprecated
+    public static AbstractJacksonLayout createLayout(final Configuration config, final boolean locationInfo,
+            final boolean properties, final String headerPattern, final String footerPattern, final Charset charset,
+            final boolean includeStacktrace) {
+        return new YamlLayout(config, locationInfo, properties, false, false, true, headerPattern, footerPattern,
+                charset, includeStacktrace, false, false, null);
+    }
+
+    @PluginBuilderFactory
+    public static <B extends Builder<B>> B newBuilder() {
+        return new Builder<B>().asBuilder();
+    }
+
+    /**
+     * @deprecated Use {@link #newBuilder()} instead
+     */
+    @Deprecated
+    protected 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) {
+        super(config, new YamlJacksonFactory(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(),
+                false, null);
+    }
+
+    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 includeNullDelimiter,
+            final KeyValuePair[] additionalFields) {
+        super(config,
+                new YamlJacksonFactory(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(),
+                includeNullDelimiter, additionalFields);
+    }
+
+    @Override
+    protected LogEventWithAdditionalFields createLogEventWithAdditionalFields(final LogEvent event,
+            final Map<String, String> additionalFieldsMap) {
+        return new YamlLogEventWithAdditionalFields(event, additionalFieldsMap);
+    }
+
+    @Override
+    public Map<String, String> getContentFormat() {
+        final Map<String, String> result = new HashMap<>();
+        result.put("version", "3.0");
+        return result;
+    }
+
+    /**
+     * @return The content type.
+     */
+    @Override
+    public String getContentType() {
+        return CONTENT_TYPE + "; charset=" + this.getCharset();
+    }
+
+    /**
+     * Returns appropriate YAML footer.
+     *
+     * @return a byte array containing the footer, closing the YAML array.
+     */
+    @Override
+    public byte[] getFooter() {
+        if (!this.complete) {
+            return null;
+        }
+        final StringBuilder buf = new StringBuilder();
+        buf.append(this.eol);
+        final String str = serializeToString(getFooterSerializer());
+        if (str != null) {
+            buf.append(str);
+        }
+        buf.append(this.eol);
+        return getBytes(buf.toString());
+    }
+
+    /**
+     * Returns appropriate YAML header.
+     *
+     * @return a byte array containing the header, opening the YAML array.
+     */
+    @Override
+    public byte[] getHeader() {
+        if (!this.complete) {
+            return null;
+        }
+        final StringBuilder buf = new StringBuilder();
+        final String str = serializeToString(getHeaderSerializer());
+        if (str != null) {
+            buf.append(str);
+        }
+        buf.append(this.eol);
+        return getBytes(buf.toString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/parser/YamlLogEventParser.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/parser/YamlLogEventParser.java b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/parser/YamlLogEventParser.java
new file mode 100644
index 0000000..0ef4049
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/main/java/org/apache/logging/log4j/jackson/yaml/parser/YamlLogEventParser.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.yaml.parser;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.parser.AbstractJacksonLogEventParser;
+import org.apache.logging.log4j.jackson.yaml.Log4jYamlObjectMapper;
+
+/**
+ * Parses the output from YamlLayout layout into instances of {@link LogEvent}.
+ */
+public class YamlLogEventParser extends AbstractJacksonLogEventParser {
+
+    public YamlLogEventParser() {
+        super(new Log4jYamlObjectMapper());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/site/manual/index.md
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/site/manual/index.md b/log4j-layout-jackson-yaml/src/site/manual/index.md
new file mode 100644
index 0000000..83112af
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/site/manual/index.md
@@ -0,0 +1,33 @@
+<!-- vim: set syn=markdown : -->
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+# Apache Log4j Layout for Jackson YAML module
+
+As of Log4j 3.0.0, the layout based on Jackson YAML has moved from the existing module logj-core to the new modules log4j-layout-jackson-yaml.
+
+## Requirements
+
+This module was introduced in Log4j 2.11.0 and requires Jackson.
+
+Some features may require optional
+[dependencies](../runtime-dependencies.html). These dependencies are specified in the
+documentation for those features.
+
+Some Log4j features require external dependencies.
+See the [Dependency Tree](dependencies.html#Dependency_Tree)
+for the exact list of JAR files needed for these features.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/site/site.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/site/site.xml b/log4j-layout-jackson-yaml/src/site/site.xml
new file mode 100644
index 0000000..6d4cddc
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/site/site.xml
@@ -0,0 +1,52 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project name="Log4j Core"
+         xmlns="http://maven.apache.org/DECORATION/1.4.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
+  <body>
+    <links>
+      <item name="Apache" href="http://www.apache.org/" />
+      <item name="Logging Services" href="http://logging.apache.org/"/>
+      <item name="Log4j" href="../index.html"/>
+    </links>
+
+    <!-- Component-specific reports -->
+    <menu ref="reports"/>
+
+	<!-- Overall Project Info -->
+    <menu name="Log4j Project Information" img="icon-info-sign">
+      <item name="Dependencies" href="../dependencies.html" />
+      <item name="Dependency Convergence" href="../dependency-convergence.html" />
+      <item name="Dependency Management" href="../dependency-management.html" />
+      <item name="Project Team" href="../team-list.html" />
+      <item name="Mailing Lists" href="../mail-lists.html" />
+      <item name="Issue Tracking" href="../issue-tracking.html" />
+      <item name="Project License" href="../license.html" />
+      <item name="Source Repository" href="../source-repository.html" />
+      <item name="Project Summary" href="../project-summary.html" />
+    </menu>
+
+    <menu name="Log4j Project Reports" img="icon-cog">
+      <item name="Changes Report" href="../changes-report.html" />
+      <item name="JIRA Report" href="../jira-report.html" />
+      <item name="Surefire Report" href="../surefire-report.html" />
+      <item name="RAT Report" href="../rat-report.html" />
+    </menu>
+  </body>
+</project>


[05/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlMarkerMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlMarkerMixIn.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlMarkerMixIn.java
new file mode 100644
index 0000000..9fa0e8a
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlMarkerMixIn.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.jackson.MarkerMixIn;
+import org.apache.logging.log4j.core.jackson.XmlConstants;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+/**
+ * Jackson mix-in for {@link Marker}.
+ * <p>
+ * If we want to deal with more than one {@link Marker} implementation then recode these annotations to include
+ * metadata.
+ * </p>
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ * <p>
+ * Example XML:
+ * </p>
+ *
+ * <pre>
+&lt;Marker name=&quot;Marker1&quot;&gt;
+    &lt;Parents&gt;
+        &lt;Marker name=&quot;ParentMarker1&quot;&gt;
+            &lt;Parents&gt;
+                &lt;Marker name=&quot;GrandMotherMarker&quot;/&gt;
+                &lt;Marker name=&quot;GrandFatherMarker&quot;/&gt;
+            &lt;/Parents&gt;
+        &lt;/Marker&gt;
+        &lt;Marker name=&quot;ParentMarker2&quot;/&gt;
+    &lt;/Parents&gt;
+&lt;/Marker&gt;
+ * </pre>
+ *
+ * @see Marker
+ */
+// Alternate for multiple Marker implementation.
+// @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+@JsonDeserialize(as = org.apache.logging.log4j.MarkerManager.Log4jMarker.class)
+abstract class XmlMarkerMixIn extends MarkerMixIn {
+    public static final String ATTR_NAME = "name";
+    private static final long serialVersionUID = 1L;
+
+    @JsonCreator
+    protected XmlMarkerMixIn(@JsonProperty(ATTR_NAME) final String name) {
+        super(name);
+    }
+
+    @Override
+    @JacksonXmlProperty(isAttribute = true)
+    public abstract String getName();
+
+    @Override
+    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_PARENTS)
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MARKER)
+    public abstract Marker[] getParents();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlSetupContextInitializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlSetupContextInitializer.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlSetupContextInitializer.java
new file mode 100644
index 0000000..442f9ab
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlSetupContextInitializer.java
@@ -0,0 +1,42 @@
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.core.jackson.ExtendedStackTraceElementMixIn;
+import org.apache.logging.log4j.core.jackson.LevelMixIn;
+import org.apache.logging.log4j.core.jackson.ThrowableProxyMixIn;
+import org.apache.logging.log4j.core.jackson.ThrowableProxyWithStacktraceAsStringMixIn;
+import org.apache.logging.log4j.core.jackson.ThrowableProxyWithoutStacktraceMixIn;
+import org.apache.logging.log4j.core.time.Instant;
+
+import com.fasterxml.jackson.databind.Module.SetupContext;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+/**
+ * Used to set up {@link SetupContext} from different {@link SimpleModule}s.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+class XmlSetupContextInitializer {
+
+    public void setupModule(final SetupContext context, final boolean includeStacktrace,
+            final boolean stacktraceAsString) {
+        // JRE classes: we cannot edit those with Jackson annotations
+        context.setMixInAnnotations(StackTraceElement.class, XmlStackTraceElementMixIn.class);
+        // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not
+        // depend on Jackson.
+        context.setMixInAnnotations(Marker.class, XmlMarkerMixIn.class);
+        context.setMixInAnnotations(Level.class, LevelMixIn.class);
+        context.setMixInAnnotations(Instant.class, XmlInstantMixIn.class);
+        context.setMixInAnnotations(LogEvent.class, XmlLogEventWithContextListMixIn.class);
+        // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
+        context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
+        context.setMixInAnnotations(ThrowableProxy.class, includeStacktrace
+                ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringMixIn.class : ThrowableProxyMixIn.class)
+                : ThrowableProxyWithoutStacktraceMixIn.class);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlStackTraceElementMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlStackTraceElementMixIn.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlStackTraceElementMixIn.java
new file mode 100644
index 0000000..abdba98
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlStackTraceElementMixIn.java
@@ -0,0 +1,39 @@
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.core.jackson.StackTraceElementMixIn;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+abstract class XmlStackTraceElementMixIn extends StackTraceElementMixIn {
+
+    @JsonCreator
+    protected XmlStackTraceElementMixIn(
+    // @formatter:off
+            @JsonProperty(ATTR_CLASS) final String declaringClass,
+            @JsonProperty(ATTR_METHOD) final String methodName,
+            @JsonProperty(ATTR_FILE) final String fileName,
+            @JsonProperty(ATTR_LINE) final int lineNumber)
+            // @formatter:on
+    {
+        super(declaringClass, methodName, fileName, lineNumber);
+    }
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_CLASS, isAttribute = true)
+    protected abstract String getClassName();
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_FILE, isAttribute = true)
+    protected abstract String getFileName();
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_LINE, isAttribute = true)
+    protected abstract int getLineNumber();
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_METHOD, isAttribute = true)
+    protected abstract String getMethodName();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/Log4jXmlPrettyPrinter.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/Log4jXmlPrettyPrinter.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/Log4jXmlPrettyPrinter.java
new file mode 100644
index 0000000..24c5ef0
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/Log4jXmlPrettyPrinter.java
@@ -0,0 +1,41 @@
+package org.apache.logging.log4j.jackson.xml.layout;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.codehaus.stax2.XMLStreamWriter2;
+
+import com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter;
+
+/**
+ * When &lt;Event&gt;s are written into a XML file; the "Event" object is not the root element, but an element named
+ * &lt;Events&gt; created using {@link XmlLayout#getHeader()} and {@link XmlLayout#getFooter()} methods.
+ * <p>
+ * {@link com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter} is used to print the Event object into
+ * XML; hence it assumes &lt;Event&gt; tag as the root element, so it prints the &lt;Event&gt; tag without any
+ * indentation. To add an indentation to the &lt;Event&gt; tag; hence an additional indentation for any
+ * sub-elements, this class is written. As an additional task, to avoid the blank line printed after the ending
+ * &lt;/Event&gt; tag, {@link #writePrologLinefeed(XMLStreamWriter2)} method is also overridden.
+ * </p>
+ */
+class Log4jXmlPrettyPrinter extends DefaultXmlPrettyPrinter {
+
+    private static final long serialVersionUID = 1L;
+
+    Log4jXmlPrettyPrinter(final int nesting) {
+        _nesting = nesting;
+    }
+
+    /**
+     * Sets the nesting level to 1 rather than 0, so the "Event" tag will get indentation of next level below root.
+     */
+    @Override
+    public DefaultXmlPrettyPrinter createInstance() {
+        return new Log4jXmlPrettyPrinter(XmlJacksonFactory.DEFAULT_INDENT);
+    }
+
+    @Override
+    public void writePrologLinefeed(final XMLStreamWriter2 sw) throws XMLStreamException {
+        // nothing
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/XmlJacksonFactory.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/XmlJacksonFactory.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/XmlJacksonFactory.java
new file mode 100644
index 0000000..0289c71
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/XmlJacksonFactory.java
@@ -0,0 +1,54 @@
+package org.apache.logging.log4j.jackson.xml.layout;
+
+import org.apache.logging.log4j.core.jackson.AbstractJacksonFactory;
+import org.apache.logging.log4j.core.jackson.JsonConstants;
+import org.apache.logging.log4j.core.jackson.XmlConstants;
+import org.apache.logging.log4j.jackson.xml.Log4jXmlObjectMapper;
+
+import com.fasterxml.jackson.core.PrettyPrinter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+class XmlJacksonFactory extends AbstractJacksonFactory {
+
+    static final int DEFAULT_INDENT = 1;
+
+    public XmlJacksonFactory(final boolean includeStacktrace, final boolean stacktraceAsString) {
+        super(includeStacktrace, stacktraceAsString);
+    }
+
+    @Override
+    protected String getPropertyNameForContextMap() {
+        return XmlConstants.ELT_CONTEXT_MAP;
+    }
+
+    @Override
+    protected String getPropertyNameForNanoTime() {
+        return JsonConstants.ELT_NANO_TIME;
+    }
+
+    @Override
+    protected String getPropertyNameForSource() {
+        return XmlConstants.ELT_SOURCE;
+    }
+
+    @Override
+    protected String getPropertyNameForStackTrace() {
+        return XmlConstants.ELT_EXTENDED_STACK_TRACE;
+    }
+
+    @Override
+    protected PrettyPrinter newCompactPrinter() {
+        // Yes, null is the proper answer.
+        return null;
+    }
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jXmlObjectMapper(includeStacktrace, stacktraceAsString);
+    }
+
+    @Override
+    protected PrettyPrinter newPrettyPrinter() {
+        return new Log4jXmlPrettyPrinter(DEFAULT_INDENT);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayout.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayout.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayout.java
new file mode 100644
index 0000000..c305c33
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayout.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml.layout;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+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.PluginBuilderFactory;
+import org.apache.logging.log4j.core.jackson.AbstractJacksonLayout;
+import org.apache.logging.log4j.core.jackson.XmlConstants;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+
+/**
+ * Appends a series of {@code event} elements as defined in the <a href="log4j.dtd">log4j.dtd</a>.
+ *
+ * <h3>Complete well-formed XML vs. fragment XML</h3>
+ * <p>
+ * If you configure {@code complete="true"}, the appender outputs a well-formed XML document where the default namespace
+ * is the log4j namespace {@value XmlConstants#XML_NAMESPACE}. By default, with {@code complete="false"}, you should
+ * include the output as an <em>external entity</em> in a separate file to form a well-formed XML document.
+ * </p>
+ * <p>
+ * If {@code complete="false"}, the appender does not write the XML processing instruction and the root element.
+ * </p>
+ * <h3>Encoding</h3>
+ * <p>
+ * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise
+ * events containing non-ASCII characters could result in corrupted log files.
+ * </p>
+ * <h3>Pretty vs. compact XML</h3>
+ * <p>
+ * By default, the XML layout is not compact (compact = not "pretty") with {@code compact="false"}, which means the
+ * appender uses end-of-line characters and indents lines to format the XML. If {@code compact="true"}, then no
+ * end-of-line or indentation is used. Message content may contain, of course, end-of-lines.
+ * </p>
+ * <h3>Additional Fields</h3>
+ * <p>
+ * This property allows addition of custom fields into generated JSON.
+ * {@code <XmlLayout><KeyValuePair key="foo" value="bar"/></XmlLayout>} inserts {@code <foo>bar</foo>} directly into XML
+ * output. Supports Lookup expressions.
+ * </p>
+ */
+@Plugin(name = "XmlLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
+public final class XmlLayout extends AbstractJacksonLayout {
+
+    public static class Builder<B extends Builder<B>> extends AbstractJacksonLayout.Builder<B>
+            implements org.apache.logging.log4j.core.util.Builder<XmlLayout> {
+
+        public Builder() {
+            super();
+            setCharset(StandardCharsets.UTF_8);
+        }
+
+        @Override
+        public XmlLayout build() {
+            return new XmlLayout(getConfiguration(), isLocationInfo(), isProperties(), isComplete(), isCompact(),
+                    getCharset(), isIncludeStacktrace(), isStacktraceAsString(), isIncludeNullDelimiter(),
+                    getAdditionalFields());
+        }
+    }
+
+    @JacksonXmlRootElement(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EVENT)
+    public static class XmlLogEventWithAdditionalFields extends LogEventWithAdditionalFields {
+
+        public XmlLogEventWithAdditionalFields(final Object logEvent, final Map<String, String> additionalFields) {
+            super(logEvent, additionalFields);
+        }
+
+    }
+
+    private static final String ROOT_TAG = "Events";
+
+    /**
+     * Creates an XML Layout using the default settings.
+     *
+     * @return an XML Layout.
+     */
+    public static XmlLayout createDefaultLayout() {
+        return new XmlLayout(null, false, false, false, false, StandardCharsets.UTF_8, true, false, false, null);
+    }
+
+    /**
+     * Creates an XML Layout.
+     *
+     * @param locationInfo
+     *            If "true", includes the location information in the generated XML.
+     * @param properties
+     *            If "true", includes the thread context map in the generated XML.
+     * @param complete
+     *            If "true", includes the XML header and footer, defaults to "false".
+     * @param compact
+     *            If "true", does not use end-of-lines and indentation, defaults to "false".
+     * @param charset
+     *            The character set to use, if {@code null}, uses "UTF-8".
+     * @param includeStacktrace
+     *            If "true", includes the stacktrace of any Throwable in the generated XML, defaults to "true".
+     * @return An XML Layout.
+     *
+     * @deprecated Use {@link #newBuilder()} instead
+     */
+    @Deprecated
+    public static XmlLayout createLayout(final boolean locationInfo, final boolean properties, final boolean complete,
+            final boolean compact, final Charset charset, final boolean includeStacktrace) {
+        return new XmlLayout(null, locationInfo, properties, complete, compact, charset, includeStacktrace, false,
+                false, null);
+    }
+
+    @PluginBuilderFactory
+    public static <B extends Builder<B>> B newBuilder() {
+        return new Builder<B>().asBuilder();
+    }
+
+    /**
+     * @deprecated Use {@link #newBuilder()} instead
+     */
+    @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, false, null);
+    }
+
+    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 includeNullDelimiter,
+            final KeyValuePair[] additionalFields) {
+        super(config,
+                new XmlJacksonFactory(includeStacktrace, stacktraceAsString).newWriter(locationInfo, properties,
+                        compact),
+                charset, compact, complete, false, null, null, includeNullDelimiter, additionalFields);
+    }
+
+    @Override
+    protected LogEventWithAdditionalFields createLogEventWithAdditionalFields(final LogEvent event,
+            final Map<String, String> additionalFieldsMap) {
+        return new XmlLogEventWithAdditionalFields(event, additionalFieldsMap);
+    }
+
+    /**
+     * Gets this XmlLayout's content format. Specified by:
+     * <ul>
+     * <li>Key: "dtd" Value: "log4j-events.dtd"</li>
+     * <li>Key: "version" Value: "2.0"</li>
+     * </ul>
+     *
+     * @return Map of content format keys supporting XmlLayout
+     */
+    @Override
+    public Map<String, String> getContentFormat() {
+        final Map<String, String> result = new HashMap<>();
+        // result.put("dtd", "log4j-events.dtd");
+        result.put("xsd", "log4j-events.xsd");
+        result.put("version", "2.0");
+        return result;
+    }
+
+    /**
+     * @return The content type.
+     */
+    @Override
+    public String getContentType() {
+        return "text/xml; charset=" + this.getCharset();
+    }
+
+    /**
+     * Returns appropriate XML footer.
+     *
+     * @return a byte array containing the footer, closing the XML root element.
+     */
+    @Override
+    public byte[] getFooter() {
+        if (!complete) {
+            return null;
+        }
+        return getBytes("</" + ROOT_TAG + '>' + this.eol);
+    }
+
+    /**
+     * Returns appropriate XML headers.
+     * <ol>
+     * <li>XML processing instruction</li>
+     * <li>XML root element</li>
+     * </ol>
+     *
+     * @return a byte array containing the header.
+     */
+    @Override
+    public byte[] getHeader() {
+        if (!complete) {
+            return null;
+        }
+        final StringBuilder buf = new StringBuilder();
+        buf.append("<?xml version=\"1.0\" encoding=\"");
+        buf.append(this.getCharset().name());
+        buf.append("\"?>");
+        buf.append(this.eol);
+        // Make the log4j namespace the default namespace, no need to use more space with a namespace prefix.
+        buf.append('<');
+        buf.append(ROOT_TAG);
+        buf.append(" xmlns=\"" + XmlConstants.XML_NAMESPACE + "\">");
+        buf.append(this.eol);
+        return buf.toString().getBytes(this.getCharset());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParser.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParser.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParser.java
new file mode 100644
index 0000000..32776a2
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/parser/XmlLogEventParser.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml.parser;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.parser.AbstractJacksonLogEventParser;
+import org.apache.logging.log4j.jackson.xml.Log4jXmlObjectMapper;
+
+/**
+ * Parses the output from XmlLayout layout into instances of {@link LogEvent}.
+ */
+public class XmlLogEventParser extends AbstractJacksonLogEventParser {
+
+    public XmlLogEventParser() {
+        super(new Log4jXmlObjectMapper());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/pom.xml b/log4j-layout-jackson-xml/pom.xml
new file mode 100644
index 0000000..4a8989d
--- /dev/null
+++ b/log4j-layout-jackson-xml/pom.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ~ Licensed to the Apache Software Foundation (ASF) under one or more ~ contributor license agreements. See the NOTICE 
+  file distributed with ~ this work for additional information regarding copyright ownership. ~ The ASF licenses this file 
+  to You under the Apache License, Version 2.0 ~ (the "License"); you may not use this file except in compliance with ~ the 
+  License. You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable 
+  law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES 
+  OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and 
+  ~ limitations under the License. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>org.apache.logging.log4j</groupId>
+    <artifactId>log4j</artifactId>
+    <version>3.0.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>log4j-layout-jackson-xml</artifactId>
+  <name>Apache Log4j Layout for Jackson XML</name>
+  <description>
+    Apache Log4j Layout for Jackson XML.
+  </description>
+  <properties>
+    <log4jParentDir>${basedir}/..</log4jParentDir>
+    <docLabel>Log4j Layout for Jackson XML Documentation</docLabel>
+    <projectDir>/log4j-layout-xml</projectDir>
+    <module.name>org.apache.logging.log4j.jackson.xml</module.name>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-layout-jackson</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-xml</artifactId>
+    </dependency>
+    <!-- Test Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <type>test-jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <type>test-jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-layout-jackson</artifactId>
+      <type>test-jar</type>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Fragment-Host>org.apache.logging.log4j.jackson.xml</Fragment-Host>
+            <Export-Package>*</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-changes-plugin</artifactId>
+        <version>${changes.plugin.version}</version>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>changes-report</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+        <configuration>
+          <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
+          <useJql>true</useJql>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>${checkstyle.plugin.version}</version>
+        <configuration>
+          <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
+          <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
+          <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
+          <enableRulesSummary>false</enableRulesSummary>
+          <propertyExpansion>basedir=${basedir}</propertyExpansion>
+          <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>${javadoc.plugin.version}</version>
+        <configuration>
+          <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
+            Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
+            and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
+          <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating project -->
+          <detectOfflineLinks>false</detectOfflineLinks>
+          <linksource>true</linksource>
+        </configuration>
+        <reportSets>
+          <reportSet>
+            <id>non-aggregate</id>
+            <reports>
+              <report>javadoc</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>${findbugs.plugin.version}</version>
+        <configuration>
+          <fork>true</fork>
+          <jvmArgs>-Duser.language=en</jvmArgs>
+          <threshold>Normal</threshold>
+          <effort>Default</effort>
+          <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jxr-plugin</artifactId>
+        <version>${jxr.plugin.version}</version>
+        <reportSets>
+          <reportSet>
+            <id>non-aggregate</id>
+            <reports>
+              <report>jxr</report>
+            </reports>
+          </reportSet>
+          <reportSet>
+            <id>aggregate</id>
+            <reports>
+              <report>aggregate</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-pmd-plugin</artifactId>
+        <version>${pmd.plugin.version}</version>
+        <configuration>
+          <targetJdk>${maven.compiler.target}</targetJdk>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+</project>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/AbstractLogEventXmlMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/AbstractLogEventXmlMixIn.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/AbstractLogEventXmlMixIn.java
new file mode 100644
index 0000000..9d8687d
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/AbstractLogEventXmlMixIn.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext.ContextStack;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.core.time.Instant;
+import org.apache.logging.log4j.jackson.AbstractLogEventMixIn;
+import org.apache.logging.log4j.jackson.ContextDataAsEntryListDeserializer;
+import org.apache.logging.log4j.jackson.Log4jStackTraceElementDeserializer;
+import org.apache.logging.log4j.jackson.MessageSerializer;
+import org.apache.logging.log4j.jackson.SimpleMessageDeserializer;
+import org.apache.logging.log4j.jackson.XmlConstants;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+
+import com.fasterxml.jackson.annotation.JsonFilter;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+
+/**
+* <pre>AbstractLogEventMixIn
+*├─ XmlLogEventMixIn
+*├──── XmlLogEventWithContextListMixIn
+*├──── XmlLogEventWithContextMapMixIn
+*├─ JsonLogEventMixIn
+*├──── JsonLogEventWithContextListMixIn
+*├──── JsonLogEventWithContextMapMixIn</pre>
+*/
+@JacksonXmlRootElement(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EVENT)
+@JsonFilter(AbstractLogEventMixIn.JSON_FILTER_ID)
+@JsonPropertyOrder({
+    // @formatter:off
+    AbstractLogEventMixIn.ATTR_THREAD,
+    AbstractLogEventMixIn.ATTR_LEVEL,
+    AbstractLogEventMixIn.ATTR_LOGGER_NAME,
+    AbstractLogEventMixIn.ATTR_LOGGER_FQCN,
+    AbstractLogEventMixIn.ATTR_END_OF_BATCH,
+    XmlConstants.ELT_INSTANT,
+    XmlConstants.ELT_MARKER,
+    XmlConstants.ELT_MESSAGE,
+    AbstractLogEventXmlMixIn.ELT_THROWN,
+    XmlConstants.ELT_CONTEXT_MAP,
+    XmlConstants.ELT_CONTEXT_STACK,
+    XmlConstants.ELT_SOURCE})
+    // @formatter:on
+public abstract class AbstractLogEventXmlMixIn extends AbstractLogEventMixIn {
+
+    public static final String ELT_THROWN = "Thrown";
+
+    private static final long serialVersionUID = 1L;
+
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
+    @JsonSerialize(using = ContextDataAsEntryListXmlSerializer.class)
+    @JsonDeserialize(using = ContextDataAsEntryListDeserializer.class)
+    @Override
+    public abstract ReadOnlyStringMap getContextData();
+
+    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK)
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK_ITEM)
+    @Override
+    public abstract ContextStack getContextStack();
+
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_INSTANT)
+    @Override
+    public abstract Instant getInstant();
+
+    @JacksonXmlProperty(isAttribute = true)
+    @Override
+    public abstract Level getLevel();
+
+    @JacksonXmlProperty(isAttribute = true)
+    @Override
+    public abstract String getLoggerFqcn();
+
+    @JacksonXmlProperty(isAttribute = true)
+    @Override
+    public abstract String getLoggerName();
+
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MARKER)
+    @Override
+    public abstract Marker getMarker();
+
+    @JsonSerialize(using = MessageSerializer.class)
+    @JsonDeserialize(using = SimpleMessageDeserializer.class)
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MESSAGE)
+    @Override
+    public abstract Message getMessage();
+
+    @JsonDeserialize(using = Log4jStackTraceElementDeserializer.class)
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SOURCE)
+    @Override
+    public abstract StackTraceElement getSource();
+
+    @Override
+    @JacksonXmlProperty(isAttribute = true, localName = ATTR_THREAD_ID)
+    public abstract long getThreadId();
+
+    @Override
+    @JacksonXmlProperty(isAttribute = true, localName = ATTR_THREAD)
+    public abstract String getThreadName();
+
+    @Override
+    @JacksonXmlProperty(isAttribute = true, localName = ATTR_THREAD_PRIORITY)
+    public abstract int getThreadPriority();
+
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_THROWN)
+    @Override
+    public abstract ThrowableProxy getThrownProxy();
+
+    @JacksonXmlProperty(isAttribute = true)
+    @Override
+    public abstract boolean isEndOfBatch();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ContextDataAsEntryListXmlSerializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ContextDataAsEntryListXmlSerializer.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ContextDataAsEntryListXmlSerializer.java
new file mode 100644
index 0000000..b916c44
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ContextDataAsEntryListXmlSerializer.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.jackson.ContextDataAsEntryListSerializer;
+import org.apache.logging.log4j.jackson.MapEntry;
+
+public class ContextDataAsEntryListXmlSerializer extends ContextDataAsEntryListSerializer {
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected MapEntry createMapEntry(final String key, final String value) {
+        return new XmlMapEntry(key, value);
+    }
+
+    @Override
+    protected MapEntry[] createMapEntryArray(final int size) {
+        return new XmlMapEntry[size];
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ExtendedStackTraceElementXmlMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ExtendedStackTraceElementXmlMixIn.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ExtendedStackTraceElementXmlMixIn.java
new file mode 100644
index 0000000..224ef40
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ExtendedStackTraceElementXmlMixIn.java
@@ -0,0 +1,68 @@
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.core.impl.ExtendedClassInfo;
+import org.apache.logging.log4j.jackson.ExtendedStackTraceElementMixIn;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+public abstract class ExtendedStackTraceElementXmlMixIn extends ExtendedStackTraceElementMixIn {
+
+    private static final long serialVersionUID = 1L;
+
+    @JsonCreator
+    public ExtendedStackTraceElementXmlMixIn(
+    // @formatter:off
+            @JsonProperty(ATTR_CLASS) final String declaringClass,
+            @JsonProperty(ATTR_METHOD) final String methodName,
+            @JsonProperty(ATTR_FILE) final String fileName,
+            @JsonProperty(ATTR_LINE) final int lineNumber,
+            @JsonProperty(ATTR_EXACT) final boolean exact,
+            @JsonProperty(ATTR_LOCATION) final String location,
+            @JsonProperty(ATTR_VERSION) final String version
+   // @formatter:on
+    ) {
+        super(declaringClass, methodName, fileName, lineNumber, exact, location, version);
+    }
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_CLASS, isAttribute = true)
+    public abstract String getClassName();
+
+    @Override
+    @JacksonXmlProperty(isAttribute = true)
+    public abstract boolean getExact();
+
+    @Override
+    @JsonIgnore
+    public abstract ExtendedClassInfo getExtraClassInfo();
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_FILE, isAttribute = true)
+    public abstract String getFileName();
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_LINE, isAttribute = true)
+    public abstract int getLineNumber();
+
+    @Override
+    @JacksonXmlProperty(isAttribute = true)
+    public abstract String getLocation();
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_METHOD, isAttribute = true)
+    public abstract String getMethodName();
+
+    @JsonIgnore
+    abstract StackTraceElement getStackTraceElement();
+
+    @Override
+    @JacksonXmlProperty(isAttribute = true)
+    public abstract String getVersion();
+
+    @Override
+    @JsonIgnore
+    public abstract boolean isNativeMethod();
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/InstantXmlMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/InstantXmlMixIn.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/InstantXmlMixIn.java
new file mode 100644
index 0000000..df5a5ce
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/InstantXmlMixIn.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.time.Instant;
+import org.apache.logging.log4j.jackson.InstantMixIn;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+/**
+ * Jackson mix-in for {@link Instant}.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ *
+ * @see Marker
+ */
+abstract class InstantXmlMixIn extends InstantMixIn {
+
+    @JsonCreator
+    protected InstantXmlMixIn(
+    // @formatter:off
+            @JsonProperty(ATTR_EPOCH_SECOND) final long epochSecond,
+            @JsonProperty(ATTR_NANO_OF_SECOND) final int nanoOfSecond)
+    // @formatter:on
+    {
+        super(epochSecond, nanoOfSecond);
+    }
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_EPOCH_SECOND, isAttribute = true)
+    public abstract long getEpochSecond();
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_NANO_OF_SECOND, isAttribute = true)
+    public abstract int getNanoOfSecond();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/Log4jXmlModule.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/Log4jXmlModule.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/Log4jXmlModule.java
new file mode 100644
index 0000000..76166b0
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/Log4jXmlModule.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.jackson.SimpleModuleInitializer;
+
+import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ * <p>
+ * Extends Jackson's {@link JacksonXmlModule} for Log4j XML's specific needs.
+ * </p>
+ */
+final class Log4jXmlModule extends JacksonXmlModule {
+
+    private static final long serialVersionUID = 1L;
+    private final boolean includeStacktrace;
+    private final boolean stacktraceAsString;
+
+    Log4jXmlModule(final boolean includeStacktrace, final boolean stacktraceAsString) {
+        super();
+        this.includeStacktrace = includeStacktrace;
+        this.stacktraceAsString = stacktraceAsString;
+        // MUST init here.
+        // Calling this from setupModule is too late!
+        new SimpleModuleInitializer().initialize(this, false);
+    }
+
+    @Override
+    public void setupModule(final SetupContext context) {
+        // Calling super is a MUST!
+        super.setupModule(context);
+        new XmlSetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/Log4jXmlObjectMapper.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/Log4jXmlObjectMapper.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/Log4jXmlObjectMapper.java
new file mode 100644
index 0000000..ec802f4
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/Log4jXmlObjectMapper.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+
+/**
+ * A Jackson XML {@link ObjectMapper} initialized for Log4j.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class Log4jXmlObjectMapper extends XmlMapper {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Create a new instance using the {@code Log4jXmlModule}.
+     */
+    public Log4jXmlObjectMapper() {
+        this(true, false);
+    }
+
+    /**
+     * Create a new instance using the {@code Log4jXmlModule}.
+     */
+    public Log4jXmlObjectMapper(final boolean includeStacktrace, final boolean stacktraceAsString) {
+        super(new Log4jXmlModule(includeStacktrace, stacktraceAsString));
+        this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/LogEventWithContextListXmlMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/LogEventWithContextListXmlMixIn.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/LogEventWithContextListXmlMixIn.java
new file mode 100644
index 0000000..04f1d3d
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/LogEventWithContextListXmlMixIn.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.jackson.ContextDataAsEntryListDeserializer;
+import org.apache.logging.log4j.jackson.XmlConstants;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+/**
+ * <pre>
+ * AbstractLogEventMixIn
+*├─ AbstractLogEventXmlMixIn
+*├──── LogEventWithContextListXmlMixIn
+*├──── LogEventWithContextMapXmlMixIn
+*├─ JsonLogEventMixIn
+*├──── JsonLogEventWithContextListMixIn
+*├──── JsonLogEventWithContextMapMixIn
+ * </pre>
+ */
+public abstract class LogEventWithContextListXmlMixIn extends AbstractLogEventXmlMixIn {
+
+    private static final long serialVersionUID = 1L;
+
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
+    @JsonSerialize(using = ContextDataAsEntryListXmlSerializer.class)
+    @JsonDeserialize(using = ContextDataAsEntryListDeserializer.class)
+    @Override
+    public abstract ReadOnlyStringMap getContextData();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/MarkerXmlMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/MarkerXmlMixIn.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/MarkerXmlMixIn.java
new file mode 100644
index 0000000..a101ed5
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/MarkerXmlMixIn.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.jackson.MarkerMixIn;
+import org.apache.logging.log4j.jackson.XmlConstants;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+/**
+ * Jackson mix-in for {@link Marker}.
+ * <p>
+ * If we want to deal with more than one {@link Marker} implementation then recode these annotations to include
+ * metadata.
+ * </p>
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ * <p>
+ * Example XML:
+ * </p>
+ *
+ * <pre>
+&lt;Marker name=&quot;Marker1&quot;&gt;
+    &lt;Parents&gt;
+        &lt;Marker name=&quot;ParentMarker1&quot;&gt;
+            &lt;Parents&gt;
+                &lt;Marker name=&quot;GrandMotherMarker&quot;/&gt;
+                &lt;Marker name=&quot;GrandFatherMarker&quot;/&gt;
+            &lt;/Parents&gt;
+        &lt;/Marker&gt;
+        &lt;Marker name=&quot;ParentMarker2&quot;/&gt;
+    &lt;/Parents&gt;
+&lt;/Marker&gt;
+ * </pre>
+ *
+ * @see Marker
+ */
+// Alternate for multiple Marker implementation.
+// @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+@JsonDeserialize(as = org.apache.logging.log4j.MarkerManager.Log4jMarker.class)
+abstract class MarkerXmlMixIn extends MarkerMixIn {
+    public static final String ATTR_NAME = "name";
+    private static final long serialVersionUID = 1L;
+
+    @JsonCreator
+    protected MarkerXmlMixIn(@JsonProperty(ATTR_NAME) final String name) {
+        super(name);
+    }
+
+    @Override
+    @JacksonXmlProperty(isAttribute = true)
+    public abstract String getName();
+
+    @Override
+    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_PARENTS)
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MARKER)
+    public abstract Marker[] getParents();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/StackTraceElementXmlMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/StackTraceElementXmlMixIn.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/StackTraceElementXmlMixIn.java
new file mode 100644
index 0000000..93a3a45
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/StackTraceElementXmlMixIn.java
@@ -0,0 +1,40 @@
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.jackson.StackTraceElementConstants;
+import org.apache.logging.log4j.jackson.StackTraceElementMixIn;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+abstract class StackTraceElementXmlMixIn extends StackTraceElementMixIn {
+
+    @JsonCreator
+    protected StackTraceElementXmlMixIn(
+    // @formatter:off
+            @JsonProperty(StackTraceElementConstants.ATTR_CLASS) final String declaringClass,
+            @JsonProperty(StackTraceElementConstants.ATTR_METHOD) final String methodName,
+            @JsonProperty(StackTraceElementConstants.ATTR_FILE) final String fileName,
+            @JsonProperty(StackTraceElementConstants.ATTR_LINE) final int lineNumber)
+    // @formatter:on
+    {
+        super(declaringClass, methodName, fileName, lineNumber);
+    }
+
+    @Override
+    @JacksonXmlProperty(localName = StackTraceElementConstants.ATTR_CLASS, isAttribute = true)
+    protected abstract String getClassName();
+
+    @Override
+    @JacksonXmlProperty(localName = StackTraceElementConstants.ATTR_FILE, isAttribute = true)
+    protected abstract String getFileName();
+
+    @Override
+    @JacksonXmlProperty(localName = StackTraceElementConstants.ATTR_LINE, isAttribute = true)
+    protected abstract int getLineNumber();
+
+    @Override
+    @JacksonXmlProperty(localName = StackTraceElementConstants.ATTR_METHOD, isAttribute = true)
+    protected abstract String getMethodName();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyWithStacktraceAsStringXmlMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyWithStacktraceAsStringXmlMixIn.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyWithStacktraceAsStringXmlMixIn.java
new file mode 100644
index 0000000..9cc85c3
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyWithStacktraceAsStringXmlMixIn.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.jackson.ThrowableProxyWithStacktraceAsStringMixIn;
+import org.apache.logging.log4j.jackson.XmlConstants;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+public abstract class ThrowableProxyWithStacktraceAsStringXmlMixIn extends ThrowableProxyWithStacktraceAsStringMixIn {
+
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CAUSE)
+    private ThrowableProxyWithStacktraceAsStringMixIn causeProxy;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private int commonElementCount;
+
+    @JsonIgnore
+    private ExtendedStackTraceElement[] extendedStackTrace;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String localizedMessage;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String message;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String name;
+
+    @JsonIgnore
+    private transient Throwable throwable;
+
+    @Override
+    @JsonIgnore
+    public abstract String getCauseStackTraceAsString();
+
+    @Override
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EXTENDED_STACK_TRACE)
+    public abstract String getExtendedStackTraceAsString();
+
+    @Override
+    @JsonIgnore
+    public abstract StackTraceElement[] getStackTrace();
+
+    @Override
+    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED)
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED_ITEM)
+    public abstract ThrowableProxy[] getSuppressedProxies();
+
+    @Override
+    @JsonIgnore
+    public abstract String getSuppressedStackTrace();
+
+    @Override
+    @JsonIgnore
+    public abstract Throwable getThrowable();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyWithoutStacktraceXmlMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyWithoutStacktraceXmlMixIn.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyWithoutStacktraceXmlMixIn.java
new file mode 100644
index 0000000..4ecffae
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyWithoutStacktraceXmlMixIn.java
@@ -0,0 +1,60 @@
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.jackson.ThrowableProxyWithoutStacktraceMixIn;
+import org.apache.logging.log4j.jackson.XmlConstants;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+public abstract class ThrowableProxyWithoutStacktraceXmlMixIn extends ThrowableProxyWithoutStacktraceMixIn {
+
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CAUSE)
+    private ThrowableProxyWithoutStacktraceMixIn causeProxy;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private int commonElementCount;
+
+    @JsonIgnore
+    private ExtendedStackTraceElement[] extendedStackTrace;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String localizedMessage;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String message;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String name;
+
+    @JsonIgnore
+    private transient Throwable throwable;
+
+    @Override
+    @JsonIgnore
+    public abstract String getCauseStackTraceAsString();
+
+    @Override
+    @JsonIgnore
+    public abstract String getExtendedStackTraceAsString();
+
+    @Override
+    @JsonIgnore
+    public abstract StackTraceElement[] getStackTrace();
+
+    @Override
+    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED)
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED_ITEM)
+    public abstract ThrowableProxy[] getSuppressedProxies();
+
+    @Override
+    @JsonIgnore
+    public abstract String getSuppressedStackTrace();
+
+    @Override
+    @JsonIgnore
+    public abstract Throwable getThrowable();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyXmlMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyXmlMixIn.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyXmlMixIn.java
new file mode 100644
index 0000000..b52f7f6
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/ThrowableProxyXmlMixIn.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.jackson.ThrowableProxyMixIn;
+import org.apache.logging.log4j.jackson.XmlConstants;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+public abstract class ThrowableProxyXmlMixIn extends ThrowableProxyMixIn {
+
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CAUSE)
+    private ThrowableProxyMixIn causeProxy;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private int commonElementCount;
+
+    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EXTENDED_STACK_TRACE)
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EXTENDED_STACK_TRACE_ITEM)
+    private ExtendedStackTraceElement[] extendedStackTrace;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String localizedMessage;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String message;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String name;
+
+    @JsonIgnore
+    private transient Throwable throwable;
+
+    @Override
+    @JsonIgnore
+    public abstract String getCauseStackTraceAsString();
+
+    @Override
+    @JsonIgnore
+    public abstract String getExtendedStackTraceAsString();
+
+    @Override
+    @JsonIgnore
+    public abstract StackTraceElement[] getStackTrace();
+
+    @Override
+    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED)
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED_ITEM)
+    public abstract ThrowableProxy[] getSuppressedProxies();
+
+    @Override
+    @JsonIgnore
+    public abstract String getSuppressedStackTrace();
+
+    @Override
+    @JsonIgnore
+    public abstract Throwable getThrowable();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/XmlMapEntry.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/XmlMapEntry.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/XmlMapEntry.java
new file mode 100644
index 0000000..2500c11
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/XmlMapEntry.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.jackson.MapEntry;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+@JsonPropertyOrder({ "key", "value" })
+class XmlMapEntry extends MapEntry {
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String key;
+
+    @JacksonXmlProperty(isAttribute = true)
+    private String value;
+
+    @JsonCreator
+    public XmlMapEntry(@JsonProperty("key") final String key, @JsonProperty("value") final String value) {
+        super(key, value);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/XmlSetupContextInitializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/XmlSetupContextInitializer.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/XmlSetupContextInitializer.java
new file mode 100644
index 0000000..4cc5124
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/XmlSetupContextInitializer.java
@@ -0,0 +1,38 @@
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.core.time.Instant;
+import org.apache.logging.log4j.jackson.LevelMixIn;
+
+import com.fasterxml.jackson.databind.Module.SetupContext;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+/**
+ * Used to set up {@link SetupContext} from different {@link SimpleModule}s.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+class XmlSetupContextInitializer {
+
+    public void setupModule(final SetupContext context, final boolean includeStacktrace,
+            final boolean stacktraceAsString) {
+        // JRE classes: we cannot edit those with Jackson annotations
+        context.setMixInAnnotations(StackTraceElement.class, StackTraceElementXmlMixIn.class);
+        // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not
+        // depend on Jackson.
+        context.setMixInAnnotations(Marker.class, MarkerXmlMixIn.class);
+        context.setMixInAnnotations(Level.class, LevelMixIn.class);
+        context.setMixInAnnotations(Instant.class, InstantXmlMixIn.class);
+        context.setMixInAnnotations(LogEvent.class, LogEventWithContextListXmlMixIn.class);
+        // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
+        context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementXmlMixIn.class);
+        context.setMixInAnnotations(ThrowableProxy.class, includeStacktrace
+                ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringXmlMixIn.class : ThrowableProxyXmlMixIn.class)
+                : ThrowableProxyWithoutStacktraceXmlMixIn.class);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/Log4jXmlPrettyPrinter.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/Log4jXmlPrettyPrinter.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/Log4jXmlPrettyPrinter.java
new file mode 100644
index 0000000..6956861
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/Log4jXmlPrettyPrinter.java
@@ -0,0 +1,41 @@
+package org.apache.logging.log4j.jackson.xml.layout;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.codehaus.stax2.XMLStreamWriter2;
+
+import com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter;
+
+/**
+ * When &lt;Event&gt;s are written into a XML file; the "Event" object is not the root element, but an element named
+ * &lt;Events&gt; created using {@link XmlLayout#getHeader()} and {@link XmlLayout#getFooter()} methods.
+ * <p>
+ * {@link com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter} is used to print the Event object into
+ * XML; hence it assumes &lt;Event&gt; tag as the root element, so it prints the &lt;Event&gt; tag without any
+ * indentation. To add an indentation to the &lt;Event&gt; tag; hence an additional indentation for any
+ * sub-elements, this class is written. As an additional task, to avoid the blank line printed after the ending
+ * &lt;/Event&gt; tag, the {@code #writePrologLinefeed(XMLStreamWriter2)} method is also overridden.
+ * </p>
+ */
+class Log4jXmlPrettyPrinter extends DefaultXmlPrettyPrinter {
+
+    private static final long serialVersionUID = 1L;
+
+    Log4jXmlPrettyPrinter(final int nesting) {
+        _nesting = nesting;
+    }
+
+    /**
+     * Sets the nesting level to 1 rather than 0, so the "Event" tag will get indentation of next level below root.
+     */
+    @Override
+    public DefaultXmlPrettyPrinter createInstance() {
+        return new Log4jXmlPrettyPrinter(XmlJacksonFactory.DEFAULT_INDENT);
+    }
+
+    @Override
+    public void writePrologLinefeed(final XMLStreamWriter2 sw) throws XMLStreamException {
+        // nothing
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/XmlJacksonFactory.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/XmlJacksonFactory.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/XmlJacksonFactory.java
new file mode 100644
index 0000000..0cfba5b
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/XmlJacksonFactory.java
@@ -0,0 +1,54 @@
+package org.apache.logging.log4j.jackson.xml.layout;
+
+import org.apache.logging.log4j.jackson.AbstractJacksonFactory;
+import org.apache.logging.log4j.jackson.JsonConstants;
+import org.apache.logging.log4j.jackson.XmlConstants;
+import org.apache.logging.log4j.jackson.xml.Log4jXmlObjectMapper;
+
+import com.fasterxml.jackson.core.PrettyPrinter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+class XmlJacksonFactory extends AbstractJacksonFactory {
+
+    static final int DEFAULT_INDENT = 1;
+
+    public XmlJacksonFactory(final boolean includeStacktrace, final boolean stacktraceAsString) {
+        super(includeStacktrace, stacktraceAsString);
+    }
+
+    @Override
+    protected String getPropertyNameForContextMap() {
+        return XmlConstants.ELT_CONTEXT_MAP;
+    }
+
+    @Override
+    protected String getPropertyNameForNanoTime() {
+        return JsonConstants.ELT_NANO_TIME;
+    }
+
+    @Override
+    protected String getPropertyNameForSource() {
+        return XmlConstants.ELT_SOURCE;
+    }
+
+    @Override
+    protected String getPropertyNameForStackTrace() {
+        return XmlConstants.ELT_EXTENDED_STACK_TRACE;
+    }
+
+    @Override
+    protected PrettyPrinter newCompactPrinter() {
+        // Yes, null is the proper answer.
+        return null;
+    }
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jXmlObjectMapper(includeStacktrace, stacktraceAsString);
+    }
+
+    @Override
+    protected PrettyPrinter newPrettyPrinter() {
+        return new Log4jXmlPrettyPrinter(DEFAULT_INDENT);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayout.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayout.java b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayout.java
new file mode 100644
index 0000000..6d723b0
--- /dev/null
+++ b/log4j-layout-jackson-xml/src/main/java/org/apache/logging/log4j/jackson/xml/layout/XmlLayout.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml.layout;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+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.PluginBuilderFactory;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.apache.logging.log4j.jackson.AbstractJacksonLayout;
+import org.apache.logging.log4j.jackson.XmlConstants;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+
+/**
+ * Appends a series of {@code event} elements as defined in the <a href="log4j.dtd">log4j.dtd</a>.
+ *
+ * <h3>Complete well-formed XML vs. fragment XML</h3>
+ * <p>
+ * If you configure {@code complete="true"}, the appender outputs a well-formed XML document where the default namespace
+ * is the log4j namespace {@value XmlConstants#XML_NAMESPACE}. By default, with {@code complete="false"}, you should
+ * include the output as an <em>external entity</em> in a separate file to form a well-formed XML document.
+ * </p>
+ * <p>
+ * If {@code complete="false"}, the appender does not write the XML processing instruction and the root element.
+ * </p>
+ * <h3>Encoding</h3>
+ * <p>
+ * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise
+ * events containing non-ASCII characters could result in corrupted log files.
+ * </p>
+ * <h3>Pretty vs. compact XML</h3>
+ * <p>
+ * By default, the XML layout is not compact (compact = not "pretty") with {@code compact="false"}, which means the
+ * appender uses end-of-line characters and indents lines to format the XML. If {@code compact="true"}, then no
+ * end-of-line or indentation is used. Message content may contain, of course, end-of-lines.
+ * </p>
+ * <h3>Additional Fields</h3>
+ * <p>
+ * This property allows addition of custom fields into generated JSON.
+ * {@code <XmlLayout><KeyValuePair key="foo" value="bar"/></XmlLayout>} inserts {@code <foo>bar</foo>} directly into XML
+ * output. Supports Lookup expressions.
+ * </p>
+ */
+@Plugin(name = "XmlLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
+public final class XmlLayout extends AbstractJacksonLayout {
+
+    public static class Builder<B extends Builder<B>> extends AbstractJacksonLayout.Builder<B>
+            implements org.apache.logging.log4j.core.util.Builder<XmlLayout> {
+
+        public Builder() {
+            super();
+            setCharset(StandardCharsets.UTF_8);
+        }
+
+        @Override
+        public XmlLayout build() {
+            return new XmlLayout(getConfiguration(), isLocationInfo(), isProperties(), isComplete(), isCompact(),
+                    getCharset(), isIncludeStacktrace(), isStacktraceAsString(), isIncludeNullDelimiter(),
+                    getAdditionalFields());
+        }
+    }
+
+    @JacksonXmlRootElement(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EVENT)
+    public static class XmlLogEventWithAdditionalFields extends LogEventWithAdditionalFields {
+
+        public XmlLogEventWithAdditionalFields(final Object logEvent, final Map<String, String> additionalFields) {
+            super(logEvent, additionalFields);
+        }
+
+    }
+
+    private static final String ROOT_TAG = "Events";
+
+    /**
+     * Creates an XML Layout using the default settings.
+     *
+     * @return an XML Layout.
+     */
+    public static XmlLayout createDefaultLayout() {
+        return new XmlLayout(null, false, false, false, false, StandardCharsets.UTF_8, true, false, false, null);
+    }
+
+    /**
+     * Creates an XML Layout.
+     *
+     * @param locationInfo
+     *            If "true", includes the location information in the generated XML.
+     * @param properties
+     *            If "true", includes the thread context map in the generated XML.
+     * @param complete
+     *            If "true", includes the XML header and footer, defaults to "false".
+     * @param compact
+     *            If "true", does not use end-of-lines and indentation, defaults to "false".
+     * @param charset
+     *            The character set to use, if {@code null}, uses "UTF-8".
+     * @param includeStacktrace
+     *            If "true", includes the stacktrace of any Throwable in the generated XML, defaults to "true".
+     * @return An XML Layout.
+     *
+     * @deprecated Use {@link #newBuilder()} instead
+     */
+    @Deprecated
+    public static XmlLayout createLayout(final boolean locationInfo, final boolean properties, final boolean complete,
+            final boolean compact, final Charset charset, final boolean includeStacktrace) {
+        return new XmlLayout(null, locationInfo, properties, complete, compact, charset, includeStacktrace, false,
+                false, null);
+    }
+
+    @PluginBuilderFactory
+    public static <B extends Builder<B>> B newBuilder() {
+        return new Builder<B>().asBuilder();
+    }
+
+    /**
+     * @deprecated Use {@link #newBuilder()} instead
+     */
+    @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, false, null);
+    }
+
+    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 includeNullDelimiter,
+            final KeyValuePair[] additionalFields) {
+        super(config,
+                new XmlJacksonFactory(includeStacktrace, stacktraceAsString).newWriter(locationInfo, properties,
+                        compact),
+                charset, compact, complete, false, null, null, includeNullDelimiter, additionalFields);
+    }
+
+    @Override
+    protected LogEventWithAdditionalFields createLogEventWithAdditionalFields(final LogEvent event,
+            final Map<String, String> additionalFieldsMap) {
+        return new XmlLogEventWithAdditionalFields(event, additionalFieldsMap);
+    }
+
+    /**
+     * Gets this XmlLayout's content format. Specified by:
+     * <ul>
+     * <li>Key: "dtd" Value: "log4j-events.dtd"</li>
+     * <li>Key: "version" Value: "2.0"</li>
+     * </ul>
+     *
+     * @return Map of content format keys supporting XmlLayout
+     */
+    @Override
+    public Map<String, String> getContentFormat() {
+        final Map<String, String> result = new HashMap<>();
+        // result.put("dtd", "log4j-events.dtd");
+        result.put("xsd", "log4j-events.xsd");
+        result.put("version", "2.0");
+        return result;
+    }
+
+    /**
+     * @return The content type.
+     */
+    @Override
+    public String getContentType() {
+        return "text/xml; charset=" + this.getCharset();
+    }
+
+    /**
+     * Returns appropriate XML footer.
+     *
+     * @return a byte array containing the footer, closing the XML root element.
+     */
+    @Override
+    public byte[] getFooter() {
+        if (!complete) {
+            return null;
+        }
+        return getBytes("</" + ROOT_TAG + '>' + this.eol);
+    }
+
+    /**
+     * Returns appropriate XML headers.
+     * <ol>
+     * <li>XML processing instruction</li>
+     * <li>XML root element</li>
+     * </ol>
+     *
+     * @return a byte array containing the header.
+     */
+    @Override
+    public byte[] getHeader() {
+        if (!complete) {
+            return null;
+        }
+        final StringBuilder buf = new StringBuilder();
+        buf.append("<?xml version=\"1.0\" encoding=\"");
+        buf.append(this.getCharset().name());
+        buf.append("\"?>");
+        buf.append(this.eol);
+        // Make the log4j namespace the default namespace, no need to use more space with a namespace prefix.
+        buf.append('<');
+        buf.append(ROOT_TAG);
+        buf.append(" xmlns=\"" + XmlConstants.XML_NAMESPACE + "\">");
+        buf.append(this.eol);
+        return buf.toString().getBytes(this.getCharset());
+    }
+}


[09/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/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
deleted file mode 100644
index 1d8576f..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.layout;
-
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.logging.log4j.core.Layout;
-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.PluginBuilderFactory;
-import org.apache.logging.log4j.core.util.KeyValuePair;
-import org.apache.logging.log4j.util.Strings;
-
-/**
- * Appends a series of YAML events as strings serialized as bytes.
- *
- * <h3>Encoding</h3>
- * <p>
- * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise
- * events containing non ASCII characters could result in corrupted log files.
- * </p>
- * <h3>Additional Fields</h3>
- * <p>
- * This property allows addition of custom fields into generated JSON.
- * {@code <YamlLayout><KeyValuePair key="foo" value="bar"/></YamlLayout>} inserts {@code foo: "bar"} directly
- * into YAML output. Supports Lookup expressions.
- * </p>
- */
-@Plugin(name = "YamlLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
-public final class YamlLayout extends AbstractJacksonLayout {
-
-    private static final String DEFAULT_FOOTER = Strings.EMPTY;
-
-    private static final String DEFAULT_HEADER = Strings.EMPTY;
-
-    static final String CONTENT_TYPE = "application/yaml";
-
-    public static class Builder<B extends Builder<B>> extends AbstractJacksonLayout.Builder<B>
-        implements org.apache.logging.log4j.core.util.Builder<YamlLayout> {
-
-        public Builder() {
-            super();
-            setCharset(StandardCharsets.UTF_8);
-        }
-
-        @Override
-        public YamlLayout build() {
-            final String headerPattern = toStringOrNull(getHeader());
-            final String footerPattern = toStringOrNull(getFooter());
-            return new YamlLayout(getConfiguration(), isLocationInfo(), isProperties(), isComplete(),
-                    isCompact(), getEventEol(), headerPattern, footerPattern, getCharset(),
-                    isIncludeStacktrace(), isStacktraceAsString(), isIncludeNullDelimiter(),
-                    getAdditionalFields());
-        }
-    }
-
-    /**
-     * @deprecated Use {@link #newBuilder()} instead
-     */
-    @Deprecated
-    protected 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) {
-        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(),
-                false, null);
-    }
-
-    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 includeNullDelimiter,
-                       final KeyValuePair[] additionalFields) {
-        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(),
-                includeNullDelimiter,
-                additionalFields);
-    }
-
-    /**
-     * Returns appropriate YAML header.
-     *
-     * @return a byte array containing the header, opening the YAML array.
-     */
-    @Override
-    public byte[] getHeader() {
-        if (!this.complete) {
-            return null;
-        }
-        final StringBuilder buf = new StringBuilder();
-        final String str = serializeToString(getHeaderSerializer());
-        if (str != null) {
-            buf.append(str);
-        }
-        buf.append(this.eol);
-        return getBytes(buf.toString());
-    }
-
-    /**
-     * Returns appropriate YAML footer.
-     *
-     * @return a byte array containing the footer, closing the YAML array.
-     */
-    @Override
-    public byte[] getFooter() {
-        if (!this.complete) {
-            return null;
-        }
-        final StringBuilder buf = new StringBuilder();
-        buf.append(this.eol);
-        final String str = serializeToString(getFooterSerializer());
-        if (str != null) {
-            buf.append(str);
-        }
-        buf.append(this.eol);
-        return getBytes(buf.toString());
-    }
-
-    @Override
-    public Map<String, String> getContentFormat() {
-        final Map<String, String> result = new HashMap<>();
-        result.put("version", "2.0");
-        return result;
-    }
-
-    /**
-     * @return The content type.
-     */
-    @Override
-    public String getContentType() {
-        return CONTENT_TYPE + "; charset=" + this.getCharset();
-    }
-
-    /**
-     * Creates a YAML Layout.
-     * 
-     * @param config
-     *            The plugin configuration.
-     * @param locationInfo
-     *            If "true", includes the location information in the generated YAML.
-     * @param properties
-     *            If "true", includes the thread context map in the generated YAML.
-     * @param headerPattern
-     *            The header pattern, defaults to {@code ""} if null.
-     * @param footerPattern
-     *            The header pattern, defaults to {@code ""} if null.
-     * @param charset
-     *            The character set to use, if {@code null}, uses "UTF-8".
-     * @param includeStacktrace
-     *            If "true", includes the stacktrace of any Throwable in the generated YAML, defaults to "true".
-     * @return A YAML Layout.
-     *
-     * @deprecated Use {@link #newBuilder()} instead
-     */
-    @Deprecated
-    public static AbstractJacksonLayout createLayout(
-            final Configuration config,
-            final boolean locationInfo,
-            final boolean properties,
-            final String headerPattern,
-            final String footerPattern,
-            final Charset charset,
-            final boolean includeStacktrace) {
-        return new YamlLayout(config, locationInfo, properties, false, false, true, headerPattern, footerPattern,
-                charset, includeStacktrace, false, false, null);
-    }
-
-    @PluginBuilderFactory
-    public static <B extends Builder<B>> B newBuilder() {
-        return new Builder<B>().asBuilder();
-    }
-
-    /**
-     * Creates a YAML Layout using the default settings. Useful for testing.
-     *
-     * @return A YAML Layout.
-     */
-    public static AbstractJacksonLayout createDefaultLayout() {
-        return new YamlLayout(new DefaultConfiguration(), false, false, false, false, false, DEFAULT_HEADER,
-                DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, null);
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/AbstractJacksonLogEventParser.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/AbstractJacksonLogEventParser.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/AbstractJacksonLogEventParser.java
index c764368..8c36c11 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/AbstractJacksonLogEventParser.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/AbstractJacksonLogEventParser.java
@@ -24,10 +24,10 @@ import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 
 import java.io.IOException;
 
-class AbstractJacksonLogEventParser implements TextLogEventParser {
+public class AbstractJacksonLogEventParser implements TextLogEventParser {
     private final ObjectReader objectReader;
 
-    AbstractJacksonLogEventParser(final ObjectMapper objectMapper) {
+    protected AbstractJacksonLogEventParser(final ObjectMapper objectMapper) {
         objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
         this.objectReader = objectMapper.readerFor(Log4jLogEvent.class);
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/JsonLogEventParser.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/JsonLogEventParser.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/JsonLogEventParser.java
deleted file mode 100644
index 084ca4c..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/JsonLogEventParser.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.parser;
-
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
-
-/**
- * Parses the output from JsonLayout layout into instances of {@link LogEvent}.
- */
-public class JsonLogEventParser extends AbstractJacksonLogEventParser {
-
-    public JsonLogEventParser() {
-        super(new Log4jJsonObjectMapper());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/XmlLogEventParser.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/XmlLogEventParser.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/XmlLogEventParser.java
deleted file mode 100644
index e5b5a3a..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/XmlLogEventParser.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.parser;
-
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
-
-/**
- * Parses the output from XmlLayout layout into instances of {@link LogEvent}.
- */
-public class XmlLogEventParser extends AbstractJacksonLogEventParser {
-
-    public XmlLogEventParser() {
-        super(new Log4jXmlObjectMapper());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/YamlLogEventParser.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/YamlLogEventParser.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/YamlLogEventParser.java
deleted file mode 100644
index 3efe662..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/parser/YamlLogEventParser.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.parser;
-
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.jackson.Log4jYamlObjectMapper;
-
-/**
- * Parses the output from YamlLayout layout into instances of {@link LogEvent}.
- */
-public class YamlLogEventParser extends AbstractJacksonLogEventParser {
-
-    public YamlLogEventParser() {
-        super(new Log4jYamlObjectMapper());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInJsonTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInJsonTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInJsonTest.java
deleted file mode 100644
index 8777696..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInJsonTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements. See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You under the Apache license, Version 2.0
-* (the "License"); you may not use this file except in compliance with
-* the License. You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the license for the specific language governing permissions and
-* limitations under the license.
-*/
-
-package org.apache.logging.log4j;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
-import org.junit.experimental.categories.Category;
-
-@Category(Layouts.Json.class)
-public class MarkerMixInJsonTest extends MarkerMixInTest {
-
-    @Override
-    protected ObjectMapper newObjectMapper() {
-        return new Log4jJsonObjectMapper();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInTest.java
deleted file mode 100644
index d8bbae8..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements. See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You under the Apache license, Version 2.0
-* (the "License"); you may not use this file except in compliance with
-* the License. You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the license for the specific language governing permissions and
-* limitations under the license.
-*/
-package org.apache.logging.log4j;
-
-import java.io.IOException;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectReader;
-import com.fasterxml.jackson.databind.ObjectWriter;
-import org.apache.logging.log4j.MarkerManager.Log4jMarker;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Tests {@link MarkerMixIn}.
- *
- * This class is in this package to let {@link Log4jMarker} have the least visibility.
- */
-public abstract class MarkerMixInTest {
-
-    private ObjectReader reader;
-    private ObjectWriter writer;
-
-    @Before
-    public void setUp() {
-        final ObjectMapper log4jObjectMapper = newObjectMapper();
-        writer = log4jObjectMapper.writer();
-        reader = log4jObjectMapper.readerFor(Log4jMarker.class);
-        MarkerManager.clear();
-    }
-
-    protected abstract ObjectMapper newObjectMapper();
-
-    @Test
-    public void testNameOnly() throws IOException {
-        final Marker expected = MarkerManager.getMarker("A");
-        final String str = writeValueAsString(expected);
-        Assert.assertFalse(str.contains("parents"));
-        final Marker actual = reader.readValue(str);
-        Assert.assertEquals(expected, actual);
-    }
-
-    @Test
-    public void testOneParent() throws IOException {
-        final Marker expected = MarkerManager.getMarker("A");
-        final Marker parent = MarkerManager.getMarker("PARENT_MARKER");
-        expected.addParents(parent);
-        final String str = writeValueAsString(expected);
-        Assert.assertTrue(str.contains("PARENT_MARKER"));
-        final Marker actual = reader.readValue(str);
-        Assert.assertEquals(expected, actual);
-    }
-
-    /**
-     * @param expected
-     * @return
-     * @throws JsonProcessingException
-     */
-    private String writeValueAsString(final Marker expected) throws JsonProcessingException {
-        final String str = writer.writeValueAsString(expected);
-        // System.out.println(str);
-        return str;
-    }
-
-    @Test
-    public void testTwoParents() throws IOException {
-        final Marker expected = MarkerManager.getMarker("A");
-        final Marker parent1 = MarkerManager.getMarker("PARENT_MARKER1");
-        final Marker parent2 = MarkerManager.getMarker("PARENT_MARKER2");
-        expected.addParents(parent1);
-        expected.addParents(parent2);
-        final String str = writeValueAsString(expected);
-        Assert.assertTrue(str.contains("PARENT_MARKER1"));
-        Assert.assertTrue(str.contains("PARENT_MARKER2"));
-        final Marker actual = reader.readValue(str);
-        Assert.assertEquals(expected, actual);
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInXmlTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInXmlTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInXmlTest.java
deleted file mode 100644
index 963d3f6..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInXmlTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements. See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You under the Apache license, Version 2.0
-* (the "License"); you may not use this file except in compliance with
-* the License. You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the license for the specific language governing permissions and
-* limitations under the license.
-*/
-
-package org.apache.logging.log4j;
-
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.experimental.categories.Category;
-
-@Category(Layouts.Xml.class)
-public class MarkerMixInXmlTest extends MarkerMixInTest {
-
-    @Override
-    protected ObjectMapper newObjectMapper() {
-        return new Log4jXmlObjectMapper(true, false);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInYamlTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInYamlTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInYamlTest.java
deleted file mode 100644
index 2d14b6b..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInYamlTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements. See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You under the Apache license, Version 2.0
-* (the "License"); you may not use this file except in compliance with
-* the License. You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the license for the specific language governing permissions and
-* limitations under the license.
-*/
-
-package org.apache.logging.log4j;
-
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.jackson.Log4jYamlObjectMapper;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.experimental.categories.Category;
-
-@Category(Layouts.Yaml.class)
-public class MarkerMixInYamlTest extends MarkerMixInTest {
-
-    @Override
-    protected ObjectMapper newObjectMapper() {
-        return new Log4jYamlObjectMapper();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
deleted file mode 100644
index 25261f9..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.containing;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
-import static com.github.tomakehurst.wiremock.client.WireMock.post;
-import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.put;
-import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.io.IOException;
-import java.net.URL;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.config.Property;
-import org.apache.logging.log4j.core.impl.Log4jLogEvent;
-import org.apache.logging.log4j.core.layout.JsonLayout;
-import org.apache.logging.log4j.core.lookup.JavaLookup;
-import org.apache.logging.log4j.core.net.ssl.KeyStoreConfiguration;
-import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
-import org.apache.logging.log4j.core.net.ssl.TestConstants;
-import org.apache.logging.log4j.core.net.ssl.TrustStoreConfiguration;
-import org.apache.logging.log4j.junit.LoggerContextRule;
-import org.apache.logging.log4j.message.SimpleMessage;
-import org.apache.logging.log4j.status.StatusData;
-import org.apache.logging.log4j.status.StatusListener;
-import org.apache.logging.log4j.status.StatusLogger;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-
-import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
-import com.github.tomakehurst.wiremock.junit.WireMockRule;
-
-@Ignore("Fails often on Windows")
-
-/* Fails often on Windows, for example:
-[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.20.1:test (default-test) on project log4j-core: There are test failures.
-[ERROR]
-[ERROR] Please refer to C:\vcs\git\apache\logging\logging-log4j2\log4j-core\target\surefire-reports for the individual test results.
-[ERROR] Please refer to dump files (if any exist) [date]-jvmRun[N].dump, [date].dumpstream and [date]-jvmRun[N].dumpstream.
-[ERROR] ExecutionException The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
-[ERROR] Command was cmd.exe /X /C ""C:\Program Files\Java\jdk1.8.0_152\jre\bin\java" -Xms256m -Xmx1024m -jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112\surefirebooter1486874613063862199.jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112 2018-01-23T11-03-18_847-jvmRun6 surefire6375637980242546356tmp surefire_441335531705722358735tmp"
-[ERROR] Process Exit Code: 0
-[ERROR] Crashed tests:
-[ERROR] org.apache.logging.log4j.core.appender.HttpAppenderTest
-[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: ExecutionException The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
-[ERROR] Command was cmd.exe /X /C ""C:\Program Files\Java\jdk1.8.0_152\jre\bin\java" -Xms256m -Xmx1024m -jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112\surefirebooter1486874613063862199.jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112 2018-01-23T11-03-18_847-jvmRun6 surefire6375637980242546356tmp surefire_441335531705722358735tmp"
-[ERROR] Process Exit Code: 0
-[ERROR] Crashed tests:
-[ERROR] org.apache.logging.log4j.core.appender.HttpAppenderTest
-[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.awaitResultsDone(ForkStarter.java:496)
-[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.runSuitesForkPerTestSet(ForkStarter.java:443)
-[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:295)
-[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:246)
-[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1124)
-[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:954)
-[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:832)
-[ERROR]         at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
-[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
-[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
-[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
-[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
-[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
-[ERROR]         at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
-[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
-[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:309)
-[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:194)
-[ERROR]         at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:107)
-[ERROR]         at org.apache.maven.cli.MavenCli.execute(MavenCli.java:955)
-[ERROR]         at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:290)
-[ERROR]         at org.apache.maven.cli.MavenCli.main(MavenCli.java:194)
-[ERROR]         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-[ERROR]         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
-[ERROR]         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-[ERROR]         at java.lang.reflect.Method.invoke(Method.java:498)
-[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
-[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
-[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
-[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
-[ERROR] Caused by: org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
-[ERROR] Command was cmd.exe /X /C ""C:\Program Files\Java\jdk1.8.0_152\jre\bin\java" -Xms256m -Xmx1024m -jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112\surefirebooter1486874613063862199.jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112 2018-01-23T11-03-18_847-jvmRun6 surefire6375637980242546356tmp surefire_441335531705722358735tmp"
-[ERROR] Process Exit Code: 0
-[ERROR] Crashed tests:
-[ERROR] org.apache.logging.log4j.core.appender.HttpAppenderTest
-[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:686)
-[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:535)
-[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.access$700(ForkStarter.java:116)
-[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter$2.call(ForkStarter.java:431)
-[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter$2.call(ForkStarter.java:408)
-[ERROR]         at java.util.concurrent.FutureTask.run(FutureTask.java:266)
-[ERROR]         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
-[ERROR]         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
-[ERROR]         at java.lang.Thread.run(Thread.java:748)
-[ERROR]
-[ERROR] -> [Help 1]
-[ERROR]
-[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
-[ERROR] Re-run Maven using the -X switch to enable full debug logging.
-[ERROR]
-[ERROR] For more information about the errors and possible solutions, please read the following articles:
-[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
-[ERROR]
-[ERROR] After correcting the problems, you can resume the build with the command
-[ERROR]   mvn <goals> -rf :log4j-core
- */
-public class HttpAppenderTest {
-
-    private static final String LOG_MESSAGE = "Hello, world!";
-
-    private static Log4jLogEvent createLogEvent() {
-        return Log4jLogEvent.newBuilder()
-            .setLoggerName(HttpAppenderTest.class.getName())
-            .setLoggerFqcn(HttpAppenderTest.class.getName())
-            .setLevel(Level.INFO)
-            .setMessage(new SimpleMessage(LOG_MESSAGE))
-            .build();
-    }
-
-    private final ResponseDefinitionBuilder SUCCESS_RESPONSE = aResponse().withStatus(201)
-        .withHeader("Content-Type", "application/json")
-        .withBody("{\"status\":\"created\"}");
-
-    private final ResponseDefinitionBuilder FAILURE_RESPONSE = aResponse().withStatus(400)
-        .withHeader("Content-Type", "application/json")
-        .withBody("{\"status\":\"error\"}");
-
-    private final JavaLookup JAVA_LOOKUP = new JavaLookup();
-
-    @Rule
-    public LoggerContextRule ctx = new LoggerContextRule("HttpAppenderTest.xml");
-
-    @Rule
-    public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort()
-        .keystorePath(TestConstants.KEYSTORE_FILE)
-        .keystorePassword(String.valueOf(TestConstants.KEYSTORE_PWD()))
-        .keystoreType(TestConstants.KEYSTORE_TYPE));
-
-    @Test
-    public void testAppend() throws Exception {
-        wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
-            .willReturn(SUCCESS_RESPONSE));
-
-        final Appender appender = HttpAppender.newBuilder()
-            .withName("Http")
-            .withLayout(JsonLayout.createDefaultLayout())
-            .setConfiguration(ctx.getConfiguration())
-            .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
-            .build();
-        appender.append(createLogEvent());
-
-        wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
-            .withHeader("Host", containing("localhost"))
-            .withHeader("Content-Type", containing("application/json"))
-            .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
-    }
-
-    @Test
-    public void testAppendHttps() throws Exception {
-        wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
-            .willReturn(SUCCESS_RESPONSE));
-
-        final Appender appender = HttpAppender.newBuilder()
-            .withName("Http")
-            .withLayout(JsonLayout.createDefaultLayout())
-            .setConfiguration(ctx.getConfiguration())
-            .setUrl(new URL("https://localhost:" + wireMockRule.httpsPort() + "/test/log4j/"))
-            .setSslConfiguration(SslConfiguration.createSSLConfiguration(null,
-                KeyStoreConfiguration.createKeyStoreConfiguration(TestConstants.KEYSTORE_FILE, TestConstants.KEYSTORE_PWD(), TestConstants.KEYSTORE_TYPE, null),
-                TrustStoreConfiguration.createKeyStoreConfiguration(TestConstants.TRUSTSTORE_FILE, TestConstants.TRUSTSTORE_PWD(), TestConstants.TRUSTSTORE_TYPE, null)))
-            .setVerifyHostname(false)
-            .build();
-        appender.append(createLogEvent());
-
-        wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
-            .withHeader("Host", containing("localhost"))
-            .withHeader("Content-Type", containing("application/json"))
-            .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
-    }
-
-    @Test
-    public void testAppendMethodPut() throws Exception {
-        wireMockRule.stubFor(put(urlEqualTo("/test/log4j/1234"))
-            .willReturn(SUCCESS_RESPONSE));
-
-        final Appender appender = HttpAppender.newBuilder()
-            .withName("Http")
-            .withLayout(JsonLayout.createDefaultLayout())
-            .setConfiguration(ctx.getConfiguration())
-            .setMethod("PUT")
-            .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/1234"))
-            .build();
-        appender.append(createLogEvent());
-
-        wireMockRule.verify(putRequestedFor(urlEqualTo("/test/log4j/1234"))
-            .withHeader("Host", containing("localhost"))
-            .withHeader("Content-Type", containing("application/json"))
-            .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
-    }
-
-    @Test
-    public void testAppendCustomHeader() throws Exception {
-        wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
-            .willReturn(SUCCESS_RESPONSE));
-
-        final Appender appender = HttpAppender.newBuilder()
-            .withName("Http")
-            .withLayout(JsonLayout.createDefaultLayout())
-            .setConfiguration(ctx.getConfiguration())
-            .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
-            .setHeaders(new Property[] {
-                Property.createProperty("X-Test", "header value"),
-                Property.createProperty("X-Runtime", "${java:runtime}")
-            })
-            .build();
-        appender.append(createLogEvent());
-
-        wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
-            .withHeader("Host", containing("localhost"))
-            .withHeader("X-Test", equalTo("header value"))
-            .withHeader("X-Runtime", equalTo(JAVA_LOOKUP.getRuntime()))
-            .withHeader("Content-Type", containing("application/json"))
-            .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
-    }
-
-    volatile StatusData error;
-
-    @Test
-    public void testAppendErrorIgnore() throws Exception {
-        wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
-            .willReturn(FAILURE_RESPONSE));
-
-        StatusLogger.getLogger().registerListener(new StatusListener() {
-            @Override
-            public void log(final StatusData data) {
-                error = data;
-            }
-
-            @Override
-            public Level getStatusLevel() {
-                return Level.ERROR;
-            }
-
-            @Override
-            public void close() throws IOException { }
-        });
-
-        error = null;
-
-        final Appender appender = HttpAppender.newBuilder()
-            .withName("Http")
-            .withLayout(JsonLayout.createDefaultLayout())
-            .setConfiguration(ctx.getConfiguration())
-            .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
-            .build();
-        appender.append(createLogEvent());
-
-        wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
-            .withHeader("Host", containing("localhost"))
-            .withHeader("Content-Type", containing("application/json"))
-            .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
-
-        assertNotNull(error);
-        assertEquals(Level.ERROR, error.getLevel());
-        assertEquals("Unable to send HTTP in appender [Http]", error.getMessage().toString());
-    }
-
-    @Test(expected = AppenderLoggingException.class)
-    public void testAppendError() throws Exception {
-        wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
-            .willReturn(FAILURE_RESPONSE));
-
-        final Appender appender = HttpAppender.newBuilder()
-            .withName("Http")
-            .withLayout(JsonLayout.createDefaultLayout())
-            .setConfiguration(ctx.getConfiguration())
-            .withIgnoreExceptions(false)
-            .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
-            .build();
-        appender.append(createLogEvent());
-    }
-
-    @Test(expected = AppenderLoggingException.class)
-    public void testAppendConnectError() throws Exception {
-        final Appender appender = HttpAppender.newBuilder()
-            .withName("Http")
-            .withLayout(JsonLayout.createDefaultLayout())
-            .setConfiguration(ctx.getConfiguration())
-            .withIgnoreExceptions(false)
-            .setUrl(new URL("http://localhost:"+(wireMockRule.port()+1)+"/test/log4j/"))
-            .build();
-        appender.append(createLogEvent());
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
deleted file mode 100644
index 853f7e3..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import java.io.File;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.util.List;
-
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.impl.Log4jLogEventTest;
-import org.apache.logging.log4j.core.selector.ContextSelector;
-import org.apache.logging.log4j.core.selector.CoreContextSelectors;
-import org.apache.logging.log4j.core.time.ClockFactory;
-import org.apache.logging.log4j.junit.CleanFiles;
-import org.apache.logging.log4j.junit.LoggerContextRule;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.RuleChain;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import static org.junit.Assert.*;
-
-/**
- * Tests a "complete" JSON file.
- */
-@RunWith(Parameterized.class)
-@Category(Layouts.Json.class)
-public class JsonCompleteFileAppenderTest {
-
-    public JsonCompleteFileAppenderTest(final Class<ContextSelector> contextSelector) {
-        this.loggerContextRule = new LoggerContextRule("JsonCompleteFileAppenderTest.xml", contextSelector);
-        this.cleanFiles = new CleanFiles(logFile);
-        this.ruleChain = RuleChain.outerRule(cleanFiles).around(loggerContextRule);
-    }
-
-    @BeforeClass
-    public static void beforeClass() {
-        System.setProperty(ClockFactory.PROPERTY_NAME, Log4jLogEventTest.FixedTimeClock.class.getName());
-    }
-
-    @AfterClass
-    public static void afterClass() {
-        System.clearProperty(ClockFactory.PROPERTY_NAME);
-    }
-
-    @Parameters(name = "{0}")
-    public static Class<?>[] getParameters() {
-        return CoreContextSelectors.CLASSES;
-    }
-
-    private final File logFile = new File("target", "JsonCompleteFileAppenderTest.log");
-    private final LoggerContextRule loggerContextRule;
-    private final CleanFiles cleanFiles;
-
-    @Rule
-    public RuleChain ruleChain;
-
-    @Test
-    public void testFlushAtEndOfBatch() throws Exception {
-        final Logger logger = this.loggerContextRule.getLogger("com.foo.Bar");
-        final String logMsg = "Message flushed with immediate flush=true";
-        logger.info(logMsg);
-        logger.error(logMsg, new IllegalArgumentException("badarg"));
-        this.loggerContextRule.getLoggerContext().stop(); // stops async thread
-
-        List<String> lines = Files.readAllLines(logFile.toPath(), Charset.forName("UTF8"));
-
-        String[] expected = {
-                "[", // equals
-                "{", // equals
-                "  \"thread\" : \"main\",", //
-                "  \"level\" : \"INFO\",", //
-                "  \"loggerName\" : \"com.foo.Bar\",", //
-                "  \"message\" : \"Message flushed with immediate flush=true\",", //
-                "  \"endOfBatch\" : false,", //
-                "  \"loggerFqcn\" : \"org.apache.logging.log4j.spi.AbstractLogger\",", //
-                "  \"instant\" : {", //
-                "    \"epochSecond\" : 1234567,", //
-                "    \"nanoOfSecond\" : 890000000", //
-                "  },", //
-        };
-        for (int i = 0; i < expected.length; i++) {
-            String line = lines.get(i);
-            assertTrue("line " + i + " incorrect: [" + line + "], does not contain: [" + expected[i] + ']', line.contains(expected[i]));
-        }
-        final String location = "testFlushAtEndOfBatch";
-        assertTrue("no location", !lines.get(0).contains(location));
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
deleted file mode 100644
index abee218..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.Socket;
-
-import javax.net.ssl.SSLServerSocketFactory;
-
-import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
-import org.apache.logging.log4j.core.net.Rfc1349TrafficClass;
-import org.apache.logging.log4j.core.net.SocketOptions;
-import org.apache.logging.log4j.core.net.TcpSocketManager;
-import org.apache.logging.log4j.core.net.ssl.KeyStoreConfiguration;
-import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
-import org.apache.logging.log4j.core.net.ssl.StoreConfigurationException;
-import org.apache.logging.log4j.core.net.ssl.TestConstants;
-import org.apache.logging.log4j.core.net.ssl.TrustStoreConfiguration;
-import org.apache.logging.log4j.core.util.NullOutputStream;
-import org.apache.logging.log4j.junit.LoggerContextRule;
-import org.apache.logging.log4j.test.AvailablePortFinder;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-public class SecureSocketAppenderSocketOptionsTest {
-
-    private static final int PORT;
-    private static TcpSocketTestServer tcpSocketTestServer;
-
-    private static SSLServerSocketFactory serverSocketFactory;
-    private static SslConfiguration sslConfiguration;
-
-    static {
-        PORT = AvailablePortFinder.getNextAvailable();
-        System.setProperty("SecureSocketAppenderSocketOptionsTest.port", Integer.toString(PORT));
-        try {
-            initServerSocketFactory();
-            tcpSocketTestServer = new TcpSocketTestServer(serverSocketFactory.createServerSocket(PORT));
-            tcpSocketTestServer.start();
-            loggerContextRule = new LoggerContextRule("log4j-ssl-socket-options.xml");
-        } catch (IOException | StoreConfigurationException e) {
-            throw new IllegalStateException(e);
-        }
-
-    }
-
-    @ClassRule
-    public static final LoggerContextRule loggerContextRule;
-
-    @AfterClass
-    public static void afterClass() {
-        if (tcpSocketTestServer != null) {
-            tcpSocketTestServer.shutdown();
-        }
-    }
-
-    public static void initServerSocketFactory() throws StoreConfigurationException {
-        final KeyStoreConfiguration ksc = KeyStoreConfiguration.createKeyStoreConfiguration(
-                TestConstants.KEYSTORE_FILE, // file
-                TestConstants.KEYSTORE_PWD(),  // password
-                null, // passwordEnvironmentVariable
-                null, // passwordFile
-                null, // key store type
-                null); // algorithm
-
-        final TrustStoreConfiguration tsc = TrustStoreConfiguration.createKeyStoreConfiguration(
-                TestConstants.TRUSTSTORE_FILE, // file
-                TestConstants.TRUSTSTORE_PWD(), // password
-                null, // passwordEnvironmentVariable
-                null, // passwordFile
-                null, // key store type
-                null); // algorithm
-        sslConfiguration = SslConfiguration.createSSLConfiguration(null, ksc, tsc);
-        serverSocketFactory = sslConfiguration.getSslServerSocketFactory();
-    }
-
-    @Test
-    public void testSocketOptions() throws IOException {
-        Assert.assertNotNull(loggerContextRule);
-        Assert.assertNotNull(loggerContextRule.getConfiguration());
-        final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
-        Assert.assertNotNull(appender);
-        final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
-        Assert.assertNotNull(manager);
-        final OutputStream outputStream = manager.getOutputStream();
-        Assert.assertFalse(outputStream instanceof NullOutputStream);
-        final SocketOptions socketOptions = manager.getSocketOptions();
-        Assert.assertNotNull(socketOptions);
-        final Socket socket = manager.getSocket();
-        Assert.assertNotNull(socket);
-        // Test config request
-        Assert.assertEquals(false, socketOptions.isKeepAlive());
-        Assert.assertEquals(null, socketOptions.isOobInline());
-        Assert.assertEquals(false, socketOptions.isReuseAddress());
-        Assert.assertEquals(false, socketOptions.isTcpNoDelay());
-        Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(),
-                socketOptions.getActualTrafficClass().intValue());
-        Assert.assertEquals(10000, socketOptions.getReceiveBufferSize().intValue());
-        Assert.assertEquals(8000, socketOptions.getSendBufferSize().intValue());
-        Assert.assertEquals(12345, socketOptions.getSoLinger().intValue());
-        Assert.assertEquals(54321, socketOptions.getSoTimeout().intValue());
-        // Test live socket
-        Assert.assertEquals(false, socket.getKeepAlive());
-        Assert.assertEquals(false, socket.getReuseAddress());
-        Assert.assertEquals(false, socket.getTcpNoDelay());
-        // Assert.assertEquals(10000, socket.getReceiveBufferSize());
-        // This settings changes while we are running, so we cannot assert it.
-        // Assert.assertEquals(8000, socket.getSendBufferSize());
-        Assert.assertEquals(12345, socket.getSoLinger());
-        Assert.assertEquals(54321, socket.getSoTimeout());
-    }
-
-    @Test
-    public void testSocketTrafficClass() throws IOException {
-        Assume.assumeTrue("Run only on Java 7", System.getProperty("java.specification.version").equals("1.7"));
-        Assume.assumeFalse("Do not run on Travis CI", "true".equals(System.getenv("TRAVIS")));
-        final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
-        final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
-        final Socket socket = manager.getSocket();
-        Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(), socket.getTrafficClass());
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java
deleted file mode 100644
index 85b6b17..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import org.apache.logging.log4j.ThreadContext;
-import org.apache.logging.log4j.core.Logger;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
-import org.apache.logging.log4j.core.util.Constants;
-import org.apache.logging.log4j.junit.LoggerContextRule;
-import org.apache.logging.log4j.test.AvailablePortFinder;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-/**
- *
- */
-public class SocketAppenderBufferSizeTest {
-
-    private TcpSocketTestServer tcpServer;
-
-    private LoggerContext loggerContext;
-    private Logger logger;
-
-    @Rule
-    public LoggerContextRule loggerContextRule = new LoggerContextRule("log4j-empty.xml");
-
-    @Before
-    public void setup() throws Exception {
-        tcpServer = new TcpSocketTestServer(AvailablePortFinder.getNextAvailable());
-        tcpServer.start();
-        ThreadContext.clearAll();
-        loggerContext = loggerContextRule.getLoggerContext();
-        logger = loggerContext.getLogger(SocketAppenderBufferSizeTest.class.getName());
-    }
-
-    @After
-    public void teardown() {
-        tcpServer.shutdown();
-        loggerContext = null;
-        logger = null;
-        tcpServer.reset();
-        ThreadContext.clearAll();
-    }
-
-    @Test
-    public void testTcpAppenderDefaultEncoderBufferSize() throws Exception {
-        SocketAppenderTest.testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
-    }
-
-    @Test
-    public void testTcpAppenderLargeEncoderBufferSize() throws Exception {
-        SocketAppenderTest.testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE * 100);
-    }
-
-    @Test
-    public void testTcpAppenderSmallestEncoderBufferSize() throws Exception {
-        SocketAppenderTest.testTcpAppender(tcpServer, logger, 1);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
deleted file mode 100644
index 030fa80..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.Socket;
-
-import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
-import org.apache.logging.log4j.core.net.Rfc1349TrafficClass;
-import org.apache.logging.log4j.core.net.SocketOptions;
-import org.apache.logging.log4j.core.net.TcpSocketManager;
-import org.apache.logging.log4j.core.util.NullOutputStream;
-import org.apache.logging.log4j.junit.LoggerContextRule;
-import org.apache.logging.log4j.test.AvailablePortFinder;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-public class SocketAppenderSocketOptionsTest {
-
-    private static final int PORT;
-    private static TcpSocketTestServer tcpSocketTestServer;
-
-    static {
-        PORT = AvailablePortFinder.getNextAvailable();
-        System.setProperty("SocketAppenderSocketOptionsTest.port", Integer.toString(PORT));
-        try {
-            tcpSocketTestServer = new TcpSocketTestServer(PORT);
-        } catch (final IOException e) {
-            throw new IllegalStateException(e);
-        }
-        tcpSocketTestServer.start();
-        loggerContextRule = new LoggerContextRule("log4j-socket-options.xml");
-    }
-
-    @ClassRule
-    public static final LoggerContextRule loggerContextRule;
-
-    @AfterClass
-    public static void afterClass() {
-        if (tcpSocketTestServer != null) {
-            tcpSocketTestServer.shutdown();
-        }
-    }
-
-    @Test
-    public void testSocketOptions() throws IOException {
-        Assert.assertNotNull(loggerContextRule);
-        Assert.assertNotNull(loggerContextRule.getConfiguration());
-        final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
-        Assert.assertNotNull(appender);
-        final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
-        Assert.assertNotNull(manager);
-        final OutputStream outputStream = manager.getOutputStream();
-        Assert.assertFalse(outputStream instanceof NullOutputStream);
-        final SocketOptions socketOptions = manager.getSocketOptions();
-        Assert.assertNotNull(socketOptions);
-        final Socket socket = manager.getSocket();
-        Assert.assertNotNull(socket);
-        // Test config request
-        Assert.assertEquals(false, socketOptions.isKeepAlive());
-        Assert.assertEquals(false, socketOptions.isOobInline());
-        Assert.assertEquals(false, socketOptions.isReuseAddress());
-        Assert.assertEquals(false, socketOptions.isTcpNoDelay());
-        Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(),
-                socketOptions.getActualTrafficClass().intValue());
-        Assert.assertEquals(10000, socketOptions.getReceiveBufferSize().intValue());
-        Assert.assertEquals(8000, socketOptions.getSendBufferSize().intValue());
-        Assert.assertEquals(12345, socketOptions.getSoLinger().intValue());
-        Assert.assertEquals(54321, socketOptions.getSoTimeout().intValue());
-        // Test live socket
-        Assert.assertEquals(false, socket.getKeepAlive());
-        Assert.assertEquals(false, socket.getOOBInline());
-        Assert.assertEquals(false, socket.getReuseAddress());
-        Assert.assertEquals(false, socket.getTcpNoDelay());
-        // Assert.assertEquals(10000, socket.getReceiveBufferSize());
-        // This settings changes while we are running, so we cannot assert it.
-        // Assert.assertEquals(8000, socket.getSendBufferSize());
-        Assert.assertEquals(12345, socket.getSoLinger());
-        Assert.assertEquals(54321, socket.getSoTimeout());
-    }
-
-    @Test
-    public void testSocketTrafficClass() throws IOException {
-        Assume.assumeTrue("Run only on Java 7", System.getProperty("java.specification.version").equals("1.7"));
-        Assume.assumeFalse("Do not run on Travis CI", "true".equals(System.getenv("TRAVIS")));
-        final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
-        final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
-        final Socket socket = manager.getSocket();
-        Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(), socket.getTrafficClass());
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
deleted file mode 100644
index 8aee640..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import com.fasterxml.jackson.databind.MappingIterator;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.LoggingException;
-import org.apache.logging.log4j.ThreadContext;
-import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.Logger;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.impl.Log4jLogEvent;
-import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
-import org.apache.logging.log4j.core.layout.JsonLayout;
-import org.apache.logging.log4j.core.net.Protocol;
-import org.apache.logging.log4j.core.util.Constants;
-import org.apache.logging.log4j.core.util.Throwables;
-import org.apache.logging.log4j.test.AvailablePortFinder;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-
-/**
- *
- */
-public class SocketAppenderTest {
-
-    private static final int PORT = AvailablePortFinder.getNextAvailable();
-    private static final int DYN_PORT = AvailablePortFinder.getNextAvailable();
-    private static final int ERROR_PORT = AvailablePortFinder.getNextAvailable();
-
-    private static TcpSocketTestServer tcpServer;
-    private static UdpSocketTestServer udpServer;
-
-    private final LoggerContext context = LoggerContext.getContext();
-    private final Logger logger = context.getLogger(SocketAppenderTest.class.getName());
-
-    @BeforeClass
-    public static void setupClass() throws Exception {
-        tcpServer = new TcpSocketTestServer(PORT);
-        tcpServer.start();
-        udpServer = new UdpSocketTestServer();
-        udpServer.start();
-        LoggerContext.getContext().reconfigure();
-        ThreadContext.clearAll();
-    }
-
-    @AfterClass
-    public static void cleanupClass() {
-        tcpServer.shutdown();
-        udpServer.shutdown();
-        ThreadContext.clearAll();
-    }
-
-    @After
-    public void teardown() {
-        ThreadContext.clearAll();
-        removeAndStopAppenders();
-        reset();
-    }
-
-    void removeAndStopAppenders() {
-        final Map<String, Appender> map = logger.getAppenders();
-        for (final Map.Entry<String, Appender> entry : map.entrySet()) {
-            final Appender appender = entry.getValue();
-            logger.removeAppender(appender);
-            appender.stop();
-        }
-    }
-
-    static void reset() {
-        tcpServer.reset();
-        udpServer.reset();
-    }
-
-    @Test
-    public void testTcpAppender1() throws Exception {
-        testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
-    }
-
-    @Test
-    @Ignore("WIP Bug when this method runs after testTcpAppender1()")
-    public void testTcpAppender2() throws Exception {
-        testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
-    }
-
-    static void testTcpAppender(final TcpSocketTestServer tcpTestServer, final Logger logger, final int bufferSize)
-            throws Exception {
-        // @formatter:off
-        final SocketAppender appender = SocketAppender.newBuilder()
-                .withHost("localhost")
-                .withPort(tcpTestServer.getLocalPort())
-                .withReconnectDelayMillis(-1)
-                .withName("test")
-                .withImmediateFail(false)
-                .withBufferSize(bufferSize)
-                .withLayout(JsonLayout.newBuilder().setProperties(true).build())
-                .build();
-        // @formatter:on
-        appender.start();
-        Assert.assertEquals(bufferSize, appender.getManager().getByteBuffer().capacity());
-
-        // set appender on root and set level to debug
-        logger.addAppender(appender);
-        logger.setAdditive(false);
-        logger.setLevel(Level.DEBUG);
-        final String tcKey = "UUID";
-        final String expectedUuidStr = UUID.randomUUID().toString();
-        ThreadContext.put(tcKey, expectedUuidStr);
-        ThreadContext.push(expectedUuidStr);
-        final String expectedExMsg = "This is a test";
-        try {
-            logger.debug("This is a test message");
-            final Throwable child = new LoggingException(expectedExMsg);
-            logger.error("Throwing an exception", child);
-            logger.debug("This is another test message");
-        } finally {
-            ThreadContext.remove(tcKey);
-            ThreadContext.pop();
-        }
-        Thread.sleep(250);
-        LogEvent event = tcpTestServer.getQueue().poll(3, TimeUnit.SECONDS);
-        assertNotNull("No event retrieved", event);
-        assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("This is a test message"));
-        assertTrue("Message not delivered via TCP", tcpTestServer.getCount() > 0);
-        assertEquals(expectedUuidStr, event.getContextData().getValue(tcKey));
-        event = tcpTestServer.getQueue().poll(3, TimeUnit.SECONDS);
-        assertNotNull("No event retrieved", event);
-        assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("Throwing an exception"));
-        assertTrue("Message not delivered via TCP", tcpTestServer.getCount() > 1);
-        assertEquals(expectedUuidStr, event.getContextStack().pop());
-        assertNotNull(event.getThrownProxy());
-        assertEquals(expectedExMsg, event.getThrownProxy().getMessage());
-    }
-
-    @Test
-    public void testDefaultProtocol() throws Exception {
-        // @formatter:off
-        final SocketAppender appender = SocketAppender.newBuilder()
-                .withPort(tcpServer.getLocalPort())
-                .withReconnectDelayMillis(-1)
-                .withName("test")
-                .withImmediateFail(false)
-                .withLayout(JsonLayout.newBuilder().setProperties(true).build())
-                .build();
-        // @formatter:on
-        assertNotNull(appender);
-        appender.stop();
-    }
-
-    @Test
-    public void testUdpAppender() throws Exception {
-        try {
-            udpServer.latch.await();
-        } catch (final InterruptedException ex) {
-            ex.printStackTrace();
-        }
-
-        // @formatter:off
-        final SocketAppender appender = SocketAppender.newBuilder()
-                .withProtocol(Protocol.UDP)
-                .withPort(tcpServer.getLocalPort())
-                .withReconnectDelayMillis(-1)
-                .withName("test")
-                .withImmediateFail(false)
-                .withLayout(JsonLayout.newBuilder().setProperties(true).build())
-                .build();
-        // @formatter:on
-        appender.start();
-
-        // set appender on root and set level to debug
-        logger.addAppender(appender);
-        logger.setAdditive(false);
-        logger.setLevel(Level.DEBUG);
-        logger.debug("This is a udp message");
-        final LogEvent event = udpServer.getQueue().poll(3, TimeUnit.SECONDS);
-        assertNotNull("No event retrieved", event);
-        assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("This is a udp message"));
-        assertTrue("Message not delivered via UDP", udpServer.getCount() > 0);
-    }
-
-    @Test
-    public void testTcpAppenderDeadlock() throws Exception {
-
-        // @formatter:off
-        final SocketAppender appender = SocketAppender.newBuilder()
-                .withHost("localhost")
-                .withPort(DYN_PORT)
-                .withReconnectDelayMillis(100)
-                .withName("test")
-                .withImmediateFail(false)
-                .withLayout(JsonLayout.newBuilder().setProperties(true).build())
-                .build();
-        // @formatter:on
-        appender.start();
-        // set appender on root and set level to debug
-        logger.addAppender(appender);
-        logger.setAdditive(false);
-        logger.setLevel(Level.DEBUG);
-
-        final TcpSocketTestServer tcpSocketServer = new TcpSocketTestServer(DYN_PORT);
-        try {
-            tcpSocketServer.start();
-
-            logger.debug("This message is written because a deadlock never.");
-
-            final LogEvent event = tcpSocketServer.getQueue().poll(3, TimeUnit.SECONDS);
-            assertNotNull("No event retrieved", event);
-        } finally {
-            tcpSocketServer.shutdown();
-        }
-    }
-
-    @Test
-    public void testTcpAppenderNoWait() throws Exception {
-        // @formatter:off
-        final SocketAppender appender = SocketAppender.newBuilder()
-                .withHost("localhost")
-                .withPort(ERROR_PORT)
-                .withReconnectDelayMillis(100)
-                .withName("test")
-                .withImmediateFail(false)
-                .withIgnoreExceptions(false)
-                .withLayout(JsonLayout.newBuilder().setProperties(true).build())
-                .build();
-        // @formatter:on
-        appender.start();
-        // set appender on root and set level to debug
-        logger.addAppender(appender);
-        logger.setAdditive(false);
-        logger.setLevel(Level.DEBUG);
-
-        try {
-            logger.debug("This message is written because a deadlock never.");
-            fail("No Exception was thrown");
-        } catch (final Exception ex) {
-            // TODO: move exception to @Test(expect = Exception.class)
-            // Failure is expected.
-            // ex.printStackTrace();
-        }
-    }
-
-    public static class UdpSocketTestServer extends Thread {
-
-        private final DatagramSocket sock;
-        private boolean shutdown = false;
-        private Thread thread;
-        private final CountDownLatch latch = new CountDownLatch(1);
-        private volatile int count = 0;
-        private final BlockingQueue<LogEvent> queue;
-        private final ObjectMapper objectMapper = new Log4jJsonObjectMapper();
-
-        public UdpSocketTestServer() throws IOException {
-            this.sock = new DatagramSocket(PORT);
-            this.queue = new ArrayBlockingQueue<>(10);
-        }
-
-        public void reset() {
-            queue.clear();
-            count = 0;
-        }
-
-        public void shutdown() {
-            this.shutdown = true;
-            thread.interrupt();
-            try {
-                thread.join(100);
-            } catch (InterruptedException ie) {
-                System.out.println("Unable to stop server");
-            }
-        }
-
-        @Override
-        public void run() {
-            this.thread = Thread.currentThread();
-            final byte[] bytes = new byte[4096];
-            final DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
-            try {
-                while (!shutdown) {
-                    latch.countDown();
-                    sock.receive(packet);
-                    ++count;
-                    final LogEvent event = objectMapper.readValue(packet.getData(), Log4jLogEvent.class);
-                    queue.add(event);
-                }
-            } catch (final Throwable e) {
-                e.printStackTrace();
-                if (!shutdown) {
-                    Throwables.rethrow(e);
-                }
-            }
-        }
-
-        public int getCount() {
-            return count;
-        }
-
-        public BlockingQueue<LogEvent> getQueue() {
-            return queue;
-        }
-    }
-
-    public static class TcpSocketTestServer extends Thread {
-
-        private final ServerSocket serverSocket;
-        private volatile boolean shutdown = false;
-        private volatile int count = 0;
-        private final BlockingQueue<LogEvent> queue;
-        private final ObjectMapper objectMapper = new Log4jJsonObjectMapper();
-
-        @SuppressWarnings("resource")
-        public TcpSocketTestServer(final int port) throws IOException {
-            this(new ServerSocket(port));
-        }
-
-        public TcpSocketTestServer(final ServerSocket serverSocket) {
-            this.serverSocket = serverSocket;
-            this.queue = new ArrayBlockingQueue<>(10);
-        }
-
-        public int getLocalPort() {
-            return serverSocket.getLocalPort();
-        }
-
-        public void reset() {
-            queue.clear();
-            count = 0;
-        }
-
-        public void shutdown() {
-            this.shutdown = true;
-            interrupt();
-            try {
-                this.join(100);
-            } catch (InterruptedException ie) {
-                System.out.println("Unable to stop server");
-            }
-        }
-
-        @Override
-        public void run() {
-            try {
-                try (final Socket socket = serverSocket.accept()) {
-                    if (socket != null) {
-                        final InputStream is = socket.getInputStream();
-                        while (!shutdown) {
-                            final MappingIterator<LogEvent> mappingIterator = objectMapper.readerFor(Log4jLogEvent.class).readValues(is);
-                            while (mappingIterator.hasNextValue()) {
-                                queue.add(mappingIterator.nextValue());
-                                ++count;
-                            }
-                        }
-                    }
-                }
-            } catch (final EOFException eof) {
-                // Socket is closed.
-            } catch (final Exception e) {
-                if (!shutdown) {
-                    Throwables.rethrow(e);
-                }
-            }
-        }
-
-        public BlockingQueue<LogEvent> getQueue() {
-            return queue;
-        }
-
-        public int getCount() {
-            return count;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java
deleted file mode 100644
index c59ad9d..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.CoreLoggerContexts;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import static org.junit.Assert.*;
-
-/**
- * Tests a "compact" XML file, no extra spaces or end of lines.
- */
-@Category(Layouts.Xml.class)
-public class XmlCompactFileAppenderTest {
-
-    @BeforeClass
-    public static void beforeClass() {
-        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
-                "XmlCompactFileAppenderTest.xml");
-    }
-
-    @Test
-    public void testFlushAtEndOfBatch() throws Exception {
-        final File file = new File("target", "XmlCompactFileAppenderTest.log");
-        file.delete();
-        final Logger log = LogManager.getLogger("com.foo.Bar");
-        final String logMsg = "Message flushed with immediate flush=false";
-        log.info(logMsg);
-        CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread
-
-        String line1;
-        try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
-            line1 = reader.readLine();
-        } finally {
-            file.delete();
-        }
-        assertNotNull("line1", line1);
-        final String msg1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
-        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg1 + ']', line1.contains(msg1));
-
-        final String msg2 = "<Events xmlns=\"http://logging.apache.org/log4j/2.0/events\">";
-        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg2 + ']', line1.contains(msg2));
-
-        final String msg3 = "<Event ";
-        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg3 + ']', line1.contains(msg3));
-
-        final String msg4 = logMsg;
-        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg4 + ']', line1.contains(msg4));
-
-        final String location = "testFlushAtEndOfBatch";
-        assertTrue("no location", !line1.contains(location));
-
-        assertTrue(line1.indexOf('\r') == -1);
-        assertTrue(line1.indexOf('\n') == -1);
-    }
-
-}


[02/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/JsonConstants.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/JsonConstants.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/JsonConstants.java
new file mode 100644
index 0000000..1db6f52
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/JsonConstants.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+/**
+ * Keeps constants separate from any class that may depend on third party jars.
+ */
+public final class JsonConstants {
+    public static final String ELT_CAUSE = "cause";
+    public static final String ELT_EVENT = "event";
+    public static final String ELT_CONTEXT_MAP = "contextMap";
+    public static final String ELT_CONTEXT_STACK = "contextStack";
+    public static final String ELT_MARKER = "marker";
+    public static final String ELT_PARENTS = "parents";
+    public static final String ELT_SOURCE = "source";
+    public static final String ELT_SUPPRESSED = "suppressed";
+    public static final String ELT_THROWN = "thrown";
+    public static final String ELT_MESSAGE = "message";
+    public static final String ELT_EXTENDED_STACK_TRACE = "extendedStackTrace";
+    public static final String ELT_NANO_TIME = "nanoTime";
+    public static final String ELT_INSTANT = "instant";
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LevelMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LevelMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LevelMixIn.java
new file mode 100644
index 0000000..c11d22e
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LevelMixIn.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * Jackson mix-in for {@link Level}.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ * @see Marker
+ */
+@JsonIgnoreProperties({ "name", "declaringClass", "standardLevel" })
+public abstract class LevelMixIn {
+
+    @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
+    public static Level getLevel(final String name) {
+        return null;
+    }
+
+    @JsonValue
+    public abstract String name();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntryDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntryDeserializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntryDeserializer.java
new file mode 100644
index 0000000..4a1199d
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntryDeserializer.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class ListOfMapEntryDeserializer extends StdDeserializer<Map<String, String>> {
+
+    private static final long serialVersionUID = 1L;
+
+    ListOfMapEntryDeserializer() {
+        super(Map.class);
+    }
+
+    @Override
+    public Map<String, String> deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
+            JsonProcessingException {
+        final List<MapEntry> list = jp.readValueAs(new TypeReference<List<MapEntry>>() {
+            // empty
+        });
+        final HashMap<String, String> map = new HashMap<>(list.size());
+        for (final MapEntry mapEntry : list) {
+            map.put(mapEntry.getKey(), mapEntry.getValue());
+        }
+        return map;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntrySerializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntrySerializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntrySerializer.java
new file mode 100644
index 0000000..48a9911
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ListOfMapEntrySerializer.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class ListOfMapEntrySerializer extends StdSerializer<Map<String, String>> {
+
+    private static final long serialVersionUID = 1L;
+
+    protected ListOfMapEntrySerializer() {
+        super(Map.class, false);
+    }
+
+    protected MapEntry[] createMapEntryArray(final Set<Entry<String, String>> entrySet) {
+        return new MapEntry[entrySet.size()];
+    }
+
+    @Override
+    public void serialize(final Map<String, String> map, final JsonGenerator jgen, final SerializerProvider provider)
+            throws IOException, JsonGenerationException {
+        final Set<Entry<String, String>> entrySet = map.entrySet();
+        final MapEntry[] pairs = createMapEntryArray(entrySet);
+        int i = 0;
+        for (final Entry<String, String> entry : entrySet) {
+            pairs[i++] = new MapEntry(entry.getKey(), entry.getValue());
+        }
+        jgen.writeObject(pairs);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/Log4jStackTraceElementDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/Log4jStackTraceElementDeserializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/Log4jStackTraceElementDeserializer.java
new file mode 100644
index 0000000..7d03805
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/Log4jStackTraceElementDeserializer.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
+
+/**
+ * Copy and edit the Jackson (Apache License 2.0) class to use Log4j attribute names. Does not work as of Jackson 2.3.2.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public final class Log4jStackTraceElementDeserializer extends StdScalarDeserializer<StackTraceElement> {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructs a new initialized instance.
+     */
+    public Log4jStackTraceElementDeserializer() {
+        super(StackTraceElement.class);
+    }
+
+    @Override
+    public StackTraceElement deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
+            JsonProcessingException {
+        JsonToken t = jp.getCurrentToken();
+        // Must get an Object
+        if (t == JsonToken.START_OBJECT) {
+            String className = null, methodName = null, fileName = null;
+            int lineNumber = -1;
+
+            while ((t = jp.nextValue()) != JsonToken.END_OBJECT) {
+                final String propName = jp.getCurrentName();
+                if ("class".equals(propName)) {
+                    className = jp.getText();
+                } else if ("file".equals(propName)) {
+                    fileName = jp.getText();
+                } else if ("line".equals(propName)) {
+                    if (t.isNumeric()) {
+                        lineNumber = jp.getIntValue();
+                    } else {
+                        // An XML number always comes in a string since there is no syntax help as with JSON.
+                        try {
+                            lineNumber = Integer.parseInt(jp.getText().trim());
+                        } catch (final NumberFormatException e) {
+                            throw JsonMappingException.from(jp, "Non-numeric token (" + t + ") for property 'line'", e);
+                        }
+                    }
+                } else if ("method".equals(propName)) {
+                    methodName = jp.getText();
+                } else if ("nativeMethod".equals(propName)) {
+                    // no setter, not passed via constructor: ignore
+                } else {
+                    this.handleUnknownProperty(jp, ctxt, this._valueClass, propName);
+                }
+            }
+            return new StackTraceElement(className, methodName, fileName, lineNumber);
+        }
+        throw ctxt.mappingException(this._valueClass, t);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventJsonMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventJsonMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventJsonMixIn.java
new file mode 100644
index 0000000..e9607bd
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventJsonMixIn.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.util.Map;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext.ContextStack;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.core.time.Instant;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+
+import com.fasterxml.jackson.annotation.JsonFilter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonRootName;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+@JsonRootName(JsonConstants.ELT_EVENT)
+@JsonFilter("org.apache.logging.log4j.core.impl.Log4jLogEvent")
+@JsonPropertyOrder({
+    // @formatter:off
+    "timeMillis",
+    JsonConstants.ELT_INSTANT,
+    "threadName",
+    "level",
+    "loggerName",
+    "marker",
+    "message",
+    "thrown",
+    JsonConstants.ELT_CONTEXT_MAP,
+    JsonConstants.ELT_CONTEXT_STACK,
+    "loggerFQCN",
+    "Source",
+    "endOfBatch" })
+    // @formatter:on
+/**
+ * As of Jackson 2.9.4, if we extend AbstractLogEventMixIn, then the {@link ObjectMessage} serializer
+ * {@code ObjectMessageSerializer} does not get invoked. Either a bug in Jackson or in our set up code.
+ */
+public abstract class LogEventJsonMixIn /* extends AbstractLogEventMixIn */ implements LogEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
+    @JsonSerialize(using = ContextDataSerializer.class)
+    @JsonDeserialize(using = ContextDataDeserializer.class)
+    @Override
+    public abstract ReadOnlyStringMap getContextData();
+
+    @Override
+    @JsonIgnore
+    public abstract Map<String, String> getContextMap();
+
+    @JsonProperty(JsonConstants.ELT_CONTEXT_STACK)
+    @Override
+    public abstract ContextStack getContextStack();
+
+    @JsonProperty(JsonConstants.ELT_INSTANT)
+    @Override
+    public abstract Instant getInstant();
+
+    @JsonProperty()
+    @Override
+    public abstract Level getLevel();
+
+    @JsonProperty()
+    @Override
+    public abstract String getLoggerFqcn();
+
+    @JsonProperty()
+    @Override
+    public abstract String getLoggerName();
+
+    @JsonProperty(JsonConstants.ELT_MARKER)
+    @Override
+    public abstract Marker getMarker();
+
+    @JsonProperty(JsonConstants.ELT_MESSAGE)
+    @JsonDeserialize(using = SimpleMessageDeserializer.class)
+    @Override
+    public abstract Message getMessage();
+
+    @JsonProperty(JsonConstants.ELT_SOURCE)
+    @JsonDeserialize(using = Log4jStackTraceElementDeserializer.class)
+    @Override
+    public abstract StackTraceElement getSource();
+
+    @Override
+    @JsonProperty("threadId")
+    public abstract long getThreadId();
+
+    @Override
+    @JsonProperty("thread")
+    public abstract String getThreadName();
+
+    @Override
+    @JsonProperty("threadPriority")
+    public abstract int getThreadPriority();
+
+    @JsonIgnore
+    @Override
+    public abstract Throwable getThrown();
+
+    @JsonProperty(JsonConstants.ELT_THROWN)
+    @Override
+    public abstract ThrowableProxy getThrownProxy();
+
+    @JsonIgnore // ignore from 2.11
+    @Override
+    public abstract long getTimeMillis();
+
+    @JsonProperty()
+    @Override
+    public abstract boolean isEndOfBatch();
+
+    @JsonIgnore
+    @Override
+    public abstract boolean isIncludeLocation();
+
+    @Override
+    public abstract void setEndOfBatch(boolean endOfBatch);
+
+    @Override
+    public abstract void setIncludeLocation(boolean locationRequired);
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventWithContextListMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventWithContextListMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventWithContextListMixIn.java
new file mode 100644
index 0000000..cd0639b
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/LogEventWithContextListMixIn.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.util.Map;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext.ContextStack;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.core.time.Instant;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+
+import com.fasterxml.jackson.annotation.JsonFilter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonRootName;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+@JsonRootName(XmlConstants.ELT_EVENT)
+@JsonFilter("org.apache.logging.log4j.core.impl.Log4jLogEvent")
+@JsonPropertyOrder({ "timeMillis", XmlConstants.ELT_INSTANT, "threadName", "level", "loggerName", "marker", "message", "thrown", XmlConstants.ELT_CONTEXT_MAP,
+        JsonConstants.ELT_CONTEXT_STACK, "loggerFQCN", "Source", "endOfBatch" })
+abstract class LogEventWithContextListMixIn implements LogEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
+    @JsonSerialize(using = ContextDataAsEntryListSerializer.class)
+    @JsonDeserialize(using = ContextDataAsEntryListDeserializer.class)
+//    @JsonIgnore
+    @Override
+    public abstract ReadOnlyStringMap getContextData();
+
+    @Override
+    @JsonIgnore
+    public abstract Map<String, String> getContextMap();
+
+    @JsonProperty(JsonConstants.ELT_CONTEXT_STACK)
+    @Override
+    public abstract ContextStack getContextStack();
+
+    @JsonProperty(JsonConstants.ELT_INSTANT)
+    @Override
+    public abstract Instant getInstant();
+
+    @JsonProperty()
+    @Override
+    public abstract Level getLevel();
+
+    @JsonProperty()
+    @Override
+    public abstract String getLoggerFqcn();
+
+    @JsonProperty()
+    @Override
+    public abstract String getLoggerName();
+
+    @JsonProperty(JsonConstants.ELT_MARKER)
+    @Override
+    public abstract Marker getMarker();
+
+    @JsonProperty(JsonConstants.ELT_MESSAGE)
+    @JsonSerialize(using = MessageSerializer.class)
+    @JsonDeserialize(using = SimpleMessageDeserializer.class)
+    @Override
+    public abstract Message getMessage();
+
+    @JsonProperty(JsonConstants.ELT_SOURCE)
+    @JsonDeserialize(using = Log4jStackTraceElementDeserializer.class)
+    @Override
+    public abstract StackTraceElement getSource();
+
+    @Override
+    @JsonProperty("threadId")
+    public abstract long getThreadId();
+
+    @Override
+    @JsonProperty("thread")
+    public abstract String getThreadName();
+
+    @Override
+    @JsonProperty("threadPriority")
+    public abstract int getThreadPriority();
+
+    @JsonIgnore
+    @Override
+    public abstract Throwable getThrown();
+
+    @JsonProperty(JsonConstants.ELT_THROWN)
+    @Override
+    public abstract ThrowableProxy getThrownProxy();
+
+    @JsonIgnore // ignore from 2.11
+    @Override
+    public abstract long getTimeMillis();
+
+    @JsonProperty()
+    @Override
+    public abstract boolean isEndOfBatch();
+
+    @JsonIgnore
+    @Override
+    public abstract boolean isIncludeLocation();
+
+    @Override
+    public abstract void setEndOfBatch(boolean endOfBatch);
+
+    @Override
+    public abstract void setIncludeLocation(boolean locationRequired);
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MapEntry.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MapEntry.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MapEntry.java
new file mode 100644
index 0000000..fc02180
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MapEntry.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson;
+
+import org.apache.logging.log4j.util.Strings;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ * <p>
+ * Used to represent map entries in a generic fashion because the default Jackson behavior uses the key as the element
+ * tag. Using the key as an element/property name would mean that you cannot have a generic JSON/XML schema for all log
+ * event.
+ * </p>
+ */
+@JsonPropertyOrder({ "key", "value" })
+public class MapEntry {
+
+    @JsonProperty
+    private String key;
+
+    @JsonProperty
+    private String value;
+
+    @JsonCreator
+    public MapEntry(@JsonProperty("key") final String key, @JsonProperty("value") final String value) {
+        this.setKey(key);
+        this.setValue(value);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof MapEntry)) {
+            return false;
+        }
+        final MapEntry other = (MapEntry) obj;
+        if (this.getKey() == null) {
+            if (other.getKey() != null) {
+                return false;
+            }
+        } else if (!this.getKey().equals(other.getKey())) {
+            return false;
+        }
+        if (this.getValue() == null) {
+            if (other.getValue() != null) {
+                return false;
+            }
+        } else if (!this.getValue().equals(other.getValue())) {
+            return false;
+        }
+        return true;
+    }
+
+    public String getKey() {
+        return this.key;
+    }
+
+    public String getValue() {
+        return this.value;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((this.getKey() == null) ? 0 : this.getKey().hashCode());
+        result = prime * result + ((this.getValue() == null) ? 0 : this.getValue().hashCode());
+        return result;
+    }
+
+    public void setKey(final String key) {
+        this.key = key;
+    }
+
+    public void setValue(final String value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return Strings.EMPTY + this.getKey() + "=" + this.getValue();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MarkerMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MarkerMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MarkerMixIn.java
new file mode 100644
index 0000000..45bbcc3
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MarkerMixIn.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import org.apache.logging.log4j.Marker;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+/**
+ * Jackson mix-in for {@link Marker}.
+ * <p>
+ * If we want to deal with more than one {@link Marker} implementation then recode these annotations to include metadata.
+ * </p>
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ * <p>
+ * Example XML:
+ * </p>
+ * <pre>
+&lt;Marker name=&quot;Marker1&quot;&gt;
+    &lt;Parents&gt;
+        &lt;Marker name=&quot;ParentMarker1&quot;&gt;
+            &lt;Parents&gt;
+                &lt;Marker name=&quot;GrandMotherMarker&quot;/&gt;
+                &lt;Marker name=&quot;GrandFatherMarker&quot;/&gt;
+            &lt;/Parents&gt;
+        &lt;/Marker&gt;
+        &lt;Marker name=&quot;ParentMarker2&quot;/&gt;
+    &lt;/Parents&gt;
+&lt;/Marker&gt;
+ * </pre>
+ *
+ * @see Marker
+ */
+// Alternate for multiple Marker implementation.
+// @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+@JsonDeserialize(as = org.apache.logging.log4j.MarkerManager.Log4jMarker.class)
+public abstract class MarkerMixIn implements Marker {
+    private static final long serialVersionUID = 1L;
+
+    @JsonCreator
+    public MarkerMixIn(@JsonProperty("name") final String name) {
+        // empty
+    }
+
+    @Override
+    @JsonProperty("name")
+    public abstract String getName();
+
+    @Override
+    @JsonProperty(JsonConstants.ELT_PARENTS)
+    public abstract Marker[] getParents();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MessageSerializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MessageSerializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MessageSerializer.java
new file mode 100644
index 0000000..faff2da
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MessageSerializer.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.message.Message;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public final class MessageSerializer extends StdScalarSerializer<Message> {
+
+    private static final long serialVersionUID = 1L;
+
+    public MessageSerializer() {
+        super(Message.class);
+    }
+
+    @Override
+    public void serialize(final Message value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException,
+            JsonGenerationException {
+        jgen.writeString(value.getFormattedMessage());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MutableThreadContextStackDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MutableThreadContextStackDeserializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MutableThreadContextStackDeserializer.java
new file mode 100644
index 0000000..b98edb5
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/MutableThreadContextStackDeserializer.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.logging.log4j.spi.MutableThreadContextStack;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+final class MutableThreadContextStackDeserializer extends StdDeserializer<MutableThreadContextStack> {
+
+    private static final long serialVersionUID = 1L;
+
+    MutableThreadContextStackDeserializer() {
+        super(MutableThreadContextStack.class);
+    }
+
+    @Override
+    public MutableThreadContextStack deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
+            JsonProcessingException {
+        final List<String> list = jp.readValueAs(new TypeReference<List<String>>() {
+            // empty
+        });
+        return new MutableThreadContextStack(list);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ObjectMessageSerializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ObjectMessageSerializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ObjectMessageSerializer.java
new file mode 100644
index 0000000..3cb9af2
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ObjectMessageSerializer.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.message.ObjectMessage;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+final class ObjectMessageSerializer extends StdScalarSerializer<ObjectMessage> {
+
+    private static final long serialVersionUID = 1L;
+
+    ObjectMessageSerializer() {
+        super(ObjectMessage.class);
+    }
+
+    @Override
+    public void serialize(final ObjectMessage value, final JsonGenerator jsonGenerator,
+            final SerializerProvider serializerProvider) throws IOException, JsonGenerationException {
+        jsonGenerator.writeObject(value.getParameter());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SetupContextInitializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SetupContextInitializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SetupContextInitializer.java
new file mode 100644
index 0000000..3d73d93
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SetupContextInitializer.java
@@ -0,0 +1,38 @@
+package org.apache.logging.log4j.jackson;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.core.time.Instant;
+
+import com.fasterxml.jackson.databind.Module.SetupContext;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+/**
+ * Used to set up {@link SetupContext} from different {@link SimpleModule}s.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class SetupContextInitializer {
+
+    public void setupModule(final SetupContext context, final boolean includeStacktrace,
+            final boolean stacktraceAsString) {
+        // JRE classes: we cannot edit those with Jackson annotations
+        context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class);
+        // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not
+        // depend on Jackson.
+        context.setMixInAnnotations(Marker.class, MarkerMixIn.class);
+        context.setMixInAnnotations(Level.class, LevelMixIn.class);
+        context.setMixInAnnotations(Instant.class, InstantMixIn.class);
+        context.setMixInAnnotations(LogEvent.class, LogEventWithContextListMixIn.class);
+        // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
+        context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
+        context.setMixInAnnotations(ThrowableProxy.class, includeStacktrace
+                ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringMixIn.class : ThrowableProxyMixIn.class)
+                : ThrowableProxyWithoutStacktraceMixIn.class);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleMessageDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleMessageDeserializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleMessageDeserializer.java
new file mode 100644
index 0000000..2ab948c
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleMessageDeserializer.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.message.SimpleMessage;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public final class SimpleMessageDeserializer extends StdScalarDeserializer<SimpleMessage> {
+
+    private static final long serialVersionUID = 1L;
+
+    SimpleMessageDeserializer() {
+        super(SimpleMessage.class);
+    }
+
+    @Override
+    public SimpleMessage deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext)
+            throws IOException, JsonProcessingException {
+        return new SimpleMessage(jsonParser.getValueAsString());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleModuleInitializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleModuleInitializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleModuleInitializer.java
new file mode 100644
index 0000000..edae1bc
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/SimpleModuleInitializer.java
@@ -0,0 +1,26 @@
+package org.apache.logging.log4j.jackson;
+
+import org.apache.logging.log4j.ThreadContext.ContextStack;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.ObjectMessage;
+
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+/**
+ * Used to set up {@link SimpleModule} from different {@link SimpleModule} subclasses.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class SimpleModuleInitializer {
+    public void initialize(final SimpleModule simpleModule, final boolean objectMessageAsJsonObject) {
+        // Workaround because mix-ins do not work for classes that already have a built-in deserializer.
+        // See Jackson issue 429.
+        simpleModule.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
+        simpleModule.addDeserializer(ContextStack.class, new MutableThreadContextStackDeserializer());
+        if (objectMessageAsJsonObject) {
+            simpleModule.addSerializer(ObjectMessage.class, new ObjectMessageSerializer());
+        }
+        simpleModule.addSerializer(Message.class, new MessageSerializer());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementConstants.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementConstants.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementConstants.java
new file mode 100644
index 0000000..0f0f025
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementConstants.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson;
+
+/**
+ * Defines constants use for naming stack trace elements.
+ */
+public class StackTraceElementConstants {
+
+    public static final String ATTR_CLASS = "class";
+    public static final String ATTR_FILE = "file";
+    public static final String ATTR_LINE = "line";
+    public static final String ATTR_METHOD = "method";
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementMixIn.java
new file mode 100644
index 0000000..b3bff92
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/StackTraceElementMixIn.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Jackson mix-in for {@link StackTraceElement}.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ *
+ * @see StackTraceElement
+ */
+@JsonIgnoreProperties("nativeMethod")
+public abstract class StackTraceElementMixIn {
+
+    @JsonCreator
+    protected StackTraceElementMixIn(
+    // @formatter:off
+            @JsonProperty(StackTraceElementConstants.ATTR_CLASS) final String declaringClass,
+            @JsonProperty(StackTraceElementConstants.ATTR_METHOD) final String methodName,
+            @JsonProperty(StackTraceElementConstants.ATTR_FILE) final String fileName,
+            @JsonProperty(StackTraceElementConstants.ATTR_LINE) final int lineNumber)
+    // @formatter:on
+    {
+        // empty
+    }
+
+    @JsonProperty(StackTraceElementConstants.ATTR_CLASS)
+    protected abstract String getClassName();
+
+    @JsonProperty(StackTraceElementConstants.ATTR_FILE)
+    protected abstract String getFileName();
+
+    @JsonProperty(StackTraceElementConstants.ATTR_LINE)
+    protected abstract int getLineNumber();
+
+    @JsonProperty(StackTraceElementConstants.ATTR_METHOD)
+    protected abstract String getMethodName();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyMixIn.java
new file mode 100644
index 0000000..7116c80
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyMixIn.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson;
+
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Mix-in for {@link ThrowableProxy}.
+ */
+public abstract class ThrowableProxyMixIn {
+
+    @JsonProperty(JsonConstants.ELT_CAUSE)
+    private ThrowableProxyMixIn causeProxy;
+
+    @JsonProperty
+    private int commonElementCount;
+
+    @JsonProperty(JsonConstants.ELT_EXTENDED_STACK_TRACE)
+    private ExtendedStackTraceElement[] extendedStackTrace;
+
+    @JsonProperty
+    private String localizedMessage;
+
+    @JsonProperty
+    private String message;
+
+    @JsonProperty
+    private String name;
+
+    @JsonIgnore
+    private transient Throwable throwable;
+
+    @JsonIgnore
+    public abstract String getCauseStackTraceAsString();
+
+    @JsonIgnore
+    public abstract String getExtendedStackTraceAsString();
+
+    @JsonIgnore
+    public abstract StackTraceElement[] getStackTrace();
+
+    @JsonProperty(JsonConstants.ELT_SUPPRESSED)
+    public abstract ThrowableProxy[] getSuppressedProxies();
+
+    @JsonIgnore
+    public abstract String getSuppressedStackTrace();
+
+    @JsonIgnore
+    public abstract Throwable getThrowable();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java
new file mode 100644
index 0000000..e73a108
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson;
+
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Mix-in for {@link org.apache.logging.log4j.core.impl.ThrowableProxy}.
+ */
+public abstract class ThrowableProxyWithStacktraceAsStringMixIn {
+
+    @JsonProperty(JsonConstants.ELT_CAUSE)
+    private ThrowableProxyWithStacktraceAsStringMixIn causeProxy;
+
+    @JsonProperty
+    private int commonElementCount;
+
+    @JsonIgnore
+    private ExtendedStackTraceElement[] extendedStackTrace;
+
+    @JsonProperty
+    private String localizedMessage;
+
+    @JsonProperty
+    private String message;
+
+    @JsonProperty
+    private String name;
+
+    @JsonIgnore
+    private transient Throwable throwable;
+
+    @JsonIgnore
+    public abstract String getCauseStackTraceAsString();
+
+    @JsonProperty(JsonConstants.ELT_EXTENDED_STACK_TRACE)
+    public abstract String getExtendedStackTraceAsString();
+
+    @JsonIgnore
+    public abstract StackTraceElement[] getStackTrace();
+
+    @JsonProperty(JsonConstants.ELT_SUPPRESSED)
+    public abstract ThrowableProxy[] getSuppressedProxies();
+
+    @JsonIgnore
+    public abstract String getSuppressedStackTrace();
+
+    @JsonIgnore
+    public abstract Throwable getThrowable();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithoutStacktraceMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithoutStacktraceMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithoutStacktraceMixIn.java
new file mode 100644
index 0000000..b80c89c
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ThrowableProxyWithoutStacktraceMixIn.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Mix-in for {@link ThrowableProxy}.
+ */
+public abstract class ThrowableProxyWithoutStacktraceMixIn {
+
+    @JsonProperty(JsonConstants.ELT_CAUSE)
+    private ThrowableProxyWithoutStacktraceMixIn causeProxy;
+
+    @JsonProperty
+    private int commonElementCount;
+
+    @JsonIgnore
+    private ExtendedStackTraceElement[] extendedStackTrace;
+
+    @JsonProperty
+    private String localizedMessage;
+
+    @JsonProperty
+    private String message;
+
+    @JsonProperty
+    private String name;
+
+    @JsonIgnore
+    private transient Throwable throwable;
+
+    @JsonIgnore
+    public abstract String getCauseStackTraceAsString();
+
+    @JsonIgnore
+    public abstract String getExtendedStackTraceAsString();
+
+    @JsonIgnore
+    public abstract StackTraceElement[] getStackTrace();
+
+    @JsonProperty(JsonConstants.ELT_SUPPRESSED)
+    public abstract ThrowableProxy[] getSuppressedProxies();
+
+    @JsonIgnore
+    public abstract String getSuppressedStackTrace();
+
+    @JsonIgnore
+    public abstract Throwable getThrowable();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/XmlConstants.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/XmlConstants.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/XmlConstants.java
new file mode 100644
index 0000000..10dc37d
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/XmlConstants.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+/**
+ * Keeps constants separate from any class that may depend on third party jars.
+ */
+public final class XmlConstants {
+    public static final String ELT_CAUSE = "Cause";
+    public static final String ELT_CONTEXT_MAP = "ContextMap";
+    public static final String ELT_CONTEXT_STACK = "ContextStack";
+    public static final String ELT_CONTEXT_STACK_ITEM = "ContextStackItem";
+    public static final String ELT_EVENT = "Event";
+    public static final String ELT_EXTENDED_STACK_TRACE = "ExtendedStackTrace";
+    public static final String ELT_EXTENDED_STACK_TRACE_ITEM = "ExtendedStackTraceItem";
+    public static final String ELT_INSTANT = "Instant";
+    public static final String ELT_MARKER = "Marker";
+    public static final String ELT_MESSAGE = "Message";
+    public static final String ELT_PARENTS = "Parents";
+    public static final String ELT_SOURCE = "Source";
+    public static final String ELT_SUPPRESSED = "Suppressed";
+    public static final String ELT_SUPPRESSED_ITEM = "SuppressedItem";
+    public static final String ELT_THROWN = "Thrown";
+    public static final String XML_NAMESPACE = "http://logging.apache.org/log4j/2.0/events";
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/layout/AbstractJacksonLayout.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/layout/AbstractJacksonLayout.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/layout/AbstractJacksonLayout.java
new file mode 100644
index 0000000..a468c1e
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/layout/AbstractJacksonLayout.java
@@ -0,0 +1,378 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.layout;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.impl.MutableLogEvent;
+import org.apache.logging.log4j.core.layout.AbstractStringLayout;
+import org.apache.logging.log4j.core.lookup.StrSubstitutor;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.apache.logging.log4j.core.util.StringBuilderWriter;
+import org.apache.logging.log4j.jackson.XmlConstants;
+import org.apache.logging.log4j.util.Strings;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonRootName;
+import com.fasterxml.jackson.annotation.JsonUnwrapped;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectWriter;
+
+abstract class AbstractJacksonLayout extends AbstractStringLayout {
+
+    public static abstract class Builder<B extends Builder<B>> extends AbstractStringLayout.Builder<B> {
+
+        @PluginBuilderAttribute
+        private boolean eventEol;
+
+        @PluginBuilderAttribute
+        private boolean compact;
+
+        @PluginBuilderAttribute
+        private boolean complete;
+
+        @PluginBuilderAttribute
+        private boolean locationInfo;
+
+        @PluginBuilderAttribute
+        private boolean properties;
+
+        @PluginBuilderAttribute
+        private boolean includeStacktrace = true;
+
+        @PluginBuilderAttribute
+        private boolean stacktraceAsString = false;
+
+        @PluginBuilderAttribute
+        private boolean includeNullDelimiter = false;
+
+        @PluginElement("AdditionalField")
+        private KeyValuePair[] additionalFields;
+
+        public KeyValuePair[] getAdditionalFields() {
+            return additionalFields;
+        }
+
+        public boolean getEventEol() {
+            return eventEol;
+        }
+
+        public boolean isCompact() {
+            return compact;
+        }
+
+        public boolean isComplete() {
+            return complete;
+        }
+
+        public boolean isIncludeNullDelimiter() {
+            return includeNullDelimiter;
+        }
+
+        /**
+         * If "true", includes the stacktrace of any Throwable in the generated data, defaults to "true".
+         *
+         * @return If "true", includes the stacktrace of any Throwable in the generated data, defaults to "true".
+         */
+        public boolean isIncludeStacktrace() {
+            return includeStacktrace;
+        }
+
+        public boolean isLocationInfo() {
+            return locationInfo;
+        }
+
+        public boolean isProperties() {
+            return properties;
+        }
+
+        public boolean isStacktraceAsString() {
+            return stacktraceAsString;
+        }
+
+        /**
+         * Additional fields to set on each log event.
+         *
+         * @return this builder
+         */
+        public B setAdditionalFields(final KeyValuePair[] additionalFields) {
+            this.additionalFields = additionalFields;
+            return asBuilder();
+        }
+
+        public B setCompact(final boolean compact) {
+            this.compact = compact;
+            return asBuilder();
+        }
+
+        public B setComplete(final boolean complete) {
+            this.complete = complete;
+            return asBuilder();
+        }
+
+        public B setEventEol(final boolean eventEol) {
+            this.eventEol = eventEol;
+            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();
+        }
+
+        /**
+         * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true".
+         *
+         * @param includeStacktrace
+         *            If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true".
+         * @return this builder
+         */
+        public B setIncludeStacktrace(final boolean includeStacktrace) {
+            this.includeStacktrace = includeStacktrace;
+            return asBuilder();
+        }
+
+        public B setLocationInfo(final boolean locationInfo) {
+            this.locationInfo = locationInfo;
+            return asBuilder();
+        }
+
+        public B setProperties(final boolean properties) {
+            this.properties = properties;
+            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(final boolean stacktraceAsString) {
+            this.stacktraceAsString = stacktraceAsString;
+            return asBuilder();
+        }
+
+        protected String toStringOrNull(final byte[] header) {
+            return header == null ? null : new String(header, Charset.defaultCharset());
+        }
+    }
+    @JsonRootName(XmlConstants.ELT_EVENT)
+    public static class LogEventWrapperWithAdditionalFields {
+
+        private final Object logEvent;
+        private final Map<String, String> additionalFields;
+
+        public LogEventWrapperWithAdditionalFields(final Object logEvent, final Map<String, String> additionalFields) {
+            this.logEvent = logEvent;
+            this.additionalFields = additionalFields;
+        }
+
+        @JsonAnyGetter
+        @SuppressWarnings("unused")
+        public Map<String, String> getAdditionalFields() {
+            return additionalFields;
+        }
+
+        @JsonUnwrapped
+        public Object getLogEvent() {
+            return logEvent;
+        }
+    }
+
+    protected static class ResolvableKeyValuePair {
+
+        final String key;
+        final String value;
+        final boolean valueNeedsLookup;
+
+        ResolvableKeyValuePair(final KeyValuePair pair) {
+            this.key = pair.getKey();
+            this.value = pair.getValue();
+            this.valueNeedsLookup = AbstractJacksonLayout.valueNeedsLookup(this.value);
+        }
+    }
+
+    protected static final String DEFAULT_EOL = "\r\n";
+
+    protected static final String COMPACT_EOL = Strings.EMPTY;
+    private static LogEvent convertMutableToLog4jEvent(final LogEvent event) {
+        // TODO Jackson-based layouts have certain filters set up for Log4jLogEvent.
+        // TODO Need to set up the same filters for MutableLogEvent but don't know how...
+        // This is a workaround.
+        return event instanceof MutableLogEvent ? ((MutableLogEvent) event).createMemento() : event;
+    }
+    private static ResolvableKeyValuePair[] prepareAdditionalFields(final Configuration config,
+            final KeyValuePair[] additionalFields) {
+        if (additionalFields == null || additionalFields.length == 0) {
+            // No fields set
+            return new ResolvableKeyValuePair[0];
+        }
+
+        // Convert to specific class which already determines whether values needs lookup during serialization
+        final ResolvableKeyValuePair[] resolvableFields = new ResolvableKeyValuePair[additionalFields.length];
+
+        for (int i = 0; i < additionalFields.length; i++) {
+            final ResolvableKeyValuePair resolvable = resolvableFields[i] = new ResolvableKeyValuePair(additionalFields[i]);
+
+            // Validate
+            if (config == null && resolvable.valueNeedsLookup) {
+                throw new IllegalArgumentException(
+                        "configuration needs to be set when there are additional fields with variables");
+            }
+        }
+
+        return resolvableFields;
+    }
+    protected static boolean valueNeedsLookup(final String value) {
+        return value != null && value.contains("${");
+    }
+    protected final String eol;
+    protected final ObjectWriter objectWriter;
+
+    protected final boolean compact;
+
+    protected final boolean complete;
+
+    protected final boolean includeNullDelimiter;
+
+    protected final ResolvableKeyValuePair[] additionalFields;
+
+    @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);
+    }
+
+    @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, final boolean includeNullDelimiter) {
+        this(config, objectWriter, charset, compact, complete, eventEol, headerSerializer, footerSerializer,
+                includeNullDelimiter, null);
+    }
+
+    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,
+            final KeyValuePair[] additionalFields) {
+        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;
+        this.additionalFields = prepareAdditionalFields(config, additionalFields);
+    }
+
+    protected LogEventWrapperWithAdditionalFields createLogEventWrapperWithAdditionalFields(final LogEvent event,
+            final Map<String, String> additionalFieldsMap) {
+        return new LogEventWrapperWithAdditionalFields(event, additionalFieldsMap);
+    }
+
+    private Map<String, String> resolveAdditionalFields(final LogEvent logEvent) {
+        // Note: LinkedHashMap retains order
+        final Map<String, String> additionalFieldsMap = new LinkedHashMap<>(additionalFields.length);
+        final StrSubstitutor strSubstitutor = configuration.getStrSubstitutor();
+
+        // Go over each field
+        for (final ResolvableKeyValuePair pair : additionalFields) {
+            if (pair.valueNeedsLookup) {
+                // Resolve value
+                additionalFieldsMap.put(pair.key, strSubstitutor.replace(logEvent, pair.value));
+            } else {
+                // Plain text value
+                additionalFieldsMap.put(pair.key, pair.value);
+            }
+        }
+
+        return additionalFieldsMap;
+    }
+
+    /**
+     * Formats a {@link org.apache.logging.log4j.core.LogEvent}.
+     *
+     * @param event
+     *            The LogEvent.
+     * @return The XML representation of the LogEvent.
+     */
+    @Override
+    public String toSerializable(final LogEvent event) {
+        final StringBuilderWriter writer = new StringBuilderWriter();
+        try {
+            toSerializable(event, writer);
+            return writer.toString();
+        } catch (final IOException e) {
+            // Should this be an ISE or IAE?
+            LOGGER.error(e);
+            return Strings.EMPTY;
+        }
+    }
+
+    public void toSerializable(final LogEvent event, final Writer writer)
+            throws JsonGenerationException, JsonMappingException, IOException {
+        objectWriter.writeValue(writer, wrapLogEvent(convertMutableToLog4jEvent(event)));
+        writer.write(eol);
+        if (includeNullDelimiter) {
+            writer.write('\0');
+        }
+        markEvent();
+    }
+
+    protected Object wrapLogEvent(final LogEvent event) {
+        if (additionalFields.length > 0) {
+            // Construct map for serialization - note that we are intentionally using original LogEvent
+            final Map<String, String> additionalFieldsMap = resolveAdditionalFields(event);
+            // This class combines LogEvent with AdditionalFields during serialization
+            return createLogEventWrapperWithAdditionalFields(event, additionalFieldsMap);
+        }
+        // No additional fields, return original object
+        return event;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/package-info.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/package-info.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/package-info.java
new file mode 100644
index 0000000..3b5c435
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+/**
+ * Classes and interfaces for serializing and deserializing Log4j 2 log events to XML and JSON using the Jackson
+ * library.
+ */
+package org.apache.logging.log4j.jackson;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/site/manual/index.md
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/site/manual/index.md b/log4j-layout-jackson/src/site/manual/index.md
new file mode 100644
index 0000000..b1d22b6
--- /dev/null
+++ b/log4j-layout-jackson/src/site/manual/index.md
@@ -0,0 +1,33 @@
+<!-- vim: set syn=markdown : -->
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+# Apache Log4j Layout for Jackson module
+
+As of Log4j 3.0.0, common code for layouts based on Jackson have moved from the existing module logj-core to the new modules log4j-layout-jackson.
+
+## Requirements
+
+This module was introduced in Log4j 2.11.0 and requires Jackson.
+
+Some features may require optional
+[dependencies](../runtime-dependencies.html). These dependencies are specified in the
+documentation for those features.
+
+Some Log4j features require external dependencies.
+See the [Dependency Tree](dependencies.html#Dependency_Tree)
+for the exact list of JAR files needed for these features.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/site/site.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/site/site.xml b/log4j-layout-jackson/src/site/site.xml
new file mode 100644
index 0000000..6d4cddc
--- /dev/null
+++ b/log4j-layout-jackson/src/site/site.xml
@@ -0,0 +1,52 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project name="Log4j Core"
+         xmlns="http://maven.apache.org/DECORATION/1.4.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
+  <body>
+    <links>
+      <item name="Apache" href="http://www.apache.org/" />
+      <item name="Logging Services" href="http://logging.apache.org/"/>
+      <item name="Log4j" href="../index.html"/>
+    </links>
+
+    <!-- Component-specific reports -->
+    <menu ref="reports"/>
+
+	<!-- Overall Project Info -->
+    <menu name="Log4j Project Information" img="icon-info-sign">
+      <item name="Dependencies" href="../dependencies.html" />
+      <item name="Dependency Convergence" href="../dependency-convergence.html" />
+      <item name="Dependency Management" href="../dependency-management.html" />
+      <item name="Project Team" href="../team-list.html" />
+      <item name="Mailing Lists" href="../mail-lists.html" />
+      <item name="Issue Tracking" href="../issue-tracking.html" />
+      <item name="Project License" href="../license.html" />
+      <item name="Source Repository" href="../source-repository.html" />
+      <item name="Project Summary" href="../project-summary.html" />
+    </menu>
+
+    <menu name="Log4j Project Reports" img="icon-cog">
+      <item name="Changes Report" href="../changes-report.html" />
+      <item name="JIRA Report" href="../jira-report.html" />
+      <item name="Surefire Report" href="../surefire-report.html" />
+      <item name="RAT Report" href="../rat-report.html" />
+    </menu>
+  </body>
+</project>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/AbstractMarkerMixInTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/AbstractMarkerMixInTest.java b/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/AbstractMarkerMixInTest.java
new file mode 100644
index 0000000..acfae96
--- /dev/null
+++ b/log4j-layout-jackson/src/test/java/org/apache/logging/log4j/jackson/AbstractMarkerMixInTest.java
@@ -0,0 +1,97 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache license, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the license for the specific language governing permissions and
+* limitations under the license.
+*/
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.logging.log4j.MarkerManager.Log4jMarker;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
+
+/**
+ * Tests {@link MarkerMixIn}.
+ *
+ * This class is in this package to let {@link Log4jMarker} have the least visibility.
+ */
+public abstract class AbstractMarkerMixInTest {
+
+    private ObjectReader reader;
+    private ObjectWriter writer;
+
+    protected abstract ObjectMapper newObjectMapper();
+
+    @Before
+    public void setUp() {
+        final ObjectMapper log4jObjectMapper = newObjectMapper();
+        writer = log4jObjectMapper.writer();
+        reader = log4jObjectMapper.readerFor(Log4jMarker.class);
+        MarkerManager.clear();
+    }
+
+    @Test
+    public void testNameOnly() throws IOException {
+        final Marker expected = MarkerManager.getMarker("A");
+        final String str = writeValueAsString(expected);
+        Assert.assertFalse(str.contains("parents"));
+        final Marker actual = reader.readValue(str);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testOneParent() throws IOException {
+        final Marker expected = MarkerManager.getMarker("A");
+        final Marker parent = MarkerManager.getMarker("PARENT_MARKER");
+        expected.addParents(parent);
+        final String str = writeValueAsString(expected);
+        Assert.assertTrue(str.contains("PARENT_MARKER"));
+        final Marker actual = reader.readValue(str);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testTwoParents() throws IOException {
+        final Marker expected = MarkerManager.getMarker("A");
+        final Marker parent1 = MarkerManager.getMarker("PARENT_MARKER1");
+        final Marker parent2 = MarkerManager.getMarker("PARENT_MARKER2");
+        expected.addParents(parent1);
+        expected.addParents(parent2);
+        final String str = writeValueAsString(expected);
+        Assert.assertTrue(str.contains("PARENT_MARKER1"));
+        Assert.assertTrue(str.contains("PARENT_MARKER2"));
+        final Marker actual = reader.readValue(str);
+        Assert.assertEquals(expected, actual);
+    }
+
+    /**
+     * @param expected
+     * @return
+     * @throws JsonProcessingException
+     */
+    private String writeValueAsString(final Marker expected) throws JsonProcessingException {
+        final String str = writer.writeValueAsString(expected);
+        // System.out.println(str);
+        return str;
+    }
+}


[11/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java
new file mode 100644
index 0000000..9d86f6e
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.List;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.CoreLoggerContexts;
+import org.apache.logging.log4j.core.selector.ContextSelector;
+import org.apache.logging.log4j.core.selector.CoreContextSelectors;
+import org.apache.logging.log4j.junit.CleanFiles;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Tests a "complete" XML file a.k.a. a well-formed XML file.
+ */
+@RunWith(Parameterized.class)
+@Category(Layouts.Xml.class)
+public class XmlCompleteFileAppenderTest {
+
+    public XmlCompleteFileAppenderTest(final Class<ContextSelector> contextSelector) {
+        this.loggerContextRule = new LoggerContextRule("XmlCompleteFileAppenderTest.xml", contextSelector);
+        this.cleanFiles = new CleanFiles(logFile);
+        this.ruleChain = RuleChain.outerRule(cleanFiles).around(loggerContextRule);
+    }
+
+    @Parameters(name = "{0}")
+    public static Class<?>[] getParameters() {
+        return CoreContextSelectors.CLASSES;
+    }
+
+    private final File logFile = new File("target", "XmlCompleteFileAppenderTest.log");
+    private final LoggerContextRule loggerContextRule;
+    private final CleanFiles cleanFiles;
+
+    @Rule
+    public RuleChain ruleChain;
+
+    @Test
+    public void testFlushAtEndOfBatch() throws Exception {
+        final Logger logger = this.loggerContextRule.getLogger("com.foo.Bar");
+        final String logMsg = "Message flushed with immediate flush=false";
+        logger.info(logMsg);
+        CoreLoggerContexts.stopLoggerContext(false, logFile); // stop async thread
+
+        String line1;
+        String line2;
+        String line3;
+        String line4;
+        String line5;
+        try (final BufferedReader reader = new BufferedReader(new FileReader(logFile))) {
+            line1 = reader.readLine();
+            line2 = reader.readLine();
+            reader.readLine(); // ignore the empty line after the <Events> root
+            line3 = reader.readLine();
+            line4 = reader.readLine();
+            line5 = reader.readLine();
+        } finally {
+            logFile.delete();
+        }
+        assertNotNull("line1", line1);
+        final String msg1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg1 + ']', line1.equals(msg1));
+
+        assertNotNull("line2", line2);
+        final String msg2 = "<Events xmlns=\"http://logging.apache.org/log4j/2.0/events\">";
+        assertTrue("line2 incorrect: [" + line2 + "], does not contain: [" + msg2 + ']', line2.equals(msg2));
+
+        assertNotNull("line3", line3);
+        final String msg3 = "<Event ";
+        assertTrue("line3 incorrect: [" + line3 + "], does not contain: [" + msg3 + ']', line3.contains(msg3));
+
+        assertNotNull("line4", line4);
+        final String msg4 = "<Instant epochSecond=";
+        assertTrue("line4 incorrect: [" + line4 + "], does not contain: [" + msg4 + ']', line4.contains(msg4));
+
+        assertNotNull("line5", line5);
+        final String msg5 = logMsg;
+        assertTrue("line5 incorrect: [" + line5 + "], does not contain: [" + msg5 + ']', line5.contains(msg5));
+
+        final String location = "testFlushAtEndOfBatch";
+        assertTrue("no location", !line1.contains(location));
+    }
+
+    /**
+     * Test the indentation of the Events XML.
+     * <p>Expected Events XML is as below.</p>
+     * <pre>
+&lt;?xml version="1.0" encoding="UTF-8"?>
+&lt;Events xmlns="http://logging.apache.org/log4j/2.0/events">
+
+  &lt;Event xmlns="http://logging.apache.org/log4j/2.0/events" thread="main" level="INFO" loggerName="com.foo.Bar" endOfBatch="true" loggerFqcn="org.apache.logging.log4j.spi.AbstractLogger" threadId="12" threadPriority="5">
+    &lt;Instant epochSecond="1515889414" nanoOfSecond="144000000" epochMillisecond="1515889414144" nanoOfMillisecond="0"/>
+    &lt;Message>First Msg tag must be in level 2 after correct indentation&lt;/Message>
+  &lt;/Event>
+
+  &lt;Event xmlns="http://logging.apache.org/log4j/2.0/events" thread="main" level="INFO" loggerName="com.foo.Bar" endOfBatch="true" loggerFqcn="org.apache.logging.log4j.spi.AbstractLogger" threadId="12" threadPriority="5">
+    &lt;Instant epochSecond="1515889414" nanoOfSecond="144000000" epochMillisecond="1515889414144" nanoOfMillisecond="0"/>
+    &lt;Message>Second Msg tag must also be in level 2 after correct indentation&lt;/Message>
+  &lt;/Event>
+&lt;/Events>
+     * </pre>
+     * @throws Exception
+     */
+    @Test
+    public void testChildElementsAreCorrectlyIndented() throws Exception {
+        final Logger logger = this.loggerContextRule.getLogger("com.foo.Bar");
+        final String firstLogMsg = "First Msg tag must be in level 2 after correct indentation";
+        logger.info(firstLogMsg);
+        final String secondLogMsg = "Second Msg tag must also be in level 2 after correct indentation";
+        logger.info(secondLogMsg);
+        CoreLoggerContexts.stopLoggerContext(false, logFile); // stop async thread
+
+        int[] indentations = {
+                0, //"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+                0, //"<Events xmlns=\"http://logging.apache.org/log4j/2.0/events\">\n"
+                -1, // empty
+                2, //"  <Event xmlns=\"http://logging.apache.org/log4j/2.0/events\" thread=\"main\" level=\"INFO\" loggerName=\"com.foo.Bar\" endOfBatch=\"true\" loggerFqcn=\"org.apache.logging.log4j.spi.AbstractLogger\" threadId=\"12\" threadPriority=\"5\">\n"
+                4, //"    <Instant epochSecond=\"1515889414\" nanoOfSecond=\"144000000\" epochMillisecond=\"1515889414144\" nanoOfMillisecond=\"0\"/>\n"
+                4, //"    <Message>First Msg tag must be in level 2 after correct indentation</Message>\n" +
+                2, //"  </Event>\n"
+                -1, // empty
+                2, //"  <Event xmlns=\"http://logging.apache.org/log4j/2.0/events\" thread=\"main\" level=\"INFO\" loggerName=\"com.foo.Bar\" endOfBatch=\"true\" loggerFqcn=\"org.apache.logging.log4j.spi.AbstractLogger\" threadId=\"12\" threadPriority=\"5\">\n" +
+                4, //"    <Instant epochSecond=\"1515889414\" nanoOfSecond=\"144000000\" epochMillisecond=\"1515889414144\" nanoOfMillisecond=\"0\"/>\n" +
+                4, //"    <Message>Second Msg tag must also be in level 2 after correct indentation</Message>\n" +
+                2, //"  </Event>\n" +
+                0, //"</Events>\n";
+        };
+        List<String> lines1 = Files.readAllLines(logFile.toPath(), Charset.forName("UTF-8"));
+
+        assertEquals("number of lines", indentations.length, lines1.size());
+        for (int i = 0; i < indentations.length; i++) {
+            String line = lines1.get(i);
+            if (line.trim().isEmpty()) {
+                assertEquals(-1, indentations[i]);
+            } else {
+                String padding = "        ".substring(0, indentations[i]);
+                assertTrue("Expected " + indentations[i] + " leading spaces but got: " + line, line.startsWith(padding));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java
new file mode 100644
index 0000000..107ef22
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.List;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.CoreLoggerContexts;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * Tests a "complete" XML file a.k.a. a well-formed XML file.
+ */
+@Category(Layouts.Xml.class)
+public class XmlFileAppenderTest {
+
+    @BeforeClass
+    public static void beforeClass() {
+        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
+                "XmlFileAppenderTest.xml");
+    }
+
+    @Test
+    public void testFlushAtEndOfBatch() throws Exception {
+        final File file = new File("target", "XmlFileAppenderTest.log");
+        // System.out.println(f.getAbsolutePath());
+        file.delete();
+        final Logger log = LogManager.getLogger("com.foo.Bar");
+        final String logMsg = "Message flushed with immediate flush=false";
+        log.info(logMsg);
+        CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread
+
+        List<String> lines = Files.readAllLines(file.toPath(), Charset.forName("UTF8"));
+        file.delete();
+
+        String[] expect = {
+                "", // ? unsure why initial empty line...
+            "<Event ", //
+            "<Instant epochSecond=", //
+            logMsg, //
+            "</Event>", //
+        };
+
+        for (int i = 0; i < expect.length; i++) {
+            assertTrue("Expected line " + i + " to contain " + expect[i] + " but got: " + lines.get(i),
+                    lines.get(i).contains(expect[i]));
+        }
+
+        final String location = "testFlushAtEndOfBatch";
+        assertTrue("no location", !lines.get(0).contains(location));
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlRandomAccessFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlRandomAccessFileAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlRandomAccessFileAppenderTest.java
new file mode 100644
index 0000000..1794160
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlRandomAccessFileAppenderTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.CoreLoggerContexts;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * Tests a "complete" XML file a.k.a. a well-formed XML file.
+ */
+@Category(Layouts.Xml.class)
+public class XmlRandomAccessFileAppenderTest {
+
+    @BeforeClass
+    public static void beforeClass() {
+        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
+                "XmlRandomAccessFileAppenderTest.xml");
+    }
+
+    @Test
+    @Ignore
+    public void testFlushAtEndOfBatch() throws Exception {
+        final File file = new File("target", "XmlRandomAccessFileAppenderTest.log");
+        // System.out.println(f.getAbsolutePath());
+        file.delete();
+        final Logger log = LogManager.getLogger("com.foo.Bar");
+        final String logMsg = "Message flushed with immediate flush=false";
+        log.info(logMsg);
+        CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread
+
+        String line1;
+        String line2;
+        String line3;
+        String line4;
+        try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
+            line1 = reader.readLine();
+            line2 = reader.readLine();
+            line3 = reader.readLine();
+            line4 = reader.readLine();
+        } finally {
+            file.delete();
+        }
+        assertNotNull("line1", line1);
+        final String msg1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg1 + ']', line1.equals(msg1));
+
+        assertNotNull("line2", line2);
+        final String msg2 = "<log4j:events xmlns:log4j=\"http://logging.apache.org/log4j/\">";
+        assertTrue("line2 incorrect: [" + line2 + "], does not contain: [" + msg2 + ']', line2.equals(msg2));
+
+        assertNotNull("line3", line3);
+        final String msg3 = "<log4j:event ";
+        assertTrue("line3 incorrect: [" + line3 + "], does not contain: [" + msg3 + ']', line3.contains(msg3));
+
+        assertNotNull("line4", line4);
+        final String msg4 = logMsg;
+        assertTrue("line4 incorrect: [" + line4 + "], does not contain: [" + msg4 + ']', line4.contains(msg4));
+
+        final String location = "testFlushAtEndOfBatch";
+        assertTrue("no location", !line1.contains(location));
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-core/pom.xml b/log4j-core/pom.xml
index b791acc..196e4e5 100644
--- a/log4j-core/pom.xml
+++ b/log4j-core/pom.xml
@@ -279,12 +279,6 @@
       <artifactId>groovy-all</artifactId>
       <scope>test</scope>
     </dependency>
-    <!-- Used for testing HttpAppender -->
-    <dependency>
-      <groupId>com.github.tomakehurst</groupId>
-      <artifactId>wiremock</artifactId>
-      <scope>test</scope>
-    </dependency>
     <!-- GC-free -->
     <dependency>
       <groupId>com.google.code.java-allocation-instrumenter</groupId>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataAsEntryListDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataAsEntryListDeserializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataAsEntryListDeserializer.java
deleted file mode 100644
index 85dd21e..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataAsEntryListDeserializer.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.logging.log4j.core.impl.ContextDataFactory;
-import org.apache.logging.log4j.util.StringMap;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public class ContextDataAsEntryListDeserializer extends StdDeserializer<StringMap> {
-
-    private static final long serialVersionUID = 1L;
-
-    ContextDataAsEntryListDeserializer() {
-        super(Map.class);
-    }
-
-    @Override
-    public StringMap deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
-            JsonProcessingException {
-        final List<MapEntry> list = jp.readValueAs(new TypeReference<List<MapEntry>>() {
-            // empty
-        });
-        final StringMap contextData = new ContextDataFactory().createContextData();
-        for (final MapEntry mapEntry : list) {
-            contextData.putValue(mapEntry.getKey(), mapEntry.getValue());
-        }
-        return contextData;
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataAsEntryListSerializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataAsEntryListSerializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataAsEntryListSerializer.java
deleted file mode 100644
index ccf17ff..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataAsEntryListSerializer.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.apache.logging.log4j.util.ReadOnlyStringMap;
-import org.apache.logging.log4j.util.BiConsumer;
-
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public class ContextDataAsEntryListSerializer extends StdSerializer<ReadOnlyStringMap> {
-
-    private static final long serialVersionUID = 1L;
-
-    protected ContextDataAsEntryListSerializer() {
-        super(Map.class, false);
-    }
-
-    @Override
-    public void serialize(final ReadOnlyStringMap contextData, final JsonGenerator jgen, final SerializerProvider provider)
-            throws IOException, JsonGenerationException {
-
-        final MapEntry[] pairs = new MapEntry[contextData.size()];
-        contextData.forEach(new BiConsumer<String, Object>() {
-            int i = 0;
-
-            @Override
-            public void accept(final String key, final Object value) {
-                pairs[i++] = new MapEntry(key, String.valueOf(value));
-            }
-        });
-        jgen.writeObject(pairs);
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataDeserializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataDeserializer.java
deleted file mode 100644
index 3a9a13e..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataDeserializer.java
+++ /dev/null
@@ -1,65 +0,0 @@
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.apache.logging.log4j.core.impl.ContextDataFactory;
-import org.apache.logging.log4j.util.StringMap;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public class ContextDataDeserializer extends StdDeserializer<StringMap> {
-
-    private static final long serialVersionUID = 1L;
-
-    ContextDataDeserializer() {
-        super(Map.class);
-    }
-
-    @Override
-    public StringMap deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
-            JsonProcessingException {
-
-        // Sanity check: verify that we got "Json Object":
-//        JsonToken tok = jp.nextToken();
-//        if (tok != JsonToken.START_OBJECT) {
-//            throw new IOException("Expected data to start with an Object");
-//        }
-        final StringMap contextData = ContextDataFactory.createContextData();
-        // Iterate over object fields:
-        while (jp.nextToken() != JsonToken.END_OBJECT) {
-            final String fieldName = jp.getCurrentName();
-
-            // move to value
-            jp.nextToken();
-            contextData.putValue(fieldName, jp.getText());
-        }
-        return contextData;
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataSerializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataSerializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataSerializer.java
deleted file mode 100644
index 8808d3d..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ContextDataSerializer.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.apache.logging.log4j.util.ReadOnlyStringMap;
-import org.apache.logging.log4j.util.TriConsumer;
-
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public class ContextDataSerializer extends StdSerializer<ReadOnlyStringMap> {
-
-    private static final long serialVersionUID = 1L;
-
-    protected ContextDataSerializer() {
-        super(Map.class, false);
-    }
-
-    @Override
-    public void serialize(final ReadOnlyStringMap contextData, final JsonGenerator jgen,
-            final SerializerProvider provider) throws IOException, JsonGenerationException {
-
-        jgen.writeStartObject();
-        contextData.forEach(WRITE_STRING_FIELD_INTO, jgen);
-        jgen.writeEndObject();
-    }
-
-    private static final TriConsumer<String, Object, JsonGenerator> WRITE_STRING_FIELD_INTO =
-            new TriConsumer<String, Object, JsonGenerator>() {
-
-        @Override
-        public void accept(final String key, final Object value, final JsonGenerator jsonGenerator) {
-            try {
-                jsonGenerator.writeStringField(key, String.valueOf(value));
-            } catch (final Exception ex) {
-                throw new IllegalStateException("Problem with key " + key, ex);
-            }
-        }
-    };
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ExtendedStackTraceElementMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ExtendedStackTraceElementMixIn.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ExtendedStackTraceElementMixIn.java
deleted file mode 100644
index 84df3d6..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ExtendedStackTraceElementMixIn.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.Serializable;
-
-import org.apache.logging.log4j.core.impl.ExtendedClassInfo;
-import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-
-/**
- * Mix-in for {@link ExtendedStackTraceElement}.
- */
-@JsonPropertyOrder({ "class", "method", "file", "line", "exact", "location", "version" })
-abstract class ExtendedStackTraceElementMixIn implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @JsonCreator
-    public ExtendedStackTraceElementMixIn(
-            // @formatter:off
-            @JsonProperty("class") final String declaringClass,
-            @JsonProperty("method") final String methodName,
-            @JsonProperty("file") final String fileName,
-            @JsonProperty("line") final int lineNumber,
-            @JsonProperty("exact") final boolean exact,
-            @JsonProperty("location") final String location,
-            @JsonProperty("version") final String version
-            // @formatter:on
-    ) {
-        // empty
-    }
-
-    @JsonProperty("class")
-    @JacksonXmlProperty(localName = "class", isAttribute = true)
-    public abstract String getClassName();
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    public abstract boolean getExact();
-
-    @JsonIgnore
-    public abstract ExtendedClassInfo getExtraClassInfo();
-
-    @JsonProperty("file")
-    @JacksonXmlProperty(localName = "file", isAttribute = true)
-    public abstract String getFileName();
-
-    @JsonProperty("line")
-    @JacksonXmlProperty(localName = "line", isAttribute = true)
-    public abstract int getLineNumber();
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    public abstract String getLocation();
-
-    @JsonProperty("method")
-    @JacksonXmlProperty(localName = "method", isAttribute = true)
-    public abstract String getMethodName();
-    
-    @JsonIgnore
-    abstract StackTraceElement getStackTraceElement();
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    public abstract String getVersion();
-
-    @JsonIgnore
-    public abstract boolean isNativeMethod();
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Initializers.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Initializers.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Initializers.java
deleted file mode 100644
index 3bc3447..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Initializers.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.Marker;
-import org.apache.logging.log4j.ThreadContext.ContextStack;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
-import org.apache.logging.log4j.core.impl.ThrowableProxy;
-import org.apache.logging.log4j.message.Message;
-import org.apache.logging.log4j.message.ObjectMessage;
-
-import com.fasterxml.jackson.databind.Module.SetupContext;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-import org.apache.logging.log4j.core.time.Instant;
-
-/**
- * Initialization utils.
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-class Initializers {
-
-    /**
-     * Used to set up {@link SetupContext} from different {@link SimpleModule}s.
-     */
-    static class SetupContextInitializer {
-
-        void setupModule(final SetupContext context, final boolean includeStacktrace, final boolean stacktraceAsString) {
-            // JRE classes: we cannot edit those with Jackson annotations
-            context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class);
-            // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not depend on Jackson.
-            context.setMixInAnnotations(Marker.class, MarkerMixIn.class);
-            context.setMixInAnnotations(Level.class, LevelMixIn.class);
-            context.setMixInAnnotations(Instant.class, InstantMixIn.class);
-            context.setMixInAnnotations(LogEvent.class, LogEventWithContextListMixIn.class);
-            // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
-            context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
-            context.setMixInAnnotations(ThrowableProxy.class,
-                    includeStacktrace ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringMixIn.class : ThrowableProxyMixIn.class ) : ThrowableProxyWithoutStacktraceMixIn.class);
-        }
-    }
-
-    /**
-     * Used to set up {@link SetupContext} from different {@link SimpleModule}s.
-     * Differs from SetupContextInitializer by installing {@code LogEventJsonMixIn} for LogEvents,
-     * not {@code LogEventMixIn}, so it handles ThreadContext serialization differently.
-     */
-    static class SetupContextJsonInitializer {
-
-        void setupModule(final SetupContext context, final boolean includeStacktrace, final boolean stacktraceAsString) {
-            // JRE classes: we cannot edit those with Jackson annotations
-            context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class);
-            // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not depend on Jackson.
-            context.setMixInAnnotations(Marker.class, MarkerMixIn.class);
-            context.setMixInAnnotations(Level.class, LevelMixIn.class);
-            context.setMixInAnnotations(Instant.class, InstantMixIn.class);
-            context.setMixInAnnotations(LogEvent.class, LogEventJsonMixIn.class); // different ThreadContext handling
-            // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
-            context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
-            context.setMixInAnnotations(ThrowableProxy.class,
-                    includeStacktrace ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringMixIn.class : ThrowableProxyMixIn.class ) : ThrowableProxyWithoutStacktraceMixIn.class);
-        }
-    }
-
-    /**
-     * Used to set up {@link SimpleModule} from different {@link SimpleModule} subclasses.
-     */
-    static class SimpleModuleInitializer {
-        void initialize(final SimpleModule simpleModule, final boolean objectMessageAsJsonObject) {
-            // Workaround because mix-ins do not work for classes that already have a built-in deserializer.
-            // See Jackson issue 429.
-            simpleModule.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
-            simpleModule.addDeserializer(ContextStack.class, new MutableThreadContextStackDeserializer());
-            if (objectMessageAsJsonObject) {
-            	    simpleModule.addSerializer(ObjectMessage.class, new ObjectMessageSerializer());
-            }
-            simpleModule.addSerializer(Message.class, new MessageSerializer());
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/InstantMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/InstantMixIn.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/InstantMixIn.java
deleted file mode 100644
index 216534b..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/InstantMixIn.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import org.apache.logging.log4j.Marker;
-import org.apache.logging.log4j.core.time.Instant;
-
-/**
- * Jackson mix-in for {@link Instant}.
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- * @see Marker
- */
-@JsonIgnoreProperties({ "epochMillisecond", "nanoOfMillisecond" })
-abstract class InstantMixIn {
-
-    @JsonCreator
-    InstantMixIn(
-            // @formatter:off
-            @JsonProperty("epochSecond") final long epochSecond,
-            @JsonProperty("nanoOfSecond") final int nanoOfSecond)
-            // @formatter:on
-    {
-        // empty
-    }
-
-    @JsonProperty("epochSecond")
-    @JacksonXmlProperty(localName = "epochSecond", isAttribute = true)
-    abstract long getEpochSecond();
-
-    @JsonProperty("nanoOfSecond")
-    @JacksonXmlProperty(localName = "nanoOfSecond", isAttribute = true)
-    abstract int getNanoOfSecond();
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/JsonConstants.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/JsonConstants.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/JsonConstants.java
deleted file mode 100644
index bb9898d..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/JsonConstants.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-/**
- * Keeps constants separate from any class that may depend on third party jars.
- */
-public final class JsonConstants {
-    public static final String ELT_CAUSE = "cause";
-    public static final String ELT_CONTEXT_MAP = "contextMap";
-    public static final String ELT_CONTEXT_STACK = "contextStack";
-    public static final String ELT_MARKER = "marker";
-    public static final String ELT_PARENTS = "parents";
-    public static final String ELT_SOURCE = "source";
-    public static final String ELT_SUPPRESSED = "suppressed";
-    public static final String ELT_THROWN = "thrown";
-    public static final String ELT_MESSAGE = "message";
-    public static final String ELT_EXTENDED_STACK_TRACE = "extendedStackTrace";
-    public static final String ELT_NANO_TIME = "nanoTime";
-    public static final String ELT_INSTANT = "instant";
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LevelMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LevelMixIn.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LevelMixIn.java
deleted file mode 100644
index bb252c8..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LevelMixIn.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.Marker;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonValue;
-
-/**
- * Jackson mix-in for {@link Level}.
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- * @see Marker
- */
-@JsonIgnoreProperties({ "name", "declaringClass", "standardLevel" })
-abstract class LevelMixIn {
-
-    @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
-    public static Level getLevel(final String name) {
-        return null;
-    }
-
-    @JsonValue
-    public abstract String name();
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ListOfMapEntryDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ListOfMapEntryDeserializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ListOfMapEntryDeserializer.java
deleted file mode 100644
index 0a7281e..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ListOfMapEntryDeserializer.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public class ListOfMapEntryDeserializer extends StdDeserializer<Map<String, String>> {
-
-    private static final long serialVersionUID = 1L;
-
-    ListOfMapEntryDeserializer() {
-        super(Map.class);
-    }
-
-    @Override
-    public Map<String, String> deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
-            JsonProcessingException {
-        final List<MapEntry> list = jp.readValueAs(new TypeReference<List<MapEntry>>() {
-            // empty
-        });
-        final HashMap<String, String> map = new HashMap<>(list.size());
-        for (final MapEntry mapEntry : list) {
-            map.put(mapEntry.getKey(), mapEntry.getValue());
-        }
-        return map;
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ListOfMapEntrySerializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ListOfMapEntrySerializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ListOfMapEntrySerializer.java
deleted file mode 100644
index 02f47a2..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ListOfMapEntrySerializer.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public class ListOfMapEntrySerializer extends StdSerializer<Map<String, String>> {
-
-    private static final long serialVersionUID = 1L;
-
-    protected ListOfMapEntrySerializer() {
-        super(Map.class, false);
-    }
-
-    @Override
-    public void serialize(final Map<String, String> map, final JsonGenerator jgen, final SerializerProvider provider)
-            throws IOException, JsonGenerationException {
-        final Set<Entry<String, String>> entrySet = map.entrySet();
-        final MapEntry[] pairs = new MapEntry[entrySet.size()];
-        int i = 0;
-        for (final Entry<String, String> entry : entrySet) {
-            pairs[i++] = new MapEntry(entry.getKey(), entry.getValue());
-        }
-        jgen.writeObject(pairs);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jJsonModule.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jJsonModule.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jJsonModule.java
deleted file mode 100644
index ceb53b4..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jJsonModule.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import org.apache.logging.log4j.core.jackson.Initializers.SetupContextInitializer;
-import org.apache.logging.log4j.core.jackson.Initializers.SetupContextJsonInitializer;
-import org.apache.logging.log4j.core.jackson.Initializers.SimpleModuleInitializer;
-
-import com.fasterxml.jackson.core.Version;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-class Log4jJsonModule extends SimpleModule {
-
-    private static final long serialVersionUID = 1L;
-    private final boolean encodeThreadContextAsList;
-    private final boolean includeStacktrace;
-    private final boolean stacktraceAsString;
-    private final boolean objectMessageAsJsonObject;
-
-    Log4jJsonModule(final boolean encodeThreadContextAsList, final boolean includeStacktrace, final boolean stacktraceAsString, final boolean objectMessageAsJsonObject) {
-        super(Log4jJsonModule.class.getName(), new Version(2, 0, 0, null, null, null));
-        this.encodeThreadContextAsList = encodeThreadContextAsList;
-        this.includeStacktrace = includeStacktrace;
-        this.stacktraceAsString = stacktraceAsString;
-        this.objectMessageAsJsonObject = objectMessageAsJsonObject;
-        // MUST init here.
-        // Calling this from setupModule is too late!
-        //noinspection ThisEscapedInObjectConstruction
-        new SimpleModuleInitializer().initialize(this, objectMessageAsJsonObject);
-    }
-
-    @Override
-    public void setupModule(final SetupContext context) {
-        // Calling super is a MUST!
-        super.setupModule(context);
-        if (encodeThreadContextAsList) {
-            new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
-        } else {
-            new SetupContextJsonInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jJsonObjectMapper.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jJsonObjectMapper.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jJsonObjectMapper.java
deleted file mode 100644
index 4997c91..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jJsonObjectMapper.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-/**
- * A Jackson JSON {@link ObjectMapper} initialized for Log4j.
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public class Log4jJsonObjectMapper extends ObjectMapper {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Create a new instance using the {@link Log4jJsonModule}.
-     */
-    public Log4jJsonObjectMapper() {
-        this(false, true, false, false);
-    }
-
-    /**
-     * Create a new instance using the {@link Log4jJsonModule}.
-     */
-    public Log4jJsonObjectMapper(final boolean encodeThreadContextAsList, final boolean includeStacktrace, final boolean stacktraceAsString, final boolean objectMessageAsJsonObject) {
-        this.registerModule(new Log4jJsonModule(encodeThreadContextAsList, includeStacktrace, stacktraceAsString, objectMessageAsJsonObject));
-        this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jStackTraceElementDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jStackTraceElementDeserializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jStackTraceElementDeserializer.java
deleted file mode 100644
index 936ace1..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jStackTraceElementDeserializer.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
-
-/**
- * Copy and edit the Jackson (Apache License 2.0) class to use Log4j attribute names. Does not work as of Jackson 2.3.2.
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public final class Log4jStackTraceElementDeserializer extends StdScalarDeserializer<StackTraceElement> {
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Constructs a new initialized instance.
-     */
-    public Log4jStackTraceElementDeserializer() {
-        super(StackTraceElement.class);
-    }
-
-    @Override
-    public StackTraceElement deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
-            JsonProcessingException {
-        JsonToken t = jp.getCurrentToken();
-        // Must get an Object
-        if (t == JsonToken.START_OBJECT) {
-            String className = null, methodName = null, fileName = null;
-            int lineNumber = -1;
-
-            while ((t = jp.nextValue()) != JsonToken.END_OBJECT) {
-                final String propName = jp.getCurrentName();
-                if ("class".equals(propName)) {
-                    className = jp.getText();
-                } else if ("file".equals(propName)) {
-                    fileName = jp.getText();
-                } else if ("line".equals(propName)) {
-                    if (t.isNumeric()) {
-                        lineNumber = jp.getIntValue();
-                    } else {
-                        // An XML number always comes in a string since there is no syntax help as with JSON.
-                        try {
-                            lineNumber = Integer.parseInt(jp.getText().trim());
-                        } catch (final NumberFormatException e) {
-                            throw JsonMappingException.from(jp, "Non-numeric token (" + t + ") for property 'line'", e);
-                        }
-                    }
-                } else if ("method".equals(propName)) {
-                    methodName = jp.getText();
-                } else if ("nativeMethod".equals(propName)) {
-                    // no setter, not passed via constructor: ignore
-                } else {
-                    this.handleUnknownProperty(jp, ctxt, this._valueClass, propName);
-                }
-            }
-            return new StackTraceElement(className, methodName, fileName, lineNumber);
-        }
-        throw ctxt.mappingException(this._valueClass, t);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jXmlModule.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jXmlModule.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jXmlModule.java
deleted file mode 100644
index 34f0f68..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jXmlModule.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import org.apache.logging.log4j.core.jackson.Initializers.SetupContextInitializer;
-import org.apache.logging.log4j.core.jackson.Initializers.SimpleModuleInitializer;
-
-import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-final class Log4jXmlModule extends JacksonXmlModule {
-
-    private static final long serialVersionUID = 1L;
-    private final boolean includeStacktrace;
-    private final boolean stacktraceAsString;
-
-    Log4jXmlModule(final boolean includeStacktrace, final boolean stacktraceAsString) {
-        super();
-        this.includeStacktrace = includeStacktrace;
-        this.stacktraceAsString = stacktraceAsString;
-        // MUST init here.
-        // Calling this from setupModule is too late!
-        new SimpleModuleInitializer().initialize(this, false);
-    }
-
-    @Override
-    public void setupModule(final SetupContext context) {
-        // Calling super is a MUST!
-        super.setupModule(context);
-        new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jXmlObjectMapper.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jXmlObjectMapper.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jXmlObjectMapper.java
deleted file mode 100644
index b390a3f..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jXmlObjectMapper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.dataformat.xml.XmlMapper;
-
-/**
- * A Jackson XML {@link ObjectMapper} initialized for Log4j.
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public class Log4jXmlObjectMapper extends XmlMapper {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Create a new instance using the {@link Log4jXmlModule}.
-     */
-    public Log4jXmlObjectMapper() {
-        this(true, false);
-    }
-
-    /**
-     * Create a new instance using the {@link Log4jXmlModule}.
-     */
-    public Log4jXmlObjectMapper(final boolean includeStacktrace, final boolean stacktraceAsString) {
-        super(new Log4jXmlModule(includeStacktrace, stacktraceAsString));
-        this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlModule.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlModule.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlModule.java
deleted file mode 100644
index c7b92f0..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlModule.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import org.apache.logging.log4j.core.jackson.Initializers.SetupContextInitializer;
-import org.apache.logging.log4j.core.jackson.Initializers.SetupContextJsonInitializer;
-import org.apache.logging.log4j.core.jackson.Initializers.SimpleModuleInitializer;
-
-import com.fasterxml.jackson.core.Version;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-final class Log4jYamlModule extends SimpleModule {
-
-    private static final long serialVersionUID = 1L;
-    private final boolean encodeThreadContextAsList;
-    private final boolean includeStacktrace;
-    private final boolean stacktraceAsString;
-
-    Log4jYamlModule(final boolean encodeThreadContextAsList, final boolean includeStacktrace, final boolean stacktraceAsString) {
-        super(Log4jYamlModule.class.getName(), new Version(2, 0, 0, null, null, null));
-        this.encodeThreadContextAsList = encodeThreadContextAsList;
-        this.includeStacktrace = includeStacktrace;
-        this.stacktraceAsString = stacktraceAsString;
-        // MUST init here.
-        // Calling this from setupModule is too late!
-        //noinspection ThisEscapedInObjectConstruction
-        new SimpleModuleInitializer().initialize(this, false);
-    }
-
-    @Override
-    public void setupModule(final SetupContext context) {
-        // Calling super is a MUST!
-        super.setupModule(context);
-        if (encodeThreadContextAsList) {
-            new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
-        } else {
-            new SetupContextJsonInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlObjectMapper.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlObjectMapper.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlObjectMapper.java
deleted file mode 100644
index 0b80591..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlObjectMapper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
-
-/**
- * A Jackson {@link ObjectMapper} initialized for Log4j.
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public class Log4jYamlObjectMapper extends YAMLMapper {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Create a new instance using the {@link Log4jYamlModule}.
-     */
-    public Log4jYamlObjectMapper() {
-        this(false, true, false);
-    }
-
-    /**
-     * Create a new instance using the {@link Log4jYamlModule}.
-     */
-    public Log4jYamlObjectMapper(final boolean encodeThreadContextAsList, final boolean includeStacktrace, final boolean stacktraceAsString) {
-        this.registerModule(new Log4jYamlModule(encodeThreadContextAsList, includeStacktrace, stacktraceAsString));
-        this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventJsonMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventJsonMixIn.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventJsonMixIn.java
deleted file mode 100644
index bbb024d..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventJsonMixIn.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.util.Map;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.Marker;
-import org.apache.logging.log4j.ThreadContext.ContextStack;
-import org.apache.logging.log4j.core.time.Instant;
-import org.apache.logging.log4j.util.ReadOnlyStringMap;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.impl.ThrowableProxy;
-import org.apache.logging.log4j.message.Message;
-
-import com.fasterxml.jackson.annotation.JsonFilter;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.annotation.JsonRootName;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-
-@JsonRootName(XmlConstants.ELT_EVENT)
-@JacksonXmlRootElement(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EVENT)
-@JsonFilter("org.apache.logging.log4j.core.impl.Log4jLogEvent")
-@JsonPropertyOrder({ "timeMillis", XmlConstants.ELT_INSTANT, "threadName", "level", "loggerName", "marker", "message", "thrown", XmlConstants.ELT_CONTEXT_MAP,
-        JsonConstants.ELT_CONTEXT_STACK, "loggerFQCN", "Source", "endOfBatch" })
-abstract class LogEventJsonMixIn implements LogEvent {
-
-    private static final long serialVersionUID = 1L;
-
-//    @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
-//    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
-//    @JsonSerialize(using = MapSerializer.class)
-//    @JsonDeserialize(using = MapDeserializer.class)
-    @Override
-    @JsonIgnore
-//    @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
-//    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
-    public abstract Map<String, String> getContextMap();
-
-    @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
-    @JsonSerialize(using = ContextDataSerializer.class)
-    @JsonDeserialize(using = ContextDataDeserializer.class)
-    //@JsonIgnore
-    @Override
-    public abstract ReadOnlyStringMap getContextData();
-
-    @JsonProperty(JsonConstants.ELT_CONTEXT_STACK)
-    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK_ITEM)
-    @Override
-    public abstract ContextStack getContextStack();
-
-    @JsonProperty()
-    @JacksonXmlProperty(isAttribute = true)
-    @Override
-    public abstract Level getLevel();
-
-    @JsonProperty()
-    @JacksonXmlProperty(isAttribute = true)
-    @Override
-    public abstract String getLoggerFqcn();
-
-    @JsonProperty()
-    @JacksonXmlProperty(isAttribute = true)
-    @Override
-    public abstract String getLoggerName();
-
-    @JsonProperty(JsonConstants.ELT_MARKER)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MARKER)
-    @Override
-    public abstract Marker getMarker();
-
-    @JsonProperty(JsonConstants.ELT_MESSAGE)
-    @JsonDeserialize(using = SimpleMessageDeserializer.class)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MESSAGE)
-    @Override
-    public abstract Message getMessage();
-
-    @JsonProperty(JsonConstants.ELT_SOURCE)
-    @JsonDeserialize(using = Log4jStackTraceElementDeserializer.class)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SOURCE)
-    @Override
-    public abstract StackTraceElement getSource();
-
-    @Override
-    @JsonProperty("threadId")
-    @JacksonXmlProperty(isAttribute = true, localName = "threadId")
-    public abstract long getThreadId();
-
-    @Override
-    @JsonProperty("thread")
-    @JacksonXmlProperty(isAttribute = true, localName = "thread")
-    public abstract String getThreadName();
-
-    @Override
-    @JsonProperty("threadPriority")
-    @JacksonXmlProperty(isAttribute = true, localName = "threadPriority")
-    public abstract int getThreadPriority();
-
-    @JsonIgnore
-    @Override
-    public abstract Throwable getThrown();
-
-    @JsonProperty(JsonConstants.ELT_THROWN)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_THROWN)
-    @Override
-    public abstract ThrowableProxy getThrownProxy();
-
-    @JsonIgnore // ignore from 2.11
-//    @JsonProperty()
-//    @JacksonXmlProperty(isAttribute = true)
-    @Override
-    public abstract long getTimeMillis();
-
-    @JsonProperty(JsonConstants.ELT_INSTANT)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_INSTANT)
-    @Override
-    public abstract Instant getInstant();
-
-    @JsonProperty()
-    @JacksonXmlProperty(isAttribute = true)
-    @Override
-    public abstract boolean isEndOfBatch();
-
-    @JsonIgnore
-    @Override
-    public abstract boolean isIncludeLocation();
-
-    @Override
-    public abstract void setEndOfBatch(boolean endOfBatch);
-
-    @Override
-    public abstract void setIncludeLocation(boolean locationRequired);
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventWithContextListMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventWithContextListMixIn.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventWithContextListMixIn.java
deleted file mode 100644
index 12b61fa..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/LogEventWithContextListMixIn.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.util.Map;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.Marker;
-import org.apache.logging.log4j.ThreadContext.ContextStack;
-import org.apache.logging.log4j.core.time.Instant;
-import org.apache.logging.log4j.util.ReadOnlyStringMap;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.impl.ThrowableProxy;
-import org.apache.logging.log4j.message.Message;
-
-import com.fasterxml.jackson.annotation.JsonFilter;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.annotation.JsonRootName;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-
-@JsonRootName(XmlConstants.ELT_EVENT)
-@JacksonXmlRootElement(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EVENT)
-@JsonFilter("org.apache.logging.log4j.core.impl.Log4jLogEvent")
-@JsonPropertyOrder({ "timeMillis", XmlConstants.ELT_INSTANT, "threadName", "level", "loggerName", "marker", "message", "thrown", XmlConstants.ELT_CONTEXT_MAP,
-        JsonConstants.ELT_CONTEXT_STACK, "loggerFQCN", "Source", "endOfBatch" })
-abstract class LogEventWithContextListMixIn implements LogEvent {
-
-    private static final long serialVersionUID = 1L;
-
-//    @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
-//    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
-//    @JsonSerialize(using = ListOfMapEntrySerializer.class)
-//    @JsonDeserialize(using = ListOfMapEntryDeserializer.class)
-    @Override
-    @JsonIgnore
-    public abstract Map<String, String> getContextMap();
-
-    @JsonProperty(JsonConstants.ELT_CONTEXT_MAP)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
-    @JsonSerialize(using = ContextDataAsEntryListSerializer.class)
-    @JsonDeserialize(using = ContextDataAsEntryListDeserializer.class)
-//    @JsonIgnore
-    @Override
-    public abstract ReadOnlyStringMap getContextData();
-
-    @JsonProperty(JsonConstants.ELT_CONTEXT_STACK)
-    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_STACK_ITEM)
-    @Override
-    public abstract ContextStack getContextStack();
-
-    @JsonProperty()
-    @JacksonXmlProperty(isAttribute = true)
-    @Override
-    public abstract Level getLevel();
-
-    @JsonProperty()
-    @JacksonXmlProperty(isAttribute = true)
-    @Override
-    public abstract String getLoggerFqcn();
-
-    @JsonProperty()
-    @JacksonXmlProperty(isAttribute = true)
-    @Override
-    public abstract String getLoggerName();
-
-    @JsonProperty(JsonConstants.ELT_MARKER)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MARKER)
-    @Override
-    public abstract Marker getMarker();
-
-    @JsonProperty(JsonConstants.ELT_MESSAGE)
-    @JsonSerialize(using = MessageSerializer.class)
-    @JsonDeserialize(using = SimpleMessageDeserializer.class)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MESSAGE)
-    @Override
-    public abstract Message getMessage();
-
-    @JsonProperty(JsonConstants.ELT_SOURCE)
-    @JsonDeserialize(using = Log4jStackTraceElementDeserializer.class)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SOURCE)
-    @Override
-    public abstract StackTraceElement getSource();
-
-    @Override
-    @JsonProperty("threadId")
-    @JacksonXmlProperty(isAttribute = true, localName = "threadId")
-    public abstract long getThreadId();
-
-    @Override
-    @JsonProperty("thread")
-    @JacksonXmlProperty(isAttribute = true, localName = "thread")
-    public abstract String getThreadName();
-
-    @Override
-    @JsonProperty("threadPriority")
-    @JacksonXmlProperty(isAttribute = true, localName = "threadPriority")
-    public abstract int getThreadPriority();
-
-    @JsonIgnore
-    @Override
-    public abstract Throwable getThrown();
-
-    @JsonProperty(JsonConstants.ELT_THROWN)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_THROWN)
-    @Override
-    public abstract ThrowableProxy getThrownProxy();
-
-    @JsonIgnore // ignore from 2.11
-//    @JsonProperty()
-//    @JacksonXmlProperty(isAttribute = true)
-    @Override
-    public abstract long getTimeMillis();
-
-    @JsonProperty(JsonConstants.ELT_INSTANT)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_INSTANT)
-    @Override
-    public abstract Instant getInstant();
-
-    @JsonProperty()
-    @JacksonXmlProperty(isAttribute = true)
-    @Override
-    public abstract boolean isEndOfBatch();
-
-    @JsonIgnore
-    @Override
-    public abstract boolean isIncludeLocation();
-
-    @Override
-    public abstract void setEndOfBatch(boolean endOfBatch);
-
-    @Override
-    public abstract void setIncludeLocation(boolean locationRequired);
-
-}


[03/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/LevelMixInYamlTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/LevelMixInYamlTest.java b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/LevelMixInYamlTest.java
new file mode 100644
index 0000000..86b9984
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/LevelMixInYamlTest.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.yaml;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.jackson.LevelMixInTest;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Category(Layouts.Yaml.class)
+public class LevelMixInYamlTest extends LevelMixInTest {
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jYamlObjectMapper();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/MarkerMixInYamlTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/MarkerMixInYamlTest.java b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/MarkerMixInYamlTest.java
new file mode 100644
index 0000000..98132cd
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/MarkerMixInYamlTest.java
@@ -0,0 +1,34 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache license, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the license for the specific language governing permissions and
+* limitations under the license.
+*/
+
+package org.apache.logging.log4j.jackson.yaml;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.jackson.AbstractMarkerMixInTest;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Category(Layouts.Yaml.class)
+public class MarkerMixInYamlTest extends AbstractMarkerMixInTest {
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jYamlObjectMapper();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/StackTraceElementYamlMixInTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/StackTraceElementYamlMixInTest.java b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/StackTraceElementYamlMixInTest.java
new file mode 100644
index 0000000..9746655
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/StackTraceElementYamlMixInTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.yaml;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.jackson.Log4jStackTraceElementDeserializer;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
+
+@Category(Layouts.Json.class)
+public class StackTraceElementYamlMixInTest {
+
+    protected String aposToQuotes(final String json) {
+        return json.replace("'", "\"");
+    }
+
+    private void roundtrip(final ObjectMapper mapper)
+            throws JsonProcessingException, IOException, JsonParseException, JsonMappingException {
+        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java",
+                123);
+        final String s = mapper.writeValueAsString(expected);
+        final StackTraceElement actual = mapper.readValue(s, StackTraceElement.class);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testFromYamlWithLog4jModule() throws Exception {
+        final ObjectMapper mapper = new YAMLMapper();
+        final boolean encodeThreadContextAsList = false;
+        final SimpleModule module = new Log4jYamlModule(encodeThreadContextAsList, true, false);
+        module.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
+        mapper.registerModule(module);
+        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java",
+                123);
+        final StackTraceElement actual = mapper.readValue(
+                "---\nclass: package.SomeClass\nmethod: someMethod\nfile: SomeClass.java\nline: 123\n...",
+                StackTraceElement.class);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testFromYamlWithSimpleModule() throws Exception {
+        final ObjectMapper mapper = new YAMLMapper();
+        final SimpleModule module = new SimpleModule();
+        module.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
+        mapper.registerModule(module);
+        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java",
+                123);
+        final StackTraceElement actual = mapper.readValue(
+                "---\nclass: package.SomeClass\nmethod: someMethod\nfile: SomeClass.java\nline: 123\n...",
+                StackTraceElement.class);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testLog4jYamlObjectMapper() throws Exception {
+        this.roundtrip(new Log4jYamlObjectMapper());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/ConcurrentLoggingWithYamlLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/ConcurrentLoggingWithYamlLayoutTest.java b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/ConcurrentLoggingWithYamlLayoutTest.java
new file mode 100644
index 0000000..a0e821c
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/ConcurrentLoggingWithYamlLayoutTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.yaml.layout;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertThat;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.junit.AfterClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+/**
+ * Like the test for LOG4J2-1769.
+ */
+public class ConcurrentLoggingWithYamlLayoutTest {
+
+    private class LoggingThread extends Thread {
+        private final Set<Thread> threads;
+        private final Logger log;
+
+        LoggingThread(final Set<Thread> threads, final Logger log) {
+            this.threads = threads;
+            this.log = log;
+        }
+
+        @Override
+        public void run() {
+            log.info(threads.size());
+            try {
+                for (int i = 0; i < 64; i++) {
+                    log.info("First message.");
+                    log.info("Second message.");
+                }
+            } finally {
+                threads.remove(this);
+            }
+        }
+    }
+
+    @ClassRule
+    public static LoggerContextRule context = new LoggerContextRule("log4j2-yaml-layout.xml");
+
+    private static final String PATH = "target/test-yaml-layout.log";
+
+    @AfterClass
+    public static void after() {
+        new File(PATH).delete();
+    }
+
+    @Test
+    public void testConcurrentLogging() throws Throwable {
+        final Logger log = context.getLogger(ConcurrentLoggingWithYamlLayoutTest.class);
+        final Set<Thread> threads = Collections.synchronizedSet(new HashSet<Thread>());
+        final List<Throwable> thrown = Collections.synchronizedList(new ArrayList<Throwable>());
+
+        for (int x = 0; x < Runtime.getRuntime().availableProcessors() * 2; x++) {
+            final Thread t = new LoggingThread(threads, log);
+            threads.add(t);
+
+            // Appender is configured with ignoreExceptions="false";
+            // any exceptions are propagated to the caller, so we can catch them here.
+            t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+                @Override
+                public void uncaughtException(final Thread t, final Throwable e) {
+                    thrown.add(e);
+                }
+            });
+            t.start();
+        }
+
+        while (!threads.isEmpty()) {
+            log.info("not done going to sleep...");
+            Thread.sleep(10);
+        }
+
+        // if any error occurred, fail this test
+        if (!thrown.isEmpty()) {
+            throw thrown.get(0);
+        }
+
+        // simple test to ensure content is not corrupted
+        if (new File(PATH).exists()) {
+            final List<String> lines = Files.readAllLines(new File(PATH).toPath(), Charset.defaultCharset());
+            assertThat(lines.get(0), startsWith("---"));
+            // TODO more
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayoutTest.java b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayoutTest.java
new file mode 100644
index 0000000..b8e3ee6
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/layout/YamlLayoutTest.java
@@ -0,0 +1,382 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.yaml.layout;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.BasicConfigurationFactory;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.layout.LogEventFixtures;
+import org.apache.logging.log4j.core.lookup.JavaLookup;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.apache.logging.log4j.jackson.AbstractJacksonLayout;
+import org.apache.logging.log4j.jackson.yaml.Log4jYamlObjectMapper;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.spi.AbstractLogger;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * Tests the YamlLayout class.
+ */
+@Category(Layouts.Yaml.class)
+public class YamlLayoutTest {
+    static ConfigurationFactory cf = new BasicConfigurationFactory();
+
+    @AfterClass
+    public static void cleanupClass() {
+        ConfigurationFactory.removeConfigurationFactory(cf);
+        ThreadContext.clearAll();
+    }
+
+    @BeforeClass
+    public static void setupClass() {
+        ThreadContext.clearAll();
+        ConfigurationFactory.setConfigurationFactory(cf);
+        final LoggerContext ctx = LoggerContext.getContext();
+        ctx.reconfigure();
+    }
+
+    LoggerContext ctx = LoggerContext.getContext();
+
+    Logger rootLogger = this.ctx.getRootLogger();
+
+    private void checkAt(final String expected, final int lineIndex, final List<String> list) {
+        final String trimedLine = list.get(lineIndex).trim();
+        assertTrue("Incorrect line index " + lineIndex + ": " + Strings.dquote(trimedLine),
+                trimedLine.equals(expected));
+    }
+
+    private void checkContains(final String expected, final List<String> list) {
+        for (final String string : list) {
+            final String trimedLine = string.trim();
+            if (trimedLine.equals(expected)) {
+                return;
+            }
+        }
+        Assert.fail("Cannot find " + expected + " in " + list);
+    }
+
+    private void checkMapEntry(final String key, final String value, final boolean compact, final String str) {
+        // "name":"value"
+        //final String expected = String.format("- key: \"%s\"\n  value: \"%s\"", key, value);
+        final String expected = String.format("%s: \"%s\"", key, value);
+        assertTrue("Cannot find " + expected + " in " + str, str.contains(expected));
+    }
+
+    private void checkProperty(final String key, final String value, final boolean compact, final String str,
+            final boolean isValue) {
+        final String propSep = this.toPropertySeparator(compact, isValue);
+        // {"key":"MDC.B","value":"B_Value"}
+        final String expected = String.format("%s%s\"%s\"", key, propSep, value);
+        assertTrue("Cannot find " + expected + " in " + str, str.contains(expected));
+    }
+
+    private void checkPropertyName(final String name, final boolean compact, final String str, final boolean isValue) {
+        final String propSep = this.toPropertySeparator(compact, isValue);
+        assertTrue(str, str.contains(name + propSep));
+    }
+
+    private void checkPropertyNameAbsent(final String name, final boolean compact, final String str, final boolean isValue) {
+        final String propSep = this.toPropertySeparator(compact, isValue);
+        assertFalse(str, str.contains(name + propSep));
+    }
+
+    private String prepareYAMLForStacktraceTests(final boolean stacktraceAsString) {
+        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
+        // @formatter:off
+        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
+                .setIncludeStacktrace(true)
+                .setStacktraceAsString(stacktraceAsString)
+                .build();
+        // @formatter:off
+        return layout.toSerializable(expected);
+    }
+
+    @Test
+    public void testAdditionalFields() throws Exception {
+        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
+                .setLocationInfo(false)
+                .setProperties(false)
+                .setIncludeStacktrace(false)
+                .setAdditionalFields(new KeyValuePair[] {
+                    new KeyValuePair("KEY1", "VALUE1"),
+                    new KeyValuePair("KEY2", "${java:runtime}"), })
+                .setCharset(StandardCharsets.UTF_8)
+                .setConfiguration(ctx.getConfiguration())
+                .build();
+        final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
+        assertTrue(str, str.contains("KEY1: \"VALUE1\""));
+        assertTrue(str, str.contains("KEY2: \"" + new JavaLookup().getRuntime() + "\""));
+    }
+
+    private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean eventEol,
+            final boolean includeContext, final boolean contextMapAslist, final boolean includeStacktrace) throws Exception {
+        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
+        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
+                .setLocationInfo(includeSource)
+                .setProperties(includeContext)
+                .setIncludeStacktrace(includeStacktrace)
+                .setCharset(StandardCharsets.UTF_8)
+                .build();
+        final String str = layout.toSerializable(expected);
+        // System.out.println(str);
+        // Just check for \n since \r might or might not be there.
+        assertEquals(str, !compact || eventEol, str.contains("\n"));
+        assertEquals(str, includeSource, str.contains("source"));
+        assertEquals(str, includeContext, str.contains("contextMap"));
+        final Log4jLogEvent actual = new Log4jYamlObjectMapper(contextMapAslist, includeStacktrace,false).readValue(str, Log4jLogEvent.class);
+        LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext, includeStacktrace);
+        if (includeContext) {
+            this.checkMapEntry("MDC.A", "A_Value", compact, str);
+            this.checkMapEntry("MDC.B", "B_Value", compact, str);
+        }
+        //
+        assertNull(actual.getThrown());
+        // make sure the names we want are used
+        this.checkPropertyName("instant", compact, str, false);
+        this.checkPropertyName("thread", compact, str, true); // and not threadName
+        this.checkPropertyName("level", compact, str, true);
+        this.checkPropertyName("loggerName", compact, str, true);
+        this.checkPropertyName("marker", compact, str, false);
+        this.checkPropertyName("name", compact, str, true);
+        this.checkPropertyName("parents", compact, str, false);
+        this.checkPropertyName("message", compact, str, true);
+        this.checkPropertyName("thrown", compact, str, false);
+        this.checkPropertyName("cause", compact, str, false);
+        this.checkPropertyName("commonElementCount", compact, str, true);
+        this.checkPropertyName("localizedMessage", compact, str, true);
+        if (includeStacktrace) {
+            this.checkPropertyName("extendedStackTrace", compact, str, false);
+            this.checkPropertyName("class", compact, str, true);
+            this.checkPropertyName("method", compact, str, true);
+            this.checkPropertyName("file", compact, str, true);
+            this.checkPropertyName("line", compact, str, true);
+            this.checkPropertyName("exact", compact, str, true);
+            this.checkPropertyName("location", compact, str, true);
+            this.checkPropertyName("version", compact, str, true);
+        } else {
+            this.checkPropertyNameAbsent("extendedStackTrace", compact, str, false);
+        }
+        this.checkPropertyName("suppressed", compact, str, false);
+        this.checkPropertyName("loggerFqcn", compact, str, true);
+        this.checkPropertyName("endOfBatch", compact, str, true);
+        if (includeContext) {
+            this.checkPropertyName("contextMap", compact, str, false);
+        } else {
+            this.checkPropertyNameAbsent("contextMap", compact, str, false);
+        }
+        this.checkPropertyName("contextStack", compact, str, false);
+        if (includeSource) {
+            this.checkPropertyName("source", compact, str, false);
+        } else {
+            this.checkPropertyNameAbsent("source", compact, str, false);
+        }
+        // check some attrs
+        this.checkProperty("loggerFqcn", "f.q.c.n", compact, str, true);
+        this.checkProperty("loggerName", "a.B", compact, str, true);
+    }
+
+    @Test
+    public void testContentType() {
+        final AbstractJacksonLayout layout = YamlLayout.createDefaultLayout();
+        assertEquals("application/yaml; charset=UTF-8", layout.getContentType());
+    }
+
+    @Test
+    public void testDefaultCharset() {
+        final AbstractJacksonLayout layout = YamlLayout.createDefaultLayout();
+        assertEquals(StandardCharsets.UTF_8, layout.getCharset());
+    }
+
+    @Test
+    public void testEscapeLayout() throws Exception {
+        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
+        for (final Appender appender : appenders.values()) {
+            this.rootLogger.removeAppender(appender);
+        }
+        final Configuration configuration = rootLogger.getContext().getConfiguration();
+        // set up appender
+        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
+                .setLocationInfo(true)
+                .setProperties(true)
+                .setIncludeStacktrace(true)
+                .setConfiguration(configuration)
+                .build();
+
+        final ListAppender appender = new ListAppender("List", null, layout, true, false);
+        appender.start();
+
+        // set appender on root and set level to debug
+        this.rootLogger.addAppender(appender);
+        this.rootLogger.setLevel(Level.DEBUG);
+
+        // output starting message
+        this.rootLogger.debug("Here is a quote ' and then a double quote \"");
+
+        appender.stop();
+
+        final List<String> list = appender.getMessages();
+
+        this.checkAt("---", 0, list);
+        this.checkContains("level: \"DEBUG\"", list);
+        this.checkContains("message: \"Here is a quote ' and then a double quote \\\"\"", list);
+        this.checkContains("loggerFqcn: \"" + AbstractLogger.class.getName() + "\"", list);
+        for (final Appender app : appenders.values()) {
+            this.rootLogger.addAppender(app);
+        }
+    }
+
+    @Test
+    public void testExcludeStacktrace() throws Exception {
+        this.testAllFeatures(false, false, false, false, false, false);
+    }
+
+    @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"));
+    }
+
+    @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 case for MDC conversion pattern.
+     */
+    @Test
+    public void testLayout() throws Exception {
+        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
+        for (final Appender appender : appenders.values()) {
+            this.rootLogger.removeAppender(appender);
+        }
+        final Configuration configuration = rootLogger.getContext().getConfiguration();
+        // set up appender
+        // Use [[ and ]] to test header and footer (instead of [ and ])
+        final AbstractJacksonLayout layout = YamlLayout.createLayout(configuration, true, true, "[[", "]]", null, true);
+        final ListAppender appender = new ListAppender("List", null, layout, true, false);
+        appender.start();
+
+        // set appender on root and set level to debug
+        this.rootLogger.addAppender(appender);
+        this.rootLogger.setLevel(Level.DEBUG);
+
+        // output starting message
+        this.rootLogger.debug("starting mdc pattern test");
+
+        this.rootLogger.debug("empty mdc");
+
+        ThreadContext.put("key1", "value1");
+        ThreadContext.put("key2", "value2");
+
+        this.rootLogger.debug("filled mdc");
+
+        ThreadContext.remove("key1");
+        ThreadContext.remove("key2");
+
+        this.rootLogger.error("finished mdc pattern test", new NullPointerException("test"));
+
+        appender.stop();
+
+        final List<String> list = appender.getMessages();
+
+        this.checkAt("---", 0, list);
+        this.checkContains("loggerFqcn: \"" + AbstractLogger.class.getName() + "\"", list);
+        this.checkContains("level: \"DEBUG\"", list);
+        this.checkContains("message: \"starting mdc pattern test\"", list);
+        for (final Appender app : appenders.values()) {
+            this.rootLogger.addAppender(app);
+        }
+    }
+
+    @Test
+    public void testLayoutLoggerName() throws Exception {
+        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
+                .setLocationInfo(false)
+                .setProperties(false)
+                .setIncludeStacktrace(true)
+                .setCharset(StandardCharsets.UTF_8)
+                .build();
+        final Log4jLogEvent expected = Log4jLogEvent.newBuilder() //
+                .setLoggerName("a.B") //
+                .setLoggerFqcn("f.q.c.n") //
+                .setLevel(Level.DEBUG) //
+                .setMessage(new SimpleMessage("M")) //
+                .setThreadName("threadName") //
+                .setTimeMillis(1).build();
+        final String str = layout.toSerializable(expected);
+        assertTrue(str, str.contains("loggerName: \"a.B\""));
+        final Log4jLogEvent actual = new Log4jYamlObjectMapper(false, true, false).readValue(str, Log4jLogEvent.class);
+        assertEquals(expected.getLoggerName(), actual.getLoggerName());
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testLocationOffCompactOffMdcOff() throws Exception {
+        this.testAllFeatures(false, false, false, false, false, true);
+    }
+
+    @Test
+    public void testLocationOnCompactOffEventEolOffMdcOn() throws Exception {
+        this.testAllFeatures(true, false, false, true, false, true);
+    }
+
+    @Test
+    public void testStacktraceAsNonString() throws Exception {
+        final String str = prepareYAMLForStacktraceTests(false);
+        assertTrue(str, str.contains("extendedStackTrace:\n    - "));
+    }
+
+    @Test
+    public void testStacktraceAsString() throws Exception {
+        final String str = prepareYAMLForStacktraceTests(true);
+        assertTrue(str, str.contains("extendedStackTrace: \"java.lang.NullPointerException"));
+    }
+
+    private String toPropertySeparator(final boolean compact, final boolean value) {
+        return value ? ": " : ":";
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/parser/YamlLogEventParserTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/parser/YamlLogEventParserTest.java b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/parser/YamlLogEventParserTest.java
new file mode 100644
index 0000000..7e689e6
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/test/java/org/apache/logging/log4j/jackson/yaml/parser/YamlLogEventParserTest.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.yaml.parser;
+
+import java.nio.charset.StandardCharsets;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.parser.AbstractLogEventParserTest;
+import org.apache.logging.log4j.core.parser.ParseException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class YamlLogEventParserTest extends AbstractLogEventParserTest {
+
+    private static final String YAML = "---\n" +
+            "timeMillis: 1493121664118\n" +
+            "instant:\n" +
+            " epochSecond: 1493121664\n" +
+            " nanoOfSecond: 118000000\n" +
+            "thread: \"main\"\n" +
+            "level: \"INFO\"\n" +
+            "loggerName: \"HelloWorld\"\n" +
+            "marker:\n" +
+            " name: \"child\"\n" +
+            " parents:\n" +
+            " - name: \"parent\"\n" +
+            "   parents:\n" +
+            "   - name: \"grandparent\"\n" +
+            "message: \"Hello, world!\"\n" +
+            "thrown:\n" +
+            " commonElementCount: 0\n" +
+            " message: \"error message\"\n" +
+            " name: \"java.lang.RuntimeException\"\n" +
+            " extendedStackTrace:\n" +
+            " - class: \"logtest.Main\"\n" +
+            "   method: \"main\"\n" +
+            "   file: \"Main.java\"\n" +
+            "   line: 29\n" +
+            "   exact: true\n" +
+            "   location: \"classes/\"\n" +
+            "   version: \"?\"\n" +
+            "contextStack:\n" +
+            "- \"one\"\n" +
+            "- \"two\"\n" +
+            "endOfBatch: false\n" +
+            "loggerFqcn: \"org.apache.logging.log4j.spi.AbstractLogger\"\n" +
+            "contextMap:\n" +
+            " bar: \"BAR\"\n" +
+            " foo: \"FOO\"\n" +
+            "threadId: 1\n" +
+            "threadPriority: 5\n" +
+            "source:\n" +
+            " class: \"logtest.Main\"\n" +
+            " method: \"main\"\n" +
+            " file: \"Main.java\"\n" +
+            " line: 29";
+
+    private YamlLogEventParser parser;
+
+    @Before
+    public void setup() {
+        parser = new YamlLogEventParser();
+    }
+
+    @Test
+    public void testByteArray() throws ParseException {
+        final LogEvent logEvent = parser.parseFrom(YAML.getBytes(StandardCharsets.UTF_8));
+        assertLogEvent(logEvent);
+    }
+
+    @Test
+    public void testByteArrayOffsetLength() throws ParseException {
+        final byte[] bytes = ("abc" + YAML + "def").getBytes(StandardCharsets.UTF_8);
+        final LogEvent logEvent = parser.parseFrom(bytes, 3, bytes.length - 6);
+        assertLogEvent(logEvent);
+    }
+
+    @Test
+    public void testEmptyObject() throws ParseException {
+        parser.parseFrom("---\n");
+    }
+
+    @Test
+    public void testString() throws ParseException {
+        final LogEvent logEvent = parser.parseFrom(YAML);
+        assertLogEvent(logEvent);
+    }
+
+    @Test(expected = ParseException.class)
+    public void testStringEmpty() throws ParseException {
+        parser.parseFrom("");
+    }
+
+    @Test
+    public void testStringIgnoreInvalidProperty() throws ParseException {
+        parser.parseFrom("---\nfoo: \"bar\"\n");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testStringInvalidYaml() throws ParseException {
+        parser.parseFrom("foobar");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testStringWrongPropertyType() throws ParseException {
+        parser.parseFrom("---\nthreadId: \"foobar\"\n");
+    }
+
+    @Test
+    public void testTimeMillisIgnored() throws ParseException {
+        parser.parseFrom("---\ntimeMillis: \"foobar\"\n");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-yaml/src/test/resources/log4j2-yaml-layout.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-yaml/src/test/resources/log4j2-yaml-layout.xml b/log4j-layout-jackson-yaml/src/test/resources/log4j2-yaml-layout.xml
new file mode 100644
index 0000000..f01d1e6
--- /dev/null
+++ b/log4j-layout-jackson-yaml/src/test/resources/log4j2-yaml-layout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<Configuration status="INFO" packages="">
+  <Appenders>
+    <File name="stdout" ignoreExceptions="false" fileName="target/test-yaml-layout.log" append="false">
+      <YamlLayout compact="true" eventEol="true" />
+    </File>
+  </Appenders>
+
+  <Loggers>
+    <Root level="INFO">
+      <AppenderRef ref="stdout" />
+    </Root>
+  </Loggers>
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/pom.xml b/log4j-layout-jackson/pom.xml
new file mode 100644
index 0000000..ad61835
--- /dev/null
+++ b/log4j-layout-jackson/pom.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ~ Licensed to the Apache Software Foundation (ASF) under one or more ~ contributor license agreements. See the NOTICE 
+  file distributed with ~ this work for additional information regarding copyright ownership. ~ The ASF licenses this file 
+  to You under the Apache License, Version 2.0 ~ (the "License"); you may not use this file except in compliance with ~ the 
+  License. You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable 
+  law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES 
+  OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and 
+  ~ limitations under the License. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>org.apache.logging.log4j</groupId>
+    <artifactId>log4j</artifactId>
+    <version>3.0.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>log4j-layout-jackson</artifactId>
+  <name>Apache Log4j Layout for Jackson</name>
+  <description>
+    Apache Log4j Layout for Jackson.
+  </description>
+  <properties>
+    <log4jParentDir>${basedir}/..</log4jParentDir>
+    <docLabel>Log4j Layout for Jackson Documentation</docLabel>
+    <projectDir>/log4j-layout-jackson</projectDir>
+    <module.name>org.apache.logging.log4j.jackson</module.name>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+    </dependency>
+    <!-- Test Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <type>test-jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <type>test-jar</type>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>default-jar</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+            <configuration>
+              <archive>
+                <manifestFile>${manifestfile}</manifestFile>
+                <manifestEntries>
+                  <Specification-Title>${project.name}</Specification-Title>
+                  <Specification-Version>${project.version}</Specification-Version>
+                  <Specification-Vendor>${project.organization.name}</Specification-Vendor>
+                  <Implementation-Title>${project.name}</Implementation-Title>
+                  <Implementation-Version>${project.version}</Implementation-Version>
+                  <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+                  <Implementation-Vendor-Id>org.apache</Implementation-Vendor-Id>
+                  <X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
+                  <X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
+                </manifestEntries>
+              </archive>
+            </configuration>
+          </execution>
+          <execution>
+            <id>default</id>
+            <goals>
+              <goal>test-jar</goal>
+            </goals>
+            <configuration>
+              <archive>
+                <manifestFile>${manifestfile}</manifestFile>
+                <manifestEntries>
+                  <Specification-Title>${project.name}</Specification-Title>
+                  <Specification-Version>${project.version}</Specification-Version>
+                  <Specification-Vendor>${project.organization.name}</Specification-Vendor>
+                  <Implementation-Title>${project.name}</Implementation-Title>
+                  <Implementation-Version>${project.version}</Implementation-Version>
+                  <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+                  <Implementation-Vendor-Id>org.apache</Implementation-Vendor-Id>
+                  <X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
+                  <X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
+                </manifestEntries>
+              </archive>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Fragment-Host>org.apache.logging.log4j.jackson</Fragment-Host>
+            <Export-Package>*</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-changes-plugin</artifactId>
+        <version>${changes.plugin.version}</version>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>changes-report</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+        <configuration>
+          <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
+          <useJql>true</useJql>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>${checkstyle.plugin.version}</version>
+        <configuration>
+          <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
+          <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
+          <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
+          <enableRulesSummary>false</enableRulesSummary>
+          <propertyExpansion>basedir=${basedir}</propertyExpansion>
+          <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>${javadoc.plugin.version}</version>
+        <configuration>
+          <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
+            Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
+            and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
+          <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating project -->
+          <detectOfflineLinks>false</detectOfflineLinks>
+          <linksource>true</linksource>
+        </configuration>
+        <reportSets>
+          <reportSet>
+            <id>non-aggregate</id>
+            <reports>
+              <report>javadoc</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>${findbugs.plugin.version}</version>
+        <configuration>
+          <fork>true</fork>
+          <jvmArgs>-Duser.language=en</jvmArgs>
+          <threshold>Normal</threshold>
+          <effort>Default</effort>
+          <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jxr-plugin</artifactId>
+        <version>${jxr.plugin.version}</version>
+        <reportSets>
+          <reportSet>
+            <id>non-aggregate</id>
+            <reports>
+              <report>jxr</report>
+            </reports>
+          </reportSet>
+          <reportSet>
+            <id>aggregate</id>
+            <reports>
+              <report>aggregate</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-pmd-plugin</artifactId>
+        <version>${pmd.plugin.version}</version>
+        <configuration>
+          <targetJdk>${maven.compiler.target}</targetJdk>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+</project>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractJacksonFactory.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractJacksonFactory.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractJacksonFactory.java
new file mode 100644
index 0000000..ad4503c
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractJacksonFactory.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+
+import com.fasterxml.jackson.core.PrettyPrinter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
+
+public abstract class AbstractJacksonFactory {
+
+    protected final boolean includeStacktrace;
+
+    protected final boolean stacktraceAsString;
+    public AbstractJacksonFactory(final boolean includeStacktrace, final boolean stacktraceAsString) {
+        super();
+        this.includeStacktrace = includeStacktrace;
+        this.stacktraceAsString = stacktraceAsString;
+    }
+
+    abstract protected String getPropertyNameForContextMap();
+
+    abstract protected String getPropertyNameForNanoTime();
+
+    abstract protected String getPropertyNameForSource();
+
+    abstract protected String getPropertyNameForStackTrace();
+
+    abstract protected PrettyPrinter newCompactPrinter();
+
+    abstract protected ObjectMapper newObjectMapper();
+
+    abstract protected PrettyPrinter newPrettyPrinter();
+
+    public ObjectWriter newWriter(final boolean locationInfo, final boolean properties, final boolean compact) {
+        final SimpleFilterProvider filters = new SimpleFilterProvider();
+        final Set<String> except = new HashSet<>(4);
+        if (!locationInfo) {
+            except.add(this.getPropertyNameForSource());
+        }
+        if (!properties) {
+            except.add(this.getPropertyNameForContextMap());
+        }
+        if (!includeStacktrace) {
+            except.add(this.getPropertyNameForStackTrace());
+        }
+        except.add(this.getPropertyNameForNanoTime());
+        filters.addFilter(Log4jLogEvent.class.getName(), SimpleBeanPropertyFilter.serializeAllExcept(except));
+        final ObjectWriter writer = this.newObjectMapper()
+                .writer(compact ? this.newCompactPrinter() : this.newPrettyPrinter());
+        return writer.with(filters);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractJacksonLayout.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractJacksonLayout.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractJacksonLayout.java
new file mode 100644
index 0000000..da66b9d
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractJacksonLayout.java
@@ -0,0 +1,351 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.impl.MutableLogEvent;
+import org.apache.logging.log4j.core.layout.AbstractStringLayout;
+import org.apache.logging.log4j.core.lookup.StrSubstitutor;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.apache.logging.log4j.core.util.StringBuilderWriter;
+import org.apache.logging.log4j.util.Strings;
+
+import com.fasterxml.jackson.databind.ObjectWriter;
+
+public abstract class AbstractJacksonLayout extends AbstractStringLayout {
+
+    public static abstract class Builder<B extends Builder<B>> extends AbstractStringLayout.Builder<B> {
+
+        @PluginBuilderAttribute
+        private boolean eventEol;
+
+        @PluginBuilderAttribute
+        private boolean compact;
+
+        @PluginBuilderAttribute
+        private boolean complete;
+
+        @PluginBuilderAttribute
+        private boolean locationInfo;
+
+        @PluginBuilderAttribute
+        private boolean properties;
+
+        @PluginBuilderAttribute
+        private boolean includeStacktrace = true;
+
+        @PluginBuilderAttribute
+        private boolean stacktraceAsString = false;
+
+        @PluginBuilderAttribute
+        private boolean includeNullDelimiter = false;
+
+        @PluginElement("AdditionalField")
+        private KeyValuePair[] additionalFields;
+
+        public KeyValuePair[] getAdditionalFields() {
+            return additionalFields;
+        }
+
+        public boolean getEventEol() {
+            return eventEol;
+        }
+
+        public boolean isCompact() {
+            return compact;
+        }
+
+        public boolean isComplete() {
+            return complete;
+        }
+
+        public boolean isIncludeNullDelimiter() {
+            return includeNullDelimiter;
+        }
+
+        /**
+         * If "true", includes the stack trace of any Throwable in the generated data, defaults to "true".
+         *
+         * @return If "true", includes the stack trace of any Throwable in the generated data, defaults to "true".
+         */
+        public boolean isIncludeStacktrace() {
+            return includeStacktrace;
+        }
+
+        public boolean isLocationInfo() {
+            return locationInfo;
+        }
+
+        public boolean isProperties() {
+            return properties;
+        }
+
+        public boolean isStacktraceAsString() {
+            return stacktraceAsString;
+        }
+
+        /**
+         * Additional fields to set on each log event.
+         *
+         * @return this builder
+         */
+        public B setAdditionalFields(final KeyValuePair[] additionalFields) {
+            this.additionalFields = additionalFields;
+            return asBuilder();
+        }
+
+        public B setCompact(final boolean compact) {
+            this.compact = compact;
+            return asBuilder();
+        }
+
+        public B setComplete(final boolean complete) {
+            this.complete = complete;
+            return asBuilder();
+        }
+
+        public B setEventEol(final boolean eventEol) {
+            this.eventEol = eventEol;
+            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();
+        }
+
+        /**
+         * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true".
+         *
+         * @param includeStacktrace
+         *            If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true".
+         * @return this builder
+         */
+        public B setIncludeStacktrace(final boolean includeStacktrace) {
+            this.includeStacktrace = includeStacktrace;
+            return asBuilder();
+        }
+
+        public B setLocationInfo(final boolean locationInfo) {
+            this.locationInfo = locationInfo;
+            return asBuilder();
+        }
+
+        public B setProperties(final boolean properties) {
+            this.properties = properties;
+            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(final boolean stacktraceAsString) {
+            this.stacktraceAsString = stacktraceAsString;
+            return asBuilder();
+        }
+
+        protected String toStringOrNull(final byte[] header) {
+            return header == null ? null : new String(header, Charset.defaultCharset());
+        }
+    }
+    /**
+     * Subclasses can annotate with Jackson annotations for JSON example.
+     */
+    public static class LogEventWithAdditionalFields {
+
+        private final Object logEvent;
+        private final Map<String, String> additionalFields;
+
+        public LogEventWithAdditionalFields(final Object logEvent, final Map<String, String> additionalFields) {
+            this.logEvent = logEvent;
+            this.additionalFields = additionalFields;
+        }
+
+        public Map<String, String> getAdditionalFields() {
+            return additionalFields;
+        }
+
+        public Object getLogEvent() {
+            return logEvent;
+        }
+    }
+
+    protected static class ResolvableKeyValuePair {
+
+        final String key;
+        final String value;
+        final boolean valueNeedsLookup;
+
+        ResolvableKeyValuePair(final KeyValuePair pair) {
+            this.key = pair.getKey();
+            this.value = pair.getValue();
+            this.valueNeedsLookup = AbstractJacksonLayout.valueNeedsLookup(this.value);
+        }
+    }
+
+    protected static final String DEFAULT_EOL = "\r\n";
+    protected static final String COMPACT_EOL = Strings.EMPTY;
+    private static LogEvent convertMutableToLog4jEvent(final LogEvent event) {
+        // TODO Jackson-based layouts have certain filters set up for Log4jLogEvent.
+        // TODO Need to set up the same filters for MutableLogEvent but don't know how...
+        // This is a workaround.
+        return event instanceof MutableLogEvent ? ((MutableLogEvent) event).createMemento() : event;
+    }
+    private static ResolvableKeyValuePair[] prepareAdditionalFields(final Configuration config,
+            final KeyValuePair[] additionalFields) {
+        if (additionalFields == null || additionalFields.length == 0) {
+            // No fields set
+            return new ResolvableKeyValuePair[0];
+        }
+
+        // Convert to specific class which already determines whether values needs lookup during serialization
+        final ResolvableKeyValuePair[] resolvableFields = new ResolvableKeyValuePair[additionalFields.length];
+
+        for (int i = 0; i < additionalFields.length; i++) {
+            final ResolvableKeyValuePair resolvable = resolvableFields[i] = new ResolvableKeyValuePair(additionalFields[i]);
+
+            // Validate
+            if (config == null && resolvable.valueNeedsLookup) {
+                throw new IllegalArgumentException(
+                        "configuration needs to be set when there are additional fields with variables");
+            }
+        }
+
+        return resolvableFields;
+    }
+    protected static boolean valueNeedsLookup(final String value) {
+        return value != null && value.contains("${");
+    }
+    protected final String eol;
+
+    protected final ObjectWriter objectWriter;
+
+    protected final boolean compact;
+
+    protected final boolean complete;
+
+    protected final boolean includeNullDelimiter;
+
+    protected final ResolvableKeyValuePair[] additionalFields;
+
+    @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);
+    }
+
+    @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, final boolean includeNullDelimiter) {
+        this(config, objectWriter, charset, compact, complete, eventEol, headerSerializer, footerSerializer,
+                includeNullDelimiter, null);
+    }
+
+    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,
+            final KeyValuePair[] additionalFields) {
+        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;
+        this.additionalFields = prepareAdditionalFields(config, additionalFields);
+    }
+
+    protected LogEventWithAdditionalFields createLogEventWithAdditionalFields(final LogEvent event,
+            final Map<String, String> additionalFieldsMap) {
+        return new LogEventWithAdditionalFields(event, additionalFieldsMap);
+    }
+
+    private Map<String, String> resolveAdditionalFields(final LogEvent logEvent) {
+        // Note: LinkedHashMap retains order
+        final Map<String, String> additionalFieldsMap = new LinkedHashMap<>(additionalFields.length);
+        final StrSubstitutor strSubstitutor = configuration.getStrSubstitutor();
+
+        // Go over each field
+        for (final ResolvableKeyValuePair pair : additionalFields) {
+            if (pair.valueNeedsLookup) {
+                // Resolve value
+                additionalFieldsMap.put(pair.key, strSubstitutor.replace(logEvent, pair.value));
+            } else {
+                // Plain text value
+                additionalFieldsMap.put(pair.key, pair.value);
+            }
+        }
+
+        return additionalFieldsMap;
+    }
+
+    /**
+     * Formats a {@link org.apache.logging.log4j.core.LogEvent}.
+     *
+     * @param event
+     *            The LogEvent.
+     * @return The XML representation of the LogEvent.
+     */
+    @Override
+    public String toSerializable(final LogEvent event) {
+        try (final StringBuilderWriter writer = new StringBuilderWriter()) {
+            toSerializable(event, writer);
+            return writer.toString();
+        } catch (final IOException e) {
+            // Should this be an ISE or IAE?
+            LOGGER.error(e);
+            return Strings.EMPTY;
+        }
+    }
+
+    public void toSerializable(final LogEvent event, final Writer writer) throws IOException {
+        objectWriter.writeValue(writer, wrapLogEvent(convertMutableToLog4jEvent(event)));
+        writer.write(eol);
+        if (includeNullDelimiter) {
+            writer.write('\0');
+        }
+        markEvent();
+    }
+
+    protected Object wrapLogEvent(final LogEvent event) {
+        if (additionalFields.length > 0) {
+            // Construct map for serialization - note that we are intentionally using original LogEvent
+            final Map<String, String> additionalFieldsMap = resolveAdditionalFields(event);
+            // This class combines LogEvent with AdditionalFields during serialization
+            return createLogEventWithAdditionalFields(event, additionalFieldsMap);
+        }
+        // No additional fields, return original object
+        return event;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractLogEventMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractLogEventMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractLogEventMixIn.java
new file mode 100644
index 0000000..43784d6
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/AbstractLogEventMixIn.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.util.Map;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.message.Message;
+
+import com.fasterxml.jackson.annotation.JsonFilter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+/**
+ * <pre>
+ * AbstractLogEventMixIn
+*├─ AbstractLogEventXmlMixIn
+*├──── LogEventWithContextListXmlMixIn
+*├──── LogEventWithContextMapXmlMixIn
+*├─ AbstractLogEventJsonMixIn
+*├──── LogEventWithContextListJsonMixIn
+*├──── LogEventWithContextMapJsonMixIn
+ * </pre>
+ */
+@JsonFilter(AbstractLogEventMixIn.JSON_FILTER_ID)
+public abstract class AbstractLogEventMixIn implements LogEvent {
+
+    public static final String ATTR_END_OF_BATCH = "endOfBatch";
+    public static final String ATTR_LEVEL = "level";
+    public static final String ATTR_LOGGER_FQCN = "loggerFqcn";
+    public static final String ATTR_LOGGER_NAME = "loggerName";
+    public static final String ATTR_MARKER = "marker";
+    public static final String ATTR_THREAD = "thread";
+    public static final String ATTR_THREAD_ID = "threadId";
+    public static final String ATTR_THREAD_PRIORITY = "threadPriority";
+    public static final String ELT_MESSAGE = "message";
+    public static final String JSON_FILTER_ID = "org.apache.logging.log4j.core.impl.Log4jLogEvent";
+
+    private static final long serialVersionUID = 1L;
+
+    @Deprecated
+    @Override
+    @JsonIgnore
+    public abstract Map<String, String> getContextMap();
+
+    @JsonSerialize(using = MessageSerializer.class)
+    @JsonDeserialize(using = SimpleMessageDeserializer.class)
+    @Override
+    public abstract Message getMessage();
+
+    @JsonIgnore
+    @Override
+    public abstract Throwable getThrown();
+
+    @JsonIgnore // ignore from 2.11.0
+    @Override
+    public abstract long getTimeMillis();
+
+    @JsonIgnore
+    @Override
+    public abstract boolean isIncludeLocation();
+
+    @Override
+    public abstract void setEndOfBatch(boolean endOfBatch);
+
+    @Override
+    public abstract void setIncludeLocation(boolean locationRequired);
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataAsEntryListDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataAsEntryListDeserializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataAsEntryListDeserializer.java
new file mode 100644
index 0000000..6efee4f
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataAsEntryListDeserializer.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.logging.log4j.core.impl.ContextDataFactory;
+import org.apache.logging.log4j.util.StringMap;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class ContextDataAsEntryListDeserializer extends StdDeserializer<StringMap> {
+
+    private static final long serialVersionUID = 1L;
+
+    ContextDataAsEntryListDeserializer() {
+        super(Map.class);
+    }
+
+    @Override
+    public StringMap deserialize(final JsonParser jp, final DeserializationContext ctxt)
+            throws IOException, JsonProcessingException {
+        final List<MapEntry> list = jp.readValueAs(new TypeReference<List<MapEntry>>() {
+            // do nothing
+        });
+        final StringMap contextData = ContextDataFactory.createContextData();
+        for (final MapEntry mapEntry : list) {
+            contextData.putValue(mapEntry.getKey(), mapEntry.getValue());
+        }
+        return contextData;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataAsEntryListSerializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataAsEntryListSerializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataAsEntryListSerializer.java
new file mode 100644
index 0000000..d3c7551
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataAsEntryListSerializer.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.logging.log4j.util.BiConsumer;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class ContextDataAsEntryListSerializer extends StdSerializer<ReadOnlyStringMap> {
+
+    private static final long serialVersionUID = 1L;
+
+    protected ContextDataAsEntryListSerializer() {
+        super(Map.class, false);
+    }
+
+    protected MapEntry createMapEntry(final String key, final String value) {
+        return new MapEntry(key, value);
+    }
+
+    protected MapEntry[] createMapEntryArray(final int size) {
+        return new MapEntry[size];
+    }
+
+    @Override
+    public void serialize(final ReadOnlyStringMap contextData, final JsonGenerator jgen,
+            final SerializerProvider provider) throws IOException, JsonGenerationException {
+
+        final MapEntry[] pairs = createMapEntryArray(contextData.size());
+        contextData.forEach(new BiConsumer<String, Object>() {
+            int i = 0;
+
+            @Override
+            public void accept(final String key, final Object value) {
+                pairs[i++] = createMapEntry(key, String.valueOf(value));
+            }
+        });
+        jgen.writeObject(pairs);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataDeserializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataDeserializer.java
new file mode 100644
index 0000000..9d6843a
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataDeserializer.java
@@ -0,0 +1,65 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.logging.log4j.core.impl.ContextDataFactory;
+import org.apache.logging.log4j.util.StringMap;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class ContextDataDeserializer extends StdDeserializer<StringMap> {
+
+    private static final long serialVersionUID = 1L;
+
+    ContextDataDeserializer() {
+        super(Map.class);
+    }
+
+    @Override
+    public StringMap deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
+            JsonProcessingException {
+
+        // Sanity check: verify that we got "Json Object":
+//        JsonToken tok = jp.nextToken();
+//        if (tok != JsonToken.START_OBJECT) {
+//            throw new IOException("Expected data to start with an Object");
+//        }
+        final StringMap contextData = ContextDataFactory.createContextData();
+        // Iterate over object fields:
+        while (jp.nextToken() != JsonToken.END_OBJECT) {
+            final String fieldName = jp.getCurrentName();
+
+            // move to value
+            jp.nextToken();
+            contextData.putValue(fieldName, jp.getText());
+        }
+        return contextData;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataSerializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataSerializer.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataSerializer.java
new file mode 100644
index 0000000..245e436
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ContextDataSerializer.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+import org.apache.logging.log4j.util.TriConsumer;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class ContextDataSerializer extends StdSerializer<ReadOnlyStringMap> {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final TriConsumer<String, Object, JsonGenerator> WRITE_STRING_FIELD_INTO =
+            new TriConsumer<String, Object, JsonGenerator>() {
+
+        @Override
+        public void accept(final String key, final Object value, final JsonGenerator jsonGenerator) {
+            try {
+                jsonGenerator.writeStringField(key, String.valueOf(value));
+            } catch (final Exception ex) {
+                throw new IllegalStateException("Problem with key " + key, ex);
+            }
+        }
+    };
+
+    protected ContextDataSerializer() {
+        super(Map.class, false);
+    }
+
+    @Override
+    public void serialize(final ReadOnlyStringMap contextData, final JsonGenerator jgen,
+            final SerializerProvider provider) throws IOException, JsonGenerationException {
+
+        jgen.writeStartObject();
+        contextData.forEach(WRITE_STRING_FIELD_INTO, jgen);
+        jgen.writeEndObject();
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ExtendedStackTraceElementMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ExtendedStackTraceElementMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ExtendedStackTraceElementMixIn.java
new file mode 100644
index 0000000..2642e42
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/ExtendedStackTraceElementMixIn.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import java.io.Serializable;
+
+import org.apache.logging.log4j.core.impl.ExtendedClassInfo;
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+/**
+ * Mix-in for {@link ExtendedStackTraceElement}.
+ */
+@JsonPropertyOrder({
+    //@formatter:off
+    ExtendedStackTraceElementMixIn.ATTR_CLASS,
+    ExtendedStackTraceElementMixIn.ATTR_METHOD,
+    ExtendedStackTraceElementMixIn.ATTR_FILE,
+    ExtendedStackTraceElementMixIn.ATTR_LINE,
+    ExtendedStackTraceElementMixIn.ATTR_EXACT,
+    ExtendedStackTraceElementMixIn.ATTR_LOCATION,
+    ExtendedStackTraceElementMixIn.ATTR_VERSION
+    //@formatter:on
+})
+public abstract class ExtendedStackTraceElementMixIn implements Serializable {
+
+    protected static final String ATTR_CLASS = StackTraceElementConstants.ATTR_CLASS;
+    protected static final String ATTR_METHOD = StackTraceElementConstants.ATTR_METHOD;
+    protected static final String ATTR_FILE = StackTraceElementConstants.ATTR_FILE;
+    protected static final String ATTR_LINE = StackTraceElementConstants.ATTR_LINE;
+    protected static final String ATTR_EXACT = "exact";
+    protected static final String ATTR_LOCATION = "location";
+    protected static final String ATTR_VERSION = "version";
+
+    private static final long serialVersionUID = 1L;
+
+    @JsonCreator
+    public ExtendedStackTraceElementMixIn(
+    // @formatter:off
+            @JsonProperty(ATTR_CLASS) final String declaringClass,
+            @JsonProperty(ATTR_METHOD) final String methodName,
+            @JsonProperty(ATTR_FILE) final String fileName,
+            @JsonProperty(ATTR_LINE) final int lineNumber,
+            @JsonProperty(ATTR_EXACT) final boolean exact,
+            @JsonProperty(ATTR_LOCATION) final String location,
+            @JsonProperty(ATTR_VERSION) final String version
+   // @formatter:on
+    ) {
+        // empty
+    }
+
+    @JsonProperty(ATTR_CLASS)
+    public abstract String getClassName();
+
+    @JsonProperty(ATTR_EXACT)
+    public abstract boolean getExact();
+
+    @JsonIgnore
+    public abstract ExtendedClassInfo getExtraClassInfo();
+
+    @JsonProperty(ATTR_FILE)
+    public abstract String getFileName();
+
+    @JsonProperty(ATTR_LINE)
+    public abstract int getLineNumber();
+
+    @JsonProperty(ATTR_LOCATION)
+    public abstract String getLocation();
+
+    @JsonProperty(ATTR_METHOD)
+    public abstract String getMethodName();
+
+    @JsonIgnore
+    abstract StackTraceElement getStackTraceElement();
+
+    @JsonProperty(ATTR_VERSION)
+    public abstract String getVersion();
+
+    @JsonIgnore
+    public abstract boolean isNativeMethod();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/InstantMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/InstantMixIn.java b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/InstantMixIn.java
new file mode 100644
index 0000000..16a3bb5
--- /dev/null
+++ b/log4j-layout-jackson/src/main/java/org/apache/logging/log4j/jackson/InstantMixIn.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson;
+
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.time.Instant;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Jackson mix-in for {@link Instant}.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ *
+ * @see Marker
+ */
+@JsonIgnoreProperties({ "epochMillisecond", "nanoOfMillisecond" })
+public abstract class InstantMixIn {
+
+    protected static final String ATTR_NANO_OF_SECOND = "nanoOfSecond";
+    protected static final String ATTR_EPOCH_SECOND = "epochSecond";
+
+    @JsonCreator
+    protected InstantMixIn(
+    // @formatter:off
+            @JsonProperty(ATTR_EPOCH_SECOND) final long epochSecond,
+            @JsonProperty(ATTR_NANO_OF_SECOND) final int nanoOfSecond)
+            // @formatter:on
+    {
+        // empty
+    }
+
+    @JsonProperty(ATTR_EPOCH_SECOND)
+    public abstract long getEpochSecond();
+
+    @JsonProperty(ATTR_NANO_OF_SECOND)
+    public abstract int getNanoOfSecond();
+}


[12/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
[LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON,
XML, and YAML.

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

Branch: refs/heads/master
Commit: 0eb5212e4ac56030f07e88b9de432977e3808e48
Parents: ec3c623
Author: Gary Gregory <ga...@gmail.com>
Authored: Mon Feb 19 19:09:06 2018 -0700
Committer: Gary Gregory <ga...@gmail.com>
Committed: Mon Feb 19 19:09:06 2018 -0700

----------------------------------------------------------------------
 log4j-bom/pom.xml                               |  24 +
 log4j-core-its/pom.xml                          |  24 +-
 .../log4j/core/appender/HttpAppenderTest.java   | 316 ++++++++++++
 .../appender/JsonCompleteFileAppenderTest.java  | 110 +++++
 .../SecureSocketAppenderSocketOptionsTest.java  | 140 ++++++
 .../appender/SocketAppenderBufferSizeTest.java  |  77 +++
 .../SocketAppenderSocketOptionsTest.java        | 109 +++++
 .../log4j/core/appender/SocketAppenderTest.java | 412 ++++++++++++++++
 .../appender/XmlCompactFileAppenderTest.java    |  82 ++++
 .../XmlCompactFileAppenderValidationTest.java   | 106 ++++
 ...lCompactFileAsyncAppenderValidationTest.java |  83 ++++
 .../appender/XmlCompleteFileAppenderTest.java   | 173 +++++++
 .../core/appender/XmlFileAppenderTest.java      |  76 +++
 .../XmlRandomAccessFileAppenderTest.java        |  90 ++++
 log4j-core/pom.xml                              |   6 -
 .../ContextDataAsEntryListDeserializer.java     |  57 ---
 .../ContextDataAsEntryListSerializer.java       |  58 ---
 .../core/jackson/ContextDataDeserializer.java   |  65 ---
 .../core/jackson/ContextDataSerializer.java     |  64 ---
 .../jackson/ExtendedStackTraceElementMixIn.java |  90 ----
 .../log4j/core/jackson/Initializers.java        |  98 ----
 .../log4j/core/jackson/InstantMixIn.java        |  53 --
 .../log4j/core/jackson/JsonConstants.java       |  35 --
 .../logging/log4j/core/jackson/LevelMixIn.java  |  44 --
 .../jackson/ListOfMapEntryDeserializer.java     |  55 ---
 .../core/jackson/ListOfMapEntrySerializer.java  |  54 --
 .../log4j/core/jackson/Log4jJsonModule.java     |  61 ---
 .../core/jackson/Log4jJsonObjectMapper.java     |  47 --
 .../Log4jStackTraceElementDeserializer.java     |  82 ----
 .../log4j/core/jackson/Log4jXmlModule.java      |  50 --
 .../core/jackson/Log4jXmlObjectMapper.java      |  48 --
 .../log4j/core/jackson/Log4jYamlModule.java     |  59 ---
 .../core/jackson/Log4jYamlObjectMapper.java     |  48 --
 .../log4j/core/jackson/LogEventJsonMixIn.java   | 156 ------
 .../jackson/LogEventWithContextListMixIn.java   | 155 ------
 .../logging/log4j/core/jackson/MapEntry.java    | 110 -----
 .../logging/log4j/core/jackson/MarkerMixIn.java |  76 ---
 .../log4j/core/jackson/MessageSerializer.java   |  47 --
 .../MutableThreadContextStackDeserializer.java  |  51 --
 .../core/jackson/ObjectMessageSerializer.java   |  47 --
 .../core/jackson/SimpleMessageDeserializer.java |  47 --
 .../core/jackson/StackTraceElementMixIn.java    |  62 ---
 .../log4j/core/jackson/ThrowableProxyMixIn.java |  80 ---
 ...rowableProxyWithStacktraceAsStringMixIn.java |  78 ---
 .../ThrowableProxyWithoutStacktraceMixIn.java   |  77 ---
 .../log4j/core/jackson/XmlConstants.java        |  39 --
 .../log4j/core/jackson/package-info.java        |  21 -
 .../core/layout/AbstractJacksonLayout.java      | 350 -------------
 .../logging/log4j/core/layout/GelfLayout.java   |   2 +-
 .../log4j/core/layout/JacksonFactory.java       | 237 ---------
 .../logging/log4j/core/layout/JsonLayout.java   | 293 -----------
 .../logging/log4j/core/layout/XmlLayout.java    | 208 --------
 .../logging/log4j/core/layout/YamlLayout.java   | 206 --------
 .../parser/AbstractJacksonLogEventParser.java   |   4 +-
 .../log4j/core/parser/JsonLogEventParser.java   |  31 --
 .../log4j/core/parser/XmlLogEventParser.java    |  31 --
 .../log4j/core/parser/YamlLogEventParser.java   |  31 --
 .../logging/log4j/MarkerMixInJsonTest.java      |  33 --
 .../apache/logging/log4j/MarkerMixInTest.java   |  94 ----
 .../logging/log4j/MarkerMixInXmlTest.java       |  34 --
 .../logging/log4j/MarkerMixInYamlTest.java      |  34 --
 .../log4j/core/appender/HttpAppenderTest.java   | 316 ------------
 .../appender/JsonCompleteFileAppenderTest.java  | 110 -----
 .../SecureSocketAppenderSocketOptionsTest.java  | 140 ------
 .../appender/SocketAppenderBufferSizeTest.java  |  77 ---
 .../SocketAppenderSocketOptionsTest.java        | 109 -----
 .../log4j/core/appender/SocketAppenderTest.java | 411 ----------------
 .../appender/XmlCompactFileAppenderTest.java    |  81 ---
 .../XmlCompactFileAppenderValidationTest.java   | 106 ----
 ...lCompactFileAsyncAppenderValidationTest.java |  83 ----
 .../appender/XmlCompleteFileAppenderTest.java   | 172 -------
 .../core/appender/XmlFileAppenderTest.java      |  78 ---
 .../XmlRandomAccessFileAppenderTest.java        |  89 ----
 .../log4j/core/impl/ThrowableProxyTest.java     |  18 +-
 .../jackson/JacksonIssue429MyNamesTest.java     | 130 -----
 .../log4j/core/jackson/JacksonIssue429Test.java |  95 ----
 .../log4j/core/jackson/LevelMixInJsonTest.java  |  32 --
 .../log4j/core/jackson/LevelMixInTest.java      | 106 ----
 .../log4j/core/jackson/LevelMixInXmlTest.java   |  35 --
 .../log4j/core/jackson/LevelMixInYamlTest.java  |  32 --
 .../jackson/StackTraceElementMixInTest.java     |  92 ----
 .../ConcurrentLoggingWithJsonLayoutTest.java    | 116 -----
 .../log4j/core/layout/JsonLayoutTest.java       | 487 ------------------
 .../log4j/core/layout/LogEventFixtures.java     |   6 +-
 .../log4j/core/layout/XmlLayoutTest.java        | 387 ---------------
 .../log4j/core/layout/YamlLayoutTest.java       | 380 --------------
 .../core/parser/AbstractLogEventParserTest.java |  59 +++
 .../core/parser/JsonLogEventParserTest.java     | 130 -----
 .../log4j/core/parser/LogEventParserTest.java   |  55 ---
 .../core/parser/XmlLogEventParserTest.java      | 130 -----
 .../core/parser/YamlLogEventParserTest.java     | 126 -----
 .../src/test/resources/log4j2-xml-layout.xml    |  31 ++
 log4j-layout-jackson-json/pom.xml               | 167 +++++++
 .../json/JsonSetupContextInitializer.java       |  51 ++
 .../log4j/jackson/json/Log4jJsonModule.java     |  58 +++
 .../jackson/json/Log4jJsonObjectMapper.java     |  47 ++
 .../jackson/json/layout/JsonJacksonFactory.java |  60 +++
 .../log4j/jackson/json/layout/JsonLayout.java   | 327 +++++++++++++
 .../jackson/json/parser/JsonLogEventParser.java |  32 ++
 .../src/site/manual/index.md                    |  33 ++
 log4j-layout-jackson-json/src/site/site.xml     |  52 ++
 .../json/JacksonIssue429MyNamesTest.java        | 130 +++++
 .../log4j/jackson/json/JacksonIssue429Test.java |  95 ++++
 .../log4j/jackson/json/LevelMixInJsonTest.java  |  34 ++
 .../log4j/jackson/json/MarkerMixInJsonTest.java |  34 ++
 .../json/StackTraceElementJsonMixInTest.java    |  83 ++++
 .../ConcurrentLoggingWithJsonLayoutTest.java    | 117 +++++
 .../jackson/json/layout/JsonLayoutTest.java     | 489 +++++++++++++++++++
 .../json/layout/ThrowableProxyJsonTest.java     |  33 ++
 .../json/parser/JsonLogEventParserTest.java     | 132 +++++
 .../src/test/resources/log4j2-json-layout.xml   |  31 ++
 .../log4j/jackson/xml/Log4jXmlModule.java       |  49 ++
 .../log4j/jackson/xml/Log4jXmlObjectMapper.java |  48 ++
 .../log4j/jackson/xml/XmlInstantMixIn.java      |  56 +++
 .../xml/XmlLogEventWithContextListMixIn.java    |  50 ++
 .../log4j/jackson/xml/XmlMarkerMixIn.java       |  79 +++
 .../jackson/xml/XmlSetupContextInitializer.java |  42 ++
 .../jackson/xml/XmlStackTraceElementMixIn.java  |  39 ++
 .../xml/layout/Log4jXmlPrettyPrinter.java       |  41 ++
 .../jackson/xml/layout/XmlJacksonFactory.java   |  54 ++
 .../log4j/jackson/xml/layout/XmlLayout.java     | 226 +++++++++
 .../jackson/xml/parser/XmlLogEventParser.java   |  32 ++
 log4j-layout-jackson-xml/pom.xml                | 171 +++++++
 .../jackson/xml/AbstractLogEventXmlMixIn.java   | 135 +++++
 .../ContextDataAsEntryListXmlSerializer.java    |  37 ++
 .../xml/ExtendedStackTraceElementXmlMixIn.java  |  68 +++
 .../log4j/jackson/xml/InstantXmlMixIn.java      |  56 +++
 .../log4j/jackson/xml/Log4jXmlModule.java       |  52 ++
 .../log4j/jackson/xml/Log4jXmlObjectMapper.java |  48 ++
 .../xml/LogEventWithContextListXmlMixIn.java    |  48 ++
 .../log4j/jackson/xml/MarkerXmlMixIn.java       |  79 +++
 .../jackson/xml/StackTraceElementXmlMixIn.java  |  40 ++
 ...ableProxyWithStacktraceAsStringXmlMixIn.java |  77 +++
 ...ThrowableProxyWithoutStacktraceXmlMixIn.java |  60 +++
 .../jackson/xml/ThrowableProxyXmlMixIn.java     |  78 +++
 .../logging/log4j/jackson/xml/XmlMapEntry.java  |  41 ++
 .../jackson/xml/XmlSetupContextInitializer.java |  38 ++
 .../xml/layout/Log4jXmlPrettyPrinter.java       |  41 ++
 .../jackson/xml/layout/XmlJacksonFactory.java   |  54 ++
 .../log4j/jackson/xml/layout/XmlLayout.java     | 226 +++++++++
 .../jackson/xml/parser/XmlLogEventParser.java   |  32 ++
 .../src/site/manual/index.md                    |  33 ++
 log4j-layout-jackson-xml/src/site/site.xml      |  52 ++
 .../log4j/jackson/xml/LevelMixInXmlTest.java    |  36 ++
 .../log4j/jackson/xml/MarkerMixInXmlTest.java   |  34 ++
 .../xml/StackTraceElementXmlMixInTest.java      |  82 ++++
 .../ConcurrentLoggingWithXmlLayoutTest.java     | 116 +++++
 .../xml/layout/ThrowableProxyXmlTest.java       |  33 ++
 .../log4j/jackson/xml/layout/XmlLayoutTest.java | 440 +++++++++++++++++
 .../xml/parser/XmlLogEventParserTest.java       | 132 +++++
 .../src/test/resources/log4j2-xml-layout.xml    |  31 ++
 log4j-layout-jackson-yaml/pom.xml               | 171 +++++++
 .../log4j/jackson/yaml/Log4jYamlModule.java     |  59 +++
 .../jackson/yaml/Log4jYamlObjectMapper.java     |  48 ++
 .../yaml/YamlSetupContextInitializer.java       |  47 ++
 .../jackson/yaml/layout/YamlConstants.java      |  35 ++
 .../jackson/yaml/layout/YamlJacksonFactory.java |  68 +++
 .../log4j/jackson/yaml/layout/YamlLayout.java   | 239 +++++++++
 .../jackson/yaml/parser/YamlLogEventParser.java |  32 ++
 .../src/site/manual/index.md                    |  33 ++
 log4j-layout-jackson-yaml/src/site/site.xml     |  52 ++
 .../log4j/jackson/yaml/LevelMixInYamlTest.java  |  34 ++
 .../log4j/jackson/yaml/MarkerMixInYamlTest.java |  34 ++
 .../yaml/StackTraceElementYamlMixInTest.java    |  83 ++++
 .../ConcurrentLoggingWithYamlLayoutTest.java    | 113 +++++
 .../jackson/yaml/layout/YamlLayoutTest.java     | 382 +++++++++++++++
 .../yaml/parser/YamlLogEventParserTest.java     | 128 +++++
 .../src/test/resources/log4j2-yaml-layout.xml   |  31 ++
 log4j-layout-jackson/pom.xml                    | 214 ++++++++
 .../log4j/jackson/AbstractJacksonFactory.java   |  74 +++
 .../log4j/jackson/AbstractJacksonLayout.java    | 351 +++++++++++++
 .../log4j/jackson/AbstractLogEventMixIn.java    |  84 ++++
 .../ContextDataAsEntryListDeserializer.java     |  57 +++
 .../ContextDataAsEntryListSerializer.java       |  67 +++
 .../log4j/jackson/ContextDataDeserializer.java  |  65 +++
 .../log4j/jackson/ContextDataSerializer.java    |  64 +++
 .../jackson/ExtendedStackTraceElementMixIn.java | 100 ++++
 .../logging/log4j/jackson/InstantMixIn.java     |  55 +++
 .../logging/log4j/jackson/JsonConstants.java    |  36 ++
 .../logging/log4j/jackson/LevelMixIn.java       |  44 ++
 .../jackson/ListOfMapEntryDeserializer.java     |  55 +++
 .../log4j/jackson/ListOfMapEntrySerializer.java |  58 +++
 .../Log4jStackTraceElementDeserializer.java     |  82 ++++
 .../log4j/jackson/LogEventJsonMixIn.java        | 146 ++++++
 .../jackson/LogEventWithContextListMixIn.java   | 130 +++++
 .../apache/logging/log4j/jackson/MapEntry.java  | 109 +++++
 .../logging/log4j/jackson/MarkerMixIn.java      |  71 +++
 .../log4j/jackson/MessageSerializer.java        |  47 ++
 .../MutableThreadContextStackDeserializer.java  |  51 ++
 .../log4j/jackson/ObjectMessageSerializer.java  |  47 ++
 .../log4j/jackson/SetupContextInitializer.java  |  38 ++
 .../jackson/SimpleMessageDeserializer.java      |  47 ++
 .../log4j/jackson/SimpleModuleInitializer.java  |  26 +
 .../jackson/StackTraceElementConstants.java     |  30 ++
 .../log4j/jackson/StackTraceElementMixIn.java   |  59 +++
 .../log4j/jackson/ThrowableProxyMixIn.java      |  70 +++
 ...rowableProxyWithStacktraceAsStringMixIn.java |  70 +++
 .../ThrowableProxyWithoutStacktraceMixIn.java   |  69 +++
 .../logging/log4j/jackson/XmlConstants.java     |  39 ++
 .../jackson/layout/AbstractJacksonLayout.java   | 378 ++++++++++++++
 .../logging/log4j/jackson/package-info.java     |  21 +
 log4j-layout-jackson/src/site/manual/index.md   |  33 ++
 log4j-layout-jackson/src/site/site.xml          |  52 ++
 .../log4j/jackson/AbstractMarkerMixInTest.java  |  97 ++++
 .../logging/log4j/jackson/LevelMixInTest.java   | 106 ++++
 .../jackson/ThrowableProxyJacksonTest.java      |  51 ++
 pom.xml                                         |   4 +
 src/changes/changes.xml                         |   3 +
 208 files changed, 11800 insertions(+), 7829 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-bom/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-bom/pom.xml b/log4j-bom/pom.xml
index 97021b2..5ee35e8 100644
--- a/log4j-bom/pom.xml
+++ b/log4j-bom/pom.xml
@@ -42,6 +42,30 @@
         <artifactId>log4j-core</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <!--  Commons code for Jackson-based layouts -->
+      <dependency>
+        <groupId>org.apache.logging.log4j</groupId>
+        <artifactId>log4j-layout-jackson</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <!-- Jackson-based JSON layout -->
+      <dependency>
+        <groupId>org.apache.logging.log4j</groupId>
+        <artifactId>log4j-layout-jackson-json</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <!-- Jackson-based XML layout -->
+      <dependency>
+        <groupId>org.apache.logging.log4j</groupId>
+        <artifactId>log4j-layout-jackson-xml</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <!-- Jackson-based YAML layout -->
+      <dependency>
+        <groupId>org.apache.logging.log4j</groupId>
+        <artifactId>log4j-layout-jackson-yaml</artifactId>
+        <version>${project.version}</version>
+      </dependency>
       <!-- Legacy Log4j 1.2 API -->
       <dependency>
         <groupId>org.apache.logging.log4j</groupId>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-core-its/pom.xml b/log4j-core-its/pom.xml
index 2a0cec1..513fce3 100644
--- a/log4j-core-its/pom.xml
+++ b/log4j-core-its/pom.xml
@@ -29,13 +29,14 @@
   <description>Integration Tests for the Apache Log4j Implementation</description>
   <properties>
     <log4jParentDir>${basedir}/..</log4jParentDir>
-    <docLabel>Core Documentation</docLabel>
-    <projectDir>/core</projectDir>
+    <docLabel>Core Integration Tests Documentation</docLabel>
+    <projectDir>/log4j-core-its</projectDir>
   </properties>
   <dependencies>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-api</artifactId>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
@@ -46,6 +47,19 @@
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-layout-jackson-json</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-layout-jackson-xml</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
@@ -53,6 +67,12 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
+    <!-- Used for testing HttpAppender -->
+    <dependency>
+      <groupId>com.github.tomakehurst</groupId>
+      <artifactId>wiremock</artifactId>
+      <scope>test</scope>
+    </dependency>
     <!-- Required for AsyncLoggers -->
     <dependency>
       <groupId>com.lmax</groupId>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
new file mode 100644
index 0000000..4e9a07c
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.containing;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.put;
+import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.config.Property;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.lookup.JavaLookup;
+import org.apache.logging.log4j.core.net.ssl.KeyStoreConfiguration;
+import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
+import org.apache.logging.log4j.core.net.ssl.TestConstants;
+import org.apache.logging.log4j.core.net.ssl.TrustStoreConfiguration;
+import org.apache.logging.log4j.jackson.json.layout.JsonLayout;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.status.StatusData;
+import org.apache.logging.log4j.status.StatusListener;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+
+@Ignore("Fails often on Windows")
+
+/* Fails often on Windows, for example:
+[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.20.1:test (default-test) on project log4j-core: There are test failures.
+[ERROR]
+[ERROR] Please refer to C:\vcs\git\apache\logging\logging-log4j2\log4j-core\target\surefire-reports for the individual test results.
+[ERROR] Please refer to dump files (if any exist) [date]-jvmRun[N].dump, [date].dumpstream and [date]-jvmRun[N].dumpstream.
+[ERROR] ExecutionException The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
+[ERROR] Command was cmd.exe /X /C ""C:\Program Files\Java\jdk1.8.0_152\jre\bin\java" -Xms256m -Xmx1024m -jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112\surefirebooter1486874613063862199.jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112 2018-01-23T11-03-18_847-jvmRun6 surefire6375637980242546356tmp surefire_441335531705722358735tmp"
+[ERROR] Process Exit Code: 0
+[ERROR] Crashed tests:
+[ERROR] org.apache.logging.log4j.core.appender.HttpAppenderTest
+[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: ExecutionException The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
+[ERROR] Command was cmd.exe /X /C ""C:\Program Files\Java\jdk1.8.0_152\jre\bin\java" -Xms256m -Xmx1024m -jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112\surefirebooter1486874613063862199.jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112 2018-01-23T11-03-18_847-jvmRun6 surefire6375637980242546356tmp surefire_441335531705722358735tmp"
+[ERROR] Process Exit Code: 0
+[ERROR] Crashed tests:
+[ERROR] org.apache.logging.log4j.core.appender.HttpAppenderTest
+[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.awaitResultsDone(ForkStarter.java:496)
+[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.runSuitesForkPerTestSet(ForkStarter.java:443)
+[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:295)
+[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:246)
+[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1124)
+[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:954)
+[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:832)
+[ERROR]         at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
+[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
+[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
+[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
+[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
+[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
+[ERROR]         at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
+[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
+[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:309)
+[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:194)
+[ERROR]         at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:107)
+[ERROR]         at org.apache.maven.cli.MavenCli.execute(MavenCli.java:955)
+[ERROR]         at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:290)
+[ERROR]         at org.apache.maven.cli.MavenCli.main(MavenCli.java:194)
+[ERROR]         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+[ERROR]         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
+[ERROR]         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+[ERROR]         at java.lang.reflect.Method.invoke(Method.java:498)
+[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
+[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
+[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
+[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
+[ERROR] Caused by: org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
+[ERROR] Command was cmd.exe /X /C ""C:\Program Files\Java\jdk1.8.0_152\jre\bin\java" -Xms256m -Xmx1024m -jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112\surefirebooter1486874613063862199.jar C:\Users\ggregory\AppData\Local\Temp\surefire22320217597495112 2018-01-23T11-03-18_847-jvmRun6 surefire6375637980242546356tmp surefire_441335531705722358735tmp"
+[ERROR] Process Exit Code: 0
+[ERROR] Crashed tests:
+[ERROR] org.apache.logging.log4j.core.appender.HttpAppenderTest
+[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:686)
+[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:535)
+[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.access$700(ForkStarter.java:116)
+[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter$2.call(ForkStarter.java:431)
+[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter$2.call(ForkStarter.java:408)
+[ERROR]         at java.util.concurrent.FutureTask.run(FutureTask.java:266)
+[ERROR]         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
+[ERROR]         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
+[ERROR]         at java.lang.Thread.run(Thread.java:748)
+[ERROR]
+[ERROR] -> [Help 1]
+[ERROR]
+[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
+[ERROR] Re-run Maven using the -X switch to enable full debug logging.
+[ERROR]
+[ERROR] For more information about the errors and possible solutions, please read the following articles:
+[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
+[ERROR]
+[ERROR] After correcting the problems, you can resume the build with the command
+[ERROR]   mvn <goals> -rf :log4j-core
+ */
+public class HttpAppenderTest {
+
+    private static final String LOG_MESSAGE = "Hello, world!";
+
+    private static Log4jLogEvent createLogEvent() {
+        return Log4jLogEvent.newBuilder()
+            .setLoggerName(HttpAppenderTest.class.getName())
+            .setLoggerFqcn(HttpAppenderTest.class.getName())
+            .setLevel(Level.INFO)
+            .setMessage(new SimpleMessage(LOG_MESSAGE))
+            .build();
+    }
+
+    private final ResponseDefinitionBuilder SUCCESS_RESPONSE = aResponse().withStatus(201)
+        .withHeader("Content-Type", "application/json")
+        .withBody("{\"status\":\"created\"}");
+
+    private final ResponseDefinitionBuilder FAILURE_RESPONSE = aResponse().withStatus(400)
+        .withHeader("Content-Type", "application/json")
+        .withBody("{\"status\":\"error\"}");
+
+    private final JavaLookup JAVA_LOOKUP = new JavaLookup();
+
+    @Rule
+    public LoggerContextRule ctx = new LoggerContextRule("HttpAppenderTest.xml");
+
+    @Rule
+    public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort()
+        .keystorePath(TestConstants.KEYSTORE_FILE)
+        .keystorePassword(String.valueOf(TestConstants.KEYSTORE_PWD()))
+        .keystoreType(TestConstants.KEYSTORE_TYPE));
+
+    @Test
+    public void testAppend() throws Exception {
+        wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
+            .willReturn(SUCCESS_RESPONSE));
+
+        final Appender appender = HttpAppender.newBuilder()
+            .withName("Http")
+            .withLayout(JsonLayout.createDefaultLayout())
+            .setConfiguration(ctx.getConfiguration())
+            .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
+            .build();
+        appender.append(createLogEvent());
+
+        wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
+            .withHeader("Host", containing("localhost"))
+            .withHeader("Content-Type", containing("application/json"))
+            .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
+    }
+
+    @Test
+    public void testAppendHttps() throws Exception {
+        wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
+            .willReturn(SUCCESS_RESPONSE));
+
+        final Appender appender = HttpAppender.newBuilder()
+            .withName("Http")
+            .withLayout(JsonLayout.createDefaultLayout())
+            .setConfiguration(ctx.getConfiguration())
+            .setUrl(new URL("https://localhost:" + wireMockRule.httpsPort() + "/test/log4j/"))
+            .setSslConfiguration(SslConfiguration.createSSLConfiguration(null,
+                KeyStoreConfiguration.createKeyStoreConfiguration(TestConstants.KEYSTORE_FILE, TestConstants.KEYSTORE_PWD(), TestConstants.KEYSTORE_TYPE, null),
+                TrustStoreConfiguration.createKeyStoreConfiguration(TestConstants.TRUSTSTORE_FILE, TestConstants.TRUSTSTORE_PWD(), TestConstants.TRUSTSTORE_TYPE, null)))
+            .setVerifyHostname(false)
+            .build();
+        appender.append(createLogEvent());
+
+        wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
+            .withHeader("Host", containing("localhost"))
+            .withHeader("Content-Type", containing("application/json"))
+            .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
+    }
+
+    @Test
+    public void testAppendMethodPut() throws Exception {
+        wireMockRule.stubFor(put(urlEqualTo("/test/log4j/1234"))
+            .willReturn(SUCCESS_RESPONSE));
+
+        final Appender appender = HttpAppender.newBuilder()
+            .withName("Http")
+            .withLayout(JsonLayout.createDefaultLayout())
+            .setConfiguration(ctx.getConfiguration())
+            .setMethod("PUT")
+            .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/1234"))
+            .build();
+        appender.append(createLogEvent());
+
+        wireMockRule.verify(putRequestedFor(urlEqualTo("/test/log4j/1234"))
+            .withHeader("Host", containing("localhost"))
+            .withHeader("Content-Type", containing("application/json"))
+            .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
+    }
+
+    @Test
+    public void testAppendCustomHeader() throws Exception {
+        wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
+            .willReturn(SUCCESS_RESPONSE));
+
+        final Appender appender = HttpAppender.newBuilder()
+            .withName("Http")
+            .withLayout(JsonLayout.createDefaultLayout())
+            .setConfiguration(ctx.getConfiguration())
+            .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
+            .setHeaders(new Property[] {
+                Property.createProperty("X-Test", "header value"),
+                Property.createProperty("X-Runtime", "${java:runtime}")
+            })
+            .build();
+        appender.append(createLogEvent());
+
+        wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
+            .withHeader("Host", containing("localhost"))
+            .withHeader("X-Test", equalTo("header value"))
+            .withHeader("X-Runtime", equalTo(JAVA_LOOKUP.getRuntime()))
+            .withHeader("Content-Type", containing("application/json"))
+            .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
+    }
+
+    volatile StatusData error;
+
+    @Test
+    public void testAppendErrorIgnore() throws Exception {
+        wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
+            .willReturn(FAILURE_RESPONSE));
+
+        StatusLogger.getLogger().registerListener(new StatusListener() {
+            @Override
+            public void log(final StatusData data) {
+                error = data;
+            }
+
+            @Override
+            public Level getStatusLevel() {
+                return Level.ERROR;
+            }
+
+            @Override
+            public void close() throws IOException { }
+        });
+
+        error = null;
+
+        final Appender appender = HttpAppender.newBuilder()
+            .withName("Http")
+            .withLayout(JsonLayout.createDefaultLayout())
+            .setConfiguration(ctx.getConfiguration())
+            .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
+            .build();
+        appender.append(createLogEvent());
+
+        wireMockRule.verify(postRequestedFor(urlEqualTo("/test/log4j/"))
+            .withHeader("Host", containing("localhost"))
+            .withHeader("Content-Type", containing("application/json"))
+            .withRequestBody(containing("\"message\" : \"" + LOG_MESSAGE + "\"")));
+
+        assertNotNull(error);
+        assertEquals(Level.ERROR, error.getLevel());
+        assertEquals("Unable to send HTTP in appender [Http]", error.getMessage().toString());
+    }
+
+    @Test(expected = AppenderLoggingException.class)
+    public void testAppendError() throws Exception {
+        wireMockRule.stubFor(post(urlEqualTo("/test/log4j/"))
+            .willReturn(FAILURE_RESPONSE));
+
+        final Appender appender = HttpAppender.newBuilder()
+            .withName("Http")
+            .withLayout(JsonLayout.createDefaultLayout())
+            .setConfiguration(ctx.getConfiguration())
+            .withIgnoreExceptions(false)
+            .setUrl(new URL("http://localhost:" + wireMockRule.port() + "/test/log4j/"))
+            .build();
+        appender.append(createLogEvent());
+    }
+
+    @Test(expected = AppenderLoggingException.class)
+    public void testAppendConnectError() throws Exception {
+        final Appender appender = HttpAppender.newBuilder()
+            .withName("Http")
+            .withLayout(JsonLayout.createDefaultLayout())
+            .setConfiguration(ctx.getConfiguration())
+            .withIgnoreExceptions(false)
+            .setUrl(new URL("http://localhost:"+(wireMockRule.port()+1)+"/test/log4j/"))
+            .build();
+        appender.append(createLogEvent());
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
new file mode 100644
index 0000000..4c2da52
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.List;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.impl.Log4jLogEventTest;
+import org.apache.logging.log4j.core.selector.ContextSelector;
+import org.apache.logging.log4j.core.selector.CoreContextSelectors;
+import org.apache.logging.log4j.core.time.ClockFactory;
+import org.apache.logging.log4j.junit.CleanFiles;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Tests a "complete" JSON file.
+ */
+@RunWith(Parameterized.class)
+@Category(Layouts.Json.class)
+public class JsonCompleteFileAppenderTest {
+
+    public JsonCompleteFileAppenderTest(final Class<ContextSelector> contextSelector) {
+        this.loggerContextRule = new LoggerContextRule("JsonCompleteFileAppenderTest.xml", contextSelector);
+        this.cleanFiles = new CleanFiles(logFile);
+        this.ruleChain = RuleChain.outerRule(cleanFiles).around(loggerContextRule);
+    }
+
+    @BeforeClass
+    public static void beforeClass() {
+        System.setProperty(ClockFactory.PROPERTY_NAME, Log4jLogEventTest.FixedTimeClock.class.getName());
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        System.clearProperty(ClockFactory.PROPERTY_NAME);
+    }
+
+    @Parameters(name = "{0}")
+    public static Class<?>[] getParameters() {
+        return CoreContextSelectors.CLASSES;
+    }
+
+    private final File logFile = new File("target", "JsonCompleteFileAppenderTest.log");
+    private final LoggerContextRule loggerContextRule;
+    private final CleanFiles cleanFiles;
+
+    @Rule
+    public RuleChain ruleChain;
+
+    @Test
+    public void testFlushAtEndOfBatch() throws Exception {
+        final Logger logger = this.loggerContextRule.getLogger("com.foo.Bar");
+        final String logMsg = "Message flushed with immediate flush=true";
+        logger.info(logMsg);
+        logger.error(logMsg, new IllegalArgumentException("badarg"));
+        this.loggerContextRule.getLoggerContext().stop(); // stops async thread
+
+        List<String> lines = Files.readAllLines(logFile.toPath(), Charset.forName("UTF8"));
+
+        String[] expected = {
+                "[", // equals
+                "{", // equals
+                "  \"thread\" : \"main\",", //
+                "  \"level\" : \"INFO\",", //
+                "  \"loggerName\" : \"com.foo.Bar\",", //
+                "  \"message\" : \"Message flushed with immediate flush=true\",", //
+                "  \"endOfBatch\" : false,", //
+                "  \"loggerFqcn\" : \"org.apache.logging.log4j.spi.AbstractLogger\",", //
+                "  \"instant\" : {", //
+                "    \"epochSecond\" : 1234567,", //
+                "    \"nanoOfSecond\" : 890000000", //
+                "  },", //
+        };
+        for (int i = 0; i < expected.length; i++) {
+            String line = lines.get(i);
+            assertTrue("line " + i + " incorrect: [" + line + "], does not contain: [" + expected[i] + ']', line.contains(expected[i]));
+        }
+        final String location = "testFlushAtEndOfBatch";
+        assertTrue("no location", !lines.get(0).contains(location));
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
new file mode 100644
index 0000000..abee218
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SecureSocketAppenderSocketOptionsTest.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+import javax.net.ssl.SSLServerSocketFactory;
+
+import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
+import org.apache.logging.log4j.core.net.Rfc1349TrafficClass;
+import org.apache.logging.log4j.core.net.SocketOptions;
+import org.apache.logging.log4j.core.net.TcpSocketManager;
+import org.apache.logging.log4j.core.net.ssl.KeyStoreConfiguration;
+import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
+import org.apache.logging.log4j.core.net.ssl.StoreConfigurationException;
+import org.apache.logging.log4j.core.net.ssl.TestConstants;
+import org.apache.logging.log4j.core.net.ssl.TrustStoreConfiguration;
+import org.apache.logging.log4j.core.util.NullOutputStream;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+public class SecureSocketAppenderSocketOptionsTest {
+
+    private static final int PORT;
+    private static TcpSocketTestServer tcpSocketTestServer;
+
+    private static SSLServerSocketFactory serverSocketFactory;
+    private static SslConfiguration sslConfiguration;
+
+    static {
+        PORT = AvailablePortFinder.getNextAvailable();
+        System.setProperty("SecureSocketAppenderSocketOptionsTest.port", Integer.toString(PORT));
+        try {
+            initServerSocketFactory();
+            tcpSocketTestServer = new TcpSocketTestServer(serverSocketFactory.createServerSocket(PORT));
+            tcpSocketTestServer.start();
+            loggerContextRule = new LoggerContextRule("log4j-ssl-socket-options.xml");
+        } catch (IOException | StoreConfigurationException e) {
+            throw new IllegalStateException(e);
+        }
+
+    }
+
+    @ClassRule
+    public static final LoggerContextRule loggerContextRule;
+
+    @AfterClass
+    public static void afterClass() {
+        if (tcpSocketTestServer != null) {
+            tcpSocketTestServer.shutdown();
+        }
+    }
+
+    public static void initServerSocketFactory() throws StoreConfigurationException {
+        final KeyStoreConfiguration ksc = KeyStoreConfiguration.createKeyStoreConfiguration(
+                TestConstants.KEYSTORE_FILE, // file
+                TestConstants.KEYSTORE_PWD(),  // password
+                null, // passwordEnvironmentVariable
+                null, // passwordFile
+                null, // key store type
+                null); // algorithm
+
+        final TrustStoreConfiguration tsc = TrustStoreConfiguration.createKeyStoreConfiguration(
+                TestConstants.TRUSTSTORE_FILE, // file
+                TestConstants.TRUSTSTORE_PWD(), // password
+                null, // passwordEnvironmentVariable
+                null, // passwordFile
+                null, // key store type
+                null); // algorithm
+        sslConfiguration = SslConfiguration.createSSLConfiguration(null, ksc, tsc);
+        serverSocketFactory = sslConfiguration.getSslServerSocketFactory();
+    }
+
+    @Test
+    public void testSocketOptions() throws IOException {
+        Assert.assertNotNull(loggerContextRule);
+        Assert.assertNotNull(loggerContextRule.getConfiguration());
+        final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
+        Assert.assertNotNull(appender);
+        final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
+        Assert.assertNotNull(manager);
+        final OutputStream outputStream = manager.getOutputStream();
+        Assert.assertFalse(outputStream instanceof NullOutputStream);
+        final SocketOptions socketOptions = manager.getSocketOptions();
+        Assert.assertNotNull(socketOptions);
+        final Socket socket = manager.getSocket();
+        Assert.assertNotNull(socket);
+        // Test config request
+        Assert.assertEquals(false, socketOptions.isKeepAlive());
+        Assert.assertEquals(null, socketOptions.isOobInline());
+        Assert.assertEquals(false, socketOptions.isReuseAddress());
+        Assert.assertEquals(false, socketOptions.isTcpNoDelay());
+        Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(),
+                socketOptions.getActualTrafficClass().intValue());
+        Assert.assertEquals(10000, socketOptions.getReceiveBufferSize().intValue());
+        Assert.assertEquals(8000, socketOptions.getSendBufferSize().intValue());
+        Assert.assertEquals(12345, socketOptions.getSoLinger().intValue());
+        Assert.assertEquals(54321, socketOptions.getSoTimeout().intValue());
+        // Test live socket
+        Assert.assertEquals(false, socket.getKeepAlive());
+        Assert.assertEquals(false, socket.getReuseAddress());
+        Assert.assertEquals(false, socket.getTcpNoDelay());
+        // Assert.assertEquals(10000, socket.getReceiveBufferSize());
+        // This settings changes while we are running, so we cannot assert it.
+        // Assert.assertEquals(8000, socket.getSendBufferSize());
+        Assert.assertEquals(12345, socket.getSoLinger());
+        Assert.assertEquals(54321, socket.getSoTimeout());
+    }
+
+    @Test
+    public void testSocketTrafficClass() throws IOException {
+        Assume.assumeTrue("Run only on Java 7", System.getProperty("java.specification.version").equals("1.7"));
+        Assume.assumeFalse("Do not run on Travis CI", "true".equals(System.getenv("TRAVIS")));
+        final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
+        final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
+        final Socket socket = manager.getSocket();
+        Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(), socket.getTrafficClass());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java
new file mode 100644
index 0000000..85b6b17
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderBufferSizeTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
+import org.apache.logging.log4j.core.util.Constants;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class SocketAppenderBufferSizeTest {
+
+    private TcpSocketTestServer tcpServer;
+
+    private LoggerContext loggerContext;
+    private Logger logger;
+
+    @Rule
+    public LoggerContextRule loggerContextRule = new LoggerContextRule("log4j-empty.xml");
+
+    @Before
+    public void setup() throws Exception {
+        tcpServer = new TcpSocketTestServer(AvailablePortFinder.getNextAvailable());
+        tcpServer.start();
+        ThreadContext.clearAll();
+        loggerContext = loggerContextRule.getLoggerContext();
+        logger = loggerContext.getLogger(SocketAppenderBufferSizeTest.class.getName());
+    }
+
+    @After
+    public void teardown() {
+        tcpServer.shutdown();
+        loggerContext = null;
+        logger = null;
+        tcpServer.reset();
+        ThreadContext.clearAll();
+    }
+
+    @Test
+    public void testTcpAppenderDefaultEncoderBufferSize() throws Exception {
+        SocketAppenderTest.testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
+    }
+
+    @Test
+    public void testTcpAppenderLargeEncoderBufferSize() throws Exception {
+        SocketAppenderTest.testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE * 100);
+    }
+
+    @Test
+    public void testTcpAppenderSmallestEncoderBufferSize() throws Exception {
+        SocketAppenderTest.testTcpAppender(tcpServer, logger, 1);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
new file mode 100644
index 0000000..030fa80
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderSocketOptionsTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+import org.apache.logging.log4j.core.appender.SocketAppenderTest.TcpSocketTestServer;
+import org.apache.logging.log4j.core.net.Rfc1349TrafficClass;
+import org.apache.logging.log4j.core.net.SocketOptions;
+import org.apache.logging.log4j.core.net.TcpSocketManager;
+import org.apache.logging.log4j.core.util.NullOutputStream;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+public class SocketAppenderSocketOptionsTest {
+
+    private static final int PORT;
+    private static TcpSocketTestServer tcpSocketTestServer;
+
+    static {
+        PORT = AvailablePortFinder.getNextAvailable();
+        System.setProperty("SocketAppenderSocketOptionsTest.port", Integer.toString(PORT));
+        try {
+            tcpSocketTestServer = new TcpSocketTestServer(PORT);
+        } catch (final IOException e) {
+            throw new IllegalStateException(e);
+        }
+        tcpSocketTestServer.start();
+        loggerContextRule = new LoggerContextRule("log4j-socket-options.xml");
+    }
+
+    @ClassRule
+    public static final LoggerContextRule loggerContextRule;
+
+    @AfterClass
+    public static void afterClass() {
+        if (tcpSocketTestServer != null) {
+            tcpSocketTestServer.shutdown();
+        }
+    }
+
+    @Test
+    public void testSocketOptions() throws IOException {
+        Assert.assertNotNull(loggerContextRule);
+        Assert.assertNotNull(loggerContextRule.getConfiguration());
+        final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
+        Assert.assertNotNull(appender);
+        final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
+        Assert.assertNotNull(manager);
+        final OutputStream outputStream = manager.getOutputStream();
+        Assert.assertFalse(outputStream instanceof NullOutputStream);
+        final SocketOptions socketOptions = manager.getSocketOptions();
+        Assert.assertNotNull(socketOptions);
+        final Socket socket = manager.getSocket();
+        Assert.assertNotNull(socket);
+        // Test config request
+        Assert.assertEquals(false, socketOptions.isKeepAlive());
+        Assert.assertEquals(false, socketOptions.isOobInline());
+        Assert.assertEquals(false, socketOptions.isReuseAddress());
+        Assert.assertEquals(false, socketOptions.isTcpNoDelay());
+        Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(),
+                socketOptions.getActualTrafficClass().intValue());
+        Assert.assertEquals(10000, socketOptions.getReceiveBufferSize().intValue());
+        Assert.assertEquals(8000, socketOptions.getSendBufferSize().intValue());
+        Assert.assertEquals(12345, socketOptions.getSoLinger().intValue());
+        Assert.assertEquals(54321, socketOptions.getSoTimeout().intValue());
+        // Test live socket
+        Assert.assertEquals(false, socket.getKeepAlive());
+        Assert.assertEquals(false, socket.getOOBInline());
+        Assert.assertEquals(false, socket.getReuseAddress());
+        Assert.assertEquals(false, socket.getTcpNoDelay());
+        // Assert.assertEquals(10000, socket.getReceiveBufferSize());
+        // This settings changes while we are running, so we cannot assert it.
+        // Assert.assertEquals(8000, socket.getSendBufferSize());
+        Assert.assertEquals(12345, socket.getSoLinger());
+        Assert.assertEquals(54321, socket.getSoTimeout());
+    }
+
+    @Test
+    public void testSocketTrafficClass() throws IOException {
+        Assume.assumeTrue("Run only on Java 7", System.getProperty("java.specification.version").equals("1.7"));
+        Assume.assumeFalse("Do not run on Travis CI", "true".equals(System.getenv("TRAVIS")));
+        final SocketAppender appender = loggerContextRule.getAppender("socket", SocketAppender.class);
+        final TcpSocketManager manager = (TcpSocketManager) appender.getManager();
+        final Socket socket = manager.getSocket();
+        Assert.assertEquals(Rfc1349TrafficClass.IPTOS_LOWCOST.value(), socket.getTrafficClass());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
new file mode 100644
index 0000000..e02590c
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/SocketAppenderTest.java
@@ -0,0 +1,412 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LoggingException;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.net.Protocol;
+import org.apache.logging.log4j.core.util.Constants;
+import org.apache.logging.log4j.core.util.Throwables;
+import org.apache.logging.log4j.jackson.json.Log4jJsonObjectMapper;
+import org.apache.logging.log4j.jackson.json.layout.JsonLayout;
+import org.apache.logging.log4j.test.AvailablePortFinder;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.MappingIterator;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ *
+ */
+public class SocketAppenderTest {
+
+    private static final int PORT = AvailablePortFinder.getNextAvailable();
+    private static final int DYN_PORT = AvailablePortFinder.getNextAvailable();
+    private static final int ERROR_PORT = AvailablePortFinder.getNextAvailable();
+
+    private static TcpSocketTestServer tcpServer;
+    private static UdpSocketTestServer udpServer;
+
+    private final LoggerContext context = LoggerContext.getContext();
+    private final Logger logger = context.getLogger(SocketAppenderTest.class.getName());
+
+    @BeforeClass
+    public static void setupClass() throws Exception {
+        tcpServer = new TcpSocketTestServer(PORT);
+        tcpServer.start();
+        udpServer = new UdpSocketTestServer();
+        udpServer.start();
+        LoggerContext.getContext().reconfigure();
+        ThreadContext.clearAll();
+    }
+
+    @AfterClass
+    public static void cleanupClass() {
+        tcpServer.shutdown();
+        udpServer.shutdown();
+        ThreadContext.clearAll();
+    }
+
+    @After
+    public void teardown() {
+        ThreadContext.clearAll();
+        removeAndStopAppenders();
+        reset();
+    }
+
+    void removeAndStopAppenders() {
+        final Map<String, Appender> map = logger.getAppenders();
+        for (final Map.Entry<String, Appender> entry : map.entrySet()) {
+            final Appender appender = entry.getValue();
+            logger.removeAppender(appender);
+            appender.stop();
+        }
+    }
+
+    static void reset() {
+        tcpServer.reset();
+        udpServer.reset();
+    }
+
+    @Test
+    public void testTcpAppender1() throws Exception {
+        testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
+    }
+
+    @Test
+    @Ignore("WIP Bug when this method runs after testTcpAppender1()")
+    public void testTcpAppender2() throws Exception {
+        testTcpAppender(tcpServer, logger, Constants.ENCODER_BYTE_BUFFER_SIZE);
+    }
+
+    static void testTcpAppender(final TcpSocketTestServer tcpTestServer, final Logger logger, final int bufferSize)
+            throws Exception {
+        // @formatter:off
+        final SocketAppender appender = SocketAppender.newBuilder()
+                .withHost("localhost")
+                .withPort(tcpTestServer.getLocalPort())
+                .withReconnectDelayMillis(-1)
+                .withName("test")
+                .withImmediateFail(false)
+                .withBufferSize(bufferSize)
+                .withLayout(JsonLayout.newBuilder().setProperties(true).build())
+                .build();
+        // @formatter:on
+        appender.start();
+        Assert.assertEquals(bufferSize, appender.getManager().getByteBuffer().capacity());
+
+        // set appender on root and set level to debug
+        logger.addAppender(appender);
+        logger.setAdditive(false);
+        logger.setLevel(Level.DEBUG);
+        final String tcKey = "UUID";
+        final String expectedUuidStr = UUID.randomUUID().toString();
+        ThreadContext.put(tcKey, expectedUuidStr);
+        ThreadContext.push(expectedUuidStr);
+        final String expectedExMsg = "This is a test";
+        try {
+            logger.debug("This is a test message");
+            final Throwable child = new LoggingException(expectedExMsg);
+            logger.error("Throwing an exception", child);
+            logger.debug("This is another test message");
+        } finally {
+            ThreadContext.remove(tcKey);
+            ThreadContext.pop();
+        }
+        Thread.sleep(250);
+        LogEvent event = tcpTestServer.getQueue().poll(3, TimeUnit.SECONDS);
+        assertNotNull("No event retrieved", event);
+        assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("This is a test message"));
+        assertTrue("Message not delivered via TCP", tcpTestServer.getCount() > 0);
+        assertEquals(expectedUuidStr, event.getContextData().getValue(tcKey));
+        event = tcpTestServer.getQueue().poll(3, TimeUnit.SECONDS);
+        assertNotNull("No event retrieved", event);
+        assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("Throwing an exception"));
+        assertTrue("Message not delivered via TCP", tcpTestServer.getCount() > 1);
+        assertEquals(expectedUuidStr, event.getContextStack().pop());
+        assertNotNull(event.getThrownProxy());
+        assertEquals(expectedExMsg, event.getThrownProxy().getMessage());
+    }
+
+    @Test
+    public void testDefaultProtocol() throws Exception {
+        // @formatter:off
+        final SocketAppender appender = SocketAppender.newBuilder()
+                .withPort(tcpServer.getLocalPort())
+                .withReconnectDelayMillis(-1)
+                .withName("test")
+                .withImmediateFail(false)
+                .withLayout(JsonLayout.newBuilder().setProperties(true).build())
+                .build();
+        // @formatter:on
+        assertNotNull(appender);
+        appender.stop();
+    }
+
+    @Test
+    public void testUdpAppender() throws Exception {
+        try {
+            udpServer.latch.await();
+        } catch (final InterruptedException ex) {
+            ex.printStackTrace();
+        }
+
+        // @formatter:off
+        final SocketAppender appender = SocketAppender.newBuilder()
+                .withProtocol(Protocol.UDP)
+                .withPort(tcpServer.getLocalPort())
+                .withReconnectDelayMillis(-1)
+                .withName("test")
+                .withImmediateFail(false)
+                .withLayout(JsonLayout.newBuilder().setProperties(true).build())
+                .build();
+        // @formatter:on
+        appender.start();
+
+        // set appender on root and set level to debug
+        logger.addAppender(appender);
+        logger.setAdditive(false);
+        logger.setLevel(Level.DEBUG);
+        logger.debug("This is a udp message");
+        final LogEvent event = udpServer.getQueue().poll(3, TimeUnit.SECONDS);
+        assertNotNull("No event retrieved", event);
+        assertTrue("Incorrect event", event.getMessage().getFormattedMessage().equals("This is a udp message"));
+        assertTrue("Message not delivered via UDP", udpServer.getCount() > 0);
+    }
+
+    @Test
+    public void testTcpAppenderDeadlock() throws Exception {
+
+        // @formatter:off
+        final SocketAppender appender = SocketAppender.newBuilder()
+                .withHost("localhost")
+                .withPort(DYN_PORT)
+                .withReconnectDelayMillis(100)
+                .withName("test")
+                .withImmediateFail(false)
+                .withLayout(JsonLayout.newBuilder().setProperties(true).build())
+                .build();
+        // @formatter:on
+        appender.start();
+        // set appender on root and set level to debug
+        logger.addAppender(appender);
+        logger.setAdditive(false);
+        logger.setLevel(Level.DEBUG);
+
+        final TcpSocketTestServer tcpSocketServer = new TcpSocketTestServer(DYN_PORT);
+        try {
+            tcpSocketServer.start();
+
+            logger.debug("This message is written because a deadlock never.");
+
+            final LogEvent event = tcpSocketServer.getQueue().poll(3, TimeUnit.SECONDS);
+            assertNotNull("No event retrieved", event);
+        } finally {
+            tcpSocketServer.shutdown();
+        }
+    }
+
+    @Test
+    public void testTcpAppenderNoWait() throws Exception {
+        // @formatter:off
+        final SocketAppender appender = SocketAppender.newBuilder()
+                .withHost("localhost")
+                .withPort(ERROR_PORT)
+                .withReconnectDelayMillis(100)
+                .withName("test")
+                .withImmediateFail(false)
+                .withIgnoreExceptions(false)
+                .withLayout(JsonLayout.newBuilder().setProperties(true).build())
+                .build();
+        // @formatter:on
+        appender.start();
+        // set appender on root and set level to debug
+        logger.addAppender(appender);
+        logger.setAdditive(false);
+        logger.setLevel(Level.DEBUG);
+
+        try {
+            logger.debug("This message is written because a deadlock never.");
+            fail("No Exception was thrown");
+        } catch (final Exception ex) {
+            // TODO: move exception to @Test(expect = Exception.class)
+            // Failure is expected.
+            // ex.printStackTrace();
+        }
+    }
+
+    public static class UdpSocketTestServer extends Thread {
+
+        private final DatagramSocket sock;
+        private boolean shutdown = false;
+        private Thread thread;
+        private final CountDownLatch latch = new CountDownLatch(1);
+        private volatile int count = 0;
+        private final BlockingQueue<LogEvent> queue;
+        private final ObjectMapper objectMapper = new Log4jJsonObjectMapper();
+
+        public UdpSocketTestServer() throws IOException {
+            this.sock = new DatagramSocket(PORT);
+            this.queue = new ArrayBlockingQueue<>(10);
+        }
+
+        public void reset() {
+            queue.clear();
+            count = 0;
+        }
+
+        public void shutdown() {
+            this.shutdown = true;
+            thread.interrupt();
+            try {
+                thread.join(100);
+            } catch (InterruptedException ie) {
+                System.out.println("Unable to stop server");
+            }
+        }
+
+        @Override
+        public void run() {
+            this.thread = Thread.currentThread();
+            final byte[] bytes = new byte[4096];
+            final DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
+            try {
+                while (!shutdown) {
+                    latch.countDown();
+                    sock.receive(packet);
+                    ++count;
+                    final LogEvent event = objectMapper.readValue(packet.getData(), Log4jLogEvent.class);
+                    queue.add(event);
+                }
+            } catch (final Throwable e) {
+                e.printStackTrace();
+                if (!shutdown) {
+                    Throwables.rethrow(e);
+                }
+            }
+        }
+
+        public int getCount() {
+            return count;
+        }
+
+        public BlockingQueue<LogEvent> getQueue() {
+            return queue;
+        }
+    }
+
+    public static class TcpSocketTestServer extends Thread {
+
+        private final ServerSocket serverSocket;
+        private volatile boolean shutdown = false;
+        private volatile int count = 0;
+        private final BlockingQueue<LogEvent> queue;
+        private final ObjectMapper objectMapper = new Log4jJsonObjectMapper();
+
+        @SuppressWarnings("resource")
+        public TcpSocketTestServer(final int port) throws IOException {
+            this(new ServerSocket(port));
+        }
+
+        public TcpSocketTestServer(final ServerSocket serverSocket) {
+            this.serverSocket = serverSocket;
+            this.queue = new ArrayBlockingQueue<>(10);
+        }
+
+        public int getLocalPort() {
+            return serverSocket.getLocalPort();
+        }
+
+        public void reset() {
+            queue.clear();
+            count = 0;
+        }
+
+        public void shutdown() {
+            this.shutdown = true;
+            interrupt();
+            try {
+                this.join(100);
+            } catch (InterruptedException ie) {
+                System.out.println("Unable to stop server");
+            }
+        }
+
+        @Override
+        public void run() {
+            try {
+                try (final Socket socket = serverSocket.accept()) {
+                    if (socket != null) {
+                        final InputStream is = socket.getInputStream();
+                        while (!shutdown) {
+                            final MappingIterator<LogEvent> mappingIterator = objectMapper.readerFor(Log4jLogEvent.class).readValues(is);
+                            while (mappingIterator.hasNextValue()) {
+                                queue.add(mappingIterator.nextValue());
+                                ++count;
+                            }
+                        }
+                    }
+                }
+            } catch (final EOFException eof) {
+                // Socket is closed.
+            } catch (final Exception e) {
+                if (!shutdown) {
+                    Throwables.rethrow(e);
+                }
+            }
+        }
+
+        public BlockingQueue<LogEvent> getQueue() {
+            return queue;
+        }
+
+        public int getCount() {
+            return count;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java
new file mode 100644
index 0000000..eea989a
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.CoreLoggerContexts;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * Tests a "compact" XML file, no extra spaces or end of lines.
+ */
+@Category(Layouts.Xml.class)
+public class XmlCompactFileAppenderTest {
+
+    @BeforeClass
+    public static void beforeClass() {
+        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
+                "XmlCompactFileAppenderTest.xml");
+    }
+
+    @Test
+    public void testFlushAtEndOfBatch() throws Exception {
+        final File file = new File("target", "XmlCompactFileAppenderTest.log");
+        file.delete();
+        final Logger log = LogManager.getLogger("com.foo.Bar");
+        final String logMsg = "Message flushed with immediate flush=false";
+        log.info(logMsg);
+        CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread
+
+        String line1;
+        try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
+            line1 = reader.readLine();
+        } finally {
+            file.delete();
+        }
+        assertNotNull("line1", line1);
+        final String msg1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg1 + ']', line1.contains(msg1));
+
+        final String msg2 = "<Events xmlns=\"http://logging.apache.org/log4j/2.0/events\">";
+        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg2 + ']', line1.contains(msg2));
+
+        final String msg3 = "<Event ";
+        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg3 + ']', line1.contains(msg3));
+
+        final String msg4 = logMsg;
+        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg4 + ']', line1.contains(msg4));
+
+        final String location = "testFlushAtEndOfBatch";
+        assertTrue("no location", !line1.contains(location));
+
+        assertTrue(line1.indexOf('\r') == -1);
+        assertTrue(line1.indexOf('\n') == -1);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java
new file mode 100644
index 0000000..9b4da79
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.xml.XMLConstants;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configurator;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.xml.sax.SAXException;
+
+/**
+ * Tests XML validation for a "compact" XML file, no extra spaces or end of lines.
+ */
+@Ignore
+@Category(Layouts.Xml.class)
+public class XmlCompactFileAppenderValidationTest {
+
+    private LoggerContext loggerContext;
+
+    @Before
+    public void before() {
+        this.loggerContext = Configurator.initialize(XmlCompactFileAppenderValidationTest.class.getName(),
+                "target/test-classes/XmlCompactFileAppenderValidationTest.xml");
+    }
+
+    @After
+    public void after() {
+        // Just in case, an @Test blew up
+        Configurator.shutdown(this.loggerContext);
+    }
+
+    @Test
+    public void validateXmlSchemaThrowable() throws Exception {
+        final File file = new File("target", "XmlCompactFileAppenderValidationTest.log.xml");
+        file.delete();
+        final Logger log = LogManager.getLogger("com.foo.Bar");
+        try {
+            throw new IllegalArgumentException("IAE");
+        } catch (final IllegalArgumentException e) {
+            log.warn("Message 1", e);
+        }
+        Configurator.shutdown(this.loggerContext);
+        this.validateXmlSchema(file);
+    }
+
+    @Test
+    public void validateXmlSchema() throws Exception {
+        final File file = new File("target", "XmlCompactFileAppenderValidationTest.log.xml");
+        file.delete();
+        final Logger log = LogManager.getLogger("com.foo.Bar");
+        log.warn("Message 1");
+        log.info("Message 2");
+        log.debug("Message 3");
+        Configurator.shutdown(this.loggerContext);
+        this.validateXmlSchema(file);
+    }
+
+    @Test
+    public void validateXmlNoEvents() throws Exception {
+        final File file = new File("target", "XmlCompactFileAppenderValidationTest.log.xml");
+        file.delete();
+        Configurator.shutdown(this.loggerContext);
+        this.validateXmlSchema(file);
+    }
+
+    private void validateXmlSchema(final File file) throws SAXException, IOException {
+        final URL schemaFile = this.getClass().getClassLoader().getResource("Log4j-events.xsd");
+        final Source xmlFile = new StreamSource(file);
+        final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        final Schema schema = schemaFactory.newSchema(schemaFile);
+        final Validator validator = schema.newValidator();
+        validator.validate(xmlFile);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java
----------------------------------------------------------------------
diff --git a/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java
new file mode 100644
index 0000000..1e048b1
--- /dev/null
+++ b/log4j-core-its/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.xml.XMLConstants;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.CoreLoggerContexts;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.xml.sax.SAXException;
+
+/**
+ * Tests XML validation for a "compact" XML file, no extra spaces or end of lines.
+ */
+@Ignore
+@Category(Layouts.Xml.class)
+public class XmlCompactFileAsyncAppenderValidationTest {
+
+    @BeforeClass
+    public static void beforeClass() {
+        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
+                "XmlCompactFileAsyncAppenderValidationTest.xml");
+    }
+
+    @Test
+    public void validateXmlSchemaSimple() throws Exception {
+        final File file = new File("target", "XmlCompactFileAsyncAppenderValidationTest.log.xml");
+        file.delete();
+        final Logger log = LogManager.getLogger("com.foo.Bar");
+        log.warn("Message 1");
+        log.info("Message 2");
+        log.debug("Message 3");
+        CoreLoggerContexts.stopLoggerContext(file); // stop async thread
+        this.validateXmlSchema(file);
+    }
+
+    @Test
+    public void validateXmlSchemaNoEvents() throws Exception {
+        final File file = new File("target", "XmlCompactFileAsyncAppenderValidationTest.log.xml");
+        file.delete();
+        CoreLoggerContexts.stopLoggerContext(file); // stop async thread
+        this.validateXmlSchema(file);
+    }
+
+    private void validateXmlSchema(final File file) throws SAXException, IOException {
+        final URL schemaFile = this.getClass().getClassLoader().getResource("Log4j-events.xsd");
+        final Source xmlFile = new StreamSource(file);
+        final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        final Schema schema = schemaFactory.newSchema(schemaFile);
+        final Validator validator = schema.newValidator();
+        validator.validate(xmlFile);
+    }
+
+}


[10/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MapEntry.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MapEntry.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MapEntry.java
deleted file mode 100644
index 239b084..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MapEntry.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import org.apache.logging.log4j.util.Strings;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- * <p>
- * Used to represent map entries in a generic fashion because the default Jackson behavior uses the key as the element tag. Using the key as
- * an element/property name would mean that you cannot have a generic JSON/XML schema for all log event.
- * </p>
- */
-@JsonPropertyOrder({ "key", "value" })
-final class MapEntry {
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String key;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String value;
-
-    @JsonCreator
-    public MapEntry(@JsonProperty("key") final String key, @JsonProperty("value") final String value) {
-        this.setKey(key);
-        this.setValue(value);
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof MapEntry)) {
-            return false;
-        }
-        final MapEntry other = (MapEntry) obj;
-        if (this.getKey() == null) {
-            if (other.getKey() != null) {
-                return false;
-            }
-        } else if (!this.getKey().equals(other.getKey())) {
-            return false;
-        }
-        if (this.getValue() == null) {
-            if (other.getValue() != null) {
-                return false;
-            }
-        } else if (!this.getValue().equals(other.getValue())) {
-            return false;
-        }
-        return true;
-    }
-
-    public String getKey() {
-        return this.key;
-    }
-
-    public String getValue() {
-        return this.value;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((this.getKey() == null) ? 0 : this.getKey().hashCode());
-        result = prime * result + ((this.getValue() == null) ? 0 : this.getValue().hashCode());
-        return result;
-    }
-
-    public void setKey(final String key) {
-        this.key = key;
-    }
-
-    public void setValue(final String value) {
-        this.value = value;
-    }
-
-    @Override
-    public String toString() {
-        return Strings.EMPTY + this.getKey() + "=" + this.getValue();
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MarkerMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MarkerMixIn.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MarkerMixIn.java
deleted file mode 100644
index 950c2c8..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MarkerMixIn.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import org.apache.logging.log4j.Marker;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-
-/**
- * Jackson mix-in for {@link Marker}.
- * <p>
- * If we want to deal with more than one {@link Marker} implementation then recode these annotations to include metadata.
- * </p>
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- * <p>
- * Example XML:
- * </p>
- * <pre>
-&lt;Marker name=&quot;Marker1&quot;&gt;
-    &lt;Parents&gt;
-        &lt;Marker name=&quot;ParentMarker1&quot;&gt;
-            &lt;Parents&gt;
-                &lt;Marker name=&quot;GrandMotherMarker&quot;/&gt;
-                &lt;Marker name=&quot;GrandFatherMarker&quot;/&gt;
-            &lt;/Parents&gt;
-        &lt;/Marker&gt;
-        &lt;Marker name=&quot;ParentMarker2&quot;/&gt;
-    &lt;/Parents&gt;
-&lt;/Marker&gt;
- * </pre>
- * 
- * @see Marker
- */
-// Alternate for multiple Marker implementation.
-// @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
-@JsonDeserialize(as = org.apache.logging.log4j.MarkerManager.Log4jMarker.class)
-abstract class MarkerMixIn implements Marker {
-    private static final long serialVersionUID = 1L;
-
-    @JsonCreator
-    MarkerMixIn(@JsonProperty("name") final String name) {
-        // empty
-    }
-
-    @Override
-    @JsonProperty("name")
-    @JacksonXmlProperty(isAttribute = true)
-    public abstract String getName();
-
-    @Override
-    @JsonProperty(JsonConstants.ELT_PARENTS)
-    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_PARENTS)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_MARKER)
-    public abstract Marker[] getParents();
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MessageSerializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MessageSerializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MessageSerializer.java
deleted file mode 100644
index 3c19672..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MessageSerializer.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-
-import org.apache.logging.log4j.message.Message;
-
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-final class MessageSerializer extends StdScalarSerializer<Message> {
-
-    private static final long serialVersionUID = 1L;
-
-    MessageSerializer() {
-        super(Message.class);
-    }
-
-    @Override
-    public void serialize(final Message value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException,
-            JsonGenerationException {
-        jgen.writeString(value.getFormattedMessage());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MutableThreadContextStackDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MutableThreadContextStackDeserializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MutableThreadContextStackDeserializer.java
deleted file mode 100644
index 4d4a530..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/MutableThreadContextStackDeserializer.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.logging.log4j.spi.MutableThreadContextStack;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-final class MutableThreadContextStackDeserializer extends StdDeserializer<MutableThreadContextStack> {
-
-    private static final long serialVersionUID = 1L;
-
-    MutableThreadContextStackDeserializer() {
-        super(MutableThreadContextStack.class);
-    }
-
-    @Override
-    public MutableThreadContextStack deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
-            JsonProcessingException {
-        final List<String> list = jp.readValueAs(new TypeReference<List<String>>() {
-            // empty
-        });
-        return new MutableThreadContextStack(list);
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ObjectMessageSerializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ObjectMessageSerializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ObjectMessageSerializer.java
deleted file mode 100644
index 8bbfe0b..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ObjectMessageSerializer.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-
-import org.apache.logging.log4j.message.ObjectMessage;
-
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-final class ObjectMessageSerializer extends StdScalarSerializer<ObjectMessage> {
-
-    private static final long serialVersionUID = 1L;
-
-    ObjectMessageSerializer() {
-        super(ObjectMessage.class);
-    }
-
-    @Override
-    public void serialize(final ObjectMessage value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException,
-            JsonGenerationException {
-        jgen.writeObject(value.getParameter());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/SimpleMessageDeserializer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/SimpleMessageDeserializer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/SimpleMessageDeserializer.java
deleted file mode 100644
index f269590..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/SimpleMessageDeserializer.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-
-import org.apache.logging.log4j.message.SimpleMessage;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
-
-/**
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- */
-public final class SimpleMessageDeserializer extends StdScalarDeserializer<SimpleMessage> {
-
-    private static final long serialVersionUID = 1L;
-
-    SimpleMessageDeserializer() {
-        super(SimpleMessage.class);
-    }
-
-    @Override
-    public SimpleMessage deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
-            JsonProcessingException {
-        return new SimpleMessage(jp.getValueAsString());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixIn.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixIn.java
deleted file mode 100644
index 9a3b022..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixIn.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-
-/**
- * Jackson mix-in for {@link StackTraceElement}.
- * <p>
- * <em>Consider this class private.</em>
- * </p>
- * 
- * @see StackTraceElement
- */
-@JsonIgnoreProperties("nativeMethod")
-abstract class StackTraceElementMixIn {
-    @JsonCreator
-    StackTraceElementMixIn(
-            // @formatter:off
-            @JsonProperty("class") final String declaringClass, 
-            @JsonProperty("method") final String methodName,
-            @JsonProperty("file") final String fileName, 
-            @JsonProperty("line") final int lineNumber)
-            // @formatter:on
-    {
-        // empty
-    }
-
-    @JsonProperty("class")
-    @JacksonXmlProperty(localName = "class", isAttribute = true)
-    abstract String getClassName();
-
-    @JsonProperty("file")
-    @JacksonXmlProperty(localName = "file", isAttribute = true)
-    abstract String getFileName();
-
-    @JsonProperty("line")
-    @JacksonXmlProperty(localName = "line", isAttribute = true)
-    abstract int getLineNumber();
-
-    @JsonProperty("method")
-    @JacksonXmlProperty(localName = "method", isAttribute = true)
-    abstract String getMethodName();
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyMixIn.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyMixIn.java
deleted file mode 100644
index a36c1b4..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyMixIn.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
-import org.apache.logging.log4j.core.impl.ThrowableProxy;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-
-/**
- * Mix-in for {@link ThrowableProxy}.
- */
-abstract class ThrowableProxyMixIn {
-
-    @JsonProperty(JsonConstants.ELT_CAUSE)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CAUSE)
-    private ThrowableProxyMixIn causeProxy;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private int commonElementCount;
-
-    @JsonProperty(JsonConstants.ELT_EXTENDED_STACK_TRACE)
-    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EXTENDED_STACK_TRACE)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EXTENDED_STACK_TRACE_ITEM)
-    private ExtendedStackTraceElement[] extendedStackTrace;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String localizedMessage;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String message;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String name;
-
-    @JsonIgnore
-    private transient Throwable throwable;
-
-    @JsonIgnore
-    public abstract String getCauseStackTraceAsString();
-
-    @JsonIgnore
-    public abstract String getExtendedStackTraceAsString();
-
-    @JsonIgnore
-    public abstract StackTraceElement[] getStackTrace();
-
-    @JsonProperty(JsonConstants.ELT_SUPPRESSED)
-    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED_ITEM)
-    public abstract ThrowableProxy[] getSuppressedProxies();
-
-    @JsonIgnore
-    public abstract String getSuppressedStackTrace();
-
-    @JsonIgnore
-    public abstract Throwable getThrowable();
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java
deleted file mode 100644
index f169d35..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyWithStacktraceAsStringMixIn.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
-import org.apache.logging.log4j.core.impl.ThrowableProxy;
-
-/**
- * Mix-in for {@link org.apache.logging.log4j.core.impl.ThrowableProxy}.
- */
-abstract class ThrowableProxyWithStacktraceAsStringMixIn {
-
-    @JsonProperty(JsonConstants.ELT_CAUSE)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CAUSE)
-    private ThrowableProxyWithStacktraceAsStringMixIn causeProxy;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private int commonElementCount;
-
-    @JsonIgnore
-    private ExtendedStackTraceElement[] extendedStackTrace;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String localizedMessage;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String message;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String name;
-
-    @JsonIgnore
-    private transient Throwable throwable;
-
-    @JsonIgnore
-    public abstract String getCauseStackTraceAsString();
-
-    @JsonProperty(JsonConstants.ELT_EXTENDED_STACK_TRACE)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EXTENDED_STACK_TRACE)
-    public abstract String getExtendedStackTraceAsString();
-
-    @JsonIgnore
-    public abstract StackTraceElement[] getStackTrace();
-
-    @JsonProperty(JsonConstants.ELT_SUPPRESSED)
-    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED_ITEM)
-    public abstract ThrowableProxy[] getSuppressedProxies();
-
-    @JsonIgnore
-    public abstract String getSuppressedStackTrace();
-
-    @JsonIgnore
-    public abstract Throwable getThrowable();
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyWithoutStacktraceMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyWithoutStacktraceMixIn.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyWithoutStacktraceMixIn.java
deleted file mode 100644
index 264bef8..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/ThrowableProxyWithoutStacktraceMixIn.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
-import org.apache.logging.log4j.core.impl.ThrowableProxy;
-
-/**
- * Mix-in for {@link ThrowableProxy}.
- */
-abstract class ThrowableProxyWithoutStacktraceMixIn {
-
-    @JsonProperty(JsonConstants.ELT_CAUSE)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CAUSE)
-    private ThrowableProxyWithoutStacktraceMixIn causeProxy;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private int commonElementCount;
-
-    @JsonIgnore
-    private ExtendedStackTraceElement[] extendedStackTrace;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String localizedMessage;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String message;
-
-    @JsonProperty
-    @JacksonXmlProperty(isAttribute = true)
-    private String name;
-
-    @JsonIgnore
-    private transient Throwable throwable;
-
-    @JsonIgnore
-    public abstract String getCauseStackTraceAsString();
-
-    @JsonIgnore
-    public abstract String getExtendedStackTraceAsString();
-
-    @JsonIgnore
-    public abstract StackTraceElement[] getStackTrace();
-
-    @JsonProperty(JsonConstants.ELT_SUPPRESSED)
-    @JacksonXmlElementWrapper(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED)
-    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_SUPPRESSED_ITEM)
-    public abstract ThrowableProxy[] getSuppressedProxies();
-
-    @JsonIgnore
-    public abstract String getSuppressedStackTrace();
-
-    @JsonIgnore
-    public abstract Throwable getThrowable();
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/XmlConstants.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/XmlConstants.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/XmlConstants.java
deleted file mode 100644
index 0871440..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/XmlConstants.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-/**
- * Keeps constants separate from any class that may depend on third party jars.
- */
-public final class XmlConstants {
-    public static final String ELT_CAUSE = "Cause";
-    public static final String ELT_CONTEXT_MAP = "ContextMap";
-    public static final String ELT_CONTEXT_STACK = "ContextStack";
-    public static final String ELT_CONTEXT_STACK_ITEM = "ContextStackItem";
-    public static final String ELT_EVENT = "Event";
-    public static final String ELT_EXTENDED_STACK_TRACE = "ExtendedStackTrace";
-    public static final String ELT_EXTENDED_STACK_TRACE_ITEM = "ExtendedStackTraceItem";
-    public static final String ELT_INSTANT = "Instant";
-    public static final String ELT_MARKER = "Marker";
-    public static final String ELT_MESSAGE = "Message";
-    public static final String ELT_PARENTS = "Parents";
-    public static final String ELT_SOURCE = "Source";
-    public static final String ELT_SUPPRESSED = "Suppressed";
-    public static final String ELT_SUPPRESSED_ITEM = "SuppressedItem";
-    public static final String ELT_THROWN = "Thrown";
-    public static final String XML_NAMESPACE = "http://logging.apache.org/log4j/2.0/events";
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/package-info.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/package-info.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/package-info.java
deleted file mode 100644
index 585da42..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-/**
- * Classes and interfaces for serializing and deserializing Log4j 2 log events to XML and JSON using the Jackson
- * library.
- */
-package org.apache.logging.log4j.core.jackson;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/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
deleted file mode 100644
index 7a04100..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.layout;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.config.Configuration;
-import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
-import org.apache.logging.log4j.core.config.plugins.PluginElement;
-import org.apache.logging.log4j.core.impl.MutableLogEvent;
-import org.apache.logging.log4j.core.jackson.XmlConstants;
-import org.apache.logging.log4j.core.lookup.StrSubstitutor;
-import org.apache.logging.log4j.core.util.KeyValuePair;
-import org.apache.logging.log4j.core.util.StringBuilderWriter;
-import org.apache.logging.log4j.util.Strings;
-
-import com.fasterxml.jackson.annotation.JsonAnyGetter;
-import com.fasterxml.jackson.annotation.JsonRootName;
-import com.fasterxml.jackson.annotation.JsonUnwrapped;
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectWriter;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
-
-abstract class AbstractJacksonLayout extends AbstractStringLayout {
-
-    protected static final String DEFAULT_EOL = "\r\n";
-    protected static final String COMPACT_EOL = Strings.EMPTY;
-
-    public static abstract class Builder<B extends Builder<B>> extends AbstractStringLayout.Builder<B> {
-
-        @PluginBuilderAttribute
-        private boolean eventEol;
-
-        @PluginBuilderAttribute
-        private boolean compact;
-
-        @PluginBuilderAttribute
-        private boolean complete;
-
-        @PluginBuilderAttribute
-        private boolean locationInfo;
-
-        @PluginBuilderAttribute
-        private boolean properties;
-
-        @PluginBuilderAttribute
-        private boolean includeStacktrace = true;
-
-        @PluginBuilderAttribute
-        private boolean stacktraceAsString = false;
-
-        @PluginBuilderAttribute
-        private boolean includeNullDelimiter = false;
-
-        @PluginElement("AdditionalField")
-        private KeyValuePair[] additionalFields;
-
-        protected String toStringOrNull(final byte[] header) {
-            return header == null ? null : new String(header, Charset.defaultCharset());
-        }
-
-        public boolean getEventEol() {
-            return eventEol;
-        }
-
-        public boolean isCompact() {
-            return compact;
-        }
-
-        public boolean isComplete() {
-            return complete;
-        }
-
-        public boolean isLocationInfo() {
-            return locationInfo;
-        }
-
-        public boolean isProperties() {
-            return properties;
-        }
-
-        /**
-         * If "true", includes the stacktrace of any Throwable in the generated data, defaults to "true".
-         * @return If "true", includes the stacktrace of any Throwable in the generated data, defaults to "true".
-         */
-        public boolean isIncludeStacktrace() {
-            return includeStacktrace;
-        }
-
-        public boolean isStacktraceAsString() {
-            return stacktraceAsString;
-        }
-
-        public boolean isIncludeNullDelimiter() { return includeNullDelimiter; }
-
-        public KeyValuePair[] getAdditionalFields() {
-            return additionalFields;
-        }
-
-        public B setEventEol(final boolean eventEol) {
-            this.eventEol = eventEol;
-            return asBuilder();
-        }
-
-        public B setCompact(final boolean compact) {
-            this.compact = compact;
-            return asBuilder();
-        }
-
-        public B setComplete(final boolean complete) {
-            this.complete = complete;
-            return asBuilder();
-        }
-
-        public B setLocationInfo(final boolean locationInfo) {
-            this.locationInfo = locationInfo;
-            return asBuilder();
-        }
-
-        public B setProperties(final boolean properties) {
-            this.properties = properties;
-            return asBuilder();
-        }
-
-        /**
-         * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true".
-         * @param includeStacktrace If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true".
-         * @return this builder
-         */
-        public B setIncludeStacktrace(final boolean includeStacktrace) {
-            this.includeStacktrace = includeStacktrace;
-            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(final 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();
-        }
-
-        /**
-         * Additional fields to set on each log event.
-         *
-         * @return this builder
-         */
-        public B setAdditionalFields(KeyValuePair[] additionalFields) {
-            this.additionalFields = additionalFields;
-            return asBuilder();
-        }
-    }
-
-    protected final String eol;
-    protected final ObjectWriter objectWriter;
-    protected final boolean compact;
-    protected final boolean complete;
-    protected final boolean includeNullDelimiter;
-    protected final ResolvableKeyValuePair[] additionalFields;
-
-    @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);
-    }
-
-    @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, final boolean includeNullDelimiter) {
-        this(config, objectWriter, charset, compact, complete, eventEol, headerSerializer, footerSerializer, includeNullDelimiter, null);
-    }
-
-    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,
-            final KeyValuePair[] additionalFields) {
-        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;
-        this.additionalFields = prepareAdditionalFields(config, additionalFields);
-    }
-
-    protected static boolean valueNeedsLookup(final String value) {
-        return value != null && value.contains("${");
-    }
-
-    private static ResolvableKeyValuePair[] prepareAdditionalFields(final Configuration config, final KeyValuePair[] additionalFields) {
-        if (additionalFields == null || additionalFields.length == 0) {
-            // No fields set
-            return new ResolvableKeyValuePair[0];
-        }
-
-        // Convert to specific class which already determines whether values needs lookup during serialization
-        final ResolvableKeyValuePair[] resolvableFields = new ResolvableKeyValuePair[additionalFields.length];
-
-        for (int i = 0; i < additionalFields.length; i++) {
-            ResolvableKeyValuePair resolvable = resolvableFields[i] = new ResolvableKeyValuePair(additionalFields[i]);
-
-            // Validate
-            if (config == null && resolvable.valueNeedsLookup) {
-                throw new IllegalArgumentException("configuration needs to be set when there are additional fields with variables");
-            }
-        }
-
-        return resolvableFields;
-    }
-
-    /**
-     * Formats a {@link org.apache.logging.log4j.core.LogEvent}.
-     *
-     * @param event The LogEvent.
-     * @return The XML representation of the LogEvent.
-     */
-    @Override
-    public String toSerializable(final LogEvent event) {
-        final StringBuilderWriter writer = new StringBuilderWriter();
-        try {
-            toSerializable(event, writer);
-            return writer.toString();
-        } catch (final IOException e) {
-            // Should this be an ISE or IAE?
-            LOGGER.error(e);
-            return Strings.EMPTY;
-        }
-    }
-
-    private static LogEvent convertMutableToLog4jEvent(final LogEvent event) {
-        // TODO Jackson-based layouts have certain filters set up for Log4jLogEvent.
-        // TODO Need to set up the same filters for MutableLogEvent but don't know how...
-        // This is a workaround.
-        return event instanceof MutableLogEvent
-                ? ((MutableLogEvent) event).createMemento()
-                : event;
-    }
-
-    protected Object wrapLogEvent(final LogEvent event) {
-        if (additionalFields.length > 0) {
-            // Construct map for serialization - note that we are intentionally using original LogEvent
-            Map<String, String> additionalFieldsMap = resolveAdditionalFields(event);
-            // This class combines LogEvent with AdditionalFields during serialization
-            return new LogEventWithAdditionalFields(event, additionalFieldsMap);
-        } else {
-            // No additional fields, return original object
-            return event;
-        }
-    }
-
-    private Map<String, String> resolveAdditionalFields(LogEvent logEvent) {
-        // Note: LinkedHashMap retains order
-        final Map<String, String> additionalFieldsMap = new LinkedHashMap<>(additionalFields.length);
-        final StrSubstitutor strSubstitutor = configuration.getStrSubstitutor();
-
-        // Go over each field
-        for (ResolvableKeyValuePair pair : additionalFields) {
-            if (pair.valueNeedsLookup) {
-                // Resolve value
-                additionalFieldsMap.put(pair.key, strSubstitutor.replace(logEvent, pair.value));
-            } else {
-                // Plain text value
-                additionalFieldsMap.put(pair.key, pair.value);
-            }
-        }
-
-        return additionalFieldsMap;
-    }
-
-    public void toSerializable(final LogEvent event, final Writer writer)
-            throws JsonGenerationException, JsonMappingException, IOException {
-        objectWriter.writeValue(writer, wrapLogEvent(convertMutableToLog4jEvent(event)));
-        writer.write(eol);
-        if (includeNullDelimiter) {
-            writer.write('\0');
-        }
-        markEvent();
-    }
-
-    @JsonRootName(XmlConstants.ELT_EVENT)
-    @JacksonXmlRootElement(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_EVENT)
-    public static class LogEventWithAdditionalFields {
-
-        private final Object logEvent;
-        private final Map<String, String> additionalFields;
-
-        public LogEventWithAdditionalFields(Object logEvent, Map<String, String> additionalFields) {
-            this.logEvent = logEvent;
-            this.additionalFields = additionalFields;
-        }
-
-        @JsonUnwrapped
-        public Object getLogEvent() {
-            return logEvent;
-        }
-
-        @JsonAnyGetter
-        @SuppressWarnings("unused")
-        public Map<String, String> getAdditionalFields() {
-            return additionalFields;
-        }
-    }
-
-    protected static class ResolvableKeyValuePair {
-
-        final String key;
-        final String value;
-        final boolean valueNeedsLookup;
-
-        ResolvableKeyValuePair(KeyValuePair pair) {
-            this.key = pair.getKey();
-            this.value = pair.getValue();
-            this.valueNeedsLookup = AbstractJacksonLayout.valueNeedsLookup(this.value);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
index 45c5f4f..7f01f8e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
@@ -294,7 +294,7 @@ public final class GelfLayout extends AbstractStringLayout {
 
     @Override
     public String getContentType() {
-        return JsonLayout.CONTENT_TYPE + "; charset=" + this.getCharset();
+        return "application/json; charset=" + this.getCharset();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
deleted file mode 100644
index b4c914c..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.layout;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.xml.stream.XMLStreamException;
-
-import org.apache.logging.log4j.core.impl.Log4jLogEvent;
-import org.apache.logging.log4j.core.jackson.JsonConstants;
-import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
-import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
-import org.apache.logging.log4j.core.jackson.Log4jYamlObjectMapper;
-import org.apache.logging.log4j.core.jackson.XmlConstants;
-import org.codehaus.stax2.XMLStreamWriter2;
-
-import com.fasterxml.jackson.core.PrettyPrinter;
-import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
-import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectWriter;
-import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
-import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
-import com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter;
-
-abstract class JacksonFactory {
-
-    static class JSON extends JacksonFactory {
-
-        private final boolean encodeThreadContextAsList;
-        private final boolean includeStacktrace;
-        private final boolean stacktraceAsString;
-        private final boolean objectMessageAsJsonObject;
-
-        public JSON(final boolean encodeThreadContextAsList, final boolean includeStacktrace, final boolean stacktraceAsString, final boolean objectMessageAsJsonObject) {
-            this.encodeThreadContextAsList = encodeThreadContextAsList;
-            this.includeStacktrace = includeStacktrace;
-            this.stacktraceAsString = stacktraceAsString;
-            this.objectMessageAsJsonObject = objectMessageAsJsonObject;
-        }
-
-        @Override
-        protected String getPropertNameForContextMap() {
-            return JsonConstants.ELT_CONTEXT_MAP;
-        }
-
-        @Override
-        protected String getPropertNameForSource() {
-            return JsonConstants.ELT_SOURCE;
-        }
-
-        @Override
-        protected String getPropertNameForNanoTime() {
-            return JsonConstants.ELT_NANO_TIME;
-        }
-
-        @Override
-        protected PrettyPrinter newCompactPrinter() {
-            return new MinimalPrettyPrinter();
-        }
-
-        @Override
-        protected ObjectMapper newObjectMapper() {
-            return new Log4jJsonObjectMapper(encodeThreadContextAsList, includeStacktrace, stacktraceAsString, objectMessageAsJsonObject);
-        }
-
-        @Override
-        protected PrettyPrinter newPrettyPrinter() {
-            return new DefaultPrettyPrinter();
-        }
-
-    }
-
-    static class XML extends JacksonFactory {
-
-        static final int DEFAULT_INDENT = 1;
-
-        private final boolean includeStacktrace;
-        private final boolean stacktraceAsString;
-
-
-        public XML(final boolean includeStacktrace, final boolean stacktraceAsString) {
-            this.includeStacktrace = includeStacktrace;
-            this.stacktraceAsString = stacktraceAsString;
-        }
-
-        @Override
-        protected String getPropertNameForContextMap() {
-            return XmlConstants.ELT_CONTEXT_MAP;
-        }
-
-        @Override
-        protected String getPropertNameForSource() {
-            return XmlConstants.ELT_SOURCE;
-        }
-
-        @Override
-        protected String getPropertNameForNanoTime() {
-            return JsonConstants.ELT_NANO_TIME;
-        }
-
-        @Override
-        protected PrettyPrinter newCompactPrinter() {
-            // Yes, null is the proper answer.
-            return null;
-        }
-
-        @Override
-        protected ObjectMapper newObjectMapper() {
-            return new Log4jXmlObjectMapper(includeStacktrace, stacktraceAsString);
-        }
-
-        @Override
-        protected PrettyPrinter newPrettyPrinter() {
-            return new Log4jXmlPrettyPrinter(DEFAULT_INDENT);
-        }
-    }
-
-    static class YAML extends JacksonFactory {
-
-        private final boolean includeStacktrace;
-        private final boolean stacktraceAsString;
-
-
-        public YAML(final boolean includeStacktrace, final boolean stacktraceAsString) {
-            this.includeStacktrace = includeStacktrace;
-            this.stacktraceAsString = stacktraceAsString;
-        }
-
-        @Override
-        protected String getPropertNameForContextMap() {
-            return JsonConstants.ELT_CONTEXT_MAP;
-        }
-
-        @Override
-        protected String getPropertNameForSource() {
-            return JsonConstants.ELT_SOURCE;
-        }
-
-        @Override
-        protected String getPropertNameForNanoTime() {
-            return JsonConstants.ELT_NANO_TIME;
-        }
-
-        @Override
-        protected PrettyPrinter newCompactPrinter() {
-            return new MinimalPrettyPrinter();
-        }
-
-        @Override
-        protected ObjectMapper newObjectMapper() {
-            return new Log4jYamlObjectMapper(false, includeStacktrace, stacktraceAsString);
-        }
-
-        @Override
-        protected PrettyPrinter newPrettyPrinter() {
-            return new DefaultPrettyPrinter();
-        }
-    }
-
-    /**
-     * When &lt;Event&gt;s are written into a XML file; the "Event" object is not the root element, but an element named
-     * &lt;Events&gt; created using {@link XmlLayout#getHeader()} and {@link XmlLayout#getFooter()} methods.
-     * <p>
-     * {@link com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter} is used to print the Event object into
-     * XML; hence it assumes &lt;Event&gt; tag as the root element, so it prints the &lt;Event&gt; tag without any
-     * indentation. To add an indentation to the &lt;Event&gt; tag; hence an additional indentation for any
-     * sub-elements, this class is written. As an additional task, to avoid the blank line printed after the ending
-     * &lt;/Event&gt; tag, {@link #writePrologLinefeed(XMLStreamWriter2)} method is also overridden.
-     * </p>
-     */
-    static class Log4jXmlPrettyPrinter extends DefaultXmlPrettyPrinter {
-
-        private static final long serialVersionUID = 1L;
-
-        Log4jXmlPrettyPrinter(final int nesting) {
-            _nesting = nesting;
-        }
-
-        @Override
-        public void writePrologLinefeed(final XMLStreamWriter2 sw) throws XMLStreamException {
-            // nothing
-        }
-
-        /**
-         * Sets the nesting level to 1 rather than 0, so the "Event" tag will get indentation of next level below root.
-         */
-        @Override
-        public DefaultXmlPrettyPrinter createInstance() {
-            return new Log4jXmlPrettyPrinter(XML.DEFAULT_INDENT);
-        }
-
-    }
-
-    abstract protected String getPropertNameForContextMap();
-
-    abstract protected String getPropertNameForSource();
-
-    abstract protected String getPropertNameForNanoTime();
-
-    abstract protected PrettyPrinter newCompactPrinter();
-
-    abstract protected ObjectMapper newObjectMapper();
-
-    abstract protected PrettyPrinter newPrettyPrinter();
-
-    ObjectWriter newWriter(final boolean locationInfo, final boolean properties, final boolean compact) {
-        final SimpleFilterProvider filters = new SimpleFilterProvider();
-        final Set<String> except = new HashSet<>(2);
-        if (!locationInfo) {
-            except.add(this.getPropertNameForSource());
-        }
-        if (!properties) {
-            except.add(this.getPropertNameForContextMap());
-        }
-        except.add(this.getPropertNameForNanoTime());
-        filters.addFilter(Log4jLogEvent.class.getName(), SimpleBeanPropertyFilter.serializeAllExcept(except));
-        final ObjectWriter writer = this.newObjectMapper().writer(compact ? this.newCompactPrinter() : this.newPrettyPrinter());
-        return writer.with(filters);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/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
deleted file mode 100644
index 607ec43..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.layout;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.logging.log4j.core.Layout;
-import org.apache.logging.log4j.core.LogEvent;
-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.PluginBuilderAttribute;
-import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
-import org.apache.logging.log4j.core.config.plugins.PluginElement;
-import org.apache.logging.log4j.core.util.KeyValuePair;
-
-/**
- * Appends a series of JSON events as strings serialized as bytes.
- *
- * <h3>Complete well-formed JSON vs. fragment JSON</h3>
- * <p>
- * If you configure {@code complete="true"}, the appender outputs a well-formed JSON document. By default, with
- * {@code complete="false"}, you should include the output as an <em>external file</em> in a separate file to form a
- * well-formed JSON document.
- * </p>
- * <p>
- * If {@code complete="false"}, the appender does not write the JSON open array character "[" at the start
- * of the document, "]" and the end, nor comma "," between records.
- * </p>
- * <h3>Encoding</h3>
- * <p>
- * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise
- * events containing non ASCII characters could result in corrupted log files.
- * </p>
- * <h3>Pretty vs. compact JSON</h3>
- * <p>
- * By default, the JSON layout is not compact (a.k.a. "pretty") with {@code compact="false"}, which means the
- * appender uses end-of-line characters and indents lines to format the text. If {@code compact="true"}, then no
- * end-of-line or indentation is used. Message content may contain, of course, escaped end-of-lines.
- * </p>
- * <h3>Additional Fields</h3>
- * <p>
- * This property allows addition of custom fields into generated JSON.
- * {@code <JsonLayout><KeyValuePair key="foo" value="bar"/></JsonLayout>} inserts {@code "foo":"bar"} directly
- * into JSON output. Supports Lookup expressions.
- * </p>
- */
-@Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
-public final class JsonLayout extends AbstractJacksonLayout {
-
-    private static final String DEFAULT_FOOTER = "]";
-
-    private static final String DEFAULT_HEADER = "[";
-
-    static final String CONTENT_TYPE = "application/json";
-
-    public static class Builder<B extends Builder<B>> extends AbstractJacksonLayout.Builder<B>
-            implements org.apache.logging.log4j.core.util.Builder<JsonLayout> {
-
-        @PluginBuilderAttribute
-        private boolean propertiesAsList;
-
-        @PluginBuilderAttribute
-        private boolean objectMessageAsJsonObject;
-
-        @PluginElement("AdditionalField")
-        private KeyValuePair[] additionalFields;
-
-        public Builder() {
-            super();
-            setCharset(StandardCharsets.UTF_8);
-        }
-
-        @Override
-        public JsonLayout build() {
-            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(), isIncludeNullDelimiter(),
-                    getAdditionalFields(), getObjectMessageAsJsonObject());
-        }
-
-        public boolean isPropertiesAsList() {
-            return propertiesAsList;
-        }
-
-        public B setPropertiesAsList(final boolean propertiesAsList) {
-            this.propertiesAsList = propertiesAsList;
-            return asBuilder();
-        }
-
-        public boolean getObjectMessageAsJsonObject() {
-            return objectMessageAsJsonObject;
-        }
-
-        public B setObjectMessageAsJsonObject(final boolean objectMessageAsJsonObject) {
-            this.objectMessageAsJsonObject = objectMessageAsJsonObject;
-            return asBuilder();
-        }
-
-        @Override
-        public KeyValuePair[] getAdditionalFields() {
-            return additionalFields;
-        }
-
-        @Override
-        public B setAdditionalFields(KeyValuePair[] additionalFields) {
-            this.additionalFields = additionalFields;
-            return asBuilder();
-        }
-    }
-
-    /**
-     * @deprecated Use {@link #newBuilder()} instead
-     */
-    @Deprecated
-    protected 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) {
-        super(config, new JacksonFactory.JSON(encodeThreadContextAsList, includeStacktrace, false, 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(),
-                false, null);
-    }
-
-    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 includeNullDelimiter,
-                       final KeyValuePair[] additionalFields, final boolean objectMessageAsJsonObject) {
-        super(config, new JacksonFactory.JSON(encodeThreadContextAsList, includeStacktrace, stacktraceAsString, objectMessageAsJsonObject).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(),
-                includeNullDelimiter,
-                additionalFields);
-    }
-
-    /**
-     * Returns appropriate JSON header.
-     *
-     * @return a byte array containing the header, opening the JSON array.
-     */
-    @Override
-    public byte[] getHeader() {
-        if (!this.complete) {
-            return null;
-        }
-        final StringBuilder buf = new StringBuilder();
-        final String str = serializeToString(getHeaderSerializer());
-        if (str != null) {
-            buf.append(str);
-        }
-        buf.append(this.eol);
-        return getBytes(buf.toString());
-    }
-
-    /**
-     * Returns appropriate JSON footer.
-     *
-     * @return a byte array containing the footer, closing the JSON array.
-     */
-    @Override
-    public byte[] getFooter() {
-        if (!this.complete) {
-            return null;
-        }
-        final StringBuilder buf = new StringBuilder();
-        buf.append(this.eol);
-        final String str = serializeToString(getFooterSerializer());
-        if (str != null) {
-            buf.append(str);
-        }
-        buf.append(this.eol);
-        return getBytes(buf.toString());
-    }
-
-    @Override
-    public Map<String, String> getContentFormat() {
-        final Map<String, String> result = new HashMap<>();
-        result.put("version", "2.0");
-        return result;
-    }
-
-    /**
-     * @return The content type.
-     */
-    @Override
-    public String getContentType() {
-        return CONTENT_TYPE + "; charset=" + this.getCharset();
-    }
-
-    /**
-     * Creates a JSON Layout.
-     * @param config
-     *           The plugin configuration.
-     * @param locationInfo
-     *            If "true", includes the location information in the generated JSON.
-     * @param properties
-     *            If "true", includes the thread context map in the generated JSON.
-     * @param propertiesAsList
-     *            If true, the thread context map is included as a list of map entry objects, where each entry has
-     *            a "key" attribute (whose value is the key) and a "value" attribute (whose value is the value).
-     *            Defaults to false, in which case the thread context map is included as a simple map of key-value
-     *            pairs.
-     * @param complete
-     *            If "true", includes the JSON header and footer, and comma between records.
-     * @param compact
-     *            If "true", does not use end-of-lines and indentation, defaults to "false".
-     * @param eventEol
-     *            If "true", forces an EOL after each log event (even if compact is "true"), defaults to "false". This
-     *            allows one even per line, even in compact mode.
-     * @param headerPattern
-     *            The header pattern, defaults to {@code "["} if null.
-     * @param footerPattern
-     *            The header pattern, defaults to {@code "]"} if null.
-     * @param charset
-     *            The character set to use, if {@code null}, uses "UTF-8".
-     * @param includeStacktrace
-     *            If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true".
-     * @return A JSON Layout.
-     *
-     * @deprecated Use {@link #newBuilder()} instead
-     */
-    @Deprecated
-    public static JsonLayout createLayout(
-            final Configuration config,
-            final boolean locationInfo,
-            final boolean properties,
-            final boolean propertiesAsList,
-            final boolean complete,
-            final boolean compact,
-            final boolean eventEol,
-            final String headerPattern,
-            final String footerPattern,
-            final Charset charset,
-            final boolean includeStacktrace) {
-        final boolean encodeThreadContextAsList = properties && propertiesAsList;
-        return new JsonLayout(config, locationInfo, properties, encodeThreadContextAsList, complete, compact, eventEol,
-                headerPattern, footerPattern, charset, includeStacktrace, false, false, null, false);
-    }
-
-    @PluginBuilderFactory
-    public static <B extends Builder<B>> B newBuilder() {
-        return new Builder<B>().asBuilder();
-    }
-
-    /**
-     * Creates a JSON Layout using the default settings. Useful for testing.
-     *
-     * @return A JSON Layout.
-     */
-    public static JsonLayout createDefaultLayout() {
-        return new JsonLayout(new DefaultConfiguration(), false, false, false, false, false, false,
-                DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, null, false);
-    }
-
-    @Override
-    public void toSerializable(final LogEvent event, final Writer writer) throws IOException {
-        if (complete && eventCount > 0) {
-            writer.append(", ");
-        }
-        super.toSerializable(event, writer);
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/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
deleted file mode 100644
index b09add7..0000000
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.layout;
-
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-
-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.PluginBuilderFactory;
-import org.apache.logging.log4j.core.jackson.XmlConstants;
-import org.apache.logging.log4j.core.util.KeyValuePair;
-
-/**
- * Appends a series of {@code event} elements as defined in the <a href="log4j.dtd">log4j.dtd</a>.
- *
- * <h3>Complete well-formed XML vs. fragment XML</h3>
- * <p>
- * If you configure {@code complete="true"}, the appender outputs a well-formed XML document where the default namespace
- * is the log4j namespace {@value XmlConstants#XML_NAMESPACE}. By default, with {@code complete="false"}, you should
- * include the output as an <em>external entity</em> in a separate file to form a well-formed XML document.
- * </p>
- * <p>
- * If {@code complete="false"}, the appender does not write the XML processing instruction and the root element.
- * </p>
- * <h3>Encoding</h3>
- * <p>
- * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise
- * events containing non-ASCII characters could result in corrupted log files.
- * </p>
- * <h3>Pretty vs. compact XML</h3>
- * <p>
- * By default, the XML layout is not compact (compact = not "pretty") with {@code compact="false"}, which means the
- * appender uses end-of-line characters and indents lines to format the XML. If {@code compact="true"}, then no
- * end-of-line or indentation is used. Message content may contain, of course, end-of-lines.
- * </p>
- * <h3>Additional Fields</h3>
- * <p>
- * This property allows addition of custom fields into generated JSON.
- * {@code <XmlLayout><KeyValuePair key="foo" value="bar"/></XmlLayout>} inserts {@code <foo>bar</foo>} directly
- * into XML output. Supports Lookup expressions.
- * </p>
- */
-@Plugin(name = "XmlLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
-public final class XmlLayout extends AbstractJacksonLayout {
-
-    private static final String ROOT_TAG = "Events";
-
-    public static class Builder<B extends Builder<B>> extends AbstractJacksonLayout.Builder<B>
-        implements org.apache.logging.log4j.core.util.Builder<XmlLayout> {
-
-        public Builder() {
-            super();
-            setCharset(StandardCharsets.UTF_8);
-        }
-
-        @Override
-        public XmlLayout build() {
-            return new XmlLayout(getConfiguration(), isLocationInfo(), isProperties(), isComplete(),
-                    isCompact(), getCharset(), isIncludeStacktrace(), isStacktraceAsString(),
-                    isIncludeNullDelimiter(), getAdditionalFields());
-        }
-    }
-
-    /**
-     * @deprecated Use {@link #newBuilder()} instead
-     */
-    @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, false, null);
-    }
-
-    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 includeNullDelimiter,
-                      final KeyValuePair[] additionalFields) {
-        super(config, new JacksonFactory.XML(includeStacktrace, stacktraceAsString).newWriter(
-            locationInfo, properties, compact),
-            charset, compact, complete, false, null, null, includeNullDelimiter,
-            additionalFields);
-    }
-
-    /**
-     * Returns appropriate XML headers.
-     * <ol>
-     * <li>XML processing instruction</li>
-     * <li>XML root element</li>
-     * </ol>
-     *
-     * @return a byte array containing the header.
-     */
-    @Override
-    public byte[] getHeader() {
-        if (!complete) {
-            return null;
-        }
-        final StringBuilder buf = new StringBuilder();
-        buf.append("<?xml version=\"1.0\" encoding=\"");
-        buf.append(this.getCharset().name());
-        buf.append("\"?>");
-        buf.append(this.eol);
-        // Make the log4j namespace the default namespace, no need to use more space with a namespace prefix.
-        buf.append('<');
-        buf.append(ROOT_TAG);
-        buf.append(" xmlns=\"" + XmlConstants.XML_NAMESPACE + "\">");
-        buf.append(this.eol);
-        return buf.toString().getBytes(this.getCharset());
-    }
-
-    /**
-     * Returns appropriate XML footer.
-     *
-     * @return a byte array containing the footer, closing the XML root element.
-     */
-    @Override
-    public byte[] getFooter() {
-        if (!complete) {
-            return null;
-        }
-        return getBytes("</" + ROOT_TAG + '>' + this.eol);
-    }
-
-    /**
-     * Gets this XmlLayout's content format. Specified by:
-     * <ul>
-     * <li>Key: "dtd" Value: "log4j-events.dtd"</li>
-     * <li>Key: "version" Value: "2.0"</li>
-     * </ul>
-     * 
-     * @return Map of content format keys supporting XmlLayout
-     */
-    @Override
-    public Map<String, String> getContentFormat() {
-        final Map<String, String> result = new HashMap<>();
-        // result.put("dtd", "log4j-events.dtd");
-        result.put("xsd", "log4j-events.xsd");
-        result.put("version", "2.0");
-        return result;
-    }
-
-    /**
-     * @return The content type.
-     */
-    @Override
-    public String getContentType() {
-        return "text/xml; charset=" + this.getCharset();
-    }
-
-    /**
-     * Creates an XML Layout.
-     *
-     * @param locationInfo If "true", includes the location information in the generated XML.
-     * @param properties If "true", includes the thread context map in the generated XML.
-     * @param complete If "true", includes the XML header and footer, defaults to "false".
-     * @param compact If "true", does not use end-of-lines and indentation, defaults to "false".
-     * @param charset The character set to use, if {@code null}, uses "UTF-8".
-     * @param includeStacktrace
-     *            If "true", includes the stacktrace of any Throwable in the generated XML, defaults to "true".
-     * @return An XML Layout.
-     *
-     * @deprecated Use {@link #newBuilder()} instead
-     */
-    @Deprecated
-    public static XmlLayout createLayout(
-            final boolean locationInfo,
-            final boolean properties,
-            final boolean complete,
-            final boolean compact,
-            final Charset charset,
-            final boolean includeStacktrace) {
-        return new XmlLayout(null, locationInfo, properties, complete, compact, charset, includeStacktrace, false,
-                false, null);
-    }
-
-    @PluginBuilderFactory
-    public static <B extends Builder<B>> B newBuilder() {
-        return new Builder<B>().asBuilder();
-    }
-
-    /**
-     * Creates an XML Layout using the default settings.
-     *
-     * @return an XML Layout.
-     */
-    public static XmlLayout createDefaultLayout() {
-        return new XmlLayout(null, false, false, false, false, StandardCharsets.UTF_8, true, false, false, null);
-    }
-}


[07/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/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
deleted file mode 100644
index 4ee8f1e..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/XmlLayoutTest.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.layout;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.Marker;
-import org.apache.logging.log4j.MarkerManager;
-import org.apache.logging.log4j.ThreadContext;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.BasicConfigurationFactory;
-import org.apache.logging.log4j.core.Logger;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.apache.logging.log4j.core.impl.Log4jLogEvent;
-import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
-import org.apache.logging.log4j.core.lookup.JavaLookup;
-import org.apache.logging.log4j.core.util.KeyValuePair;
-import org.apache.logging.log4j.junit.ThreadContextRule;
-import org.apache.logging.log4j.message.SimpleMessage;
-import org.apache.logging.log4j.spi.AbstractLogger;
-import org.apache.logging.log4j.test.appender.ListAppender;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import org.junit.experimental.categories.Category;
-
-import static org.junit.Assert.*;
-
-/**
- * Tests {@link XmlLayout}.
- */
-@Category(Layouts.Xml.class)
-public class XmlLayoutTest {
-    private static final String body = "<Message>empty mdc</Message>";
-    static ConfigurationFactory cf = new BasicConfigurationFactory();
-    private static final String markerTag = "<Marker name=\"EVENT\"/>";
-
-    @Rule
-    public final ThreadContextRule threadContextRule = new ThreadContextRule(); 
-
-    @AfterClass
-    public static void cleanupClass() {
-        ConfigurationFactory.removeConfigurationFactory(cf);
-    }
-
-    @BeforeClass
-    public static void setupClass() {
-        ConfigurationFactory.setConfigurationFactory(cf);
-        final LoggerContext ctx = LoggerContext.getContext();
-        ctx.reconfigure();
-    }
-
-    LoggerContext ctx = LoggerContext.getContext();
-
-    Logger rootLogger = this.ctx.getRootLogger();
-
-    private void checkAttribute(final String name, final String value, final boolean compact, final String str) {
-        Assert.assertTrue(str, str.contains(name + "=\"" + value + "\""));
-    }
-
-    private void checkAttributeName(final String name, final boolean compact, final String str) {
-        Assert.assertTrue(str, str.contains(name + "=\""));
-    }
-
-    private void checkContains(final String expected, final List<String> list) {
-        for (final String string : list) {
-            final String trimedLine = string.trim();
-            if (trimedLine.contains(expected)) {
-                return;
-            }
-        }
-        Assert.fail("Cannot find " + expected + " in " + list);
-    }
-
-    private void checkElement(final String key, final String value, final boolean compact, final String str) {
-        // <item key="MDC.A" value="A_Value"/>
-        assertTrue(str, str.contains(String.format("<item key=\"%s\" value=\"%s\"/>", key, value)));
-    }
-
-    private void checkElementName(final String name, final boolean compact, final String str, final boolean withAttributes,
-            final boolean withChildren) {
-        // simple checks, don't try to be too smart here, we're just looking for the names and basic shape.
-        // start
-        final String startStr = withAttributes ? "<" + name + " " : "<" + name + ">";
-        final int startPos = str.indexOf(startStr);
-        Assert.assertTrue(str, startPos >= 0);
-        // end
-        final String endStr = withChildren ? "</" + name + ">" : "/>";
-        final int endPos = str.indexOf(endStr, startPos + startStr.length());
-        Assert.assertTrue(str, endPos >= 0);
-    }
-
-    private void checkElementNameAbsent(final String name, final boolean compact, final String str) {
-        Assert.assertFalse(str.contains("<" + name));
-    }
-
-    /**
-     * @param includeSource TODO
-     * @param compact
-     * @param includeContext TODO
-     * @throws IOException
-     * @throws JsonParseException
-     * @throws JsonMappingException
-     */
-    private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean includeContext, final boolean includeStacktrace) throws IOException,
-            JsonParseException, JsonMappingException {
-        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
-        final XmlLayout layout = XmlLayout.newBuilder()
-                .setLocationInfo(includeSource)
-                .setProperties(includeContext)
-                .setComplete(false)
-                .setCompact(compact)
-                .setIncludeStacktrace(includeStacktrace)
-                .setCharset(StandardCharsets.UTF_8)
-                .build();
-        final String str = layout.toSerializable(expected);
-        // System.out.println(str);
-        assertEquals(str, !compact, str.contains("\n"));
-        assertEquals(str, includeSource, str.contains("Source"));
-        assertEquals(str, includeContext, str.contains("ContextMap"));
-        final Log4jLogEvent actual = new Log4jXmlObjectMapper().readValue(str, Log4jLogEvent.class);
-        LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext, includeStacktrace);
-        if (includeContext) {
-            this.checkElement("MDC.A", "A_Value", compact, str);
-            this.checkElement("MDC.B", "B_Value", compact, str);
-        }
-
-        //
-        assertNull(actual.getThrown());
-        // check some attrs
-        assertTrue(str, str.contains("loggerFqcn=\"f.q.c.n\""));
-        assertTrue(str, str.contains("loggerName=\"a.B\""));
-        // make sure short names are used
-        assertTrue(str, str.contains("<Event "));
-        if (includeStacktrace) {
-            assertTrue(str, str.contains("class="));
-            assertTrue(str, str.contains("method="));
-            assertTrue(str, str.contains("file="));
-            assertTrue(str, str.contains("line="));
-        }
-        //
-        // make sure the names we want are used
-        //this.checkAttributeName("timeMillis", compact, str);
-        this.checkElementName("Instant", compact, str, true, false);
-        this.checkAttributeName("epochSecond", compact, str);
-        this.checkAttributeName("nanoOfSecond", compact, str);
-        this.checkAttributeName("thread", compact, str); // and not threadName
-        this.checkAttributeName("level", compact, str);
-        this.checkAttributeName("loggerName", compact, str);
-        this.checkElementName("Marker", compact, str, true, true);
-        this.checkAttributeName("name", compact, str);
-        this.checkElementName("Parents", compact, str, false, true);
-        this.checkElementName("Message", compact, str, false, true);
-        this.checkElementName("Thrown", compact, str, true, true);
-        this.checkElementName("Cause", compact, str, true, includeStacktrace);
-        this.checkAttributeName("commonElementCount", compact, str);
-        this.checkAttributeName("message", compact, str);
-        this.checkAttributeName("localizedMessage", compact, str);
-        if (includeStacktrace) {
-            this.checkElementName("ExtendedStackTrace", compact, str, false, true);
-            this.checkAttributeName("class", compact, str);
-            this.checkAttributeName("method", compact, str);
-            this.checkAttributeName("file", compact, str);
-            this.checkAttributeName("line", compact, str);
-            this.checkAttributeName("exact", compact, str);
-            this.checkAttributeName("location", compact, str);
-            this.checkAttributeName("version", compact, str);
-        } else {
-            this.checkElementNameAbsent("ExtendedStackTrace", compact, str);
-        }
-        this.checkElementName("Suppressed", compact, str, false, true);
-        this.checkAttributeName("loggerFqcn", compact, str);
-        this.checkAttributeName("endOfBatch", compact, str);
-        if (includeContext) {
-            this.checkElementName("ContextMap", compact, str, false, true);
-        } else {
-            this.checkElementNameAbsent("ContextMap", compact, str);
-        }
-        this.checkElementName("ContextStack", compact, str, false, true);
-        if (includeSource) {
-            this.checkElementName("Source", compact, str, true, false);
-        } else {
-            this.checkElementNameAbsent("Source", compact, str);
-        }
-        // check some attrs
-        this.checkAttribute("loggerFqcn", "f.q.c.n", compact, str);
-        this.checkAttribute("loggerName", "a.B", compact, str);
-    }
-
-    @Test
-    public void testContentType() {
-        final XmlLayout layout = XmlLayout.createDefaultLayout();
-        assertEquals("text/xml; charset=UTF-8", layout.getContentType());
-    }
-
-    @Test
-    public void testDefaultCharset() {
-        final XmlLayout layout = XmlLayout.createDefaultLayout();
-        assertEquals(StandardCharsets.UTF_8, layout.getCharset());
-    }
-
-    /**
-     * Test case for MDC conversion pattern.
-     */
-    @Test
-    public void testLayout() throws Exception {
-        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
-        for (final Appender appender : appenders.values()) {
-            this.rootLogger.removeAppender(appender);
-        }
-        // set up appender
-        final XmlLayout layout = XmlLayout.newBuilder()
-                .setLocationInfo(true)
-                .setProperties(true)
-                .setComplete(true)
-                .setCompact(false)
-                .setIncludeStacktrace(true)
-                .build();
-
-        final ListAppender appender = new ListAppender("List", null, layout, true, false);
-        appender.start();
-
-        // set appender on root and set level to debug
-        this.rootLogger.addAppender(appender);
-        this.rootLogger.setLevel(Level.DEBUG);
-
-        // output starting message
-        this.rootLogger.debug("starting mdc pattern test");
-
-        this.rootLogger.debug("empty mdc");
-
-        ThreadContext.put("key1", "value1");
-        ThreadContext.put("key2", "value2");
-
-        this.rootLogger.debug("filled mdc");
-
-        ThreadContext.remove("key1");
-        ThreadContext.remove("key2");
-
-        this.rootLogger.error("finished mdc pattern test", new NullPointerException("test"));
-
-        final Marker marker = MarkerManager.getMarker("EVENT");
-        this.rootLogger.error(marker, "marker test");
-
-        appender.stop();
-
-        final List<String> list = appender.getMessages();
-
-        final String string = list.get(0);
-        assertTrue("Incorrect header: " + string, string.equals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
-        assertTrue("Incorrect footer", list.get(list.size() - 1).equals("</Events>"));
-        this.checkContains("loggerFqcn=\"" + AbstractLogger.class.getName() + "\"", list);
-        this.checkContains("level=\"DEBUG\"", list);
-        this.checkContains(">starting mdc pattern test</Message>", list);
-        // this.checkContains("<Message>starting mdc pattern test</Message>", list);
-
-        // <Marker xmlns="" _class="org.apache.logging.log4j.MarkerManager..Log4jMarker" name="EVENT"/>
-        this.checkContains("<Marker", list);
-        this.checkContains("name=\"EVENT\"/>", list);
-
-        for (final Appender app : appenders.values()) {
-            this.rootLogger.addAppender(app);
-        }
-    }
-
-    @Test
-    public void testLayoutLoggerName() {
-        final XmlLayout layout = XmlLayout.newBuilder()
-                .setLocationInfo(false)
-                .setProperties(true)
-                .setComplete(true)
-                .setCompact(false)
-                .setIncludeStacktrace(true)
-                .build();
-
-        final Log4jLogEvent event = Log4jLogEvent.newBuilder() //
-                .setLoggerName("a.B") //
-                .setLoggerFqcn("f.q.c.n") //
-                .setLevel(Level.DEBUG) //
-                .setMessage(new SimpleMessage("M")) //
-                .setThreadName("threadName") //
-                .setTimeMillis(1).build();
-        final String str = layout.toSerializable(event);
-        assertTrue(str, str.contains("loggerName=\"a.B\""));
-    }
-
-    @Test
-    public void testAdditionalFields() throws Exception {
-        final AbstractJacksonLayout layout = XmlLayout.newBuilder()
-                .setLocationInfo(false)
-                .setProperties(false)
-                .setIncludeStacktrace(false)
-                .setAdditionalFields(new KeyValuePair[] {
-                    new KeyValuePair("KEY1", "VALUE1"),
-                    new KeyValuePair("KEY2", "${java:runtime}"), })
-                .setCharset(StandardCharsets.UTF_8)
-                .setConfiguration(ctx.getConfiguration())
-                .build();
-        final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
-        assertTrue(str, str.contains("<KEY1>VALUE1</KEY1>"));
-        assertTrue(str, str.contains("<KEY2>" + new JavaLookup().getRuntime() + "</KEY2>"));
-    }
-
-    @Test
-    public void testLocationOffCompactOffMdcOff() throws Exception {
-        this.testAllFeatures(false, false, false, true);
-    }
-
-    @Test
-    public void testLocationOnCompactOnMdcOn() throws Exception {
-        this.testAllFeatures(true, true, true, true);
-    }
-
-    @Test
-    public void testExcludeStacktrace() throws Exception {
-        this.testAllFeatures(false, false, false, false);
-    }
-
-    @Test
-    public void testStacktraceAsString() throws Exception {
-        final String str = prepareXMLForStacktraceTests(true);
-        assertTrue(str, str.contains("<ExtendedStackTrace>java.lang.NullPointerException"));
-    }
-
-    @Test
-    public void testStacktraceAsNonString() throws Exception {
-        final String str = prepareXMLForStacktraceTests(false);
-        assertTrue(str, str.contains("<ExtendedStackTrace><ExtendedStackTraceItem"));
-    }
-
-    private String prepareXMLForStacktraceTests(final boolean stacktraceAsString) {
-        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
-        // @formatter:off
-        final AbstractJacksonLayout layout = XmlLayout.newBuilder()
-                .setCompact(true)
-                .setIncludeStacktrace(true)
-                .setStacktraceAsString(stacktraceAsString)
-                .build();
-        // @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/0eb5212e/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
deleted file mode 100644
index 2fef8de..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.layout;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.ThreadContext;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.BasicConfigurationFactory;
-import org.apache.logging.log4j.core.Logger;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.config.Configuration;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.apache.logging.log4j.core.impl.Log4jLogEvent;
-import org.apache.logging.log4j.core.jackson.Log4jYamlObjectMapper;
-import org.apache.logging.log4j.core.lookup.JavaLookup;
-import org.apache.logging.log4j.core.util.KeyValuePair;
-import org.apache.logging.log4j.message.SimpleMessage;
-import org.apache.logging.log4j.spi.AbstractLogger;
-import org.apache.logging.log4j.test.appender.ListAppender;
-import org.apache.logging.log4j.util.Strings;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-/**
- * Tests the YamlLayout class.
- */
-@Category(Layouts.Yaml.class)
-public class YamlLayoutTest {
-    static ConfigurationFactory cf = new BasicConfigurationFactory();
-
-    @AfterClass
-    public static void cleanupClass() {
-        ConfigurationFactory.removeConfigurationFactory(cf);
-        ThreadContext.clearAll();
-    }
-
-    @BeforeClass
-    public static void setupClass() {
-        ThreadContext.clearAll();
-        ConfigurationFactory.setConfigurationFactory(cf);
-        final LoggerContext ctx = LoggerContext.getContext();
-        ctx.reconfigure();
-    }
-
-    LoggerContext ctx = LoggerContext.getContext();
-
-    Logger rootLogger = this.ctx.getRootLogger();
-
-    private void checkAt(final String expected, final int lineIndex, final List<String> list) {
-        final String trimedLine = list.get(lineIndex).trim();
-        assertTrue("Incorrect line index " + lineIndex + ": " + Strings.dquote(trimedLine),
-                trimedLine.equals(expected));
-    }
-
-    private void checkContains(final String expected, final List<String> list) {
-        for (final String string : list) {
-            final String trimedLine = string.trim();
-            if (trimedLine.equals(expected)) {
-                return;
-            }
-        }
-        Assert.fail("Cannot find " + expected + " in " + list);
-    }
-
-    private void checkMapEntry(final String key, final String value, final boolean compact, final String str) {
-        // "name":"value"
-        //final String expected = String.format("- key: \"%s\"\n  value: \"%s\"", key, value);
-        final String expected = String.format("%s: \"%s\"", key, value);
-        assertTrue("Cannot find " + expected + " in " + str, str.contains(expected));
-    }
-
-    private void checkProperty(final String key, final String value, final boolean compact, final String str,
-            final boolean isValue) {
-        final String propSep = this.toPropertySeparator(compact, isValue);
-        // {"key":"MDC.B","value":"B_Value"}
-        final String expected = String.format("%s%s\"%s\"", key, propSep, value);
-        assertTrue("Cannot find " + expected + " in " + str, str.contains(expected));
-    }
-
-    private void checkPropertyName(final String name, final boolean compact, final String str, final boolean isValue) {
-        final String propSep = this.toPropertySeparator(compact, isValue);
-        assertTrue(str, str.contains(name + propSep));
-    }
-
-    private void checkPropertyNameAbsent(final String name, final boolean compact, final String str, final boolean isValue) {
-        final String propSep = this.toPropertySeparator(compact, isValue);
-        assertFalse(str, str.contains(name + propSep));
-    }
-
-    private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean eventEol,
-            final boolean includeContext, final boolean contextMapAslist, final boolean includeStacktrace) throws Exception {
-        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
-        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
-                .setLocationInfo(includeSource)
-                .setProperties(includeContext)
-                .setIncludeStacktrace(includeStacktrace)
-                .setCharset(StandardCharsets.UTF_8)
-                .build();
-        final String str = layout.toSerializable(expected);
-        // System.out.println(str);
-        // Just check for \n since \r might or might not be there.
-        assertEquals(str, !compact || eventEol, str.contains("\n"));
-        assertEquals(str, includeSource, str.contains("source"));
-        assertEquals(str, includeContext, str.contains("contextMap"));
-        final Log4jLogEvent actual = new Log4jYamlObjectMapper(contextMapAslist, includeStacktrace,false).readValue(str, Log4jLogEvent.class);
-        LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext, includeStacktrace);
-        if (includeContext) {
-            this.checkMapEntry("MDC.A", "A_Value", compact, str);
-            this.checkMapEntry("MDC.B", "B_Value", compact, str);
-        }
-        //
-        assertNull(actual.getThrown());
-        // make sure the names we want are used
-        this.checkPropertyName("instant", compact, str, false);
-        this.checkPropertyName("thread", compact, str, true); // and not threadName
-        this.checkPropertyName("level", compact, str, true);
-        this.checkPropertyName("loggerName", compact, str, true);
-        this.checkPropertyName("marker", compact, str, false);
-        this.checkPropertyName("name", compact, str, true);
-        this.checkPropertyName("parents", compact, str, false);
-        this.checkPropertyName("message", compact, str, true);
-        this.checkPropertyName("thrown", compact, str, false);
-        this.checkPropertyName("cause", compact, str, false);
-        this.checkPropertyName("commonElementCount", compact, str, true);
-        this.checkPropertyName("localizedMessage", compact, str, true);
-        if (includeStacktrace) {
-            this.checkPropertyName("extendedStackTrace", compact, str, false);
-            this.checkPropertyName("class", compact, str, true);
-            this.checkPropertyName("method", compact, str, true);
-            this.checkPropertyName("file", compact, str, true);
-            this.checkPropertyName("line", compact, str, true);
-            this.checkPropertyName("exact", compact, str, true);
-            this.checkPropertyName("location", compact, str, true);
-            this.checkPropertyName("version", compact, str, true);
-        } else {
-            this.checkPropertyNameAbsent("extendedStackTrace", compact, str, false);
-        }
-        this.checkPropertyName("suppressed", compact, str, false);
-        this.checkPropertyName("loggerFqcn", compact, str, true);
-        this.checkPropertyName("endOfBatch", compact, str, true);
-        if (includeContext) {
-            this.checkPropertyName("contextMap", compact, str, false);
-        } else {
-            this.checkPropertyNameAbsent("contextMap", compact, str, false);
-        }
-        this.checkPropertyName("contextStack", compact, str, false);
-        if (includeSource) {
-            this.checkPropertyName("source", compact, str, false);
-        } else {
-            this.checkPropertyNameAbsent("source", compact, str, false);
-        }
-        // check some attrs
-        this.checkProperty("loggerFqcn", "f.q.c.n", compact, str, true);
-        this.checkProperty("loggerName", "a.B", compact, str, true);
-    }
-
-    @Test
-    public void testContentType() {
-        final AbstractJacksonLayout layout = YamlLayout.createDefaultLayout();
-        assertEquals("application/yaml; charset=UTF-8", layout.getContentType());
-    }
-
-    @Test
-    public void testDefaultCharset() {
-        final AbstractJacksonLayout layout = YamlLayout.createDefaultLayout();
-        assertEquals(StandardCharsets.UTF_8, layout.getCharset());
-    }
-
-    @Test
-    public void testEscapeLayout() throws Exception {
-        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
-        for (final Appender appender : appenders.values()) {
-            this.rootLogger.removeAppender(appender);
-        }
-        final Configuration configuration = rootLogger.getContext().getConfiguration();
-        // set up appender
-        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
-                .setLocationInfo(true)
-                .setProperties(true)
-                .setIncludeStacktrace(true)
-                .setConfiguration(configuration)
-                .build();
-
-        final ListAppender appender = new ListAppender("List", null, layout, true, false);
-        appender.start();
-
-        // set appender on root and set level to debug
-        this.rootLogger.addAppender(appender);
-        this.rootLogger.setLevel(Level.DEBUG);
-
-        // output starting message
-        this.rootLogger.debug("Here is a quote ' and then a double quote \"");
-
-        appender.stop();
-
-        final List<String> list = appender.getMessages();
-
-        this.checkAt("---", 0, list);
-        this.checkContains("level: \"DEBUG\"", list);
-        this.checkContains("message: \"Here is a quote ' and then a double quote \\\"\"", list);
-        this.checkContains("loggerFqcn: \"" + AbstractLogger.class.getName() + "\"", list);
-        for (final Appender app : appenders.values()) {
-            this.rootLogger.addAppender(app);
-        }
-    }
-
-    /**
-     * Test case for MDC conversion pattern.
-     */
-    @Test
-    public void testLayout() throws Exception {
-        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
-        for (final Appender appender : appenders.values()) {
-            this.rootLogger.removeAppender(appender);
-        }
-        final Configuration configuration = rootLogger.getContext().getConfiguration();
-        // set up appender
-        // Use [[ and ]] to test header and footer (instead of [ and ])
-        final AbstractJacksonLayout layout = YamlLayout.createLayout(configuration, true, true, "[[", "]]", null, true);
-        final ListAppender appender = new ListAppender("List", null, layout, true, false);
-        appender.start();
-
-        // set appender on root and set level to debug
-        this.rootLogger.addAppender(appender);
-        this.rootLogger.setLevel(Level.DEBUG);
-
-        // output starting message
-        this.rootLogger.debug("starting mdc pattern test");
-
-        this.rootLogger.debug("empty mdc");
-
-        ThreadContext.put("key1", "value1");
-        ThreadContext.put("key2", "value2");
-
-        this.rootLogger.debug("filled mdc");
-
-        ThreadContext.remove("key1");
-        ThreadContext.remove("key2");
-
-        this.rootLogger.error("finished mdc pattern test", new NullPointerException("test"));
-
-        appender.stop();
-
-        final List<String> list = appender.getMessages();
-
-        this.checkAt("---", 0, list);
-        this.checkContains("loggerFqcn: \"" + AbstractLogger.class.getName() + "\"", list);
-        this.checkContains("level: \"DEBUG\"", list);
-        this.checkContains("message: \"starting mdc pattern test\"", list);
-        for (final Appender app : appenders.values()) {
-            this.rootLogger.addAppender(app);
-        }
-    }
-
-    @Test
-    public void testLayoutLoggerName() throws Exception {
-        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
-                .setLocationInfo(false)
-                .setProperties(false)
-                .setIncludeStacktrace(true)
-                .setCharset(StandardCharsets.UTF_8)
-                .build();
-        final Log4jLogEvent expected = Log4jLogEvent.newBuilder() //
-                .setLoggerName("a.B") //
-                .setLoggerFqcn("f.q.c.n") //
-                .setLevel(Level.DEBUG) //
-                .setMessage(new SimpleMessage("M")) //
-                .setThreadName("threadName") //
-                .setTimeMillis(1).build();
-        final String str = layout.toSerializable(expected);
-        assertTrue(str, str.contains("loggerName: \"a.B\""));
-        final Log4jLogEvent actual = new Log4jYamlObjectMapper(false, true, false).readValue(str, Log4jLogEvent.class);
-        assertEquals(expected.getLoggerName(), actual.getLoggerName());
-        assertEquals(expected, actual);
-    }
-
-    @Test
-    public void testAdditionalFields() throws Exception {
-        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
-                .setLocationInfo(false)
-                .setProperties(false)
-                .setIncludeStacktrace(false)
-                .setAdditionalFields(new KeyValuePair[] {
-                    new KeyValuePair("KEY1", "VALUE1"),
-                    new KeyValuePair("KEY2", "${java:runtime}"), })
-                .setCharset(StandardCharsets.UTF_8)
-                .setConfiguration(ctx.getConfiguration())
-                .build();
-        final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
-        assertTrue(str, str.contains("KEY1: \"VALUE1\""));
-        assertTrue(str, str.contains("KEY2: \"" + new JavaLookup().getRuntime() + "\""));
-    }
-
-    @Test
-    public void testLocationOffCompactOffMdcOff() throws Exception {
-        this.testAllFeatures(false, false, false, false, false, true);
-    }
-
-    @Test
-    public void testLocationOnCompactOffEventEolOffMdcOn() throws Exception {
-        this.testAllFeatures(true, false, false, true, false, true);
-    }
-
-    @Test
-    public void testExcludeStacktrace() throws Exception {
-        this.testAllFeatures(false, false, false, false, false, false);
-    }
-
-    @Test
-    public void testStacktraceAsString() throws Exception {
-        final String str = prepareYAMLForStacktraceTests(true);
-        assertTrue(str, str.contains("extendedStackTrace: \"java.lang.NullPointerException"));
-    }
-
-    @Test
-    public void testStacktraceAsNonString() throws Exception {
-        final String str = prepareYAMLForStacktraceTests(false);
-        assertTrue(str, str.contains("extendedStackTrace:\n    - "));
-    }
-
-    private String prepareYAMLForStacktraceTests(final boolean stacktraceAsString) {
-        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
-        // @formatter:off
-        final AbstractJacksonLayout layout = YamlLayout.newBuilder()
-                .setIncludeStacktrace(true)
-                .setStacktraceAsString(stacktraceAsString)
-                .build();
-        // @formatter:off
-        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/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/AbstractLogEventParserTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/AbstractLogEventParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/AbstractLogEventParserTest.java
new file mode 100644
index 0000000..69c00c5
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/AbstractLogEventParserTest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.parser;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.LogEvent;
+
+import java.util.Arrays;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Subclassed by JSON, XML, and YAML modules.
+ */
+public abstract class AbstractLogEventParserTest {
+    
+    protected void assertLogEvent(final LogEvent logEvent) {
+        assertThat(logEvent, is(notNullValue()));
+        assertThat(logEvent.getInstant().getEpochMillisecond(), equalTo(1493121664118L));
+        assertThat(logEvent.getThreadName(), equalTo("main"));
+        assertThat(logEvent.getThreadId(), equalTo(1L));
+        assertThat(logEvent.getThreadPriority(), equalTo(5));
+        assertThat(logEvent.getLevel(), equalTo(Level.INFO));
+        assertThat(logEvent.getLoggerName(), equalTo("HelloWorld"));
+        assertThat(logEvent.getMarker().getName(), equalTo("child"));
+        assertThat(logEvent.getMarker().getParents()[0].getName(), equalTo("parent"));
+        assertThat(logEvent.getMarker().getParents()[0].getParents()[0].getName(),
+                equalTo("grandparent"));
+        assertThat(logEvent.getMessage().getFormattedMessage(), equalTo("Hello, world!"));
+        assertThat(logEvent.getThrown(), is(nullValue()));
+        assertThat(logEvent.getThrownProxy().getMessage(), equalTo("error message"));
+        assertThat(logEvent.getThrownProxy().getName(), equalTo("java.lang.RuntimeException"));
+        assertThat(logEvent.getThrownProxy().getExtendedStackTrace()[0].getClassName(),
+                equalTo("logtest.Main"));
+        assertThat(logEvent.getLoggerFqcn(), equalTo("org.apache.logging.log4j.spi.AbstractLogger"));
+        assertThat(logEvent.getContextStack().asList(), equalTo(Arrays.asList("one", "two")));
+        assertThat((String) logEvent.getContextData().getValue("foo"), equalTo("FOO"));
+        assertThat((String) logEvent.getContextData().getValue("bar"), equalTo("BAR"));
+        assertThat(logEvent.getSource().getClassName(), equalTo("logtest.Main"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/JsonLogEventParserTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/JsonLogEventParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/JsonLogEventParserTest.java
deleted file mode 100644
index 9683d63..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/JsonLogEventParserTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.parser;
-
-import org.apache.logging.log4j.core.LogEvent;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.nio.charset.StandardCharsets;
-
-public class JsonLogEventParserTest extends LogEventParserTest {
-
-    private JsonLogEventParser parser;
-
-    private static final String JSON = "{\n" +
-            "  \"timeMillis\" : 1493121664118,\n" +
-            "  \"instant\":{\"epochSecond\":1493121664,\"nanoOfSecond\":118000000},\n" +
-            "  \"thread\" : \"main\",\n" +
-            "  \"threadId\" : 1,\n" +
-            "  \"threadPriority\" : 5,\n" +
-            "  \"level\" : \"INFO\",\n" +
-            "  \"loggerName\" : \"HelloWorld\",\n" +
-            "  \"marker\" : {\n" +
-            "    \"name\" : \"child\",\n" +
-            "    \"parents\" : [ {\n" +
-            "      \"name\" : \"parent\",\n" +
-            "      \"parents\" : [ {\n" +
-            "        \"name\" : \"grandparent\"\n" +
-            "      } ]\n" +
-            "    } ]\n" +
-            "  },\n" +
-            "  \"message\" : \"Hello, world!\",\n" +
-            "  \"thrown\" : {\n" +
-            "    \"commonElementCount\" : 0,\n" +
-            "    \"message\" : \"error message\",\n" +
-            "    \"name\" : \"java.lang.RuntimeException\",\n" +
-            "    \"extendedStackTrace\" : [ {\n" +
-            "      \"class\" : \"logtest.Main\",\n" +
-            "      \"method\" : \"main\",\n" +
-            "      \"file\" : \"Main.java\",\n" +
-            "      \"line\" : 29,\n" +
-            "      \"exact\" : true,\n" +
-            "      \"location\" : \"classes/\",\n" +
-            "      \"version\" : \"?\"\n" +
-            "    } ]\n" +
-            "  },\n" +
-            "  \"contextStack\" : [ \"one\", \"two\" ],\n" +
-            "  \"loggerFqcn\" : \"org.apache.logging.log4j.spi.AbstractLogger\",\n" +
-            "  \"endOfBatch\" : false,\n" +
-            "  \"contextMap\" : {\n" +
-            "    \"bar\" : \"BAR\",\n" +
-            "    \"foo\" : \"FOO\"\n" +
-            "  },\n" +
-            "  \"source\" : {\n" +
-            "    \"class\" : \"logtest.Main\",\n" +
-            "    \"method\" : \"main\",\n" +
-            "    \"file\" : \"Main.java\",\n" +
-            "    \"line\" : 29\n" +
-            "  }\n" +
-            "}";
-
-    @Before
-    public void setup() {
-        parser = new JsonLogEventParser();
-    }
-
-    @Test
-    public void testString() throws ParseException {
-        final LogEvent logEvent = parser.parseFrom(JSON);
-        assertLogEvent(logEvent);
-    }
-
-    @Test(expected = ParseException.class)
-    public void testStringEmpty() throws ParseException {
-        parser.parseFrom("");
-    }
-
-    @Test(expected = ParseException.class)
-    public void testStringInvalidJson() throws ParseException {
-        parser.parseFrom("foobar");
-    }
-
-    @Test(expected = ParseException.class)
-    public void testStringJsonArray() throws ParseException {
-        parser.parseFrom("[]");
-    }
-
-    @Test
-    public void testEmptyObject() throws ParseException {
-        parser.parseFrom("{}");
-    }
-
-    @Test(expected = ParseException.class)
-    public void testStringWrongPropertyType() throws ParseException {
-        parser.parseFrom("{\"threadId\":\"foobar\"}");
-    }
-
-    @Test
-    public void testStringIgnoreInvalidProperty() throws ParseException {
-        parser.parseFrom("{\"foo\":\"bar\"}");
-    }
-
-    @Test
-    public void testByteArray() throws ParseException {
-        final LogEvent logEvent = parser.parseFrom(JSON.getBytes(StandardCharsets.UTF_8));
-        assertLogEvent(logEvent);
-    }
-
-    @Test
-    public void testByteArrayOffsetLength() throws ParseException {
-        final byte[] bytes = ("abc" + JSON + "def").getBytes(StandardCharsets.UTF_8);
-        final LogEvent logEvent = parser.parseFrom(bytes, 3, bytes.length - 6);
-        assertLogEvent(logEvent);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/LogEventParserTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/LogEventParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/LogEventParserTest.java
deleted file mode 100644
index cdb3bef..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/LogEventParserTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.parser;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.core.LogEvent;
-
-import java.util.Arrays;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
-public abstract class LogEventParserTest {
-    protected void assertLogEvent(final LogEvent logEvent) {
-        assertThat(logEvent, is(notNullValue()));
-        assertThat(logEvent.getInstant().getEpochMillisecond(), equalTo(1493121664118L));
-        assertThat(logEvent.getThreadName(), equalTo("main"));
-        assertThat(logEvent.getThreadId(), equalTo(1L));
-        assertThat(logEvent.getThreadPriority(), equalTo(5));
-        assertThat(logEvent.getLevel(), equalTo(Level.INFO));
-        assertThat(logEvent.getLoggerName(), equalTo("HelloWorld"));
-        assertThat(logEvent.getMarker().getName(), equalTo("child"));
-        assertThat(logEvent.getMarker().getParents()[0].getName(), equalTo("parent"));
-        assertThat(logEvent.getMarker().getParents()[0].getParents()[0].getName(),
-                equalTo("grandparent"));
-        assertThat(logEvent.getMessage().getFormattedMessage(), equalTo("Hello, world!"));
-        assertThat(logEvent.getThrown(), is(nullValue()));
-        assertThat(logEvent.getThrownProxy().getMessage(), equalTo("error message"));
-        assertThat(logEvent.getThrownProxy().getName(), equalTo("java.lang.RuntimeException"));
-        assertThat(logEvent.getThrownProxy().getExtendedStackTrace()[0].getClassName(),
-                equalTo("logtest.Main"));
-        assertThat(logEvent.getLoggerFqcn(), equalTo("org.apache.logging.log4j.spi.AbstractLogger"));
-        assertThat(logEvent.getContextStack().asList(), equalTo(Arrays.asList("one", "two")));
-        assertThat((String) logEvent.getContextData().getValue("foo"), equalTo("FOO"));
-        assertThat((String) logEvent.getContextData().getValue("bar"), equalTo("BAR"));
-        assertThat(logEvent.getSource().getClassName(), equalTo("logtest.Main"));
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/XmlLogEventParserTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/XmlLogEventParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/XmlLogEventParserTest.java
deleted file mode 100644
index 72da8ff..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/XmlLogEventParserTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.parser;
-
-import org.apache.logging.log4j.core.LogEvent;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.nio.charset.StandardCharsets;
-
-public class XmlLogEventParserTest extends LogEventParserTest {
-
-    private XmlLogEventParser parser;
-
-    private static final String XML = "<Event xmlns=\"http://logging.apache.org/log4j/2.0/events\"\n" +
-            "       timeMillis=\"1493121664118\"\n" +
-            "       level=\"INFO\"\n" +
-            "       loggerName=\"HelloWorld\"\n" +
-            "       endOfBatch=\"false\"\n" +
-            "       thread=\"main\"\n" +
-            "       loggerFqcn=\"org.apache.logging.log4j.spi.AbstractLogger\"\n" +
-            "       threadId=\"1\"\n" +
-            "       threadPriority=\"5\">\n" +
-            "  <Instant epochSecond=\"1493121664\" nanoOfSecond=\"118000000\"/>\n" +
-            "  <Marker name=\"child\">\n" +
-            "    <Parents>\n" +
-            "      <Marker name=\"parent\">\n" +
-            "        <Parents>\n" +
-            "          <Marker name=\"grandparent\"/>\n" +
-            "        </Parents>\n" +
-            "      </Marker>\n" +
-            "    </Parents>\n" +
-            "  </Marker>\n" +
-            "  <Message>Hello, world!</Message>\n" +
-            "  <ContextMap>\n" +
-            "    <item key=\"bar\" value=\"BAR\"/>\n" +
-            "    <item key=\"foo\" value=\"FOO\"/>\n" +
-            "  </ContextMap>\n" +
-            "  <ContextStack>\n" +
-            "    <ContextStackItem>one</ContextStackItem>\n" +
-            "    <ContextStackItem>two</ContextStackItem>\n" +
-            "  </ContextStack>\n" +
-            "  <Source\n" +
-            "      class=\"logtest.Main\"\n" +
-            "      method=\"main\"\n" +
-            "      file=\"Main.java\"\n" +
-            "      line=\"29\"/>\n" +
-            "  <Thrown commonElementCount=\"0\" message=\"error message\" name=\"java.lang.RuntimeException\">\n" +
-            "    <ExtendedStackTrace>\n" +
-            "      <ExtendedStackTraceItem\n" +
-            "          class=\"logtest.Main\"\n" +
-            "          method=\"main\"\n" +
-            "          file=\"Main.java\"\n" +
-            "          line=\"29\"\n" +
-            "          exact=\"true\"\n" +
-            "          location=\"classes/\"\n" +
-            "          version=\"?\"/>\n" +
-            "    </ExtendedStackTrace>\n" +
-            "  </Thrown>\n" +
-            "</Event>";
-
-    @Before
-    public void setup() {
-        parser = new XmlLogEventParser();
-    }
-
-    @Test
-    public void testString() throws ParseException {
-        final LogEvent logEvent = parser.parseFrom(XML);
-        assertLogEvent(logEvent);
-    }
-
-    @Test(expected = ParseException.class)
-    public void testStringEmpty() throws ParseException {
-        parser.parseFrom("");
-    }
-
-    @Test(expected = ParseException.class)
-    public void testStringInvalidXml() throws ParseException {
-        parser.parseFrom("foobar");
-    }
-
-    @Test
-    public void testEmptyObject() throws ParseException {
-        parser.parseFrom("<Event></Event>");
-    }
-
-    @Test(expected = ParseException.class)
-    public void testStringWrongPropertyType() throws ParseException {
-        parser.parseFrom("<Event><Instant epochSecond=\"bar\">foobar</Instant></Event>");
-    }
-
-    @Test
-    public void testTimeMillisIgnored() throws ParseException {
-        parser.parseFrom("<Event><timeMillis>foobar</timeMillis></Event>");
-    }
-
-    @Test
-    public void testStringIgnoreInvalidProperty() throws ParseException {
-        parser.parseFrom("<Event><foo>bar</foo></Event>");
-    }
-
-    @Test
-    public void testByteArray() throws ParseException {
-        final LogEvent logEvent = parser.parseFrom(XML.getBytes(StandardCharsets.UTF_8));
-        assertLogEvent(logEvent);
-    }
-
-    @Test
-    public void testByteArrayOffsetLength() throws ParseException {
-        final byte[] bytes = ("abc" + XML + "def").getBytes(StandardCharsets.UTF_8);
-        final LogEvent logEvent = parser.parseFrom(bytes, 3, bytes.length - 6);
-        assertLogEvent(logEvent);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/YamlLogEventParserTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/YamlLogEventParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/YamlLogEventParserTest.java
deleted file mode 100644
index 16c77e7..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/parser/YamlLogEventParserTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.parser;
-
-import org.apache.logging.log4j.core.LogEvent;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.nio.charset.StandardCharsets;
-
-public class YamlLogEventParserTest extends LogEventParserTest {
-
-    private YamlLogEventParser parser;
-
-    private static final String YAML = "---\n" +
-            "timeMillis: 1493121664118\n" +
-            "instant:\n" +
-            " epochSecond: 1493121664\n" +
-            " nanoOfSecond: 118000000\n" +
-            "thread: \"main\"\n" +
-            "level: \"INFO\"\n" +
-            "loggerName: \"HelloWorld\"\n" +
-            "marker:\n" +
-            " name: \"child\"\n" +
-            " parents:\n" +
-            " - name: \"parent\"\n" +
-            "   parents:\n" +
-            "   - name: \"grandparent\"\n" +
-            "message: \"Hello, world!\"\n" +
-            "thrown:\n" +
-            " commonElementCount: 0\n" +
-            " message: \"error message\"\n" +
-            " name: \"java.lang.RuntimeException\"\n" +
-            " extendedStackTrace:\n" +
-            " - class: \"logtest.Main\"\n" +
-            "   method: \"main\"\n" +
-            "   file: \"Main.java\"\n" +
-            "   line: 29\n" +
-            "   exact: true\n" +
-            "   location: \"classes/\"\n" +
-            "   version: \"?\"\n" +
-            "contextStack:\n" +
-            "- \"one\"\n" +
-            "- \"two\"\n" +
-            "endOfBatch: false\n" +
-            "loggerFqcn: \"org.apache.logging.log4j.spi.AbstractLogger\"\n" +
-            "contextMap:\n" +
-            " bar: \"BAR\"\n" +
-            " foo: \"FOO\"\n" +
-            "threadId: 1\n" +
-            "threadPriority: 5\n" +
-            "source:\n" +
-            " class: \"logtest.Main\"\n" +
-            " method: \"main\"\n" +
-            " file: \"Main.java\"\n" +
-            " line: 29";
-
-    @Before
-    public void setup() {
-        parser = new YamlLogEventParser();
-    }
-
-    @Test
-    public void testString() throws ParseException {
-        final LogEvent logEvent = parser.parseFrom(YAML);
-        assertLogEvent(logEvent);
-    }
-
-    @Test(expected = ParseException.class)
-    public void testStringEmpty() throws ParseException {
-        parser.parseFrom("");
-    }
-
-    @Test(expected = ParseException.class)
-    public void testStringInvalidYaml() throws ParseException {
-        parser.parseFrom("foobar");
-    }
-
-    @Test
-    public void testEmptyObject() throws ParseException {
-        parser.parseFrom("---\n");
-    }
-
-    @Test
-    public void testTimeMillisIgnored() throws ParseException {
-        parser.parseFrom("---\ntimeMillis: \"foobar\"\n");
-    }
-
-    @Test(expected = ParseException.class)
-    public void testStringWrongPropertyType() throws ParseException {
-        parser.parseFrom("---\nthreadId: \"foobar\"\n");
-    }
-
-    @Test
-    public void testStringIgnoreInvalidProperty() throws ParseException {
-        parser.parseFrom("---\nfoo: \"bar\"\n");
-    }
-
-    @Test
-    public void testByteArray() throws ParseException {
-        final LogEvent logEvent = parser.parseFrom(YAML.getBytes(StandardCharsets.UTF_8));
-        assertLogEvent(logEvent);
-    }
-
-    @Test
-    public void testByteArrayOffsetLength() throws ParseException {
-        final byte[] bytes = ("abc" + YAML + "def").getBytes(StandardCharsets.UTF_8);
-        final LogEvent logEvent = parser.parseFrom(bytes, 3, bytes.length - 6);
-        assertLogEvent(logEvent);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/resources/log4j2-xml-layout.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j2-xml-layout.xml b/log4j-core/src/test/resources/log4j2-xml-layout.xml
new file mode 100644
index 0000000..c6355d0
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j2-xml-layout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<Configuration status="INFO" packages="">
+	<Appenders>
+		<File name="stdout" ignoreExceptions="false" fileName="target/test-xml-layout.log" append="false">
+			<XmlLayout compact="true" eventEol="true"/>
+		</File>
+	</Appenders>
+
+	<Loggers>
+		<Root level="INFO">
+			<AppenderRef ref="stdout"/>
+		</Root>
+	</Loggers>
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/pom.xml b/log4j-layout-jackson-json/pom.xml
new file mode 100644
index 0000000..e782338
--- /dev/null
+++ b/log4j-layout-jackson-json/pom.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ~ Licensed to the Apache Software Foundation (ASF) under one or more ~ contributor license agreements. See the NOTICE 
+  file distributed with ~ this work for additional information regarding copyright ownership. ~ The ASF licenses this file 
+  to You under the Apache License, Version 2.0 ~ (the "License"); you may not use this file except in compliance with ~ the 
+  License. You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable 
+  law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES 
+  OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and 
+  ~ limitations under the License. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>org.apache.logging.log4j</groupId>
+    <artifactId>log4j</artifactId>
+    <version>3.0.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>log4j-layout-jackson-json</artifactId>
+  <name>Apache Log4j Layout for Jackson JSON</name>
+  <description>
+    Apache Log4j Layout for Jackson JSON.
+  </description>
+  <properties>
+    <log4jParentDir>${basedir}/..</log4jParentDir>
+    <docLabel>Log4j Layout for Jackson JSON Documentation</docLabel>
+    <projectDir>/log4j-layout-json</projectDir>
+    <module.name>org.apache.logging.log4j.jackson.json</module.name>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-layout-jackson</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <!-- Test Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <type>test-jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <type>test-jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-layout-jackson</artifactId>
+      <type>test-jar</type>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Fragment-Host>org.apache.logging.log4j.jackson.json</Fragment-Host>
+            <Export-Package>*</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-changes-plugin</artifactId>
+        <version>${changes.plugin.version}</version>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>changes-report</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+        <configuration>
+          <issueLinkTemplate>%URL%/show_bug.cgi?id=%ISSUE%</issueLinkTemplate>
+          <useJql>true</useJql>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>${checkstyle.plugin.version}</version>
+        <configuration>
+          <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
+          <configLocation>${log4jParentDir}/checkstyle.xml</configLocation>
+          <suppressionsLocation>${log4jParentDir}/checkstyle-suppressions.xml</suppressionsLocation>
+          <enableRulesSummary>false</enableRulesSummary>
+          <propertyExpansion>basedir=${basedir}</propertyExpansion>
+          <propertyExpansion>licensedir=${log4jParentDir}/checkstyle-header.txt</propertyExpansion>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>${javadoc.plugin.version}</version>
+        <configuration>
+          <bottom><![CDATA[<p align="center">Copyright &#169; {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.<br />
+            Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo,
+            and the Apache Log4j logo are trademarks of The Apache Software Foundation.</p>]]></bottom>
+          <!-- module link generation is completely broken in the javadoc plugin for a multi-module non-aggregating project -->
+          <detectOfflineLinks>false</detectOfflineLinks>
+          <linksource>true</linksource>
+        </configuration>
+        <reportSets>
+          <reportSet>
+            <id>non-aggregate</id>
+            <reports>
+              <report>javadoc</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>${findbugs.plugin.version}</version>
+        <configuration>
+          <fork>true</fork>
+          <jvmArgs>-Duser.language=en</jvmArgs>
+          <threshold>Normal</threshold>
+          <effort>Default</effort>
+          <excludeFilterFile>${log4jParentDir}/findbugs-exclude-filter.xml</excludeFilterFile>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jxr-plugin</artifactId>
+        <version>${jxr.plugin.version}</version>
+        <reportSets>
+          <reportSet>
+            <id>non-aggregate</id>
+            <reports>
+              <report>jxr</report>
+            </reports>
+          </reportSet>
+          <reportSet>
+            <id>aggregate</id>
+            <reports>
+              <report>aggregate</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-pmd-plugin</artifactId>
+        <version>${pmd.plugin.version}</version>
+        <configuration>
+          <targetJdk>${maven.compiler.target}</targetJdk>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+</project>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/JsonSetupContextInitializer.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/JsonSetupContextInitializer.java b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/JsonSetupContextInitializer.java
new file mode 100644
index 0000000..e7c90a2
--- /dev/null
+++ b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/JsonSetupContextInitializer.java
@@ -0,0 +1,51 @@
+package org.apache.logging.log4j.jackson.json;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.core.time.Instant;
+import org.apache.logging.log4j.jackson.ExtendedStackTraceElementMixIn;
+import org.apache.logging.log4j.jackson.InstantMixIn;
+import org.apache.logging.log4j.jackson.LevelMixIn;
+import org.apache.logging.log4j.jackson.LogEventJsonMixIn;
+import org.apache.logging.log4j.jackson.MarkerMixIn;
+import org.apache.logging.log4j.jackson.StackTraceElementMixIn;
+import org.apache.logging.log4j.jackson.ThrowableProxyMixIn;
+import org.apache.logging.log4j.jackson.ThrowableProxyWithStacktraceAsStringMixIn;
+import org.apache.logging.log4j.jackson.ThrowableProxyWithoutStacktraceMixIn;
+
+import com.fasterxml.jackson.databind.Module.SetupContext;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+/**
+ * Used to set up {@link SetupContext} from different {@link SimpleModule}s.
+ * <p>
+ * Differs from SetupContextInitializer by installing {@code LogEventJsonMixIn} for LogEvents, not
+ * {@code LogEventMixIn}, so it handles {@link ThreadContext} serialization differently.
+ * </p>
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class JsonSetupContextInitializer {
+
+    public void setupModule(final SetupContext context, final boolean includeStacktrace,
+            final boolean stacktraceAsString) {
+        // JRE classes: we cannot edit those with Jackson annotations
+        context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class);
+        // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not
+        // depend on Jackson.
+        context.setMixInAnnotations(Marker.class, MarkerMixIn.class);
+        context.setMixInAnnotations(Level.class, LevelMixIn.class);
+        context.setMixInAnnotations(Instant.class, InstantMixIn.class);
+        context.setMixInAnnotations(LogEvent.class, LogEventJsonMixIn.class); // different ThreadContext handling
+        // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
+        context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
+        context.setMixInAnnotations(ThrowableProxy.class, includeStacktrace
+                ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringMixIn.class : ThrowableProxyMixIn.class)
+                : ThrowableProxyWithoutStacktraceMixIn.class);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonModule.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonModule.java b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonModule.java
new file mode 100644
index 0000000..ab77411
--- /dev/null
+++ b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonModule.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.json;
+
+import org.apache.logging.log4j.jackson.SetupContextInitializer;
+import org.apache.logging.log4j.jackson.SimpleModuleInitializer;
+
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+class Log4jJsonModule extends SimpleModule {
+
+    private static final long serialVersionUID = 1L;
+    private final boolean encodeThreadContextAsList;
+    private final boolean includeStacktrace;
+    private final boolean stacktraceAsString;
+
+    Log4jJsonModule(final boolean encodeThreadContextAsList, final boolean includeStacktrace, final boolean stacktraceAsString, final boolean objectMessageAsJsonObject) {
+        super(Log4jJsonModule.class.getName(), new Version(2, 0, 0, null, null, null));
+        this.encodeThreadContextAsList = encodeThreadContextAsList;
+        this.includeStacktrace = includeStacktrace;
+        this.stacktraceAsString = stacktraceAsString;
+        // MUST initialize() here.
+        // Calling this from setupModule is too late!
+        //noinspection ThisEscapedInObjectConstruction
+        new SimpleModuleInitializer().initialize(this, objectMessageAsJsonObject);
+    }
+
+    @Override
+    public void setupModule(final SetupContext context) {
+        // Calling super is a MUST!
+        super.setupModule(context);
+        if (encodeThreadContextAsList) {
+            new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
+        } else {
+            new JsonSetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonObjectMapper.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonObjectMapper.java b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonObjectMapper.java
new file mode 100644
index 0000000..f0df03b
--- /dev/null
+++ b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/Log4jJsonObjectMapper.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.json;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * A Jackson JSON {@link ObjectMapper} initialized for Log4j.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class Log4jJsonObjectMapper extends ObjectMapper {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Create a new instance using the {@link Log4jJsonModule}.
+     */
+    public Log4jJsonObjectMapper() {
+        this(false, true, false, false);
+    }
+
+    /**
+     * Create a new instance using the {@link Log4jJsonModule}.
+     */
+    public Log4jJsonObjectMapper(final boolean encodeThreadContextAsList, final boolean includeStacktrace, final boolean stacktraceAsString, final boolean objectMessageAsJsonObject) {
+        this.registerModule(new Log4jJsonModule(encodeThreadContextAsList, includeStacktrace, stacktraceAsString, objectMessageAsJsonObject));
+        this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonJacksonFactory.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonJacksonFactory.java b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonJacksonFactory.java
new file mode 100644
index 0000000..dd7b789
--- /dev/null
+++ b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonJacksonFactory.java
@@ -0,0 +1,60 @@
+package org.apache.logging.log4j.jackson.json.layout;
+
+import org.apache.logging.log4j.jackson.AbstractJacksonFactory;
+import org.apache.logging.log4j.jackson.JsonConstants;
+import org.apache.logging.log4j.jackson.json.Log4jJsonObjectMapper;
+
+import com.fasterxml.jackson.core.PrettyPrinter;
+import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
+import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+class JsonJacksonFactory extends AbstractJacksonFactory {
+
+    private final boolean encodeThreadContextAsList;
+    private final boolean objectMessageAsJsonObject;
+
+    public JsonJacksonFactory(final boolean encodeThreadContextAsList, final boolean includeStacktrace,
+            final boolean stacktraceAsString, final boolean objectMessageAsJsonObject) {
+        super(includeStacktrace, stacktraceAsString);
+        this.encodeThreadContextAsList = encodeThreadContextAsList;
+        this.objectMessageAsJsonObject = objectMessageAsJsonObject;
+    }
+
+    @Override
+    protected String getPropertyNameForContextMap() {
+        return JsonConstants.ELT_CONTEXT_MAP;
+    }
+
+    @Override
+    protected String getPropertyNameForNanoTime() {
+        return JsonConstants.ELT_NANO_TIME;
+    }
+
+    @Override
+    protected String getPropertyNameForSource() {
+        return JsonConstants.ELT_SOURCE;
+    }
+
+    @Override
+    protected String getPropertyNameForStackTrace() {
+        return JsonConstants.ELT_EXTENDED_STACK_TRACE;
+    }
+
+    @Override
+    protected PrettyPrinter newCompactPrinter() {
+        return new MinimalPrettyPrinter();
+    }
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jJsonObjectMapper(encodeThreadContextAsList, includeStacktrace, stacktraceAsString,
+                objectMessageAsJsonObject);
+    }
+
+    @Override
+    protected PrettyPrinter newPrettyPrinter() {
+        return new DefaultPrettyPrinter();
+    }
+
+}
\ No newline at end of file


[08/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java
deleted file mode 100644
index 9b4da79..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAppenderValidationTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-
-import javax.xml.XMLConstants;
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-import javax.xml.validation.Validator;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.config.Configurator;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.xml.sax.SAXException;
-
-/**
- * Tests XML validation for a "compact" XML file, no extra spaces or end of lines.
- */
-@Ignore
-@Category(Layouts.Xml.class)
-public class XmlCompactFileAppenderValidationTest {
-
-    private LoggerContext loggerContext;
-
-    @Before
-    public void before() {
-        this.loggerContext = Configurator.initialize(XmlCompactFileAppenderValidationTest.class.getName(),
-                "target/test-classes/XmlCompactFileAppenderValidationTest.xml");
-    }
-
-    @After
-    public void after() {
-        // Just in case, an @Test blew up
-        Configurator.shutdown(this.loggerContext);
-    }
-
-    @Test
-    public void validateXmlSchemaThrowable() throws Exception {
-        final File file = new File("target", "XmlCompactFileAppenderValidationTest.log.xml");
-        file.delete();
-        final Logger log = LogManager.getLogger("com.foo.Bar");
-        try {
-            throw new IllegalArgumentException("IAE");
-        } catch (final IllegalArgumentException e) {
-            log.warn("Message 1", e);
-        }
-        Configurator.shutdown(this.loggerContext);
-        this.validateXmlSchema(file);
-    }
-
-    @Test
-    public void validateXmlSchema() throws Exception {
-        final File file = new File("target", "XmlCompactFileAppenderValidationTest.log.xml");
-        file.delete();
-        final Logger log = LogManager.getLogger("com.foo.Bar");
-        log.warn("Message 1");
-        log.info("Message 2");
-        log.debug("Message 3");
-        Configurator.shutdown(this.loggerContext);
-        this.validateXmlSchema(file);
-    }
-
-    @Test
-    public void validateXmlNoEvents() throws Exception {
-        final File file = new File("target", "XmlCompactFileAppenderValidationTest.log.xml");
-        file.delete();
-        Configurator.shutdown(this.loggerContext);
-        this.validateXmlSchema(file);
-    }
-
-    private void validateXmlSchema(final File file) throws SAXException, IOException {
-        final URL schemaFile = this.getClass().getClassLoader().getResource("Log4j-events.xsd");
-        final Source xmlFile = new StreamSource(file);
-        final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-        final Schema schema = schemaFactory.newSchema(schemaFile);
-        final Validator validator = schema.newValidator();
-        validator.validate(xmlFile);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java
deleted file mode 100644
index 1e048b1..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompactFileAsyncAppenderValidationTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-
-import javax.xml.XMLConstants;
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-import javax.xml.validation.Validator;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.CoreLoggerContexts;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.xml.sax.SAXException;
-
-/**
- * Tests XML validation for a "compact" XML file, no extra spaces or end of lines.
- */
-@Ignore
-@Category(Layouts.Xml.class)
-public class XmlCompactFileAsyncAppenderValidationTest {
-
-    @BeforeClass
-    public static void beforeClass() {
-        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
-                "XmlCompactFileAsyncAppenderValidationTest.xml");
-    }
-
-    @Test
-    public void validateXmlSchemaSimple() throws Exception {
-        final File file = new File("target", "XmlCompactFileAsyncAppenderValidationTest.log.xml");
-        file.delete();
-        final Logger log = LogManager.getLogger("com.foo.Bar");
-        log.warn("Message 1");
-        log.info("Message 2");
-        log.debug("Message 3");
-        CoreLoggerContexts.stopLoggerContext(file); // stop async thread
-        this.validateXmlSchema(file);
-    }
-
-    @Test
-    public void validateXmlSchemaNoEvents() throws Exception {
-        final File file = new File("target", "XmlCompactFileAsyncAppenderValidationTest.log.xml");
-        file.delete();
-        CoreLoggerContexts.stopLoggerContext(file); // stop async thread
-        this.validateXmlSchema(file);
-    }
-
-    private void validateXmlSchema(final File file) throws SAXException, IOException {
-        final URL schemaFile = this.getClass().getClassLoader().getResource("Log4j-events.xsd");
-        final Source xmlFile = new StreamSource(file);
-        final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-        final Schema schema = schemaFactory.newSchema(schemaFile);
-        final Validator validator = schema.newValidator();
-        validator.validate(xmlFile);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java
deleted file mode 100644
index c77b464..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.List;
-
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.CoreLoggerContexts;
-import org.apache.logging.log4j.core.selector.ContextSelector;
-import org.apache.logging.log4j.core.selector.CoreContextSelectors;
-import org.apache.logging.log4j.junit.CleanFiles;
-import org.apache.logging.log4j.junit.LoggerContextRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.RuleChain;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import static org.junit.Assert.*;
-
-/**
- * Tests a "complete" XML file a.k.a. a well-formed XML file.
- */
-@RunWith(Parameterized.class)
-@Category(Layouts.Xml.class)
-public class XmlCompleteFileAppenderTest {
-
-    public XmlCompleteFileAppenderTest(final Class<ContextSelector> contextSelector) {
-        this.loggerContextRule = new LoggerContextRule("XmlCompleteFileAppenderTest.xml", contextSelector);
-        this.cleanFiles = new CleanFiles(logFile);
-        this.ruleChain = RuleChain.outerRule(cleanFiles).around(loggerContextRule);
-    }
-
-    @Parameters(name = "{0}")
-    public static Class<?>[] getParameters() {
-        return CoreContextSelectors.CLASSES;
-    }
-
-    private final File logFile = new File("target", "XmlCompleteFileAppenderTest.log");
-    private final LoggerContextRule loggerContextRule;
-    private final CleanFiles cleanFiles;
-
-    @Rule
-    public RuleChain ruleChain;
-
-    @Test
-    public void testFlushAtEndOfBatch() throws Exception {
-        final Logger logger = this.loggerContextRule.getLogger("com.foo.Bar");
-        final String logMsg = "Message flushed with immediate flush=false";
-        logger.info(logMsg);
-        CoreLoggerContexts.stopLoggerContext(false, logFile); // stop async thread
-
-        String line1;
-        String line2;
-        String line3;
-        String line4;
-        String line5;
-        try (final BufferedReader reader = new BufferedReader(new FileReader(logFile))) {
-            line1 = reader.readLine();
-            line2 = reader.readLine();
-            reader.readLine(); // ignore the empty line after the <Events> root
-            line3 = reader.readLine();
-            line4 = reader.readLine();
-            line5 = reader.readLine();
-        } finally {
-            logFile.delete();
-        }
-        assertNotNull("line1", line1);
-        final String msg1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
-        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg1 + ']', line1.equals(msg1));
-
-        assertNotNull("line2", line2);
-        final String msg2 = "<Events xmlns=\"http://logging.apache.org/log4j/2.0/events\">";
-        assertTrue("line2 incorrect: [" + line2 + "], does not contain: [" + msg2 + ']', line2.equals(msg2));
-
-        assertNotNull("line3", line3);
-        final String msg3 = "<Event ";
-        assertTrue("line3 incorrect: [" + line3 + "], does not contain: [" + msg3 + ']', line3.contains(msg3));
-
-        assertNotNull("line4", line4);
-        final String msg4 = "<Instant epochSecond=";
-        assertTrue("line4 incorrect: [" + line4 + "], does not contain: [" + msg4 + ']', line4.contains(msg4));
-
-        assertNotNull("line5", line5);
-        final String msg5 = logMsg;
-        assertTrue("line5 incorrect: [" + line5 + "], does not contain: [" + msg5 + ']', line5.contains(msg5));
-
-        final String location = "testFlushAtEndOfBatch";
-        assertTrue("no location", !line1.contains(location));
-    }
-
-    /**
-     * Test the indentation of the Events XML.
-     * <p>Expected Events XML is as below.</p>
-     * <pre>
-&lt;?xml version="1.0" encoding="UTF-8"?>
-&lt;Events xmlns="http://logging.apache.org/log4j/2.0/events">
-
-  &lt;Event xmlns="http://logging.apache.org/log4j/2.0/events" thread="main" level="INFO" loggerName="com.foo.Bar" endOfBatch="true" loggerFqcn="org.apache.logging.log4j.spi.AbstractLogger" threadId="12" threadPriority="5">
-    &lt;Instant epochSecond="1515889414" nanoOfSecond="144000000" epochMillisecond="1515889414144" nanoOfMillisecond="0"/>
-    &lt;Message>First Msg tag must be in level 2 after correct indentation&lt;/Message>
-  &lt;/Event>
-
-  &lt;Event xmlns="http://logging.apache.org/log4j/2.0/events" thread="main" level="INFO" loggerName="com.foo.Bar" endOfBatch="true" loggerFqcn="org.apache.logging.log4j.spi.AbstractLogger" threadId="12" threadPriority="5">
-    &lt;Instant epochSecond="1515889414" nanoOfSecond="144000000" epochMillisecond="1515889414144" nanoOfMillisecond="0"/>
-    &lt;Message>Second Msg tag must also be in level 2 after correct indentation&lt;/Message>
-  &lt;/Event>
-&lt;/Events>
-     * </pre>
-     * @throws Exception
-     */
-    @Test
-    public void testChildElementsAreCorrectlyIndented() throws Exception {
-        final Logger logger = this.loggerContextRule.getLogger("com.foo.Bar");
-        final String firstLogMsg = "First Msg tag must be in level 2 after correct indentation";
-        logger.info(firstLogMsg);
-        final String secondLogMsg = "Second Msg tag must also be in level 2 after correct indentation";
-        logger.info(secondLogMsg);
-        CoreLoggerContexts.stopLoggerContext(false, logFile); // stop async thread
-
-        int[] indentations = {
-                0, //"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-                0, //"<Events xmlns=\"http://logging.apache.org/log4j/2.0/events\">\n"
-                -1, // empty
-                2, //"  <Event xmlns=\"http://logging.apache.org/log4j/2.0/events\" thread=\"main\" level=\"INFO\" loggerName=\"com.foo.Bar\" endOfBatch=\"true\" loggerFqcn=\"org.apache.logging.log4j.spi.AbstractLogger\" threadId=\"12\" threadPriority=\"5\">\n"
-                4, //"    <Instant epochSecond=\"1515889414\" nanoOfSecond=\"144000000\" epochMillisecond=\"1515889414144\" nanoOfMillisecond=\"0\"/>\n"
-                4, //"    <Message>First Msg tag must be in level 2 after correct indentation</Message>\n" +
-                2, //"  </Event>\n"
-                -1, // empty
-                2, //"  <Event xmlns=\"http://logging.apache.org/log4j/2.0/events\" thread=\"main\" level=\"INFO\" loggerName=\"com.foo.Bar\" endOfBatch=\"true\" loggerFqcn=\"org.apache.logging.log4j.spi.AbstractLogger\" threadId=\"12\" threadPriority=\"5\">\n" +
-                4, //"    <Instant epochSecond=\"1515889414\" nanoOfSecond=\"144000000\" epochMillisecond=\"1515889414144\" nanoOfMillisecond=\"0\"/>\n" +
-                4, //"    <Message>Second Msg tag must also be in level 2 after correct indentation</Message>\n" +
-                2, //"  </Event>\n" +
-                0, //"</Events>\n";
-        };
-        List<String> lines1 = Files.readAllLines(logFile.toPath(), Charset.forName("UTF-8"));
-
-        assertEquals("number of lines", indentations.length, lines1.size());
-        for (int i = 0; i < indentations.length; i++) {
-            String line = lines1.get(i);
-            if (line.trim().isEmpty()) {
-                assertEquals(-1, indentations[i]);
-            } else {
-                String padding = "        ".substring(0, indentations[i]);
-                assertTrue("Expected " + indentations[i] + " leading spaces but got: " + line, line.startsWith(padding));
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java
deleted file mode 100644
index f9cdff3..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.util.List;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.CoreLoggerContexts;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import static org.junit.Assert.*;
-
-/**
- * Tests a "complete" XML file a.k.a. a well-formed XML file.
- */
-@Category(Layouts.Xml.class)
-public class XmlFileAppenderTest {
-
-    @BeforeClass
-    public static void beforeClass() {
-        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
-                "XmlFileAppenderTest.xml");
-    }
-
-    @Test
-    public void testFlushAtEndOfBatch() throws Exception {
-        final File file = new File("target", "XmlFileAppenderTest.log");
-        // System.out.println(f.getAbsolutePath());
-        file.delete();
-        final Logger log = LogManager.getLogger("com.foo.Bar");
-        final String logMsg = "Message flushed with immediate flush=false";
-        log.info(logMsg);
-        CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread
-
-        List<String> lines = Files.readAllLines(file.toPath(), Charset.forName("UTF8"));
-        file.delete();
-
-        String[] expect = {
-                "", // ? unsure why initial empty line...
-            "<Event ", //
-            "<Instant epochSecond=", //
-            logMsg, //
-            "</Event>", //
-        };
-
-        for (int i = 0; i < expect.length; i++) {
-            assertTrue("Expected line " + i + " to contain " + expect[i] + " but got: " + lines.get(i),
-                    lines.get(i).contains(expect[i]));
-        }
-
-        final String location = "testFlushAtEndOfBatch";
-        assertTrue("no location", !lines.get(0).contains(location));
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlRandomAccessFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlRandomAccessFileAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlRandomAccessFileAppenderTest.java
deleted file mode 100644
index a907c7f..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlRandomAccessFileAppenderTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.appender;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.CoreLoggerContexts;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import static org.junit.Assert.*;
-
-/**
- * Tests a "complete" XML file a.k.a. a well-formed XML file.
- */
-@Category(Layouts.Xml.class)
-public class XmlRandomAccessFileAppenderTest {
-
-    @BeforeClass
-    public static void beforeClass() {
-        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
-                "XmlRandomAccessFileAppenderTest.xml");
-    }
-
-    @Test
-    @Ignore
-    public void testFlushAtEndOfBatch() throws Exception {
-        final File file = new File("target", "XmlRandomAccessFileAppenderTest.log");
-        // System.out.println(f.getAbsolutePath());
-        file.delete();
-        final Logger log = LogManager.getLogger("com.foo.Bar");
-        final String logMsg = "Message flushed with immediate flush=false";
-        log.info(logMsg);
-        CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread
-
-        String line1;
-        String line2;
-        String line3;
-        String line4;
-        try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
-            line1 = reader.readLine();
-            line2 = reader.readLine();
-            line3 = reader.readLine();
-            line4 = reader.readLine();
-        } finally {
-            file.delete();
-        }
-        assertNotNull("line1", line1);
-        final String msg1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
-        assertTrue("line1 incorrect: [" + line1 + "], does not contain: [" + msg1 + ']', line1.equals(msg1));
-
-        assertNotNull("line2", line2);
-        final String msg2 = "<log4j:events xmlns:log4j=\"http://logging.apache.org/log4j/\">";
-        assertTrue("line2 incorrect: [" + line2 + "], does not contain: [" + msg2 + ']', line2.equals(msg2));
-
-        assertNotNull("line3", line3);
-        final String msg3 = "<log4j:event ";
-        assertTrue("line3 incorrect: [" + line3 + "], does not contain: [" + msg3 + ']', line3.contains(msg3));
-
-        assertNotNull("line4", line4);
-        final String msg4 = logMsg;
-        assertTrue("line4 incorrect: [" + line4 + "], does not contain: [" + msg4 + ']', line4.contains(msg4));
-
-        final String location = "testFlushAtEndOfBatch";
-        assertTrue("no location", !line1.contains(location));
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
index 813a5b7..ba09c99 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
@@ -35,22 +35,22 @@ import java.security.SecureRandom;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Stack;
+
 import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
 import javax.crypto.KeyGenerator;
 import javax.crypto.spec.IvParameterSpec;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.config.plugins.convert.Base64Converter;
-import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
-import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
 import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
 import org.apache.logging.log4j.util.Strings;
 import org.junit.Test;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
 /**
  *
  */
@@ -113,16 +113,6 @@ public class ThrowableProxyTest {
         assertEquals(expected.proxy, actual.proxy);
     }
 
-    @Test
-    public void testIoContainerAsJson() throws IOException {
-        testIoContainer(new Log4jJsonObjectMapper());
-    }
-
-    @Test
-    public void testIoContainerAsXml() throws IOException {
-        testIoContainer(new Log4jXmlObjectMapper());
-    }
-
     /**
      * Attempts to instantiate a class that cannot initialize and then logs the stack trace of the Error. The logger
      * must not fail when using {@link ThrowableProxy} to inspect the frames of the stack trace.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/JacksonIssue429MyNamesTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/JacksonIssue429MyNamesTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/JacksonIssue429MyNamesTest.java
deleted file mode 100644
index 63c7919..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/JacksonIssue429MyNamesTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.util.Strings;
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-import org.junit.experimental.categories.Category;
-
-@Category(Layouts.Json.class)
-public class JacksonIssue429MyNamesTest {
-
-    @SuppressWarnings("serial")
-    static class MyStackTraceElementDeserializer extends StdScalarDeserializer<StackTraceElement> {
-        private static final long serialVersionUID = 1L;
-
-        public final static MyStackTraceElementDeserializer instance = new MyStackTraceElementDeserializer();
-
-        public MyStackTraceElementDeserializer() {
-            super(StackTraceElement.class);
-        }
-
-        @Override
-        public StackTraceElement deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
-                JsonProcessingException {
-            JsonToken t = jp.getCurrentToken();
-            // Must get an Object
-            if (t == JsonToken.START_OBJECT) {
-                String className = Strings.EMPTY, methodName = Strings.EMPTY, fileName = Strings.EMPTY;
-                int lineNumber = -1;
-
-                while ((t = jp.nextValue()) != JsonToken.END_OBJECT) {
-                    final String propName = jp.getCurrentName();
-                    if ("class".equals(propName)) {
-                        className = jp.getText();
-                    } else if ("file".equals(propName)) {
-                        fileName = jp.getText();
-                    } else if ("line".equals(propName)) {
-                        if (t.isNumeric()) {
-                            lineNumber = jp.getIntValue();
-                        } else {
-                            throw JsonMappingException.from(jp, "Non-numeric token (" + t
-                                    + ") for property 'lineNumber'");
-                        }
-                    } else if ("method".equals(propName)) {
-                        methodName = jp.getText();
-                    } else if ("nativeMethod".equals(propName)) {
-                        // no setter, not passed via constructor: ignore
-                    } else {
-                        handleUnknownProperty(jp, ctxt, _valueClass, propName);
-                    }
-                }
-                return new StackTraceElement(className, methodName, fileName, lineNumber);
-            }
-            throw ctxt.mappingException(_valueClass, t);
-        }
-    }
-
-    static class StackTraceBean {
-        public final static int NUM = 13;
-
-        @JsonProperty("Location")
-        @JsonDeserialize(using = MyStackTraceElementDeserializer.class)
-        private StackTraceElement location;
-    }
-
-    private final static ObjectMapper SHARED_MAPPER = new ObjectMapper();
-
-    private final ObjectMapper MAPPER = objectMapper();
-
-    protected String aposToQuotes(final String json) {
-        return json.replace("'", "\"");
-    }
-
-    protected ObjectMapper objectMapper() {
-        return SHARED_MAPPER;
-    }
-
-    @Test
-    public void testStackTraceElementWithCustom() throws Exception {
-        // first, via bean that contains StackTraceElement
-        final StackTraceBean bean = MAPPER
-                .readValue(
-                        aposToQuotes("{'Location':{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':13}}"),
-                        StackTraceBean.class);
-        Assert.assertNotNull(bean);
-        Assert.assertNotNull(bean.location);
-        Assert.assertEquals(StackTraceBean.NUM, bean.location.getLineNumber());
-
-        // and then directly, iff registered
-        final ObjectMapper mapper = new ObjectMapper();
-        final SimpleModule module = new SimpleModule();
-        module.addDeserializer(StackTraceElement.class, new MyStackTraceElementDeserializer());
-        mapper.registerModule(module);
-
-        final StackTraceElement elem = mapper.readValue(
-                aposToQuotes("{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':13}"),
-                StackTraceElement.class);
-        Assert.assertNotNull(elem);
-        Assert.assertEquals(StackTraceBean.NUM, elem.getLineNumber());
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/JacksonIssue429Test.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/JacksonIssue429Test.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/JacksonIssue429Test.java
deleted file mode 100644
index 6cbccc6..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/JacksonIssue429Test.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-
-import org.apache.logging.log4j.categories.Layouts;
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-import org.junit.experimental.categories.Category;
-
-@Category(Layouts.Json.class)
-public class JacksonIssue429Test {
-
-    @SuppressWarnings("serial")
-    static class Jackson429StackTraceElementDeserializer extends StdDeserializer<StackTraceElement> {
-        private static final long serialVersionUID = 1L;
-
-        public Jackson429StackTraceElementDeserializer() {
-            super(StackTraceElement.class);
-        }
-
-        @Override
-        public StackTraceElement deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
-                JsonProcessingException {
-            jp.skipChildren();
-            return new StackTraceElement("a", "b", "b", StackTraceBean.NUM);
-        }
-
-    }
-
-    static class StackTraceBean {
-        public final static int NUM = 13;
-
-        @JsonProperty("Location")
-        @JsonDeserialize(using = Jackson429StackTraceElementDeserializer.class)
-        private StackTraceElement location;
-    }
-
-    private final static ObjectMapper SHARED_MAPPER = new ObjectMapper();
-
-    private final ObjectMapper MAPPER = objectMapper();
-
-    protected String aposToQuotes(final String json) {
-        return json.replace("'", "\"");
-    }
-
-    protected ObjectMapper objectMapper() {
-        return SHARED_MAPPER;
-    }
-
-    @Test
-    public void testStackTraceElementWithCustom() throws Exception {
-        // first, via bean that contains StackTraceElement
-        final StackTraceBean bean = MAPPER.readValue(aposToQuotes("{'Location':'foobar'}"), StackTraceBean.class);
-        Assert.assertNotNull(bean);
-        Assert.assertNotNull(bean.location);
-        Assert.assertEquals(StackTraceBean.NUM, bean.location.getLineNumber());
-
-        // and then directly, iff registered
-        final ObjectMapper mapper = new ObjectMapper();
-        final SimpleModule module = new SimpleModule();
-        module.addDeserializer(StackTraceElement.class, new Jackson429StackTraceElementDeserializer());
-        mapper.registerModule(module);
-
-        final StackTraceElement elem = mapper.readValue(
-                aposToQuotes("{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':123}"),
-                StackTraceElement.class);
-        Assert.assertNotNull(elem);
-        Assert.assertEquals(StackTraceBean.NUM, elem.getLineNumber());
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInJsonTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInJsonTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInJsonTest.java
deleted file mode 100644
index 14b015b..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInJsonTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-
-package org.apache.logging.log4j.core.jackson;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.logging.log4j.categories.Layouts;
-import org.junit.experimental.categories.Category;
-
-@Category(Layouts.Json.class)
-public class LevelMixInJsonTest extends LevelMixInTest {
-
-    @Override
-    protected ObjectMapper newObjectMapper() {
-        return new Log4jJsonObjectMapper(false, true, false, false);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInTest.java
deleted file mode 100644
index acff4b4..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.categories.Layouts;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectReader;
-import com.fasterxml.jackson.databind.ObjectWriter;
-import org.junit.experimental.categories.Category;
-
-/**
- * Tests {@link LevelMixIn}.
- */
-@Category(Layouts.Json.class)
-public abstract class LevelMixInTest {
-
-    static class Fixture {
-        @JsonProperty
-        private final Level level = Level.DEBUG;
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            final Fixture other = (Fixture) obj;
-            if (this.level == null) {
-                if (other.level != null) {
-                    return false;
-                }
-            } else if (!this.level.equals(other.level)) {
-                return false;
-            }
-            return true;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((this.level == null) ? 0 : this.level.hashCode());
-            return result;
-        }
-    }
-    private ObjectMapper log4jObjectMapper;
-
-    private ObjectReader reader;
-
-    private ObjectWriter writer;
-
-    @Before
-    public void setUp() {
-        log4jObjectMapper = newObjectMapper();
-        writer = log4jObjectMapper.writer();
-        reader = log4jObjectMapper.readerFor(Level.class);
-    }
-
-    protected abstract ObjectMapper newObjectMapper();
-
-    @Test
-    public void testContainer() throws IOException {
-        final Fixture expected = new Fixture();
-        final String str = writer.writeValueAsString(expected);
-        Assert.assertTrue(str.contains("DEBUG"));
-        final ObjectReader fixtureReader = log4jObjectMapper.readerFor(Fixture.class);
-        final Fixture actual = fixtureReader.readValue(str);
-        Assert.assertEquals(expected, actual);
-    }
-
-    @Test
-    public void testNameOnly() throws IOException {
-        final Level expected = Level.getLevel("DEBUG");
-        final String str = writer.writeValueAsString(expected);
-        Assert.assertTrue(str.contains("DEBUG"));
-        final Level actual = reader.readValue(str);
-        Assert.assertEquals(expected, actual);
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInXmlTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInXmlTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInXmlTest.java
deleted file mode 100644
index 3332d1a..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInXmlTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-
-package org.apache.logging.log4j.core.jackson;
-
-import org.apache.logging.log4j.categories.Layouts;
-import org.junit.Ignore;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.experimental.categories.Category;
-
-@Ignore("Fails for #testNameOnly()")
-@Category(Layouts.Xml.class)
-public class LevelMixInXmlTest extends LevelMixInTest {
-
-    @Override
-    protected ObjectMapper newObjectMapper() {
-        return new Log4jXmlObjectMapper();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInYamlTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInYamlTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInYamlTest.java
deleted file mode 100644
index 29b9e52..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInYamlTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-
-package org.apache.logging.log4j.core.jackson;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.logging.log4j.categories.Layouts;
-import org.junit.experimental.categories.Category;
-
-@Category(Layouts.Yaml.class)
-public class LevelMixInYamlTest extends LevelMixInTest {
-
-    @Override
-    protected ObjectMapper newObjectMapper() {
-        return new Log4jYamlObjectMapper();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixInTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixInTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixInTest.java
deleted file mode 100644
index f14a26e..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixInTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.jackson;
-
-import java.io.IOException;
-
-import org.apache.logging.log4j.categories.Layouts;
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-import org.junit.experimental.categories.Category;
-
-@Category(Layouts.Json.class)
-public class StackTraceElementMixInTest {
-
-    @Test
-    public void testLog4jJsonObjectMapper() throws Exception {
-        this.roundtrip(new Log4jJsonObjectMapper());
-    }
-
-    @Test
-    public void testLog4jYamlObjectMapper() throws Exception {
-        this.roundtrip(new Log4jYamlObjectMapper());
-    }
-
-    /**
-     * @param mapper
-     * @throws JsonProcessingException
-     * @throws IOException
-     * @throws JsonParseException
-     * @throws JsonMappingException
-     */
-    private void roundtrip(final ObjectMapper mapper) throws JsonProcessingException, IOException, JsonParseException, JsonMappingException {
-        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java", 123);
-        final String s = mapper.writeValueAsString(expected);
-        final StackTraceElement actual = mapper.readValue(s, StackTraceElement.class);
-        Assert.assertEquals(expected, actual);
-    }
-
-    @Test
-    public void testLog4jXmlObjectMapper() throws Exception {
-        this.roundtrip(new Log4jXmlObjectMapper());
-    }
-
-    protected String aposToQuotes(final String json) {
-        return json.replace("'", "\"");
-    }
-
-    @Test
-    public void testFromJsonWithSimpleModule() throws Exception {
-        final ObjectMapper mapper = new ObjectMapper();
-        final SimpleModule module = new SimpleModule();
-        module.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
-        mapper.registerModule(module);
-        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java", 123);
-        final String s = this.aposToQuotes("{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':123}");
-        final StackTraceElement actual = mapper.readValue(s, StackTraceElement.class);
-        Assert.assertEquals(expected, actual);
-    }
-
-    @Test
-    public void testFromJsonWithLog4jModule() throws Exception {
-        final ObjectMapper mapper = new ObjectMapper();
-        final boolean encodeThreadContextAsList = false;
-        final SimpleModule module = new Log4jJsonModule(encodeThreadContextAsList, true, false, false);
-        module.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
-        mapper.registerModule(module);
-        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java", 123);
-        final String s = this.aposToQuotes("{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':123}");
-        final StackTraceElement actual = mapper.readValue(s, StackTraceElement.class);
-        Assert.assertEquals(expected, actual);
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/ConcurrentLoggingWithJsonLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/ConcurrentLoggingWithJsonLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/ConcurrentLoggingWithJsonLayoutTest.java
deleted file mode 100644
index 0e4ad52..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/ConcurrentLoggingWithJsonLayoutTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.layout;
-
-import java.io.File;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.junit.LoggerContextRule;
-import org.junit.AfterClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import static org.hamcrest.CoreMatchers.*;
-
-import static org.junit.Assert.*;
-
-/**
- * Test for LOG4J2-1769.
- *
- * @since 2.8
- */
-public class ConcurrentLoggingWithJsonLayoutTest {
-    @ClassRule
-    public static LoggerContextRule context = new LoggerContextRule("log4j2-json-layout.xml");
-    private static final String PATH = "target/test-json-layout.log";
-
-    @AfterClass
-    public static void after() {
-        new File(PATH).delete();
-    }
-
-    @Test
-    public void testConcurrentLogging() throws Throwable {
-        final Logger log = context.getLogger(ConcurrentLoggingWithJsonLayoutTest.class);
-        final Set<Thread> threads = Collections.synchronizedSet(new HashSet<Thread>());
-        final List<Throwable> thrown = Collections.synchronizedList(new ArrayList<Throwable>());
-
-        for (int x = 0; x < Runtime.getRuntime().availableProcessors() * 2; x++) {
-            final Thread t = new LoggingThread(threads, log);
-            threads.add(t);
-
-            // Appender is configured with ignoreExceptions="false";
-            // any exceptions are propagated to the caller, so we can catch them here.
-            t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
-                @Override
-                public void uncaughtException(final Thread t, final Throwable e) {
-                    thrown.add(e);
-                }
-            });
-            t.start();
-        }
-
-        while (!threads.isEmpty()) {
-            log.info("not done going to sleep...");
-            Thread.sleep(10);
-        }
-
-        // if any error occurred, fail this test
-        if (!thrown.isEmpty()) {
-            throw thrown.get(0);
-        }
-
-        // simple test to ensure content is not corrupted
-        if (new File(PATH).exists()) {
-            final List<String> lines = Files.readAllLines(new File(PATH).toPath(), Charset.defaultCharset());
-            for (final String line : lines) {
-                assertThat(line, startsWith("{\"thread\":"));
-                assertThat(line, endsWith("\"threadPriority\":5}"));
-            }
-        }
-    }
-
-    private class LoggingThread extends Thread {
-        private final Set<Thread> threads;
-        private final Logger log;
-
-        LoggingThread(final Set<Thread> threads, final Logger log) {
-            this.threads = threads;
-            this.log = log;
-        }
-
-        @Override
-        public void run() {
-            log.info(threads.size());
-            try {
-                for (int i = 0; i < 64; i++) {
-                    log.info("First message.");
-                    log.info("Second message.");
-                }
-            } finally {
-                threads.remove(this);
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/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
deleted file mode 100644
index dba5cf3..0000000
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.layout;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.ThreadContext;
-import org.apache.logging.log4j.categories.Layouts;
-import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.BasicConfigurationFactory;
-import org.apache.logging.log4j.core.Logger;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.config.Configuration;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.apache.logging.log4j.core.impl.Log4jLogEvent;
-import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
-import org.apache.logging.log4j.core.lookup.JavaLookup;
-import org.apache.logging.log4j.core.util.KeyValuePair;
-import org.apache.logging.log4j.message.ObjectMessage;
-import org.apache.logging.log4j.message.SimpleMessage;
-import org.apache.logging.log4j.spi.AbstractLogger;
-import org.apache.logging.log4j.test.appender.ListAppender;
-import org.apache.logging.log4j.util.Strings;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-/**
- * Tests the JsonLayout class.
- */
-@Category(Layouts.Json.class)
-public class JsonLayoutTest {
-    static ConfigurationFactory cf = new BasicConfigurationFactory();
-
-    private static final String DQUOTE = "\"";
-
-    @AfterClass
-    public static void cleanupClass() {
-        ConfigurationFactory.removeConfigurationFactory(cf);
-        ThreadContext.clearAll();
-    }
-
-    @BeforeClass
-    public static void setupClass() {
-        ThreadContext.clearAll();
-        ConfigurationFactory.setConfigurationFactory(cf);
-        final LoggerContext ctx = LoggerContext.getContext();
-        ctx.reconfigure();
-    }
-
-    LoggerContext ctx = LoggerContext.getContext();
-
-    Logger rootLogger = this.ctx.getRootLogger();
-
-    private void checkAt(final String expected, final int lineIndex, final List<String> list) {
-        final String trimedLine = list.get(lineIndex).trim();
-        assertTrue("Incorrect line index " + lineIndex + ": " + Strings.dquote(trimedLine), trimedLine.equals(expected));
-    }
-
-    private void checkContains(final String expected, final List<String> list) {
-        for (final String string : list) {
-            final String trimedLine = string.trim();
-            if (trimedLine.equals(expected)) {
-                return;
-            }
-        }
-        Assert.fail("Cannot find " + expected + " in " + list);
-    }
-
-    private void checkMapEntry(final String key, final String value, final boolean compact, final String str,
-            final boolean contextMapAslist) {
-        this.toPropertySeparator(compact);
-        if (contextMapAslist) {
-            // {"key":"KEY", "value":"VALUE"}
-            final String expected = String.format("{\"key\":\"%s\",\"value\":\"%s\"}", key, value);
-            assertTrue("Cannot find contextMapAslist " + expected + " in " + str, str.contains(expected));
-        } else {
-            // "KEY":"VALUE"
-            final String expected = String.format("\"%s\":\"%s\"", key, value);
-            assertTrue("Cannot find contextMap " + expected + " in " + str, str.contains(expected));
-        }
-    }
-
-    private void checkProperty(final String key, final String value, final boolean compact, final String str) {
-        final String propSep = this.toPropertySeparator(compact);
-        // {"key":"MDC.B","value":"B_Value"}
-        final String expected = String.format("\"%s\"%s\"%s\"", key, propSep, value);
-        assertTrue("Cannot find " + expected + " in " + str, str.contains(expected));
-    }
-
-    private void checkPropertyName(final String name, final boolean compact, final String str) {
-        final String propSep = this.toPropertySeparator(compact);
-        assertTrue(str, str.contains(DQUOTE + name + DQUOTE + propSep));
-    }
-
-    private void checkPropertyNameAbsent(final String name, final boolean compact, final String str) {
-        final String propSep = this.toPropertySeparator(compact);
-        assertFalse(str, str.contains(DQUOTE + name + DQUOTE + propSep));
-    }
-
-    private void testAllFeatures(final boolean locationInfo, final boolean compact, final boolean eventEol,
-            final boolean includeContext, final boolean contextMapAslist, final boolean includeStacktrace)
-            throws Exception {
-        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
-        // @formatter:off
-        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
-                .setLocationInfo(locationInfo)
-                .setProperties(includeContext)
-                .setPropertiesAsList(contextMapAslist)
-                .setComplete(false)
-                .setCompact(compact)
-                .setEventEol(eventEol)
-                .setCharset(StandardCharsets.UTF_8)
-                .setIncludeStacktrace(includeStacktrace)
-                .build();
-        // @formatter:off
-        final String str = layout.toSerializable(expected);
-        this.toPropertySeparator(compact);
-        // Just check for \n since \r might or might not be there.
-        assertEquals(str, !compact || eventEol, str.contains("\n"));
-        assertEquals(str, locationInfo, str.contains("source"));
-        assertEquals(str, includeContext, str.contains("contextMap"));
-        final Log4jLogEvent actual = new Log4jJsonObjectMapper(contextMapAslist, includeStacktrace, false, false).readValue(str, Log4jLogEvent.class);
-        LogEventFixtures.assertEqualLogEvents(expected, actual, locationInfo, includeContext, includeStacktrace);
-        if (includeContext) {
-            this.checkMapEntry("MDC.A", "A_Value", compact, str, contextMapAslist);
-            this.checkMapEntry("MDC.B", "B_Value", compact, str, contextMapAslist);
-        }
-        //
-        assertNull(actual.getThrown());
-        // make sure the names we want are used
-        this.checkPropertyName("instant", compact, str);
-        this.checkPropertyName("thread", compact, str); // and not threadName
-        this.checkPropertyName("level", compact, str);
-        this.checkPropertyName("loggerName", compact, str);
-        this.checkPropertyName("marker", compact, str);
-        this.checkPropertyName("name", compact, str);
-        this.checkPropertyName("parents", compact, str);
-        this.checkPropertyName("message", compact, str);
-        this.checkPropertyName("thrown", compact, str);
-        this.checkPropertyName("cause", compact, str);
-        this.checkPropertyName("commonElementCount", compact, str);
-        this.checkPropertyName("localizedMessage", compact, str);
-        if (includeStacktrace) {
-            this.checkPropertyName("extendedStackTrace", compact, str);
-            this.checkPropertyName("class", compact, str);
-            this.checkPropertyName("method", compact, str);
-            this.checkPropertyName("file", compact, str);
-            this.checkPropertyName("line", compact, str);
-            this.checkPropertyName("exact", compact, str);
-            this.checkPropertyName("location", compact, str);
-            this.checkPropertyName("version", compact, str);
-        } else {
-            this.checkPropertyNameAbsent("extendedStackTrace", compact, str);
-        }
-        this.checkPropertyName("suppressed", compact, str);
-        this.checkPropertyName("loggerFqcn", compact, str);
-        this.checkPropertyName("endOfBatch", compact, str);
-        if (includeContext) {
-            this.checkPropertyName("contextMap", compact, str);
-        } else {
-            this.checkPropertyNameAbsent("contextMap", compact, str);
-        }
-        this.checkPropertyName("contextStack", compact, str);
-        if (locationInfo) {
-            this.checkPropertyName("source", compact, str);
-        } else {
-            this.checkPropertyNameAbsent("source", compact, str);
-        }
-        // check some attrs
-        this.checkProperty("loggerFqcn", "f.q.c.n", compact, str);
-        this.checkProperty("loggerName", "a.B", compact, str);
-    }
-
-    @Test
-    public void testContentType() {
-        final AbstractJacksonLayout layout = JsonLayout.createDefaultLayout();
-        assertEquals("application/json; charset=UTF-8", layout.getContentType());
-    }
-
-    @Test
-    public void testDefaultCharset() {
-        final AbstractJacksonLayout layout = JsonLayout.createDefaultLayout();
-        assertEquals(StandardCharsets.UTF_8, layout.getCharset());
-    }
-
-    @Test
-    public void testEscapeLayout() throws Exception {
-        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
-        for (final Appender appender : appenders.values()) {
-            this.rootLogger.removeAppender(appender);
-        }
-        final Configuration configuration = rootLogger.getContext().getConfiguration();
-        // set up appender
-        final boolean propertiesAsList = false;
-        // @formatter:off
-        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
-                .setConfiguration(configuration)
-                .setLocationInfo(true)
-                .setProperties(true)
-                .setPropertiesAsList(propertiesAsList)
-                .setComplete(true)
-                .setCompact(false)
-                .setEventEol(false)
-                .setIncludeStacktrace(true)
-                .build();
-        // @formatter:on
-        final ListAppender appender = new ListAppender("List", null, layout, true, false);
-        appender.start();
-
-        // set appender on root and set level to debug
-        this.rootLogger.addAppender(appender);
-        this.rootLogger.setLevel(Level.DEBUG);
-
-        // output starting message
-        this.rootLogger.debug("Here is a quote ' and then a double quote \"");
-
-        appender.stop();
-
-        final List<String> list = appender.getMessages();
-
-        this.checkAt("[", 0, list);
-        this.checkAt("{", 1, list);
-        this.checkContains("\"level\" : \"DEBUG\",", list);
-        this.checkContains("\"message\" : \"Here is a quote ' and then a double quote \\\"\",", list);
-        this.checkContains("\"loggerFqcn\" : \"" + AbstractLogger.class.getName() + "\",", list);
-        for (final Appender app : appenders.values()) {
-            this.rootLogger.addAppender(app);
-        }
-    }
-
-    /**
-     * Test case for MDC conversion pattern.
-     */
-    @Test
-    public void testLayout() throws Exception {
-        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
-        for (final Appender appender : appenders.values()) {
-            this.rootLogger.removeAppender(appender);
-        }
-        final Configuration configuration = rootLogger.getContext().getConfiguration();
-        // set up appender
-        // Use [[ and ]] to test header and footer (instead of [ and ])
-        final boolean propertiesAsList = false;
-        // @formatter:off
-        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
-                .setConfiguration(configuration)
-                .setLocationInfo(true)
-                .setProperties(true)
-                .setPropertiesAsList(propertiesAsList)
-                .setComplete(true)
-                .setCompact(false)
-                .setEventEol(false)
-                .setHeader("[[".getBytes(Charset.defaultCharset()))
-                .setFooter("]]".getBytes(Charset.defaultCharset()))
-                .setIncludeStacktrace(true)
-                .build();
-        // @formatter:on
-        final ListAppender appender = new ListAppender("List", null, layout, true, false);
-        appender.start();
-
-        // set appender on root and set level to debug
-        this.rootLogger.addAppender(appender);
-        this.rootLogger.setLevel(Level.DEBUG);
-
-        // output starting message
-        this.rootLogger.debug("starting mdc pattern test");
-
-        this.rootLogger.debug("empty mdc");
-
-        ThreadContext.put("key1", "value1");
-        ThreadContext.put("key2", "value2");
-
-        this.rootLogger.debug("filled mdc");
-
-        ThreadContext.remove("key1");
-        ThreadContext.remove("key2");
-
-        this.rootLogger.error("finished mdc pattern test", new NullPointerException("test"));
-
-        appender.stop();
-
-        final List<String> list = appender.getMessages();
-
-        this.checkAt("[[", 0, list);
-        this.checkAt("{", 1, list);
-        this.checkContains("\"loggerFqcn\" : \"" + AbstractLogger.class.getName() + "\",", list);
-        this.checkContains("\"level\" : \"DEBUG\",", list);
-        this.checkContains("\"message\" : \"starting mdc pattern test\",", list);
-        for (final Appender app : appenders.values()) {
-            this.rootLogger.addAppender(app);
-        }
-    }
-
-    @Test
-    public void testLayoutLoggerName() throws Exception {
-        final boolean propertiesAsList = false;
-        // @formatter:off
-        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
-                .setLocationInfo(false)
-                .setProperties(false)
-                .setPropertiesAsList(propertiesAsList)
-                .setComplete(false)
-                .setCompact(true)
-                .setEventEol(false)
-                .setCharset(StandardCharsets.UTF_8)
-                .setIncludeStacktrace(true)
-                .build();
-        // @formatter:on
-        // @formatter:off
-        final Log4jLogEvent expected = Log4jLogEvent.newBuilder()
-                .setLoggerName("a.B")
-                .setLoggerFqcn("f.q.c.n")
-                .setLevel(Level.DEBUG)
-                .setMessage(new SimpleMessage("M"))
-                .setThreadName("threadName")
-                .setTimeMillis(1).build();
-        // @formatter:on
-        final String str = layout.toSerializable(expected);
-        assertTrue(str, str.contains("\"loggerName\":\"a.B\""));
-        final Log4jLogEvent actual = new Log4jJsonObjectMapper(propertiesAsList, true, false, false).readValue(str, Log4jLogEvent.class);
-        assertEquals(expected.getLoggerName(), actual.getLoggerName());
-        assertEquals(expected, actual);
-    }
-
-    @Test
-    public void testAdditionalFields() throws Exception {
-        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
-                .setLocationInfo(false)
-                .setProperties(false)
-                .setComplete(false)
-                .setCompact(true)
-                .setEventEol(false)
-                .setIncludeStacktrace(false)
-                .setAdditionalFields(new KeyValuePair[] {
-                    new KeyValuePair("KEY1", "VALUE1"),
-                    new KeyValuePair("KEY2", "${java:runtime}"), })
-                .setCharset(StandardCharsets.UTF_8)
-                .setConfiguration(ctx.getConfiguration())
-                .build();
-        final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
-        assertTrue(str, str.contains("\"KEY1\":\"VALUE1\""));
-        assertTrue(str, str.contains("\"KEY2\":\"" + new JavaLookup().getRuntime() + "\""));
-    }
-
-    @Test
-    public void testLocationOffCompactOffMdcOff() throws Exception {
-        this.testAllFeatures(false, false, false, false, false, true);
-    }
-
-    @Test
-    public void testLocationOnCompactOnMdcOn() throws Exception {
-        this.testAllFeatures(true, true, false, true, false, true);
-    }
-
-    @Test
-    public void testLocationOnCompactOnEventEolOnMdcOn() throws Exception {
-        this.testAllFeatures(true, true, true, true, false, true);
-    }
-
-    @Test
-    public void testLocationOnCompactOnEventEolOnMdcOnMdcAsList() throws Exception {
-        this.testAllFeatures(true, true, true, true, true, true);
-    }
-
-    @Test
-    public void testExcludeStacktrace() throws Exception {
-        this.testAllFeatures(false, false, false, false, false, false);
-    }
-
-    @Test
-    public void testStacktraceAsString() throws Exception {
-        final String str = prepareJSONForStacktraceTests(true);
-        assertTrue(str, str.contains("\"extendedStackTrace\":\"java.lang.NullPointerException"));
-    }
-
-    @Test
-    public void testStacktraceAsNonString() throws Exception {
-        final String str = prepareJSONForStacktraceTests(false);
-        assertTrue(str, str.contains("\"extendedStackTrace\":["));
-    }
-
-    private String prepareJSONForStacktraceTests(final boolean stacktraceAsString) {
-        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
-        // @formatter:off
-        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
-                .setCompact(true)
-                .setIncludeStacktrace(true)
-                .setStacktraceAsString(stacktraceAsString)
-                .build();
-        // @formatter:off
-        return layout.toSerializable(expected);
-    }
-    
-    @Test
-    public void testObjectMessageAsJsonString() {
-    		final String str = prepareJSONForObjectMessageAsJsonObjectTests(1234, false);
-		assertTrue(str, str.contains("\"message\":\"" + this.getClass().getCanonicalName() + "$TestClass@"));
-    }
-    
-    @Test
-    public void testObjectMessageAsJsonObject() {
-    		final String str = prepareJSONForObjectMessageAsJsonObjectTests(1234, true);
-    		assertTrue(str, str.contains("\"message\":{\"value\":1234}"));
-    }
-    
-    private String prepareJSONForObjectMessageAsJsonObjectTests(final int value, final boolean objectMessageAsJsonObject) {
-    	final TestClass testClass = new TestClass();
-		testClass.setValue(value);
-		// @formatter:off
-		final Log4jLogEvent expected = Log4jLogEvent.newBuilder()
-            .setLoggerName("a.B")
-            .setLoggerFqcn("f.q.c.n")
-            .setLevel(Level.DEBUG)
-            .setMessage(new ObjectMessage(testClass))
-            .setThreadName("threadName")
-            .setTimeMillis(1).build();
-        // @formatter:off
-		final AbstractJacksonLayout layout = JsonLayout.newBuilder()
-				.setCompact(true)
-				.setObjectMessageAsJsonObject(objectMessageAsJsonObject)
-				.build();
-        // @formatter:off
-        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 ? ":" : " : ";
-    }
-    
-	private static class TestClass {
-		private int value;
-
-		public int getValue() {
-			return value;
-		}
-
-		public void setValue(int value) {
-			this.value = value;
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/LogEventFixtures.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/LogEventFixtures.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/LogEventFixtures.java
index 0bdaaca..4e85eb7 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/LogEventFixtures.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/LogEventFixtures.java
@@ -35,12 +35,12 @@ import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.spi.DefaultThreadContextStack;
 import org.apache.logging.log4j.util.StringMap;
 
-class LogEventFixtures {
+public class LogEventFixtures {
 
     /**
      * @return a log event that uses all the bells and whistles, features, nooks and crannies
      */
-    static Log4jLogEvent createLogEvent() {
+    public static Log4jLogEvent createLogEvent() {
         final Marker cMarker = MarkerManager.getMarker("Marker1");
         final Marker pMarker1 = MarkerManager.getMarker("ParentMarker1");
         final Marker pMarker2 = MarkerManager.getMarker("ParentMarker2");
@@ -84,7 +84,7 @@ class LogEventFixtures {
     }
 
     @SuppressWarnings("deprecation")
-    static void assertEqualLogEvents(final LogEvent expected, final LogEvent actual, final boolean includeSource,
+    public static void assertEqualLogEvents(final LogEvent expected, final LogEvent actual, final boolean includeSource,
             final boolean includeContext, final boolean includeStacktrace) {
         assertEquals(expected.getClass(), actual.getClass());
         assertEquals(includeContext ? expected.getContextData() : ContextDataFactory.createContextData(), actual.getContextData());


[06/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based layouts to their own modules: JSON, XML, and YAML.

Posted by gg...@apache.org.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonLayout.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonLayout.java b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonLayout.java
new file mode 100644
index 0000000..224cfb4
--- /dev/null
+++ b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/layout/JsonLayout.java
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.json.layout;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+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.PluginBuilderAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.apache.logging.log4j.jackson.AbstractJacksonLayout;
+import org.apache.logging.log4j.jackson.XmlConstants;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonRootName;
+import com.fasterxml.jackson.annotation.JsonUnwrapped;
+
+/**
+ * Appends a series of JSON events as strings serialized as bytes.
+ *
+ * <h3>Complete well-formed JSON vs. fragment JSON</h3>
+ * <p>
+ * If you configure {@code complete="true"}, the appender outputs a well-formed JSON document. By default, with
+ * {@code complete="false"}, you should include the output as an <em>external file</em> in a separate file to form a
+ * well-formed JSON document.
+ * </p>
+ * <p>
+ * If {@code complete="false"}, the appender does not write the JSON open array character "[" at the start
+ * of the document, "]" and the end, nor comma "," between records.
+ * </p>
+ * <h3>Encoding</h3>
+ * <p>
+ * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise
+ * events containing non ASCII characters could result in corrupted log files.
+ * </p>
+ * <h3>Pretty vs. compact JSON</h3>
+ * <p>
+ * By default, the JSON layout is not compact (a.k.a. "pretty") with {@code compact="false"}, which means the
+ * appender uses end-of-line characters and indents lines to format the text. If {@code compact="true"}, then no
+ * end-of-line or indentation is used. Message content may contain, of course, escaped end-of-lines.
+ * </p>
+ * <h3>Additional Fields</h3>
+ * <p>
+ * This property allows addition of custom fields into generated JSON.
+ * {@code <JsonLayout><KeyValuePair key="foo" value="bar"/></JsonLayout>} inserts {@code "foo":"bar"} directly
+ * into JSON output. Supports Lookup expressions.
+ * </p>
+ */
+@Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
+public final class JsonLayout extends AbstractJacksonLayout {
+
+    public static class Builder<B extends Builder<B>> extends AbstractJacksonLayout.Builder<B>
+            implements org.apache.logging.log4j.core.util.Builder<JsonLayout> {
+
+        @PluginBuilderAttribute
+        private boolean propertiesAsList;
+
+        @PluginBuilderAttribute
+        private boolean objectMessageAsJsonObject;
+
+        @PluginElement("AdditionalField")
+        private KeyValuePair[] additionalFields;
+
+        public Builder() {
+            super();
+            setCharset(StandardCharsets.UTF_8);
+        }
+
+        @Override
+        public JsonLayout build() {
+            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(), isIncludeNullDelimiter(),
+                    getAdditionalFields(), getObjectMessageAsJsonObject());
+        }
+
+        @Override
+        public KeyValuePair[] getAdditionalFields() {
+            return additionalFields;
+        }
+
+        public boolean getObjectMessageAsJsonObject() {
+            return objectMessageAsJsonObject;
+        }
+
+        public boolean isPropertiesAsList() {
+            return propertiesAsList;
+        }
+
+        @Override
+        public B setAdditionalFields(final KeyValuePair[] additionalFields) {
+            this.additionalFields = additionalFields;
+            return asBuilder();
+        }
+
+        public B setObjectMessageAsJsonObject(final boolean objectMessageAsJsonObject) {
+            this.objectMessageAsJsonObject = objectMessageAsJsonObject;
+            return asBuilder();
+        }
+
+        public B setPropertiesAsList(final boolean propertiesAsList) {
+            this.propertiesAsList = propertiesAsList;
+            return asBuilder();
+        }
+    }
+
+    @JsonRootName(XmlConstants.ELT_EVENT)
+    public static class JsonLogEventWithAdditionalFields extends LogEventWithAdditionalFields {
+
+        public JsonLogEventWithAdditionalFields(final Object logEvent, final Map<String, String> additionalFields) {
+            super(logEvent, additionalFields);
+        }
+
+        @Override
+        @JsonAnyGetter
+        public Map<String, String> getAdditionalFields() {
+            return super.getAdditionalFields();
+        }
+
+        @Override
+        @JsonUnwrapped
+        public Object getLogEvent() {
+            return super.getLogEvent();
+        }
+    }
+
+    private static final String DEFAULT_FOOTER = "]";
+
+    private static final String DEFAULT_HEADER = "[";
+
+
+    static final String CONTENT_TYPE = "application/json";
+
+    /**
+     * Creates a JSON Layout using the default settings. Useful for testing.
+     *
+     * @return A JSON Layout.
+     */
+    public static JsonLayout createDefaultLayout() {
+        return new JsonLayout(new DefaultConfiguration(), false, false, false, false, false, false,
+                DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, null, false);
+    }
+
+    /**
+     * Creates a JSON Layout.
+     * @param config
+     *           The plugin configuration.
+     * @param locationInfo
+     *            If "true", includes the location information in the generated JSON.
+     * @param properties
+     *            If "true", includes the thread context map in the generated JSON.
+     * @param propertiesAsList
+     *            If true, the thread context map is included as a list of map entry objects, where each entry has
+     *            a "key" attribute (whose value is the key) and a "value" attribute (whose value is the value).
+     *            Defaults to false, in which case the thread context map is included as a simple map of key-value
+     *            pairs.
+     * @param complete
+     *            If "true", includes the JSON header and footer, and comma between records.
+     * @param compact
+     *            If "true", does not use end-of-lines and indentation, defaults to "false".
+     * @param eventEol
+     *            If "true", forces an EOL after each log event (even if compact is "true"), defaults to "false". This
+     *            allows one even per line, even in compact mode.
+     * @param headerPattern
+     *            The header pattern, defaults to {@code "["} if null.
+     * @param footerPattern
+     *            The header pattern, defaults to {@code "]"} if null.
+     * @param charset
+     *            The character set to use, if {@code null}, uses "UTF-8".
+     * @param includeStacktrace
+     *            If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true".
+     * @return A JSON Layout.
+     *
+     * @deprecated Use {@link #newBuilder()} instead
+     */
+    @Deprecated
+    public static JsonLayout createLayout(
+            final Configuration config,
+            final boolean locationInfo,
+            final boolean properties,
+            final boolean propertiesAsList,
+            final boolean complete,
+            final boolean compact,
+            final boolean eventEol,
+            final String headerPattern,
+            final String footerPattern,
+            final Charset charset,
+            final boolean includeStacktrace) {
+        final boolean encodeThreadContextAsList = properties && propertiesAsList;
+        return new JsonLayout(config, locationInfo, properties, encodeThreadContextAsList, complete, compact, eventEol,
+                headerPattern, footerPattern, charset, includeStacktrace, false, false, null, false);
+    }
+
+    @PluginBuilderFactory
+    public static <B extends Builder<B>> B newBuilder() {
+        return new Builder<B>().asBuilder();
+    }
+
+    /**
+     * @deprecated Use {@link #newBuilder()} instead
+     */
+    @Deprecated
+    protected 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) {
+        super(config, new JsonJacksonFactory(encodeThreadContextAsList, includeStacktrace, false, 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(),
+                false, null);
+    }
+
+    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 includeNullDelimiter,
+                       final KeyValuePair[] additionalFields, final boolean objectMessageAsJsonObject) {
+        super(config, new JsonJacksonFactory(encodeThreadContextAsList, includeStacktrace, stacktraceAsString, objectMessageAsJsonObject).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(),
+                includeNullDelimiter,
+                additionalFields);
+    }
+
+    @Override
+    protected LogEventWithAdditionalFields createLogEventWithAdditionalFields(final LogEvent event,
+            final Map<String, String> additionalFieldsMap) {
+        return new JsonLogEventWithAdditionalFields(event, additionalFieldsMap);
+    }
+
+    @Override
+    public Map<String, String> getContentFormat() {
+        final Map<String, String> result = new HashMap<>();
+        result.put("version", "2.0");
+        return result;
+    }
+
+    /**
+     * @return The content type.
+     */
+    @Override
+    public String getContentType() {
+        return CONTENT_TYPE + "; charset=" + this.getCharset();
+    }
+
+    /**
+     * Returns appropriate JSON footer.
+     *
+     * @return a byte array containing the footer, closing the JSON array.
+     */
+    @Override
+    public byte[] getFooter() {
+        if (!this.complete) {
+            return null;
+        }
+        final StringBuilder buf = new StringBuilder();
+        buf.append(this.eol);
+        final String str = serializeToString(getFooterSerializer());
+        if (str != null) {
+            buf.append(str);
+        }
+        buf.append(this.eol);
+        return getBytes(buf.toString());
+    }
+
+    /**
+     * Returns appropriate JSON header.
+     *
+     * @return a byte array containing the header, opening the JSON array.
+     */
+    @Override
+    public byte[] getHeader() {
+        if (!this.complete) {
+            return null;
+        }
+        final StringBuilder buf = new StringBuilder();
+        final String str = serializeToString(getHeaderSerializer());
+        if (str != null) {
+            buf.append(str);
+        }
+        buf.append(this.eol);
+        return getBytes(buf.toString());
+    }
+
+    @Override
+    public void toSerializable(final LogEvent event, final Writer writer) throws IOException {
+        if (complete && eventCount > 0) {
+            writer.append(", ");
+        }
+        super.toSerializable(event, writer);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/parser/JsonLogEventParser.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/parser/JsonLogEventParser.java b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/parser/JsonLogEventParser.java
new file mode 100644
index 0000000..28279d1
--- /dev/null
+++ b/log4j-layout-jackson-json/src/main/java/org/apache/logging/log4j/jackson/json/parser/JsonLogEventParser.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.json.parser;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.parser.AbstractJacksonLogEventParser;
+import org.apache.logging.log4j.jackson.json.Log4jJsonObjectMapper;
+
+/**
+ * Parses the output from XmlLayout layout into instances of {@link LogEvent}.
+ */
+public class JsonLogEventParser extends AbstractJacksonLogEventParser {
+
+    public JsonLogEventParser() {
+        super(new Log4jJsonObjectMapper());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/site/manual/index.md
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/site/manual/index.md b/log4j-layout-jackson-json/src/site/manual/index.md
new file mode 100644
index 0000000..6cadb78
--- /dev/null
+++ b/log4j-layout-jackson-json/src/site/manual/index.md
@@ -0,0 +1,33 @@
+<!-- vim: set syn=markdown : -->
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+# Apache Log4j Layout for Jackson JSON module
+
+As of Log4j 3.0.0, the layout based on Jackson JSON has moved from the existing module logj-core to the new modules log4j-layout-jackson-json.
+
+## Requirements
+
+This module was introduced in Log4j 2.11.0 and requires Jackson.
+
+Some features may require optional
+[dependencies](../runtime-dependencies.html). These dependencies are specified in the
+documentation for those features.
+
+Some Log4j features require external dependencies.
+See the [Dependency Tree](dependencies.html#Dependency_Tree)
+for the exact list of JAR files needed for these features.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/site/site.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/site/site.xml b/log4j-layout-jackson-json/src/site/site.xml
new file mode 100644
index 0000000..6d4cddc
--- /dev/null
+++ b/log4j-layout-jackson-json/src/site/site.xml
@@ -0,0 +1,52 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project name="Log4j Core"
+         xmlns="http://maven.apache.org/DECORATION/1.4.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
+  <body>
+    <links>
+      <item name="Apache" href="http://www.apache.org/" />
+      <item name="Logging Services" href="http://logging.apache.org/"/>
+      <item name="Log4j" href="../index.html"/>
+    </links>
+
+    <!-- Component-specific reports -->
+    <menu ref="reports"/>
+
+	<!-- Overall Project Info -->
+    <menu name="Log4j Project Information" img="icon-info-sign">
+      <item name="Dependencies" href="../dependencies.html" />
+      <item name="Dependency Convergence" href="../dependency-convergence.html" />
+      <item name="Dependency Management" href="../dependency-management.html" />
+      <item name="Project Team" href="../team-list.html" />
+      <item name="Mailing Lists" href="../mail-lists.html" />
+      <item name="Issue Tracking" href="../issue-tracking.html" />
+      <item name="Project License" href="../license.html" />
+      <item name="Source Repository" href="../source-repository.html" />
+      <item name="Project Summary" href="../project-summary.html" />
+    </menu>
+
+    <menu name="Log4j Project Reports" img="icon-cog">
+      <item name="Changes Report" href="../changes-report.html" />
+      <item name="JIRA Report" href="../jira-report.html" />
+      <item name="Surefire Report" href="../surefire-report.html" />
+      <item name="RAT Report" href="../rat-report.html" />
+    </menu>
+  </body>
+</project>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/JacksonIssue429MyNamesTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/JacksonIssue429MyNamesTest.java b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/JacksonIssue429MyNamesTest.java
new file mode 100644
index 0000000..acc15c2
--- /dev/null
+++ b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/JacksonIssue429MyNamesTest.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.json;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+@Category(Layouts.Json.class)
+public class JacksonIssue429MyNamesTest {
+
+    @SuppressWarnings("serial")
+    static class MyStackTraceElementDeserializer extends StdScalarDeserializer<StackTraceElement> {
+        private static final long serialVersionUID = 1L;
+
+        public final static MyStackTraceElementDeserializer instance = new MyStackTraceElementDeserializer();
+
+        public MyStackTraceElementDeserializer() {
+            super(StackTraceElement.class);
+        }
+
+        @Override
+        public StackTraceElement deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
+                JsonProcessingException {
+            JsonToken t = jp.getCurrentToken();
+            // Must get an Object
+            if (t == JsonToken.START_OBJECT) {
+                String className = Strings.EMPTY, methodName = Strings.EMPTY, fileName = Strings.EMPTY;
+                int lineNumber = -1;
+
+                while ((t = jp.nextValue()) != JsonToken.END_OBJECT) {
+                    final String propName = jp.getCurrentName();
+                    if ("class".equals(propName)) {
+                        className = jp.getText();
+                    } else if ("file".equals(propName)) {
+                        fileName = jp.getText();
+                    } else if ("line".equals(propName)) {
+                        if (t.isNumeric()) {
+                            lineNumber = jp.getIntValue();
+                        } else {
+                            throw JsonMappingException.from(jp, "Non-numeric token (" + t
+                                    + ") for property 'lineNumber'");
+                        }
+                    } else if ("method".equals(propName)) {
+                        methodName = jp.getText();
+                    } else if ("nativeMethod".equals(propName)) {
+                        // no setter, not passed via constructor: ignore
+                    } else {
+                        handleUnknownProperty(jp, ctxt, _valueClass, propName);
+                    }
+                }
+                return new StackTraceElement(className, methodName, fileName, lineNumber);
+            }
+            throw ctxt.mappingException(_valueClass, t);
+        }
+    }
+
+    static class StackTraceBean {
+        public final static int NUM = 13;
+
+        @JsonProperty("Location")
+        @JsonDeserialize(using = MyStackTraceElementDeserializer.class)
+        private StackTraceElement location;
+    }
+
+    private final static ObjectMapper SHARED_MAPPER = new ObjectMapper();
+
+    private final ObjectMapper MAPPER = objectMapper();
+
+    protected String aposToQuotes(final String json) {
+        return json.replace("'", "\"");
+    }
+
+    protected ObjectMapper objectMapper() {
+        return SHARED_MAPPER;
+    }
+
+    @Test
+    public void testStackTraceElementWithCustom() throws Exception {
+        // first, via bean that contains StackTraceElement
+        final StackTraceBean bean = MAPPER
+                .readValue(
+                        aposToQuotes("{'Location':{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':13}}"),
+                        StackTraceBean.class);
+        Assert.assertNotNull(bean);
+        Assert.assertNotNull(bean.location);
+        Assert.assertEquals(StackTraceBean.NUM, bean.location.getLineNumber());
+
+        // and then directly, iff registered
+        final ObjectMapper mapper = new ObjectMapper();
+        final SimpleModule module = new SimpleModule();
+        module.addDeserializer(StackTraceElement.class, new MyStackTraceElementDeserializer());
+        mapper.registerModule(module);
+
+        final StackTraceElement elem = mapper.readValue(
+                aposToQuotes("{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':13}"),
+                StackTraceElement.class);
+        Assert.assertNotNull(elem);
+        Assert.assertEquals(StackTraceBean.NUM, elem.getLineNumber());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/JacksonIssue429Test.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/JacksonIssue429Test.java b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/JacksonIssue429Test.java
new file mode 100644
index 0000000..93d1d53
--- /dev/null
+++ b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/JacksonIssue429Test.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.json;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+@Category(Layouts.Json.class)
+public class JacksonIssue429Test {
+
+    @SuppressWarnings("serial")
+    static class Jackson429StackTraceElementDeserializer extends StdDeserializer<StackTraceElement> {
+        private static final long serialVersionUID = 1L;
+
+        public Jackson429StackTraceElementDeserializer() {
+            super(StackTraceElement.class);
+        }
+
+        @Override
+        public StackTraceElement deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException,
+                JsonProcessingException {
+            jp.skipChildren();
+            return new StackTraceElement("a", "b", "b", StackTraceBean.NUM);
+        }
+
+    }
+
+    static class StackTraceBean {
+        public final static int NUM = 13;
+
+        @JsonProperty("Location")
+        @JsonDeserialize(using = Jackson429StackTraceElementDeserializer.class)
+        private StackTraceElement location;
+    }
+
+    private final static ObjectMapper SHARED_MAPPER = new ObjectMapper();
+
+    private final ObjectMapper MAPPER = objectMapper();
+
+    protected String aposToQuotes(final String json) {
+        return json.replace("'", "\"");
+    }
+
+    protected ObjectMapper objectMapper() {
+        return SHARED_MAPPER;
+    }
+
+    @Test
+    public void testStackTraceElementWithCustom() throws Exception {
+        // first, via bean that contains StackTraceElement
+        final StackTraceBean bean = MAPPER.readValue(aposToQuotes("{'Location':'foobar'}"), StackTraceBean.class);
+        Assert.assertNotNull(bean);
+        Assert.assertNotNull(bean.location);
+        Assert.assertEquals(StackTraceBean.NUM, bean.location.getLineNumber());
+
+        // and then directly, iff registered
+        final ObjectMapper mapper = new ObjectMapper();
+        final SimpleModule module = new SimpleModule();
+        module.addDeserializer(StackTraceElement.class, new Jackson429StackTraceElementDeserializer());
+        mapper.registerModule(module);
+
+        final StackTraceElement elem = mapper.readValue(
+                aposToQuotes("{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':123}"),
+                StackTraceElement.class);
+        Assert.assertNotNull(elem);
+        Assert.assertEquals(StackTraceBean.NUM, elem.getLineNumber());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/LevelMixInJsonTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/LevelMixInJsonTest.java b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/LevelMixInJsonTest.java
new file mode 100644
index 0000000..7f75148
--- /dev/null
+++ b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/LevelMixInJsonTest.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.json;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.jackson.LevelMixInTest;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Category(Layouts.Json.class)
+public class LevelMixInJsonTest extends LevelMixInTest {
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jJsonObjectMapper(false, true, false, false);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/MarkerMixInJsonTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/MarkerMixInJsonTest.java b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/MarkerMixInJsonTest.java
new file mode 100644
index 0000000..db9588b
--- /dev/null
+++ b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/MarkerMixInJsonTest.java
@@ -0,0 +1,34 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache license, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the license for the specific language governing permissions and
+* limitations under the license.
+*/
+
+package org.apache.logging.log4j.jackson.json;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.jackson.AbstractMarkerMixInTest;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Category(Layouts.Json.class)
+public class MarkerMixInJsonTest extends AbstractMarkerMixInTest {
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jJsonObjectMapper();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/StackTraceElementJsonMixInTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/StackTraceElementJsonMixInTest.java b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/StackTraceElementJsonMixInTest.java
new file mode 100644
index 0000000..fc0b459
--- /dev/null
+++ b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/StackTraceElementJsonMixInTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.json;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.jackson.Log4jStackTraceElementDeserializer;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+@Category(Layouts.Json.class)
+public class StackTraceElementJsonMixInTest {
+
+    protected String aposToQuotes(final String json) {
+        return json.replace("'", "\"");
+    }
+
+    /**
+     * @param mapper
+     * @throws JsonProcessingException
+     * @throws IOException
+     * @throws JsonParseException
+     * @throws JsonMappingException
+     */
+    private void roundtrip(final ObjectMapper mapper) throws JsonProcessingException, IOException, JsonParseException, JsonMappingException {
+        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java", 123);
+        final String s = mapper.writeValueAsString(expected);
+        final StackTraceElement actual = mapper.readValue(s, StackTraceElement.class);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testFromJsonWithLog4jModule() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        final boolean encodeThreadContextAsList = false;
+        final SimpleModule module = new Log4jJsonModule(encodeThreadContextAsList, true, false, false);
+        module.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
+        mapper.registerModule(module);
+        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java", 123);
+        final String s = this.aposToQuotes("{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':123}");
+        final StackTraceElement actual = mapper.readValue(s, StackTraceElement.class);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testFromJsonWithSimpleModule() throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        final SimpleModule module = new SimpleModule();
+        module.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
+        mapper.registerModule(module);
+        final StackTraceElement expected = new StackTraceElement("package.SomeClass", "someMethod", "SomeClass.java", 123);
+        final String s = this.aposToQuotes("{'class':'package.SomeClass','method':'someMethod','file':'SomeClass.java','line':123}");
+        final StackTraceElement actual = mapper.readValue(s, StackTraceElement.class);
+        Assert.assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testLog4jJsonObjectMapper() throws Exception {
+        this.roundtrip(new Log4jJsonObjectMapper());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/ConcurrentLoggingWithJsonLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/ConcurrentLoggingWithJsonLayoutTest.java b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/ConcurrentLoggingWithJsonLayoutTest.java
new file mode 100644
index 0000000..5d6f02d
--- /dev/null
+++ b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/ConcurrentLoggingWithJsonLayoutTest.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.json.layout;
+
+import static org.hamcrest.CoreMatchers.endsWith;
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertThat;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.junit.AfterClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+/**
+ * Test for LOG4J2-1769.
+ *
+ * @since 2.8
+ */
+public class ConcurrentLoggingWithJsonLayoutTest {
+
+    private class LoggingThread extends Thread {
+        private final Set<Thread> threads;
+        private final Logger log;
+
+        LoggingThread(final Set<Thread> threads, final Logger log) {
+            this.threads = threads;
+            this.log = log;
+        }
+
+        @Override
+        public void run() {
+            log.info(threads.size());
+            try {
+                for (int i = 0; i < 64; i++) {
+                    log.info("First message.");
+                    log.info("Second message.");
+                }
+            } finally {
+                threads.remove(this);
+            }
+        }
+    }
+    @ClassRule
+    public static LoggerContextRule context = new LoggerContextRule("log4j2-json-layout.xml");
+
+    private static final String PATH = "target/test-json-layout.log";
+
+    @AfterClass
+    public static void after() {
+        new File(PATH).delete();
+    }
+
+    @Test
+    public void testConcurrentLogging() throws Throwable {
+        final Logger log = context.getLogger(ConcurrentLoggingWithJsonLayoutTest.class);
+        final Set<Thread> threads = Collections.synchronizedSet(new HashSet<Thread>());
+        final List<Throwable> thrown = Collections.synchronizedList(new ArrayList<Throwable>());
+
+        for (int x = 0; x < Runtime.getRuntime().availableProcessors() * 2; x++) {
+            final Thread t = new LoggingThread(threads, log);
+            threads.add(t);
+
+            // Appender is configured with ignoreExceptions="false";
+            // any exceptions are propagated to the caller, so we can catch them here.
+            t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+                @Override
+                public void uncaughtException(final Thread t, final Throwable e) {
+                    thrown.add(e);
+                }
+            });
+            t.start();
+        }
+
+        while (!threads.isEmpty()) {
+            log.info("not done going to sleep...");
+            Thread.sleep(10);
+        }
+
+        // if any error occurred, fail this test
+        if (!thrown.isEmpty()) {
+            throw thrown.get(0);
+        }
+
+        // simple test to ensure content is not corrupted
+        if (new File(PATH).exists()) {
+            final List<String> lines = Files.readAllLines(new File(PATH).toPath(), Charset.defaultCharset());
+            for (final String line : lines) {
+                assertThat(line, startsWith("{\"thread\":"));
+                assertThat(line, endsWith("\"threadPriority\":5}"));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/JsonLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/JsonLayoutTest.java b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/JsonLayoutTest.java
new file mode 100644
index 0000000..f8afb51
--- /dev/null
+++ b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/JsonLayoutTest.java
@@ -0,0 +1,489 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.json.layout;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.categories.Layouts;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.BasicConfigurationFactory;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.layout.LogEventFixtures;
+import org.apache.logging.log4j.core.lookup.JavaLookup;
+import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.apache.logging.log4j.jackson.AbstractJacksonLayout;
+import org.apache.logging.log4j.jackson.json.Log4jJsonObjectMapper;
+import org.apache.logging.log4j.message.ObjectMessage;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.spi.AbstractLogger;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * Tests the JsonLayout class.
+ */
+@Category(Layouts.Json.class)
+public class JsonLayoutTest {
+    private static class TestClass {
+		private int value;
+
+		public int getValue() {
+			return value;
+		}
+
+		public void setValue(final int value) {
+			this.value = value;
+		}
+	}
+
+    static ConfigurationFactory cf = new BasicConfigurationFactory();
+
+    private static final String DQUOTE = "\"";
+
+    @AfterClass
+    public static void cleanupClass() {
+        ConfigurationFactory.removeConfigurationFactory(cf);
+        ThreadContext.clearAll();
+    }
+
+    @BeforeClass
+    public static void setupClass() {
+        ThreadContext.clearAll();
+        ConfigurationFactory.setConfigurationFactory(cf);
+        final LoggerContext ctx = LoggerContext.getContext();
+        ctx.reconfigure();
+    }
+
+    LoggerContext ctx = LoggerContext.getContext();
+
+    Logger rootLogger = this.ctx.getRootLogger();
+
+    private void checkAt(final String expected, final int lineIndex, final List<String> list) {
+        final String trimedLine = list.get(lineIndex).trim();
+        assertTrue("Incorrect line index " + lineIndex + ": " + Strings.dquote(trimedLine), trimedLine.equals(expected));
+    }
+
+    private void checkContains(final String expected, final List<String> list) {
+        for (final String string : list) {
+            final String trimedLine = string.trim();
+            if (trimedLine.equals(expected)) {
+                return;
+            }
+        }
+        Assert.fail("Cannot find " + expected + " in " + list);
+    }
+
+    private void checkMapEntry(final String key, final String value, final boolean compact, final String str,
+            final boolean contextMapAslist) {
+        this.toPropertySeparator(compact);
+        if (contextMapAslist) {
+            // {"key":"KEY", "value":"VALUE"}
+            final String expected = String.format("{\"key\":\"%s\",\"value\":\"%s\"}", key, value);
+            assertTrue("Cannot find contextMapAslist " + expected + " in " + str, str.contains(expected));
+        } else {
+            // "KEY":"VALUE"
+            final String expected = String.format("\"%s\":\"%s\"", key, value);
+            assertTrue("Cannot find contextMap " + expected + " in " + str, str.contains(expected));
+        }
+    }
+
+    private void checkProperty(final String key, final String value, final boolean compact, final String str) {
+        final String propSep = this.toPropertySeparator(compact);
+        // {"key":"MDC.B","value":"B_Value"}
+        final String expected = String.format("\"%s\"%s\"%s\"", key, propSep, value);
+        assertTrue("Cannot find " + expected + " in " + str, str.contains(expected));
+    }
+
+    private void checkPropertyName(final String name, final boolean compact, final String str) {
+        final String propSep = this.toPropertySeparator(compact);
+        assertTrue(str, str.contains(DQUOTE + name + DQUOTE + propSep));
+    }
+
+    private void checkPropertyNameAbsent(final String name, final boolean compact, final String str) {
+        final String propSep = this.toPropertySeparator(compact);
+        assertFalse(str, str.contains(DQUOTE + name + DQUOTE + propSep));
+    }
+
+    private String prepareJsonForObjectMessageAsJsonObjectTests(final int value, final boolean objectMessageAsJsonObject) {
+    	final TestClass testClass = new TestClass();
+		testClass.setValue(value);
+		// @formatter:off
+		final Log4jLogEvent expected = Log4jLogEvent.newBuilder()
+            .setLoggerName("a.B")
+            .setLoggerFqcn("f.q.c.n")
+            .setLevel(Level.DEBUG)
+            .setMessage(new ObjectMessage(testClass))
+            .setThreadName("threadName")
+            .setTimeMillis(1).build();
+        // @formatter:off
+		final AbstractJacksonLayout layout = JsonLayout.newBuilder()
+				.setCompact(true)
+				.setObjectMessageAsJsonObject(objectMessageAsJsonObject)
+				.build();
+        // @formatter:off
+        return layout.toSerializable(expected);
+    }
+
+    private String prepareJsonForStacktraceTests(final boolean stacktraceAsString) {
+        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
+        // @formatter:off
+        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
+                .setCompact(true)
+                .setIncludeStacktrace(true)
+                .setStacktraceAsString(stacktraceAsString)
+                .build();
+        // @formatter:off
+        return layout.toSerializable(expected);
+    }
+
+    @Test
+    public void testAdditionalFields() throws Exception {
+        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
+                .setLocationInfo(false)
+                .setProperties(false)
+                .setComplete(false)
+                .setCompact(true)
+                .setEventEol(false)
+                .setIncludeStacktrace(false)
+                .setAdditionalFields(new KeyValuePair[] {
+                    new KeyValuePair("KEY1", "VALUE1"),
+                    new KeyValuePair("KEY2", "${java:runtime}"), })
+                .setCharset(StandardCharsets.UTF_8)
+                .setConfiguration(ctx.getConfiguration())
+                .build();
+        final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
+        assertTrue(str, str.contains("\"KEY1\":\"VALUE1\""));
+        assertTrue(str, str.contains("\"KEY2\":\"" + new JavaLookup().getRuntime() + "\""));
+    }
+
+    private void testAllFeatures(final boolean locationInfo, final boolean compact, final boolean eventEol,
+            final boolean includeContext, final boolean contextMapAslist, final boolean includeStacktrace)
+            throws Exception {
+        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
+        // @formatter:off
+        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
+                .setLocationInfo(locationInfo)
+                .setProperties(includeContext)
+                .setPropertiesAsList(contextMapAslist)
+                .setComplete(false)
+                .setCompact(compact)
+                .setEventEol(eventEol)
+                .setCharset(StandardCharsets.UTF_8)
+                .setIncludeStacktrace(includeStacktrace)
+                .build();
+        // @formatter:off
+        final String str = layout.toSerializable(expected);
+        this.toPropertySeparator(compact);
+        // Just check for \n since \r might or might not be there.
+        assertEquals(str, !compact || eventEol, str.contains("\n"));
+        assertEquals(str, locationInfo, str.contains("source"));
+        assertEquals(str, includeContext, str.contains("contextMap"));
+        final Log4jLogEvent actual = new Log4jJsonObjectMapper(contextMapAslist, includeStacktrace, false, false).readValue(str, Log4jLogEvent.class);
+        LogEventFixtures.assertEqualLogEvents(expected, actual, locationInfo, includeContext, includeStacktrace);
+        if (includeContext) {
+            this.checkMapEntry("MDC.A", "A_Value", compact, str, contextMapAslist);
+            this.checkMapEntry("MDC.B", "B_Value", compact, str, contextMapAslist);
+        }
+        //
+        assertNull(actual.getThrown());
+        // make sure the names we want are used
+        this.checkPropertyName("instant", compact, str);
+        this.checkPropertyName("thread", compact, str); // and not threadName
+        this.checkPropertyName("level", compact, str);
+        this.checkPropertyName("loggerName", compact, str);
+        this.checkPropertyName("marker", compact, str);
+        this.checkPropertyName("name", compact, str);
+        this.checkPropertyName("parents", compact, str);
+        this.checkPropertyName("message", compact, str);
+        this.checkPropertyName("thrown", compact, str);
+        this.checkPropertyName("cause", compact, str);
+        this.checkPropertyName("commonElementCount", compact, str);
+        this.checkPropertyName("localizedMessage", compact, str);
+        if (includeStacktrace) {
+            this.checkPropertyName("extendedStackTrace", compact, str);
+            this.checkPropertyName("class", compact, str);
+            this.checkPropertyName("method", compact, str);
+            this.checkPropertyName("file", compact, str);
+            this.checkPropertyName("line", compact, str);
+            this.checkPropertyName("exact", compact, str);
+            this.checkPropertyName("location", compact, str);
+            this.checkPropertyName("version", compact, str);
+        } else {
+            this.checkPropertyNameAbsent("extendedStackTrace", compact, str);
+        }
+        this.checkPropertyName("suppressed", compact, str);
+        this.checkPropertyName("loggerFqcn", compact, str);
+        this.checkPropertyName("endOfBatch", compact, str);
+        if (includeContext) {
+            this.checkPropertyName("contextMap", compact, str);
+        } else {
+            this.checkPropertyNameAbsent("contextMap", compact, str);
+        }
+        this.checkPropertyName("contextStack", compact, str);
+        if (locationInfo) {
+            this.checkPropertyName("source", compact, str);
+        } else {
+            this.checkPropertyNameAbsent("source", compact, str);
+        }
+        // check some attrs
+        this.checkProperty("loggerFqcn", "f.q.c.n", compact, str);
+        this.checkProperty("loggerName", "a.B", compact, str);
+    }
+
+    @Test
+    public void testContentType() {
+        final AbstractJacksonLayout layout = JsonLayout.createDefaultLayout();
+        assertEquals("application/json; charset=UTF-8", layout.getContentType());
+    }
+
+    @Test
+    public void testDefaultCharset() {
+        final AbstractJacksonLayout layout = JsonLayout.createDefaultLayout();
+        assertEquals(StandardCharsets.UTF_8, layout.getCharset());
+    }
+
+    @Test
+    public void testEscapeLayout() throws Exception {
+        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
+        for (final Appender appender : appenders.values()) {
+            this.rootLogger.removeAppender(appender);
+        }
+        final Configuration configuration = rootLogger.getContext().getConfiguration();
+        // set up appender
+        final boolean propertiesAsList = false;
+        // @formatter:off
+        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
+                .setConfiguration(configuration)
+                .setLocationInfo(true)
+                .setProperties(true)
+                .setPropertiesAsList(propertiesAsList)
+                .setComplete(true)
+                .setCompact(false)
+                .setEventEol(false)
+                .setIncludeStacktrace(true)
+                .build();
+        // @formatter:on
+        final ListAppender appender = new ListAppender("List", null, layout, true, false);
+        appender.start();
+
+        // set appender on root and set level to debug
+        this.rootLogger.addAppender(appender);
+        this.rootLogger.setLevel(Level.DEBUG);
+
+        // output starting message
+        this.rootLogger.debug("Here is a quote ' and then a double quote \"");
+
+        appender.stop();
+
+        final List<String> list = appender.getMessages();
+
+        this.checkAt("[", 0, list);
+        this.checkAt("{", 1, list);
+        this.checkContains("\"level\" : \"DEBUG\",", list);
+        this.checkContains("\"message\" : \"Here is a quote ' and then a double quote \\\"\",", list);
+        this.checkContains("\"loggerFqcn\" : \"" + AbstractLogger.class.getName() + "\",", list);
+        for (final Appender app : appenders.values()) {
+            this.rootLogger.addAppender(app);
+        }
+    }
+
+    @Test
+    public void testExcludeStacktrace() throws Exception {
+        this.testAllFeatures(false, false, false, false, false, false);
+    }
+
+    @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"));
+    }
+
+    @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 case for MDC conversion pattern.
+     */
+    @Test
+    public void testLayout() throws Exception {
+        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
+        for (final Appender appender : appenders.values()) {
+            this.rootLogger.removeAppender(appender);
+        }
+        final Configuration configuration = rootLogger.getContext().getConfiguration();
+        // set up appender
+        // Use [[ and ]] to test header and footer (instead of [ and ])
+        final boolean propertiesAsList = false;
+        // @formatter:off
+        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
+                .setConfiguration(configuration)
+                .setLocationInfo(true)
+                .setProperties(true)
+                .setPropertiesAsList(propertiesAsList)
+                .setComplete(true)
+                .setCompact(false)
+                .setEventEol(false)
+                .setHeader("[[".getBytes(Charset.defaultCharset()))
+                .setFooter("]]".getBytes(Charset.defaultCharset()))
+                .setIncludeStacktrace(true)
+                .build();
+        // @formatter:on
+        final ListAppender appender = new ListAppender("List", null, layout, true, false);
+        appender.start();
+
+        // set appender on root and set level to debug
+        this.rootLogger.addAppender(appender);
+        this.rootLogger.setLevel(Level.DEBUG);
+
+        // output starting message
+        this.rootLogger.debug("starting mdc pattern test");
+
+        this.rootLogger.debug("empty mdc");
+
+        ThreadContext.put("key1", "value1");
+        ThreadContext.put("key2", "value2");
+
+        this.rootLogger.debug("filled mdc");
+
+        ThreadContext.remove("key1");
+        ThreadContext.remove("key2");
+
+        this.rootLogger.error("finished mdc pattern test", new NullPointerException("test"));
+
+        appender.stop();
+
+        final List<String> list = appender.getMessages();
+
+        this.checkAt("[[", 0, list);
+        this.checkAt("{", 1, list);
+        this.checkContains("\"loggerFqcn\" : \"" + AbstractLogger.class.getName() + "\",", list);
+        this.checkContains("\"level\" : \"DEBUG\",", list);
+        this.checkContains("\"message\" : \"starting mdc pattern test\",", list);
+        for (final Appender app : appenders.values()) {
+            this.rootLogger.addAppender(app);
+        }
+    }
+
+    @Test
+    public void testLayoutLoggerName() throws Exception {
+        final boolean propertiesAsList = false;
+        // @formatter:off
+        final AbstractJacksonLayout layout = JsonLayout.newBuilder()
+                .setLocationInfo(false)
+                .setProperties(false)
+                .setPropertiesAsList(propertiesAsList)
+                .setComplete(false)
+                .setCompact(true)
+                .setEventEol(false)
+                .setCharset(StandardCharsets.UTF_8)
+                .setIncludeStacktrace(true)
+                .build();
+        // @formatter:on
+        // @formatter:off
+        final Log4jLogEvent expected = Log4jLogEvent.newBuilder()
+                .setLoggerName("a.B")
+                .setLoggerFqcn("f.q.c.n")
+                .setLevel(Level.DEBUG)
+                .setMessage(new SimpleMessage("M"))
+                .setThreadName("threadName")
+                .setTimeMillis(1).build();
+        // @formatter:on
+        final String str = layout.toSerializable(expected);
+        assertTrue(str, str.contains("\"loggerName\":\"a.B\""));
+        final Log4jLogEvent actual = new Log4jJsonObjectMapper(propertiesAsList, true, false, false).readValue(str, Log4jLogEvent.class);
+        assertEquals(expected.getLoggerName(), actual.getLoggerName());
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testLocationOffCompactOffMdcOff() throws Exception {
+        this.testAllFeatures(false, false, false, false, false, true);
+    }
+
+    @Test
+    public void testLocationOnCompactOnEventEolOnMdcOn() throws Exception {
+        this.testAllFeatures(true, true, true, true, false, true);
+    }
+
+    @Test
+    public void testLocationOnCompactOnEventEolOnMdcOnMdcAsList() throws Exception {
+        this.testAllFeatures(true, true, true, true, true, true);
+    }
+
+    @Test
+    public void testLocationOnCompactOnMdcOn() throws Exception {
+        this.testAllFeatures(true, true, false, true, false, true);
+    }
+
+    @Test
+    public void testObjectMessageAsJsonObject() {
+    		final String str = prepareJsonForObjectMessageAsJsonObjectTests(1234, true);
+    		assertTrue(str, str.contains("\"message\":{\"value\":1234}"));
+    }
+
+    @Test
+    public void testObjectMessageAsJsonString() {
+    		final String str = prepareJsonForObjectMessageAsJsonObjectTests(1234, false);
+		assertTrue(str, str.contains("\"message\":\"" + this.getClass().getCanonicalName() + "$TestClass@"));
+    }
+
+    @Test
+    public void testStacktraceAsNonString() throws Exception {
+        final String str = prepareJsonForStacktraceTests(false);
+        assertTrue(str, str.contains("\"extendedStackTrace\":["));
+    }
+
+    @Test
+    public void testStacktraceAsString() throws Exception {
+        final String str = prepareJsonForStacktraceTests(true);
+        assertTrue(str, str.contains("\"extendedStackTrace\":\"java.lang.NullPointerException"));
+    }
+
+	private String toPropertySeparator(final boolean compact) {
+        return compact ? ":" : " : ";
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/ThrowableProxyJsonTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/ThrowableProxyJsonTest.java b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/ThrowableProxyJsonTest.java
new file mode 100644
index 0000000..c5b0355
--- /dev/null
+++ b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/layout/ThrowableProxyJsonTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.json.layout;
+
+import java.io.IOException;
+
+import org.apache.logging.log4j.jackson.ThrowableProxyJacksonTest;
+import org.apache.logging.log4j.jackson.json.Log4jJsonObjectMapper;
+import org.junit.Test;
+
+public class ThrowableProxyJsonTest extends ThrowableProxyJacksonTest {
+
+    @Test
+    public void testIoContainerAsJson() throws IOException {
+        testIoContainer(new Log4jJsonObjectMapper());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/parser/JsonLogEventParserTest.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/parser/JsonLogEventParserTest.java b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/parser/JsonLogEventParserTest.java
new file mode 100644
index 0000000..a6b3cc7
--- /dev/null
+++ b/log4j-layout-jackson-json/src/test/java/org/apache/logging/log4j/jackson/json/parser/JsonLogEventParserTest.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.json.parser;
+
+import java.nio.charset.StandardCharsets;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.parser.AbstractLogEventParserTest;
+import org.apache.logging.log4j.core.parser.ParseException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JsonLogEventParserTest extends AbstractLogEventParserTest {
+
+    private static final String JSON = "{\n" +
+            "  \"timeMillis\" : 1493121664118,\n" +
+            "  \"instant\":{\"epochSecond\":1493121664,\"nanoOfSecond\":118000000},\n" +
+            "  \"thread\" : \"main\",\n" +
+            "  \"threadId\" : 1,\n" +
+            "  \"threadPriority\" : 5,\n" +
+            "  \"level\" : \"INFO\",\n" +
+            "  \"loggerName\" : \"HelloWorld\",\n" +
+            "  \"marker\" : {\n" +
+            "    \"name\" : \"child\",\n" +
+            "    \"parents\" : [ {\n" +
+            "      \"name\" : \"parent\",\n" +
+            "      \"parents\" : [ {\n" +
+            "        \"name\" : \"grandparent\"\n" +
+            "      } ]\n" +
+            "    } ]\n" +
+            "  },\n" +
+            "  \"message\" : \"Hello, world!\",\n" +
+            "  \"thrown\" : {\n" +
+            "    \"commonElementCount\" : 0,\n" +
+            "    \"message\" : \"error message\",\n" +
+            "    \"name\" : \"java.lang.RuntimeException\",\n" +
+            "    \"extendedStackTrace\" : [ {\n" +
+            "      \"class\" : \"logtest.Main\",\n" +
+            "      \"method\" : \"main\",\n" +
+            "      \"file\" : \"Main.java\",\n" +
+            "      \"line\" : 29,\n" +
+            "      \"exact\" : true,\n" +
+            "      \"location\" : \"classes/\",\n" +
+            "      \"version\" : \"?\"\n" +
+            "    } ]\n" +
+            "  },\n" +
+            "  \"contextStack\" : [ \"one\", \"two\" ],\n" +
+            "  \"loggerFqcn\" : \"org.apache.logging.log4j.spi.AbstractLogger\",\n" +
+            "  \"endOfBatch\" : false,\n" +
+            "  \"contextMap\" : {\n" +
+            "    \"bar\" : \"BAR\",\n" +
+            "    \"foo\" : \"FOO\"\n" +
+            "  },\n" +
+            "  \"source\" : {\n" +
+            "    \"class\" : \"logtest.Main\",\n" +
+            "    \"method\" : \"main\",\n" +
+            "    \"file\" : \"Main.java\",\n" +
+            "    \"line\" : 29\n" +
+            "  }\n" +
+            "}";
+
+    private JsonLogEventParser parser;
+
+    @Before
+    public void setup() {
+        parser = new JsonLogEventParser();
+    }
+
+    @Test
+    public void testByteArray() throws ParseException {
+        final LogEvent logEvent = parser.parseFrom(JSON.getBytes(StandardCharsets.UTF_8));
+        assertLogEvent(logEvent);
+    }
+
+    @Test
+    public void testByteArrayOffsetLength() throws ParseException {
+        final byte[] bytes = ("abc" + JSON + "def").getBytes(StandardCharsets.UTF_8);
+        final LogEvent logEvent = parser.parseFrom(bytes, 3, bytes.length - 6);
+        assertLogEvent(logEvent);
+    }
+
+    @Test
+    public void testEmptyObject() throws ParseException {
+        parser.parseFrom("{}");
+    }
+
+    @Test
+    public void testString() throws ParseException {
+        final LogEvent logEvent = parser.parseFrom(JSON);
+        assertLogEvent(logEvent);
+    }
+
+    @Test(expected = ParseException.class)
+    public void testStringEmpty() throws ParseException {
+        parser.parseFrom("");
+    }
+
+    @Test
+    public void testStringIgnoreInvalidProperty() throws ParseException {
+        parser.parseFrom("{\"foo\":\"bar\"}");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testStringInvalidJson() throws ParseException {
+        parser.parseFrom("foobar");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testStringJsonArray() throws ParseException {
+        parser.parseFrom("[]");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testStringWrongPropertyType() throws ParseException {
+        parser.parseFrom("{\"threadId\":\"foobar\"}");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-json/src/test/resources/log4j2-json-layout.xml
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-json/src/test/resources/log4j2-json-layout.xml b/log4j-layout-jackson-json/src/test/resources/log4j2-json-layout.xml
new file mode 100644
index 0000000..c7af4e9
--- /dev/null
+++ b/log4j-layout-jackson-json/src/test/resources/log4j2-json-layout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<Configuration status="INFO" packages="">
+  <Appenders>
+    <File name="stdout" ignoreExceptions="false" fileName="target/test-xml-layout.log" append="false">
+      <JsonLayout compact="true" eventEol="true" />
+    </File>
+  </Appenders>
+
+  <Loggers>
+    <Root level="INFO">
+      <AppenderRef ref="stdout" />
+    </Root>
+  </Loggers>
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/Log4jXmlModule.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/Log4jXmlModule.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/Log4jXmlModule.java
new file mode 100644
index 0000000..0980f94
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/Log4jXmlModule.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.core.jackson.SimpleModuleInitializer;
+
+import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+final class Log4jXmlModule extends JacksonXmlModule {
+
+    private static final long serialVersionUID = 1L;
+    private final boolean includeStacktrace;
+    private final boolean stacktraceAsString;
+
+    Log4jXmlModule(final boolean includeStacktrace, final boolean stacktraceAsString) {
+        super();
+        this.includeStacktrace = includeStacktrace;
+        this.stacktraceAsString = stacktraceAsString;
+        // MUST init here.
+        // Calling this from setupModule is too late!
+        new SimpleModuleInitializer().initialize(this, false);
+    }
+
+    @Override
+    public void setupModule(final SetupContext context) {
+        // Calling super is a MUST!
+        super.setupModule(context);
+        new XmlSetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/Log4jXmlObjectMapper.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/Log4jXmlObjectMapper.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/Log4jXmlObjectMapper.java
new file mode 100644
index 0000000..632b83f
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/Log4jXmlObjectMapper.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+
+/**
+ * A Jackson XML {@link ObjectMapper} initialized for Log4j.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class Log4jXmlObjectMapper extends XmlMapper {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Create a new instance using the {@link Log4jXmlModule}.
+     */
+    public Log4jXmlObjectMapper() {
+        this(true, false);
+    }
+
+    /**
+     * Create a new instance using the {@link Log4jXmlModule}.
+     */
+    public Log4jXmlObjectMapper(final boolean includeStacktrace, final boolean stacktraceAsString) {
+        super(new Log4jXmlModule(includeStacktrace, stacktraceAsString));
+        this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlInstantMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlInstantMixIn.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlInstantMixIn.java
new file mode 100644
index 0000000..0e18154
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlInstantMixIn.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.core.jackson.InstantMixIn;
+import org.apache.logging.log4j.core.time.Instant;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+/**
+ * Jackson mix-in for {@link Instant}.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ *
+ * @see Marker
+ */
+abstract class XmlInstantMixIn extends InstantMixIn {
+
+    @JsonCreator
+    protected XmlInstantMixIn(
+    // @formatter:off
+            @JsonProperty(ATTR_EPOCH_SECOND) final long epochSecond,
+            @JsonProperty(ATTR_NANO_OF_SECOND) final int nanoOfSecond)
+    // @formatter:on
+    {
+        super(epochSecond, nanoOfSecond);
+    }
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_EPOCH_SECOND, isAttribute = true)
+    protected abstract long getEpochSecond();
+
+    @Override
+    @JacksonXmlProperty(localName = ATTR_NANO_OF_SECOND, isAttribute = true)
+    protected abstract int getNanoOfSecond();
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0eb5212e/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlLogEventWithContextListMixIn.java
----------------------------------------------------------------------
diff --git a/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlLogEventWithContextListMixIn.java b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlLogEventWithContextListMixIn.java
new file mode 100644
index 0000000..771f955
--- /dev/null
+++ b/log4j-layout-jackson-xml/java/org/apache/logging/log4j/jackson/xml/XmlLogEventWithContextListMixIn.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.jackson.xml;
+
+import org.apache.logging.log4j.core.jackson.AbstractXmlLogEventMixIn;
+import org.apache.logging.log4j.core.jackson.ContextDataAsEntryListDeserializer;
+import org.apache.logging.log4j.core.jackson.ContextDataAsEntryListSerializer;
+import org.apache.logging.log4j.core.jackson.XmlConstants;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+
+/**
+ * <pre>
+ * AbstractLogEventMixIn
+*├─ XmlLogEventMixIn
+*├──── XmlLogEventWithContextListMixIn
+*├──── XmlLogEventWithContextMapMixIn
+*├─ JsonLogEventMixIn
+*├──── JsonLogEventWithContextListMixIn
+*├──── JsonLogEventWithContextMapMixIn
+ * </pre>
+ */
+public abstract class XmlLogEventWithContextListMixIn extends AbstractXmlLogEventMixIn {
+
+    private static final long serialVersionUID = 1L;
+
+    @JacksonXmlProperty(namespace = XmlConstants.XML_NAMESPACE, localName = XmlConstants.ELT_CONTEXT_MAP)
+    @JsonSerialize(using = ContextDataAsEntryListSerializer.class)
+    @JsonDeserialize(using = ContextDataAsEntryListDeserializer.class)
+    @Override
+    public abstract ReadOnlyStringMap getContextData();
+
+}