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.LoggingEvent; 037import org.slf4j.event.SubstituteLoggingEvent; 038import org.slf4j.helpers.LegacyAbstractLogger; 039import org.slf4j.helpers.MessageFormatter; 040import org.slf4j.helpers.NormalizedParameters; 041import org.slf4j.helpers.SubstituteLogger; 042import org.slf4j.spi.LocationAwareLogger; 043import org.slf4j.spi.LoggingEventAware; 044import org.slf4j.spi.LoggingEventBuilder; 045 046/** 047 * A wrapper over {@link org.apache.log4j.Logger org.apache.log4j.Logger} 048 * conforming to the {@link Logger} interface. 049 * 050 * <p> 051 * Note that the logging levels mentioned in this class refer to those defined 052 * in the <a href= 053 * "http://logging.apache.org/log4j/docs/api/org/apache/log4j/Level.html"> 054 * <code>org.apache.log4j.Level</code></a> class. 055 * 056 * <p>This class is a copy-and-paste of Log4j12LoggerAdapter from the 057 * slf4j-log4j12 module.</p> 058 * 059 * @author Ceki Gülcü 060 * @since 2.0.0-alpha6 061 */ 062public final class Reload4jLoggerAdapter extends LegacyAbstractLogger implements LocationAwareLogger, LoggingEventAware, Serializable { 063 064 private static final long serialVersionUID = 6989384227325275811L; 065 066 final transient org.apache.log4j.Logger logger; 067 068 final static String FQCN_NOMINAL = org.slf4j.helpers.AbstractLogger.class.getName(); 069 final static String FQCN_SUBSTITUE = FQCN_NOMINAL; 070 final static String FQCN_FLUENT = org.slf4j.spi.DefaultLoggingEventBuilder.class.getName(); 071 072 // WARN: Reload4jLoggerAdapter constructor should have only package access so 073 // that only Reload4jLoggerFactory be able to create one. 074 Reload4jLoggerAdapter(org.apache.log4j.Logger logger) { 075 this.logger = logger; 076 this.name = logger.getName(); 077 } 078 079 /** 080 * Is this logger instance enabled for the TRACE level? 081 * 082 * @return True if this Logger is enabled for level TRACE, false otherwise. 083 */ 084 public boolean isTraceEnabled() { 085 return logger.isTraceEnabled(); 086 } 087 088 /** 089 * Is this logger instance enabled for the DEBUG level? 090 * 091 * @return True if this Logger is enabled for level DEBUG, false otherwise. 092 */ 093 public boolean isDebugEnabled() { 094 return logger.isDebugEnabled(); 095 } 096 097 /** 098 * Is this logger instance enabled for the INFO level? 099 * 100 * @return True if this Logger is enabled for the INFO level, false otherwise. 101 */ 102 public boolean isInfoEnabled() { 103 return logger.isInfoEnabled(); 104 } 105 106 /** 107 * Is this logger instance enabled for the WARN level? 108 * 109 * @return True if this Logger is enabled for the WARN level, false otherwise. 110 */ 111 public boolean isWarnEnabled() { 112 return logger.isEnabledFor(Level.WARN); 113 } 114 115 /** 116 * Is this logger instance enabled for level ERROR? 117 * 118 * @return True if this Logger is enabled for level ERROR, false otherwise. 119 */ 120 public boolean isErrorEnabled() { 121 return logger.isEnabledFor(Level.ERROR); 122 } 123 124 @Override 125 public void log(Marker marker, String callerFQCN, int level, String msg, Object[] arguments, Throwable t) { 126 Level log4jLevel = toLog4jLevel(level); 127 NormalizedParameters np = NormalizedParameters.normalize(msg, arguments, t); 128 String formattedMessage = MessageFormatter.basicArrayFormat(np.getMessage(), np.getArguments()); 129 logger.log(callerFQCN, log4jLevel, formattedMessage, np.getThrowable()); 130 } 131 132 @Override 133 protected void handleNormalizedLoggingCall(org.slf4j.event.Level level, Marker marker, String msg, Object[] arguments, Throwable throwable) { 134 Level log4jLevel = toLog4jLevel(level.toInt()); 135 String formattedMessage = MessageFormatter.basicArrayFormat(msg, arguments); 136 logger.log(getFullyQualifiedCallerName(), log4jLevel, formattedMessage, throwable); 137 } 138 139 /** 140 * Called by {@link SubstituteLogger} or by {@link LoggingEventBuilder} instances 141 * @param event 142 */ 143 public void log(LoggingEvent event) { 144 Level log4jLevel = toLog4jLevel(event.getLevel().toInt()); 145 if (!logger.isEnabledFor(log4jLevel)) 146 return; 147 148 org.apache.log4j.spi.LoggingEvent log4jevent = event2Log4jEvent(event, log4jLevel); 149 logger.callAppenders(log4jevent); 150 151 } 152 153 private org.apache.log4j.spi.LoggingEvent event2Log4jEvent(LoggingEvent event, Level log4jLevel) { 154 155 String formattedMessage = MessageFormatter.basicArrayFormat(event.getMessage(), event.getArgumentArray()); 156 157 LocationInfo locationInfo = null; 158 String fqcn = null; 159 160 if (event instanceof SubstituteLoggingEvent) { 161 locationInfo = new LocationInfo(NA_SUBST, NA_SUBST, NA_SUBST, "0"); 162 fqcn = FQCN_SUBSTITUE; 163 } else { 164 fqcn = FQCN_FLUENT; 165 } 166 167 ThrowableInformation ti = null; 168 Throwable t = event.getThrowable(); 169 if (t != null) 170 ti = new ThrowableInformation(t); 171 172 org.apache.log4j.spi.LoggingEvent log4jEvent = new org.apache.log4j.spi.LoggingEvent(fqcn, logger, event.getTimeStamp(), log4jLevel, formattedMessage, 173 event.getThreadName(), ti, null, locationInfo, null); 174 175 return log4jEvent; 176 } 177 178 private Level toLog4jLevel(int slf4jLevelInt) { 179 Level log4jLevel; 180 switch (slf4jLevelInt) { 181 case LocationAwareLogger.TRACE_INT: 182 log4jLevel = Level.TRACE; 183 break; 184 case LocationAwareLogger.DEBUG_INT: 185 log4jLevel = Level.DEBUG; 186 break; 187 case LocationAwareLogger.INFO_INT: 188 log4jLevel = Level.INFO; 189 break; 190 case LocationAwareLogger.WARN_INT: 191 log4jLevel = Level.WARN; 192 break; 193 case LocationAwareLogger.ERROR_INT: 194 log4jLevel = Level.ERROR; 195 break; 196 default: 197 throw new IllegalStateException("Level number " + slf4jLevelInt + " is not recognized."); 198 } 199 return log4jLevel; 200 } 201 202 @Override 203 protected String getFullyQualifiedCallerName() { 204 return FQCN_NOMINAL; 205 } 206 207}