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:19 UTC
[02/12] logging-log4j2 git commit: [LOG4J2-2237] Move Jackson-based
layouts to their own modules: JSON, XML, and YAML.
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;
+ }
+}