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 */
017package org.apache.logging.log4j.core.config;
018
019import java.net.URI;
020import java.net.URISyntaxException;
021
022import org.apache.logging.log4j.LogManager;
023import org.apache.logging.log4j.Logger;
024import org.apache.logging.log4j.core.LoggerContext;
025import org.apache.logging.log4j.core.impl.Log4jContextFactory;
026import org.apache.logging.log4j.core.util.FileUtils;
027import org.apache.logging.log4j.spi.LoggerContextFactory;
028import org.apache.logging.log4j.status.StatusLogger;
029
030/**
031 * Initializes and configure the Logging system. This class provides several ways to construct a LoggerContext using
032 * the location of a configuration file, a context name, and various optional parameters.
033 */
034public final class Configurator {
035
036    private static final Logger LOGGER = StatusLogger.getLogger();
037
038    private static final String FQCN = Configurator.class.getName();
039
040    private Configurator() {
041    }
042
043
044    /**
045     * Initializes the Logging Context.
046     * @param name The Context name.
047     * @param loader The ClassLoader for the Context (or null).
048     * @param configLocation The configuration for the logging context.
049     * @return The LoggerContext.
050     */
051    public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation) {
052        return initialize(name, loader, configLocation, null);
053
054    }
055
056    /**
057     * Initializes the Logging Context.
058     * @param name The Context name.
059     * @param loader The ClassLoader for the Context (or null).
060     * @param configLocation The configuration for the logging context.
061     * @param externalContext The external context to be attached to the LoggerContext
062     * @return The LoggerContext.
063     */
064    public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation,
065                                           final Object externalContext) {
066
067        try {
068            final URI uri = configLocation == null ? null : FileUtils.getCorrectedFilePathUri(configLocation);
069            return initialize(name, loader, uri, externalContext);
070        } catch (final URISyntaxException ex) {
071            LOGGER.error("There was a problem parsing the configuration location [{}].", configLocation, ex);
072        }
073        return null;
074    }
075
076    /**
077     * Initializes the Logging Context.
078     * @param name The Context name.
079     * @param configLocation The configuration for the logging context.
080     * @return The LoggerContext.
081     */
082    public static LoggerContext initialize(final String name, final String configLocation) {
083        return initialize(name, null, configLocation);
084    }
085
086    /**
087     * Initializes the Logging Context.
088     * @param name The Context name.
089     * @param loader The ClassLoader for the Context (or null).
090     * @param configLocation The configuration for the logging context.
091     * @return The LoggerContext.
092     */
093    public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation) {
094        return initialize(name, loader, configLocation, null);
095    }
096
097    /**
098     * Initializes the Logging Context.
099     * @param name The Context name.
100     * @param loader The ClassLoader for the Context (or null).
101     * @param configLocation The configuration for the logging context.
102     * @param externalContext The external context to be attached to the LoggerContext
103     * @return The LoggerContext.
104     */
105    public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation,
106                                           final Object externalContext) {
107
108        try {
109            final Log4jContextFactory factory = getFactory();
110            return factory == null ? null :
111                    factory.getContext(FQCN, loader, externalContext, false, configLocation, name);
112        } catch (final Exception ex) {
113            LOGGER.error("There was a problem initializing the LoggerContext [{}] using configuration at [{}].",
114                    name, configLocation, ex);
115        }
116        return null;
117    }
118
119    /**
120     * Initializes the Logging Context.
121     * @param loader The ClassLoader for the Context (or null).
122     * @param source The InputSource for the configuration.
123     * @return The LoggerContext.
124     */
125    public static LoggerContext initialize(final ClassLoader loader,
126                                           final ConfigurationSource source) {
127        return initialize(loader, source, null);
128    }
129
130    /**
131     * Initializes the Logging Context.
132     * @param loader The ClassLoader for the Context (or null).
133     * @param source The InputSource for the configuration.
134     * @param externalContext The external context to be attached to the LoggerContext.
135     * @return The LoggerContext.
136     */
137
138    public static LoggerContext initialize(final ClassLoader loader,
139                                           final ConfigurationSource source,
140                                           final Object externalContext)
141    {
142
143        try {
144            final Log4jContextFactory factory = getFactory();
145            return factory == null ? null :
146                    factory.getContext(FQCN, loader, externalContext, false, source);
147        } catch (final Exception ex) {
148            LOGGER.error("There was a problem obtaining a LoggerContext using the configuration source [{}]", source, ex);
149        }
150        return null;
151    }
152
153    private static Log4jContextFactory getFactory() {
154        final LoggerContextFactory factory = LogManager.getFactory();
155        if (factory instanceof Log4jContextFactory) {
156            return (Log4jContextFactory) factory;
157        } else if (factory != null) {
158            LOGGER.error("LogManager returned an instance of {} which does not implement {}. Unable to initialize Log4j.",
159                    factory.getClass().getName(), Log4jContextFactory.class.getName());
160            return null;
161        } else {
162            LOGGER.error("LogManager did not return a LoggerContextFactory. This indicates something has gone terribly wrong!");
163            return null;
164        }
165    }
166
167    /**
168     * Shuts down the given logging context.
169     * @param ctx the logging context to shut down, may be null.
170     */
171    public static void shutdown(final LoggerContext ctx) {
172        if (ctx != null) {
173            ctx.stop();
174        }
175    }
176}