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 java.io.IOException; 020import java.util.concurrent.ConcurrentHashMap; 021import java.util.concurrent.ConcurrentMap; 022 023import org.apache.commons.logging.Log; 024import org.apache.commons.logging.LogFactory; 025import org.apache.logging.log4j.Level; 026import org.apache.logging.log4j.LogManager; 027import org.apache.logging.log4j.Marker; 028import org.apache.logging.log4j.MarkerManager; 029import org.apache.logging.log4j.spi.AbstractLoggerAdapter; 030import org.apache.logging.log4j.spi.ExtendedLogger; 031import org.apache.logging.log4j.spi.LoggerAdapter; 032import org.apache.logging.log4j.spi.LoggerContext; 033import org.apache.logging.log4j.util.StackLocatorUtil; 034 035/** 036 * Logger factory hardcoded to send everything to Log4j API. 037 * <p> 038 * Based on the `log4j-jcl` artifact from Apache Logging Services. 039 * </p> 040 * 041 * @since 1.3.0 042 */ 043public final class Log4jApiLogFactory extends LogFactory { 044 045 private static final class Log4j2Log implements Log { 046 047 private static final String FQCN = Log4j2Log.class.getName(); 048 049 private final ExtendedLogger logger; 050 051 public Log4j2Log(final ExtendedLogger logger) { 052 this.logger = logger; 053 } 054 055 @Override 056 public void debug(final Object message) { 057 logIfEnabled(Level.DEBUG, message, null); 058 } 059 060 @Override 061 public void debug(final Object message, final Throwable t) { 062 logIfEnabled(Level.DEBUG, message, t); 063 } 064 065 @Override 066 public void error(final Object message) { 067 logIfEnabled(Level.ERROR, message, null); 068 } 069 070 @Override 071 public void error(final Object message, final Throwable t) { 072 logIfEnabled(Level.ERROR, message, t); 073 } 074 075 @Override 076 public void fatal(final Object message) { 077 logIfEnabled(Level.FATAL, message, null); 078 } 079 080 @Override 081 public void fatal(final Object message, final Throwable t) { 082 logIfEnabled(Level.FATAL, message, t); 083 } 084 085 @Override 086 public void info(final Object message) { 087 logIfEnabled(Level.INFO, message, null); 088 } 089 090 @Override 091 public void info(final Object message, final Throwable t) { 092 logIfEnabled(Level.INFO, message, t); 093 } 094 095 @Override 096 public boolean isDebugEnabled() { 097 return isEnabled(Level.DEBUG); 098 } 099 100 private boolean isEnabled(final Level level) { 101 return logger.isEnabled(level, MARKER, null); 102 } 103 104 @Override 105 public boolean isErrorEnabled() { 106 return isEnabled(Level.ERROR); 107 } 108 109 @Override 110 public boolean isFatalEnabled() { 111 return isEnabled(Level.FATAL); 112 } 113 114 @Override 115 public boolean isInfoEnabled() { 116 return isEnabled(Level.INFO); 117 } 118 119 @Override 120 public boolean isTraceEnabled() { 121 return isEnabled(Level.TRACE); 122 } 123 124 @Override 125 public boolean isWarnEnabled() { 126 return isEnabled(Level.WARN); 127 } 128 129 private void logIfEnabled(final Level level, final Object message, final Throwable t) { 130 if (message instanceof CharSequence) { 131 logger.logIfEnabled(FQCN, level, MARKER, (CharSequence) message, t); 132 } else { 133 logger.logIfEnabled(FQCN, level, MARKER, message, t); 134 } 135 } 136 137 @Override 138 public void trace(final Object message) { 139 logIfEnabled(Level.TRACE, message, null); 140 } 141 142 @Override 143 public void trace(final Object message, final Throwable t) { 144 logIfEnabled(Level.TRACE, message, t); 145 } 146 147 @Override 148 public void warn(final Object message) { 149 logIfEnabled(Level.WARN, message, null); 150 } 151 152 @Override 153 public void warn(final Object message, final Throwable t) { 154 logIfEnabled(Level.WARN, message, t); 155 } 156 } 157 private static final class LogAdapter extends AbstractLoggerAdapter<Log> { 158 159 @Override 160 protected LoggerContext getContext() { 161 return getContext(LogManager.getFactory().isClassLoaderDependent() ? StackLocatorUtil.getCallerClass( 162 LogFactory.class) : null); 163 } 164 165 @Override 166 protected Log newLogger(final String name, final LoggerContext context) { 167 return new Log4j2Log(context.getLogger(name)); 168 } 169 170 } 171 172 private static final String[] EMPTY_ARRAY = {}; 173 174 /** 175 * Marker used by all messages coming from Apache Commons Logging. 176 */ 177 private static final Marker MARKER = MarkerManager.getMarker("COMMONS-LOGGING"); 178 179 /** 180 * Caches Log instances 181 */ 182 private final LoggerAdapter<Log> adapter = new LogAdapter(); 183 184 private final ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>(); 185 186 /** 187 * Constructs a new instance. 188 */ 189 public Log4jApiLogFactory() { 190 // empty 191 } 192 193 @Override 194 public Object getAttribute(final String name) { 195 return attributes.get(name); 196 } 197 198 @Override 199 public String[] getAttributeNames() { 200 return attributes.keySet().toArray(EMPTY_ARRAY); 201 } 202 203 @Override 204 public Log getInstance(final Class<?> clazz) { 205 return getInstance(clazz.getName()); 206 } 207 208 @Override 209 public Log getInstance(final String name) { 210 return adapter.getLogger(name); 211 } 212 213 /** 214 * This method is supposed to clear all loggers. In this implementation it will clear all the logger 215 * wrappers but the loggers managed by the underlying logger context will not be. 216 */ 217 @Override 218 public void release() { 219 try { 220 adapter.close(); 221 } catch (final IOException ignored) { 222 // Ignore 223 } 224 } 225 226 @Override 227 public void removeAttribute(final String name) { 228 attributes.remove(name); 229 } 230 231 @Override 232 public void setAttribute(final String name, final Object value) { 233 if (value != null) { 234 attributes.put(name, value); 235 } else { 236 removeAttribute(name); 237 } 238 } 239}