001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.log4j.bridge; 018 019import org.apache.log4j.Category; 020import org.apache.log4j.Level; 021import org.apache.log4j.spi.LocationInfo; 022import org.apache.log4j.spi.LoggingEvent; 023import org.apache.log4j.spi.ThrowableInformation; 024import org.apache.logging.log4j.core.LogEvent; 025import org.apache.logging.log4j.core.util.Loader; 026import org.apache.logging.log4j.core.util.Throwables; 027import org.apache.logging.log4j.spi.StandardLevel; 028import org.apache.logging.log4j.status.StatusLogger; 029import org.apache.logging.log4j.util.Strings; 030 031import java.lang.reflect.Method; 032import java.util.Map; 033import java.util.Set; 034 035/** 036 * Converts a Log4j 2 LogEvent into the components needed by a Log4j 1.x LoggingEvent. 037 * This class requires Log4j 2. 038 */ 039public class LogEventAdapter extends LoggingEvent { 040 041 private static final long JVM_START_TIME = initStartTime(); 042 043 private final LogEvent event; 044 045 public LogEventAdapter(LogEvent event) { 046 this.event = event; 047 } 048 049 /** 050 * Returns the time when the application started, in milliseconds 051 * elapsed since 01.01.1970. 052 * @return the time when the JVM started. 053 */ 054 public static long getStartTime() { 055 return JVM_START_TIME; 056 } 057 058 /** 059 * Returns the result of {@code ManagementFactory.getRuntimeMXBean().getStartTime()}, 060 * or the current system time if JMX is not available. 061 */ 062 private static long initStartTime() { 063 // We'd like to call ManagementFactory.getRuntimeMXBean().getStartTime(), 064 // but Google App Engine throws a java.lang.NoClassDefFoundError 065 // "java.lang.management.ManagementFactory is a restricted class". 066 // The reflection is necessary because without it, Google App Engine 067 // will refuse to initialize this class. 068 try { 069 final Class<?> factoryClass = Loader.loadSystemClass("java.lang.management.ManagementFactory"); 070 final Method getRuntimeMXBean = factoryClass.getMethod("getRuntimeMXBean"); 071 final Object runtimeMXBean = getRuntimeMXBean.invoke(null); 072 073 final Class<?> runtimeMXBeanClass = Loader.loadSystemClass("java.lang.management.RuntimeMXBean"); 074 final Method getStartTime = runtimeMXBeanClass.getMethod("getStartTime"); 075 return (Long) getStartTime.invoke(runtimeMXBean); 076 } catch (final Throwable t) { 077 StatusLogger.getLogger().error("Unable to call ManagementFactory.getRuntimeMXBean().getStartTime(), " 078 + "using system time for OnStartupTriggeringPolicy", t); 079 // We have little option but to declare "now" as the beginning of time. 080 return System.currentTimeMillis(); 081 } 082 } 083 084 public LogEvent getEvent() { 085 return this.event; 086 } 087 088 /** 089 * Set the location information for this logging event. The collected 090 * information is cached for future use. 091 */ 092 @Override 093 public LocationInfo getLocationInformation() { 094 return new LocationInfo(event.getSource()); 095 } 096 097 /** 098 * Return the level of this event. Use this form instead of directly 099 * 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}