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 */ 017 package org.slf4j.helpers; 018 019 import org.apache.logging.log4j.LogManager; 020 import org.apache.logging.log4j.spi.AbstractLogger; 021 import org.apache.logging.log4j.spi.LoggerContext; 022 import org.apache.logging.slf4j.SLF4JLoggingException; 023 import org.slf4j.ILoggerFactory; 024 import org.slf4j.Logger; 025 import org.slf4j.LoggerFactory; 026 import org.slf4j.impl.SLF4JLogger; 027 028 import java.util.Map; 029 import java.util.WeakHashMap; 030 import java.util.concurrent.ConcurrentHashMap; 031 import java.util.concurrent.ConcurrentMap; 032 033 /** 034 * 035 */ 036 public class Log4JLoggerFactory implements ILoggerFactory { 037 038 private static final String FQCN = Log4JLoggerFactory.class.getName(); 039 private static final String PACKAGE = "org.slf4j"; 040 041 private final Map<LoggerContext, ConcurrentMap<String, Logger>> contextMap = 042 new WeakHashMap<LoggerContext, ConcurrentMap<String, Logger>>(); 043 044 public Logger getLogger(String name) { 045 LoggerContext context = getContext(); 046 ConcurrentMap<String, Logger> loggers = getLoggersMap(context); 047 048 if (loggers.containsKey(name)) { 049 return loggers.get(name); 050 } 051 String key = Logger.ROOT_LOGGER_NAME.equals(name) ? LogManager.ROOT_LOGGER_NAME : name; 052 org.apache.logging.log4j.Logger logger = context.getLogger(key); 053 if (logger instanceof AbstractLogger) { 054 loggers.putIfAbsent(name, new SLF4JLogger((AbstractLogger) logger, name)); 055 return loggers.get(name); 056 } 057 throw new SLF4JLoggingException("SLF4J Adapter requires base logging system to extend Log4J AbstractLogger"); 058 } 059 060 private ConcurrentMap<String, Logger> getLoggersMap(LoggerContext context) { 061 synchronized (contextMap) { 062 ConcurrentMap<String, Logger> map = contextMap.get(context); 063 if (map == null) { 064 map = new ConcurrentHashMap<String, Logger>(); 065 contextMap.put(context, map); 066 } 067 return map; 068 } 069 } 070 private LoggerContext getContext() { 071 Throwable t = new Throwable(); 072 boolean next = false; 073 boolean pkg = false; 074 String fqcn = LoggerFactory.class.getName(); 075 for (StackTraceElement element : t.getStackTrace()) { 076 if (FQCN.equals(element.getClassName())) { 077 next = true; 078 continue; 079 } 080 if (next && element.getClassName().startsWith(PACKAGE)) { 081 fqcn = element.getClassName(); 082 pkg = true; 083 continue; 084 } 085 if (pkg) { 086 break; 087 } 088 } 089 return PrivateManager.getContext(fqcn); 090 } 091 092 /** 093 * The real bridge between SLF4J and Log4j. 094 */ 095 private static class PrivateManager extends LogManager { 096 private static final String FQCN = LoggerFactory.class.getName(); 097 098 public static LoggerContext getContext() { 099 return getContext(FQCN, false); 100 } 101 102 public static LoggerContext getContext(String fqcn) { 103 return getContext(fqcn, false); 104 } 105 106 public static org.apache.logging.log4j.Logger getLogger(String name) { 107 return getLogger(FQCN, name); 108 } 109 } 110 111 }