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 © {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>
+<Marker name="Marker1">
+ <Parents>
+ <Marker name="ParentMarker1">
+ <Parents>
+ <Marker name="GrandMotherMarker"/>
+ <Marker name="GrandFatherMarker"/>
+ </Parents>
+ </Marker>
+ <Marker name="ParentMarker2"/>
+ </Parents>
+</Marker>
+ * </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 <Event>s are written into a XML file; the "Event" object is not the root element, but an element named
+ * <Events> 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 <Event> tag as the root element, so it prints the <Event> tag without any
+ * indentation. To add an indentation to the <Event> 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
+ * </Event> 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 © {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>
+<Marker name="Marker1">
+ <Parents>
+ <Marker name="ParentMarker1">
+ <Parents>
+ <Marker name="GrandMotherMarker"/>
+ <Marker name="GrandFatherMarker"/>
+ </Parents>
+ </Marker>
+ <Marker name="ParentMarker2"/>
+ </Parents>
+</Marker>
+ * </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 <Event>s are written into a XML file; the "Event" object is not the root element, but an element named
+ * <Events> 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 <Event> tag as the root element, so it prints the <Event> tag without any
+ * indentation. To add an indentation to the <Event> 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
+ * </Event> 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>
+<Marker name="Marker1">
+ <Parents>
+ <Marker name="ParentMarker1">
+ <Parents>
+ <Marker name="GrandMotherMarker"/>
+ <Marker name="GrandFatherMarker"/>
+ </Parents>
+ </Marker>
+ <Marker name="ParentMarker2"/>
+ </Parents>
+</Marker>
+ * </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>
+<?xml version="1.0" encoding="UTF-8"?>
+<Events xmlns="http://logging.apache.org/log4j/2.0/events">
+
+ <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">
+ <Instant epochSecond="1515889414" nanoOfSecond="144000000" epochMillisecond="1515889414144" nanoOfMillisecond="0"/>
+ <Message>First Msg tag must be in level 2 after correct indentation</Message>
+ </Event>
+
+ <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">
+ <Instant epochSecond="1515889414" nanoOfSecond="144000000" epochMillisecond="1515889414144" nanoOfMillisecond="0"/>
+ <Message>Second Msg tag must also be in level 2 after correct indentation</Message>
+ </Event>
+</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 © {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>
-<Marker name="Marker1">
- <Parents>
- <Marker name="ParentMarker1">
- <Parents>
- <Marker name="GrandMotherMarker"/>
- <Marker name="GrandFatherMarker"/>
- </Parents>
- </Marker>
- <Marker name="ParentMarker2"/>
- </Parents>
-</Marker>
- * </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 <Event>s are written into a XML file; the "Event" object is not the root element, but an element named
- * <Events> 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 <Event> tag as the root element, so it prints the <Event> tag without any
- * indentation. To add an indentation to the <Event> 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
- * </Event> 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 © {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>
-<?xml version="1.0" encoding="UTF-8"?>
-<Events xmlns="http://logging.apache.org/log4j/2.0/events">
-
- <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">
- <Instant epochSecond="1515889414" nanoOfSecond="144000000" epochMillisecond="1515889414144" nanoOfMillisecond="0"/>
- <Message>First Msg tag must be in level 2 after correct indentation</Message>
- </Event>
-
- <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">
- <Instant epochSecond="1515889414" nanoOfSecond="144000000" epochMillisecond="1515889414144" nanoOfMillisecond="0"/>
- <Message>Second Msg tag must also be in level 2 after correct indentation</Message>
- </Event>
-</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();
+
+}