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.log4j.bridge;
18  
19  import org.apache.log4j.NDC;
20  import org.apache.log4j.helpers.OptionConverter;
21  import org.apache.log4j.spi.LocationInfo;
22  import org.apache.log4j.spi.LoggingEvent;
23  import org.apache.log4j.spi.ThrowableInformation;
24  import org.apache.logging.log4j.Level;
25  import org.apache.logging.log4j.Marker;
26  import org.apache.logging.log4j.ThreadContext;
27  import org.apache.logging.log4j.core.LogEvent;
28  import org.apache.logging.log4j.core.impl.ThrowableProxy;
29  import org.apache.logging.log4j.core.time.Instant;
30  import org.apache.logging.log4j.core.time.MutableInstant;
31  import org.apache.logging.log4j.message.Message;
32  import org.apache.logging.log4j.message.SimpleMessage;
33  import org.apache.logging.log4j.spi.MutableThreadContextStack;
34  import org.apache.logging.log4j.util.BiConsumer;
35  import org.apache.logging.log4j.util.ReadOnlyStringMap;
36  import org.apache.logging.log4j.util.TriConsumer;
37  
38  import java.util.HashMap;
39  import java.util.Map;
40  import java.util.Objects;
41  
42  /**
43   * Exposes a Log4j 1 logging event as a Log4j 2 LogEvent.
44   */
45  public class LogEventWrapper implements LogEvent {
46  
47      private final LoggingEvent event;
48      private final ContextDataMap contextData;
49      private final MutableThreadContextStack contextStack;
50      private Thread thread;
51  
52      public LogEventWrapper(LoggingEvent event) {
53          this.event = event;
54          this.contextData = new ContextDataMap(event.getProperties());
55          this.contextStack = new MutableThreadContextStack(NDC.cloneStack());
56          this.thread = Objects.equals(event.getThreadName(), Thread.currentThread().getName())
57                  ? Thread.currentThread() : null;
58      }
59  
60      @Override
61      public LogEvent toImmutable() {
62          return this;
63      }
64  
65      @Override
66      public Map<String, String> getContextMap() {
67          return contextData;
68      }
69  
70      @Override
71      public ReadOnlyStringMap getContextData() {
72          return contextData;
73      }
74  
75      @Override
76      public ThreadContext.ContextStack getContextStack() {
77          return contextStack;
78      }
79  
80      @Override
81      public String getLoggerFqcn() {
82          return null;
83      }
84  
85      @Override
86      public Level getLevel() {
87          return OptionConverter.convertLevel(event.getLevel());
88      }
89  
90      @Override
91      public String getLoggerName() {
92          return event.getLoggerName();
93      }
94  
95      @Override
96      public Marker getMarker() {
97          return null;
98      }
99  
100     @Override
101     public Message getMessage() {
102         return new SimpleMessage(event.getRenderedMessage());
103     }
104 
105     @Override
106     public long getTimeMillis() {
107         return event.getTimeStamp();
108     }
109 
110     @Override
111     public Instant getInstant() {
112         MutableInstant mutable = new MutableInstant();
113         mutable.initFromEpochMilli(event.getTimeStamp(), 0);
114         return mutable;
115     }
116 
117     @Override
118     public StackTraceElement getSource() {
119         LocationInfo info = event.getLocationInformation();
120         return new StackTraceElement(info.getClassName(), info.getMethodName(), info.getFileName(),
121                 Integer.parseInt(info.getLineNumber()));
122     }
123 
124     @Override
125     public String getThreadName() {
126         return event.getThreadName();
127     }
128 
129     @Override
130     public long getThreadId() {
131         Thread thread = getThread();
132         return thread != null ? thread.getId() : 0;
133     }
134 
135     @Override
136     public int getThreadPriority() {
137         Thread thread = getThread();
138         return thread != null ? thread.getPriority() : 0;
139     }
140 
141     private Thread getThread() {
142         if (thread == null && event.getThreadName() != null) {
143             for (Thread thread : Thread.getAllStackTraces().keySet()) {
144                 if (thread.getName().equals(event.getThreadName())) {
145                     this.thread = thread;
146                     return thread;
147                 }
148             }
149         }
150         return thread;
151     }
152 
153     @Override
154     public Throwable getThrown() {
155         ThrowableInformation throwableInformation = event.getThrowableInformation();
156         return throwableInformation == null ? null : throwableInformation.getThrowable();
157     }
158 
159     @Override
160     public ThrowableProxy getThrownProxy() {
161         return null;
162     }
163 
164     @Override
165     public boolean isEndOfBatch() {
166         return false;
167     }
168 
169     @Override
170     public boolean isIncludeLocation() {
171         return false;
172     }
173 
174     @Override
175     public void setEndOfBatch(boolean endOfBatch) {
176 
177     }
178 
179     @Override
180     public void setIncludeLocation(boolean locationRequired) {
181 
182     }
183 
184     @Override
185     public long getNanoTime() {
186         return 0;
187     }
188 
189     private static class ContextDataMap extends HashMap<String, String> implements ReadOnlyStringMap {
190 
191         ContextDataMap(Map<String, String> map) {
192             if (map != null) {
193                 super.putAll(map);
194             }
195         }
196 
197         @Override
198         public Map<String, String> toMap() {
199             return this;
200         }
201 
202         @Override
203         public boolean containsKey(String key) {
204             return super.containsKey(key);
205         }
206 
207         @Override
208         public <V> void forEach(BiConsumer<String, ? super V> action) {
209             super.forEach((k,v) -> action.accept(k, (V) v));
210         }
211 
212         @Override
213         public <V, S> void forEach(TriConsumer<String, ? super V, S> action, S state) {
214             super.forEach((k,v) -> action.accept(k, (V) v, state));
215         }
216 
217         @Override
218         public <V> V getValue(String key) {
219             return (V) super.get(key);
220         }
221     }
222 }