/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache license, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the license for the specific language governing permissions and
 * limitations under the license.
 */
package org.apache.logging.slf4j;

import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.spi.LoggerContext;
import org.apache.logging.log4j.spi.ExtendedLogger;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 */
public class Log4jLoggerFactory implements ILoggerFactory {

    private static final String FQCN = Log4jLoggerFactory.class.getName();
    private static final String PACKAGE = "org.slf4j";

    private final Map<LoggerContext, ConcurrentMap<String, Logger>> contextMap =
        new WeakHashMap<LoggerContext, ConcurrentMap<String, Logger>>();

    @Override
    public Logger getLogger(final String name) {
        final LoggerContext context = getContext();
        final ConcurrentMap<String, Logger> loggers = getLoggersMap(context);

        if (loggers.containsKey(name)) {
            return loggers.get(name);
        }
        final String key = Logger.ROOT_LOGGER_NAME.equals(name) ? LogManager.ROOT_LOGGER_NAME : name;
        loggers.putIfAbsent(name, new Log4jLogger(context.getLogger(key), name));
        return loggers.get(name);
    }

    private ConcurrentMap<String, Logger> getLoggersMap(final LoggerContext context) {
        synchronized (contextMap) {
            ConcurrentMap<String, Logger> map = contextMap.get(context);
            if (map == null) {
                map = new ConcurrentHashMap<String, Logger>();
                contextMap.put(context, map);
            }
            return map;
        }
    }
    private LoggerContext getContext() {
        final Throwable t = new Throwable();
        boolean next = false;
        boolean pkg = false;
        String fqcn = LoggerFactory.class.getName();
        for (final StackTraceElement element : t.getStackTrace()) {
            if (FQCN.equals(element.getClassName())) {
                next = true;
                continue;
            }
            if (next && element.getClassName().startsWith(PACKAGE)) {
                fqcn = element.getClassName();
                pkg = true;
                continue;
            }
            if (pkg) {
                break;
            }
        }
        return PrivateManager.getContext(fqcn);
    }

    /**
     * The real bridge between SLF4J and Log4j.
     */
    private static class PrivateManager extends LogManager {
        private static final String FQCN = LoggerFactory.class.getName();

        public static LoggerContext getContext() {
            return getContext(FQCN, false);
        }

        public static LoggerContext getContext(final String fqcn) {
            return getContext(fqcn, false);
        }

        public static ExtendedLogger getLogger(final String name) {
            return getContext(FQCN).getLogger(name);
        }
    }
}

@@ -840,144 +840,45 @@
 ort 
-java.util.Map;%0Aimport java.util.WeakHashMap;%0Aimport java.util.concurrent.ConcurrentHashMap;%0Aimport java.util.concurrent.ConcurrentMap
+org.apache.logging.log4j.LogManager
 ;%0A
-%0A
 impo
@@ -901,34 +901,65 @@
 gging.log4j.
-LogManager
+spi.AbstractExternalLoggerContextRegistry
 ;%0Aimport org
@@ -984,29 +984,30 @@
 g4j.spi.
-LoggerContext
+ExtendedLogger
 ;%0Aimport
@@ -1032,38 +1032,37 @@
 g.log4j.spi.
-ExtendedLogger
+LoggerContext
 ;%0Aimport org
@@ -1184,16 +1184,70 @@
 rFactory
+ extends AbstractExternalLoggerContextRegistry%3CLogger%3E
  impleme
@@ -1403,163 +1403,8 @@
 %22;%0A%0A
-    private final Map%3CLoggerContext, ConcurrentMap%3CString, Logger%3E%3E contextMap =%0A        new WeakHashMap%3CLoggerContext, ConcurrentMap%3CString, Logger%3E%3E();%0A%0A
     
@@ -1427,27 +1427,27 @@
 blic Logger 
-get
+new
 Logger(final
@@ -1458,27 +1458,17 @@
 ing name
-) %7B%0A       
+,
  final L
@@ -1491,192 +1491,11 @@
 text
- = getContext();%0A        final ConcurrentMap%3CString, Logger%3E loggers = getLoggersMap(context);%0A%0A        if (loggers.containsKey(name)) %7B%0A            return loggers.get(name);%0A        %7D
+) %7B
 %0A   
@@ -1605,33 +1605,14 @@
     
-loggers.putIfAbsent(name,
+return
  new
@@ -1657,453 +1657,41 @@
 ame)
-);%0A        return loggers.get(name);%0A    %7D%0A%0A    private ConcurrentMap%3CString, Logger%3E getLoggersMap(final LoggerContext context) %7B%0A        synchronized (contextMap) %7B%0A            ConcurrentMap%3CString, Logger%3E map = contextMap.get(context);%0A            if (map == null) %7B%0A                map = new ConcurrentHashMap%3CString, Logger%3E();%0A                contextMap.put(context, map);%0A            %7D%0A            return map;%0A        %7D%0A    %7D%0A    private
+;%0A    %7D%0A%0A    @Override%0A    public
  Log

Update slf4j binding to use ELCR.