View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.jackson;
18  
19  import org.apache.logging.log4j.Level;
20  import org.apache.logging.log4j.Marker;
21  import org.apache.logging.log4j.ThreadContext.ContextStack;
22  import org.apache.logging.log4j.core.LogEvent;
23  import org.apache.logging.log4j.core.impl.ExtendedStackTraceElement;
24  import org.apache.logging.log4j.core.impl.ThrowableProxy;
25  import org.apache.logging.log4j.message.Message;
26  import org.apache.logging.log4j.message.ObjectMessage;
27  
28  import com.fasterxml.jackson.databind.Module.SetupContext;
29  import com.fasterxml.jackson.databind.module.SimpleModule;
30  import org.apache.logging.log4j.core.time.Instant;
31  
32  /**
33   * Initialization utils.
34   * <p>
35   * <em>Consider this class private.</em>
36   * </p>
37   */
38  class Initializers {
39  
40      /**
41       * Used to set up {@link SetupContext} from different {@link SimpleModule}s.
42       */
43      static class SetupContextInitializer {
44  
45          void setupModule(final SetupContext context, final boolean includeStacktrace, final boolean stacktraceAsString) {
46              // JRE classes: we cannot edit those with Jackson annotations
47              context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class);
48              // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not depend on Jackson.
49              context.setMixInAnnotations(Marker.class, MarkerMixIn.class);
50              context.setMixInAnnotations(Level.class, LevelMixIn.class);
51              context.setMixInAnnotations(Instant.class, InstantMixIn.class);
52              context.setMixInAnnotations(LogEvent.class, LogEventWithContextListMixIn.class);
53              // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
54              context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
55              context.setMixInAnnotations(ThrowableProxy.class,
56                      includeStacktrace ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringMixIn.class : ThrowableProxyMixIn.class ) : ThrowableProxyWithoutStacktraceMixIn.class);
57          }
58      }
59  
60      /**
61       * Used to set up {@link SetupContext} from different {@link SimpleModule}s.
62       * Differs from SetupContextInitializer by installing {@code LogEventJsonMixIn} for LogEvents,
63       * not {@code LogEventMixIn}, so it handles ThreadContext serialization differently.
64       */
65      static class SetupContextJsonInitializer {
66  
67          void setupModule(final SetupContext context, final boolean includeStacktrace, final boolean stacktraceAsString) {
68              // JRE classes: we cannot edit those with Jackson annotations
69              context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class);
70              // Log4j API classes: we do not want to edit those with Jackson annotations because the API module should not depend on Jackson.
71              context.setMixInAnnotations(Marker.class, MarkerMixIn.class);
72              context.setMixInAnnotations(Level.class, LevelMixIn.class);
73              context.setMixInAnnotations(Instant.class, InstantMixIn.class);
74              context.setMixInAnnotations(LogEvent.class, LogEventJsonMixIn.class); // different ThreadContext handling
75              // Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
76              context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
77              context.setMixInAnnotations(ThrowableProxy.class,
78                      includeStacktrace ? (stacktraceAsString ? ThrowableProxyWithStacktraceAsStringMixIn.class : ThrowableProxyMixIn.class ) : ThrowableProxyWithoutStacktraceMixIn.class);
79          }
80      }
81  
82      /**
83       * Used to set up {@link SimpleModule} from different {@link SimpleModule} subclasses.
84       */
85      static class SimpleModuleInitializer {
86          void initialize(final SimpleModule simpleModule, final boolean objectMessageAsJsonObject) {
87              // Workaround because mix-ins do not work for classes that already have a built-in deserializer.
88              // See Jackson issue 429.
89              simpleModule.addDeserializer(StackTraceElement.class, new Log4jStackTraceElementDeserializer());
90              simpleModule.addDeserializer(ContextStack.class, new MutableThreadContextStackDeserializer());
91              if (objectMessageAsJsonObject) {
92              	    simpleModule.addSerializer(ObjectMessage.class, new ObjectMessageSerializer());
93              }
94              simpleModule.addSerializer(Message.class, new MessageSerializer());
95          }
96      }
97  
98  }