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