001/** 002 * Copyright (c) 2004-2011 QOS.ch 003 * All rights reserved. 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining 006 * a copy of this software and associated documentation files (the 007 * "Software"), to deal in the Software without restriction, including 008 * without limitation the rights to use, copy, modify, merge, publish, 009 * distribute, sublicense, and/or sell copies of the Software, and to 010 * permit persons to whom the Software is furnished to do so, subject to 011 * the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be 014 * included in all copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 023 * 024 */ 025package org.slf4j.reload4j; 026 027import static org.slf4j.event.EventConstants.NA_SUBST; 028 029import java.io.Serializable; 030 031import org.apache.log4j.Level; 032import org.apache.log4j.spi.LocationInfo; 033import org.apache.log4j.spi.ThrowableInformation; 034import org.slf4j.Logger; 035import org.slf4j.Marker; 036import org.slf4j.event.DefaultLoggingEvent; 037import org.slf4j.event.LoggingEvent; 038import org.slf4j.event.SubstituteLoggingEvent; 039import org.slf4j.helpers.LegacyAbstractLogger; 040import org.slf4j.helpers.MessageFormatter; 041import org.slf4j.helpers.NormalizedParameters; 042import org.slf4j.helpers.SubstituteLogger; 043import org.slf4j.spi.LocationAwareLogger; 044import org.slf4j.spi.LoggingEventAware; 045import org.slf4j.spi.LoggingEventBuilder; 046 047/** 048 * A wrapper over {@link org.apache.log4j.Logger org.apache.log4j.Logger} 049 * conforming to the {@link Logger} interface. 050 * 051 * <p> 052 * Note that the logging levels mentioned in this class refer to those defined 053 * in the <a href= 054 * "http://logging.apache.org/log4j/docs/api/org/apache/log4j/Level.html"> 055 * <code>org.apache.log4j.Level</code></a> class. 056 * 057 * <p>This class is a copy-and-paste of Log4j12LoggerAdapter from the 058 * slf4j-log4j12 module.</p> 059 * 060 * @author Ceki Gülcü 061 * @since 2.0.0-alpha6 062 */ 063public final class Reload4jLoggerAdapter extends LegacyAbstractLogger implements LocationAwareLogger, LoggingEventAware, Serializable { 064 065 private static final long serialVersionUID = 6989384227325275811L; 066 067 final transient org.apache.log4j.Logger logger; 068 069 final static String FQCN_NOMINAL = org.slf4j.helpers.AbstractLogger.class.getName(); 070 final static String FQCN_SUBSTITUE = FQCN_NOMINAL; 071 final static String FQCN_FLUENT = org.slf4j.spi.DefaultLoggingEventBuilder.class.getName(); 072 073 // WARN: Reload4jLoggerAdapter constructor should have only package access so 074 // that only Reload4jLoggerFactory be able to create one. 075 Reload4jLoggerAdapter(org.apache.log4j.Logger logger) { 076 this.logger = logger; 077 this.name = logger.getName(); 078 } 079 080 /** 081 * Is this logger instance enabled for the TRACE level? 082 * 083 * @return True if this Logger is enabled for level TRACE, false otherwise. 084 */ 085 public boolean isTraceEnabled() { 086 return logger.isTraceEnabled(); 087 } 088 089 /** 090 * Is this logger instance enabled for the DEBUG level? 091 * 092 * @return True if this Logger is enabled for level DEBUG, false otherwise. 093 */ 094 public boolean isDebugEnabled() { 095 return logger.isDebugEnabled(); 096 } 097 098 /** 099 * Is this logger instance enabled for the INFO level? 100 * 101 * @return True if this Logger is enabled for the INFO level, false otherwise. 102 */ 103 public boolean isInfoEnabled() { 104 return logger.isInfoEnabled(); 105 } 106 107 /** 108 * Is this logger instance enabled for the WARN level? 109 * 110 * @return True if this Logger is enabled for the WARN level, false otherwise. 111 */ 112 public boolean isWarnEnabled() { 113 return logger.isEnabledFor(Level.WARN); 114 } 115 116 /** 117 * Is this logger instance enabled for level ERROR? 118 * 119 * @return True if this Logger is enabled for level ERROR, false otherwise. 120 */ 121 public boolean isErrorEnabled() { 122 return logger.isEnabledFor(Level.ERROR); 123 } 124 125 @Override 126 public void log(Marker marker, String callerFQCN, int level, String msg, Object[] arguments, Throwable t) { 127 Level log4jLevel = toLog4jLevel(level); 128 NormalizedParameters np = NormalizedParameters.normalize(msg, arguments, t); 129 String formattedMessage = MessageFormatter.basicArrayFormat(np.getMessage(), np.getArguments()); 130 logger.log(callerFQCN, log4jLevel, formattedMessage, np.getThrowable()); 131 } 132 133 @Override 134 protected void handleNormalizedLoggingCall(org.slf4j.event.Level level, Marker marker, String msg, Object[] arguments, Throwable throwable) { 135 Level log4jLevel = toLog4jLevel(level.toInt()); 136 String formattedMessage = MessageFormatter.basicArrayFormat(msg, arguments); 137 logger.log(getFullyQualifiedCallerName(), log4jLevel, formattedMessage, throwable); 138 } 139 140 /** 141 * Called by {@link SubstituteLogger} or by {@link LoggingEventBuilder} instances 142 * @param event 143 */ 144 public void log(LoggingEvent event) { 145 Level log4jLevel = toLog4jLevel(event.getLevel().toInt()); 146 if (!logger.isEnabledFor(log4jLevel)) 147 return; 148 149 org.apache.log4j.spi.LoggingEvent log4jevent = event2Log4jEvent(event, log4jLevel); 150 logger.callAppenders(log4jevent); 151 152 } 153 154 private org.apache.log4j.spi.LoggingEvent event2Log4jEvent(LoggingEvent event, Level log4jLevel) { 155 156 String formattedMessage = MessageFormatter.basicArrayFormat(event.getMessage(), event.getArgumentArray()); 157 158 LocationInfo locationInfo = null; 159 String fqcn = null; 160 161 if (event instanceof SubstituteLoggingEvent) { 162 locationInfo = new LocationInfo(NA_SUBST, NA_SUBST, NA_SUBST, "0"); 163 fqcn = FQCN_SUBSTITUE; 164 } else { 165 fqcn = FQCN_FLUENT; 166 } 167 168 ThrowableInformation ti = null; 169 Throwable t = event.getThrowable(); 170 if (t != null) 171 ti = new ThrowableInformation(t); 172 173 if(event instanceof DefaultLoggingEvent) { 174 DefaultLoggingEvent defaultLoggingEvent = (DefaultLoggingEvent) event; 175 defaultLoggingEvent.setTimeStamp(System.currentTimeMillis()); 176 } 177 178 org.apache.log4j.spi.LoggingEvent log4jEvent = new org.apache.log4j.spi.LoggingEvent(fqcn, logger, event.getTimeStamp(), log4jLevel, formattedMessage, 179 event.getThreadName(), ti, null, locationInfo, null); 180 181 return log4jEvent; 182 } 183 184 private Level toLog4jLevel(int slf4jLevelInt) { 185 Level log4jLevel; 186 switch (slf4jLevelInt) { 187 case LocationAwareLogger.TRACE_INT: 188 log4jLevel = Level.TRACE; 189 break; 190 case LocationAwareLogger.DEBUG_INT: 191 log4jLevel = Level.DEBUG; 192 break; 193 case LocationAwareLogger.INFO_INT: 194 log4jLevel = Level.INFO; 195 break; 196 case LocationAwareLogger.WARN_INT: 197 log4jLevel = Level.WARN; 198 break; 199 case LocationAwareLogger.ERROR_INT: 200 log4jLevel = Level.ERROR; 201 break; 202 default: 203 throw new IllegalStateException("Level number " + slf4jLevelInt + " is not recognized."); 204 } 205 return log4jLevel; 206 } 207 208 @Override 209 protected String getFullyQualifiedCallerName() { 210 return FQCN_NOMINAL; 211 } 212 213}