View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.slf4j.helpers;
18  
19  import org.apache.logging.log4j.LogManager;
20  import org.apache.logging.log4j.spi.AbstractLogger;
21  import org.apache.logging.log4j.spi.LoggerContext;
22  import org.apache.logging.slf4j.SLF4JLoggingException;
23  import org.slf4j.ILoggerFactory;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  import org.slf4j.impl.SLF4JLogger;
27  
28  import java.util.Map;
29  import java.util.WeakHashMap;
30  import java.util.concurrent.ConcurrentHashMap;
31  import java.util.concurrent.ConcurrentMap;
32  
33  /**
34   *
35   */
36  public class Log4JLoggerFactory implements ILoggerFactory {
37  
38      private static final String FQCN = Log4JLoggerFactory.class.getName();
39      private static final String PACKAGE = "org.slf4j";
40  
41      private final Map<LoggerContext, ConcurrentMap<String, Logger>> contextMap =
42          new WeakHashMap<LoggerContext, ConcurrentMap<String, Logger>>();
43  
44      public Logger getLogger(String name) {
45          LoggerContext context = getContext();
46          ConcurrentMap<String, Logger> loggers = getLoggersMap(context);
47  
48          if (loggers.containsKey(name)) {
49              return loggers.get(name);
50          }
51          String key = Logger.ROOT_LOGGER_NAME.equals(name) ? LogManager.ROOT_LOGGER_NAME : name;
52          org.apache.logging.log4j.Logger logger = context.getLogger(key);
53          if (logger instanceof AbstractLogger) {
54              loggers.putIfAbsent(name, new SLF4JLogger((AbstractLogger) logger, name));
55              return loggers.get(name);
56          }
57          throw new SLF4JLoggingException("SLF4J Adapter requires base logging system to extend Log4J AbstractLogger");
58      }
59  
60      private ConcurrentMap<String, Logger> getLoggersMap(LoggerContext context) {
61          synchronized (contextMap) {
62              ConcurrentMap<String, Logger> map = contextMap.get(context);
63              if (map == null) {
64                  map = new ConcurrentHashMap<String, Logger>();
65                  contextMap.put(context, map);
66              }
67              return map;
68          }
69      }
70      private LoggerContext getContext() {
71          Throwable t = new Throwable();
72          boolean next = false;
73          boolean pkg = false;
74          String fqcn = LoggerFactory.class.getName();
75          for (StackTraceElement element : t.getStackTrace()) {
76              if (FQCN.equals(element.getClassName())) {
77                  next = true;
78                  continue;
79              }
80              if (next && element.getClassName().startsWith(PACKAGE)) {
81                  fqcn = element.getClassName();
82                  pkg = true;
83                  continue;
84              }
85              if (pkg) {
86                  break;
87              }
88          }
89          return PrivateManager.getContext(fqcn);
90      }
91  
92      /**
93       * The real bridge between SLF4J and Log4j.
94       */
95      private static class PrivateManager extends LogManager {
96          private static final String FQCN = LoggerFactory.class.getName();
97  
98          public static LoggerContext getContext() {
99              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 }