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.Category;
20  import org.apache.log4j.Level;
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.core.LogEvent;
25  import org.apache.logging.log4j.core.util.Loader;
26  import org.apache.logging.log4j.core.util.Throwables;
27  import org.apache.logging.log4j.spi.StandardLevel;
28  import org.apache.logging.log4j.status.StatusLogger;
29  import org.apache.logging.log4j.util.Strings;
30  
31  import java.lang.reflect.Method;
32  import java.util.Map;
33  import java.util.Set;
34  
35  /**
36   * Converts a Log4j 2 LogEvent into the components needed by a Log4j 1.x LoggingEvent.
37   * This class requires Log4j 2.
38   */
39  public class LogEventAdapter extends LoggingEvent {
40  
41      private static final long JVM_START_TIME = initStartTime();
42  
43      private final LogEvent event;
44  
45      public LogEventAdapter(LogEvent event) {
46          this.event = event;
47      }
48  
49      /**
50       * Returns the time when the application started, in milliseconds
51       * elapsed since 01.01.1970.
52       * @return the time when the JVM started.
53       */
54      public static long getStartTime() {
55          return JVM_START_TIME;
56      }
57  
58      /**
59       * Returns the result of {@code ManagementFactory.getRuntimeMXBean().getStartTime()},
60       * or the current system time if JMX is not available.
61       */
62      private static long initStartTime() {
63          // We'd like to call ManagementFactory.getRuntimeMXBean().getStartTime(),
64          // but Google App Engine throws a java.lang.NoClassDefFoundError
65          // "java.lang.management.ManagementFactory is a restricted class".
66          // The reflection is necessary because without it, Google App Engine
67          // will refuse to initialize this class.
68          try {
69              final Class<?> factoryClass = Loader.loadSystemClass("java.lang.management.ManagementFactory");
70              final Method getRuntimeMXBean = factoryClass.getMethod("getRuntimeMXBean");
71              final Object runtimeMXBean = getRuntimeMXBean.invoke(null);
72  
73              final Class<?> runtimeMXBeanClass = Loader.loadSystemClass("java.lang.management.RuntimeMXBean");
74              final Method getStartTime = runtimeMXBeanClass.getMethod("getStartTime");
75              return (Long) getStartTime.invoke(runtimeMXBean);
76          } catch (final Throwable t) {
77              StatusLogger.getLogger().error("Unable to call ManagementFactory.getRuntimeMXBean().getStartTime(), "
78                      + "using system time for OnStartupTriggeringPolicy", t);
79              // We have little option but to declare "now" as the beginning of time.
80              return System.currentTimeMillis();
81          }
82      }
83  
84      public LogEvent getEvent() {
85          return this.event;
86      }
87  
88      /**
89       * Set the location information for this logging event. The collected
90       * information is cached for future use.
91       */
92      @Override
93      public LocationInfo getLocationInformation() {
94          return new LocationInfo(event.getSource());
95      }
96  
97      /**
98       * Return the level of this event. Use this form instead of directly
99       * accessing the <code>level</code> field.
100      */
101     @Override
102     public Level getLevel() {
103         switch (StandardLevel.getStandardLevel(event.getLevel().intLevel())) {
104             case TRACE:
105                 return Level.TRACE;
106             case DEBUG:
107                 return Level.DEBUG;
108             case INFO:
109                 return Level.INFO;
110             case WARN:
111                 return Level.WARN;
112             case FATAL:
113                 return Level.FATAL;
114             case OFF:
115                 return Level.OFF;
116             case ALL:
117                 return Level.ALL;
118             default:
119                 return Level.ERROR;
120         }
121     }
122 
123     /**
124      * Return the name of the logger. Use this form instead of directly
125      * accessing the <code>categoryName</code> field.
126      */
127     @Override
128     public String getLoggerName() {
129         return event.getLoggerName();
130     }
131 
132     @Override
133     public long getTimeStamp() {
134         return event.getTimeMillis();
135     }
136 
137     /**
138      * Gets the logger of the event.
139      */
140     @Override
141     public Category getLogger() {
142         return Category.getInstance(event.getLoggerName());
143     }
144 
145     /*
146      Return the message for this logging event.
147     */
148     @Override
149     public Object getMessage() {
150         return event.getMessage();
151     }
152 
153     /*
154      * This method returns the NDC for this event.
155      */
156     @Override
157     public String getNDC() {
158         return event.getContextStack().toString();
159     }
160 
161     /*
162      Returns the context corresponding to the <code>key</code> parameter.
163      */
164     @Override
165     public Object getMDC(String key) {
166         if (event.getContextData() != null) {
167             return event.getContextData().getValue(key);
168         }
169         return null;
170     }
171 
172     /**
173      * Obtain a copy of this thread's MDC prior to serialization or
174      * asynchronous logging.
175      */
176     @Override
177     public void getMDCCopy() {
178     }
179 
180     @Override
181     public String getRenderedMessage() {
182         return event.getMessage().getFormattedMessage();
183     }
184 
185     @Override
186     public String getThreadName() {
187         return event.getThreadName();
188     }
189 
190     /**
191      * Returns the throwable information contained within this
192      * event. May be <code>null</code> if there is no such information.
193      *
194      * <p>Note that the {@link Throwable} object contained within a
195      * {@link ThrowableInformation} does not survive serialization.
196      *
197      * @since 1.1
198      */
199     @Override
200     public ThrowableInformation getThrowableInformation() {
201         if (event.getThrown() != null) {
202             return new ThrowableInformation(event.getThrown());
203         }
204         return null;
205     }
206 
207     /**
208      * Return this event's throwable's string[] representaion.
209      */
210     @Override
211     public String[] getThrowableStrRep() {
212         if (event.getThrown() != null) {
213             return Throwables.toStringList(event.getThrown()).toArray(Strings.EMPTY_ARRAY);
214         }
215         return null;
216     }
217 
218     @Override
219     public String getProperty(final String key) {
220         return event.getContextData().getValue(key);
221     }
222 
223     @Override
224     public Set getPropertyKeySet() {
225         return event.getContextData().toMap().keySet();
226     }
227 
228     @Override
229     public Map getProperties() {
230         return event.getContextData().toMap();
231     }
232 }