Package org.apache.logging.log4j.core.web

Source Code of org.apache.logging.log4j.core.web.Log4jWebInitializerImpl

/*
* 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.log4j.core.web;

import java.net.URI;
import javax.servlet.ServletContext;
import javax.servlet.UnavailableException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.impl.ContextAnchor;
import org.apache.logging.log4j.core.impl.Log4jContextFactory;
import org.apache.logging.log4j.core.lookup.Interpolator;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;
import org.apache.logging.log4j.core.selector.ContextSelector;
import org.apache.logging.log4j.core.selector.NamedContextSelector;
import org.apache.logging.log4j.spi.LoggerContextFactory;

/**
* This class initializes and deinitializes Log4j no matter how the initialization occurs.
*/
final class Log4jWebInitializerImpl implements Log4jWebInitializer {
    private static final Object MUTEX = new Object();

    static {
        try {
            Class.forName("org.apache.logging.log4j.core.web.JNDIContextFilter");
            throw new IllegalStateException("You are using Log4j 2 in a web application with the old, extinct " +
                    "log4j-web artifact. This is not supported and could cause serious runtime problems. Please" +
                    "remove the log4j-web JAR file from your application.");
        } catch (final ClassNotFoundException ignore) {
            /* Good. They don't have the old log4j-web artifact loaded. */
        }
    }

    private final StrSubstitutor substitutor = new StrSubstitutor(new Interpolator());
    private final ServletContext servletContext;

    private String name;
    private NamedContextSelector selector;
    private LoggerContext loggerContext;

    private boolean initialized = false;
    private boolean deinitialized = false;

    private Log4jWebInitializerImpl(final ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    @Override
    public synchronized void initialize() throws UnavailableException {
        if (this.deinitialized) {
            throw new IllegalStateException("Cannot initialize Log4jWebInitializer after it was destroyed.");
        }

        // only do this once
        if (!this.initialized) {
            this.initialized = true;

            this.name = this.substitutor.replace(this.servletContext.getInitParameter(LOG4J_CONTEXT_NAME));
            final String location = this.substitutor.replace(this.servletContext.getInitParameter(LOG4J_CONFIG_LOCATION));
            final boolean isJndi = "true".equals(this.servletContext.getInitParameter(IS_LOG4J_CONTEXT_SELECTOR_NAMED));

            if (isJndi) {
                this.initializeJndi(location);
            } else {
                this.initializeNonJndi(location);
            }
        }
    }

    private void initializeJndi(final String location) throws UnavailableException {
        URI configLocation = null;
        if (location != null) {
            try {
                configLocation = new URI(location);
            } catch (final Exception e) {
                this.servletContext.log("Unable to convert configuration location [" + location + "] to a URI!", e);
            }
        }

        if (this.name == null) {
            throw new UnavailableException("A log4jContextName context parameter is required");
        }

        LoggerContext loggerContext;
        final LoggerContextFactory factory = LogManager.getFactory();
        if (factory instanceof Log4jContextFactory) {
            final ContextSelector selector = ((Log4jContextFactory) factory).getSelector();
            if (selector instanceof NamedContextSelector) {
                this.selector = (NamedContextSelector) selector;
                loggerContext = this.selector.locateContext(this.name, this.servletContext, configLocation);
                ContextAnchor.THREAD_CONTEXT.set(loggerContext);
                if (loggerContext.getStatus() == LoggerContext.Status.INITIALIZED) {
                    loggerContext.start();
                }
                ContextAnchor.THREAD_CONTEXT.remove();
            } else {
                this.servletContext.log("Potential problem: Selector is not an instance of NamedContextSelector.");
                return;
            }
        } else {
            this.servletContext.log("Potential problem: Factory is not an instance of Log4jContextFactory.");
            return;
        }
        this.loggerContext = loggerContext;
        this.servletContext.log("Created logger context for [" + this.name + "] using [" +
                loggerContext.getClass().getClassLoader() + "].");
    }

    private void initializeNonJndi(final String location) {
        if (this.name == null) {
            this.name = this.servletContext.getServletContextName();
        }

        if (this.name == null && location == null) {
            this.servletContext.log("No Log4j context configuration provided. This is very unusual.");
            return;
        }

        this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), location, this.servletContext);
    }

    @Override
    public synchronized void deinitialize() {
        if (!this.initialized) {
            throw new IllegalStateException("Cannot deinitialize Log4jWebInitializer because it has not initialized.");
        }

        // only do this once
        if (!this.deinitialized) {
            this.deinitialized = true;

            if (this.loggerContext != null) {
                this.servletContext.log("Removing LoggerContext for [" + this.name + "].");
                if (this.selector != null) {
                    this.selector.removeContext(this.name);
                }
                this.loggerContext.stop();
                this.loggerContext.setExternalContext(null);
                this.loggerContext = null;
            }
        }
    }

    @Override
    public void setLoggerContext() {
        if (this.loggerContext != null) {
            ContextAnchor.THREAD_CONTEXT.set(this.loggerContext);
        }
    }

    @Override
    public void clearLoggerContext() {
        ContextAnchor.THREAD_CONTEXT.remove();
    }

    private ClassLoader getClassLoader() {
        try {
            // if container is Servlet 3.0, use its getClassLoader method
            // this may look odd, but the call below will throw NoSuchMethodError if user is on Servlet 2.5
            // we compile against 3.0 to support Log4jServletContainerInitializer, but we don't require 3.0
            return this.servletContext.getClassLoader();
        } catch (final Throwable ignore) {
            // otherwise, use this class's class loader
            return Log4jWebInitializerImpl.class.getClassLoader();
        }
    }

    /**
     * Get the current initializer from the {@link ServletContext}. If the initializer does not exist, create a new one
     * and add it to the {@link ServletContext}, then return that.
     *
     * @param servletContext The {@link ServletContext} for this web application
     * @return the initializer, never {@code null}.
     */
    static Log4jWebInitializer getLog4jWebInitializer(final ServletContext servletContext) {
        synchronized (MUTEX) {
            Log4jWebInitializer initializer = (Log4jWebInitializer) servletContext.getAttribute(INITIALIZER_ATTRIBUTE);
            if (initializer == null) {
                initializer = new Log4jWebInitializerImpl(servletContext);
                servletContext.setAttribute(INITIALIZER_ATTRIBUTE, initializer);
            }
            return initializer;
        }
    }
}
TOP

Related Classes of org.apache.logging.log4j.core.web.Log4jWebInitializerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.