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.apache.logging.log4j.taglib;
    18
    19  import java.util.WeakHashMap;
    20
    21  import javax.servlet.ServletContext;
    22
    23  import org.apache.logging.log4j.LogManager;
    24  import org.apache.logging.log4j.message.MessageFactory;
    25  import org.apache.logging.log4j.spi.AbstractLogger;
    26  import org.apache.logging.log4j.spi.LoggerContext;
    27  import org.apache.logging.log4j.spi.ExtendedLogger;
    28
    29  /**
    30   * This bridge between the tag library and the Log4j API ensures that instances of {@link Log4jTaglibLogger} are
    31   * appropriately held in memory and not constantly recreated.
    32   *
    33   * @since 2.0
    34   */
    35  final class Log4jTaglibLoggerContext implements LoggerContext {
    36      // These were change to WeakHashMaps to avoid ClassLoader (memory) leak, something that's particularly
    37      // important in Servlet containers.
    38      private static final WeakHashMap<ServletContext, Log4jTaglibLoggerContext> CONTEXTS =
    39              new WeakHashMap<ServletContext, Log4jTaglibLoggerContext>();
    40
    41      private final WeakHashMap<String, Log4jTaglibLogger> loggers =
    42              new WeakHashMap<String, Log4jTaglibLogger>();
    43
    44      private final ServletContext servletContext;
    45
    46      private Log4jTaglibLoggerContext(final ServletContext servletContext) {
    47          this.servletContext = servletContext;
    48      }
    49
    50      @Override
    51      public Object getExternalContext() {
    52          return this.servletContext;
    53      }
    54
    55      @Override
    56      public Log4jTaglibLogger getLogger(final String name) {
    57          return this.getLogger(name, null);
    58      }
    59
    60      @Override
    61      public Log4jTaglibLogger getLogger(final String name, final MessageFactory factory) {
    62          Log4jTaglibLogger logger = this.loggers.get(name);
    63          if (logger != null) {
    64              AbstractLogger.checkMessageFactory(logger, factory);
    65              return logger;
    66          }
    67
    68          synchronized (this.loggers) {
    69              logger = this.loggers.get(name);
    70              if (logger == null) {
    71                  final LoggerContext context = LogManager.getContext(false);
    72                  final ExtendedLogger original = factory == null ?
    73                          context.getLogger(name) : context.getLogger(name, factory);
    74                  // wrap a logger from an underlying implementation
    75                  logger = new Log4jTaglibLogger(original, name, original.getMessageFactory());
    76                  this.loggers.put(name, logger);
    77              }
    78          }
    79
    80          return logger;
    81      }
    82
    83      @Override
    84      public boolean hasLogger(final String name) {
    85          return this.loggers.containsKey(name);
    86      }
    87
    88      static synchronized Log4jTaglibLoggerContext getInstance(final ServletContext servletContext) {
    89          Log4jTaglibLoggerContext loggerContext = CONTEXTS.get(servletContext);
    90          if (loggerContext != null) {
    91              return loggerContext;
    92          }
    93
    94          synchronized (CONTEXTS) {
    95              loggerContext = CONTEXTS.get(servletContext);
    96              if (loggerContext == null) {
    97                  loggerContext = new Log4jTaglibLoggerContext(servletContext);
    98                  CONTEXTS.put(servletContext, loggerContext);
    99              }
    100         }
    101
    102         return loggerContext;
    103     }
    104 }