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.commons.logging.impl; 018 019import static org.slf4j.spi.LocationAwareLogger.DEBUG_INT; 020import static org.slf4j.spi.LocationAwareLogger.ERROR_INT; 021import static org.slf4j.spi.LocationAwareLogger.INFO_INT; 022import static org.slf4j.spi.LocationAwareLogger.TRACE_INT; 023import static org.slf4j.spi.LocationAwareLogger.WARN_INT; 024 025import java.util.concurrent.ConcurrentHashMap; 026import java.util.concurrent.ConcurrentMap; 027 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogConfigurationException; 030import org.apache.commons.logging.LogFactory; 031import org.slf4j.ILoggerFactory; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034import org.slf4j.Marker; 035import org.slf4j.MarkerFactory; 036import org.slf4j.spi.LocationAwareLogger; 037 038/** 039 * Logger factory hardcoded to send everything to SLF4J. 040 * 041 * @since 1.3.0 042 */ 043public final class Slf4jLogFactory extends LogFactory { 044 045 private static final class Slf4jLocationAwareLog implements Log { 046 047 private static final String FQCN = Slf4jLocationAwareLog.class.getName(); 048 049 private final LocationAwareLogger logger; 050 051 public Slf4jLocationAwareLog(final LocationAwareLogger logger) { 052 this.logger = logger; 053 } 054 055 @Override 056 public void debug(final Object message) { 057 log(DEBUG_INT, message, null); 058 } 059 060 @Override 061 public void debug(final Object message, final Throwable t) { 062 log(DEBUG_INT, message, t); 063 } 064 065 @Override 066 public void error(final Object message) { 067 log(ERROR_INT, message, null); 068 } 069 070 @Override 071 public void error(final Object message, final Throwable t) { 072 log(ERROR_INT, message, t); 073 } 074 075 @Override 076 public void fatal(final Object message) { 077 error(message); 078 } 079 080 @Override 081 public void fatal(final Object message, final Throwable t) { 082 error(message, t); 083 } 084 085 @Override 086 public void info(final Object message) { 087 log(INFO_INT, message, null); 088 } 089 090 @Override 091 public void info(final Object message, final Throwable t) { 092 log(INFO_INT, message, t); 093 } 094 095 @Override 096 public boolean isDebugEnabled() { 097 return logger.isDebugEnabled(MARKER); 098 } 099 100 @Override 101 public boolean isErrorEnabled() { 102 return logger.isErrorEnabled(MARKER); 103 } 104 105 @Override 106 public boolean isFatalEnabled() { 107 return isErrorEnabled(); 108 } 109 110 @Override 111 public boolean isInfoEnabled() { 112 return logger.isInfoEnabled(MARKER); 113 } 114 115 @Override 116 public boolean isTraceEnabled() { 117 return logger.isTraceEnabled(MARKER); 118 } 119 120 @Override 121 public boolean isWarnEnabled() { 122 return logger.isWarnEnabled(MARKER); 123 } 124 125 private void log(final int level, final Object message, final Throwable t) { 126 logger.log(MARKER, FQCN, level, String.valueOf(message), EMPTY_OBJECT_ARRAY, t); 127 } 128 129 @Override 130 public void trace(final Object message) { 131 log(TRACE_INT, message, null); 132 } 133 134 @Override 135 public void trace(final Object message, final Throwable t) { 136 log(TRACE_INT, message, t); 137 } 138 139 @Override 140 public void warn(final Object message) { 141 log(WARN_INT, message, null); 142 } 143 144 @Override 145 public void warn(final Object message, final Throwable t) { 146 log(WARN_INT, message, t); 147 } 148 } 149 private static class Slf4jLog implements Log { 150 151 private final Logger logger; 152 153 public Slf4jLog(final Logger logger) { 154 this.logger = logger; 155 } 156 157 @Override 158 public void debug(final Object message) { 159 logger.debug(MARKER, String.valueOf(message)); 160 } 161 162 @Override 163 public void debug(final Object message, final Throwable t) { 164 logger.debug(MARKER, String.valueOf(message), t); 165 } 166 167 @Override 168 public void error(final Object message) { 169 logger.error(MARKER, String.valueOf(message)); 170 } 171 172 @Override 173 public void error(final Object message, final Throwable t) { 174 logger.debug(MARKER, String.valueOf(message), t); 175 } 176 177 @Override 178 public void fatal(final Object message) { 179 error(message); 180 } 181 182 @Override 183 public void fatal(final Object message, final Throwable t) { 184 error(message, t); 185 } 186 187 @Override 188 public void info(final Object message) { 189 logger.info(MARKER, String.valueOf(message)); 190 } 191 192 @Override 193 public void info(final Object message, final Throwable t) { 194 logger.info(MARKER, String.valueOf(message), t); 195 } 196 197 @Override 198 public boolean isDebugEnabled() { 199 return logger.isDebugEnabled(MARKER); 200 } 201 202 @Override 203 public boolean isErrorEnabled() { 204 return logger.isErrorEnabled(MARKER); 205 } 206 207 @Override 208 public boolean isFatalEnabled() { 209 return isErrorEnabled(); 210 } 211 212 @Override 213 public boolean isInfoEnabled() { 214 return logger.isInfoEnabled(MARKER); 215 } 216 217 @Override 218 public boolean isTraceEnabled() { 219 return logger.isTraceEnabled(MARKER); 220 } 221 222 @Override 223 public boolean isWarnEnabled() { 224 return logger.isWarnEnabled(MARKER); 225 } 226 227 @Override 228 public void trace(final Object message) { 229 logger.trace(MARKER, String.valueOf(message)); 230 } 231 232 @Override 233 public void trace(final Object message, final Throwable t) { 234 logger.trace(MARKER, String.valueOf(message), t); 235 } 236 237 @Override 238 public void warn(final Object message) { 239 logger.warn(MARKER, String.valueOf(message)); 240 } 241 242 @Override 243 public void warn(final Object message, final Throwable t) { 244 logger.warn(MARKER, String.valueOf(message), t); 245 } 246 } 247 248 private static final Object[] EMPTY_OBJECT_ARRAY = {}; 249 250 private static final String[] EMPTY_STRING_ARRAY = {}; 251 252 /** 253 * Marker used by all messages coming from Apache Commons Logging. 254 */ 255 private static final Marker MARKER = MarkerFactory.getMarker("COMMONS-LOGGING"); 256 257 /** 258 * Caches Log instances. 259 * <p> 260 * The SLF4J reference implementation (Logback) has a single logger context, so each call to 261 * {@link #getInstance(String)} 262 * should give the same result. 263 * </p> 264 */ 265 private final ConcurrentMap<String, Log> loggers = new ConcurrentHashMap<>(); 266 267 private final ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>(); 268 269 /** 270 * Constructs a new instance. 271 */ 272 public Slf4jLogFactory() { 273 // empty 274 } 275 276 @Override 277 public Object getAttribute(final String name) { 278 return attributes.get(name); 279 } 280 281 @Override 282 public String[] getAttributeNames() { 283 return attributes.keySet().toArray(EMPTY_STRING_ARRAY); 284 } 285 286 @Override 287 public Log getInstance(final Class<?> clazz) throws LogConfigurationException { 288 return getInstance(clazz.getName()); 289 } 290 291 @Override 292 public Log getInstance(final String name) { 293 return loggers.computeIfAbsent(name, n -> { 294 final Logger logger = LoggerFactory.getLogger(n); 295 return logger instanceof LocationAwareLogger ? new Slf4jLocationAwareLog((LocationAwareLogger) logger) : new Slf4jLog( 296 logger); 297 }); 298 } 299 300 /** 301 * This method is supposed to clear all loggers. 302 * <p> 303 * In this implementation it calls a "stop" method if the logger factory supports it. This is the case of 304 * Logback. 305 * </p> 306 */ 307 @Override 308 public void release() { 309 final ILoggerFactory factory = LoggerFactory.getILoggerFactory(); 310 try { 311 factory.getClass().getMethod("stop").invoke(factory); 312 } catch (final ReflectiveOperationException ignored) { 313 // empty 314 } 315 } 316 317 @Override 318 public void removeAttribute(final String name) { 319 attributes.remove(name); 320 } 321 322 @Override 323 public void setAttribute(final String name, final Object value) { 324 if (value != null) { 325 attributes.put(name, value); 326 } else { 327 removeAttribute(name); 328 } 329 } 330}