Repository: logging-log4j2 Updated Branches: refs/heads/master 55c787f4f -> 1542ec121
[LOG4J2-1123] Core Configurator.initialize(String, ClassLoader, String) fails to work when config location is a file path. Replace FileUtils.getCorrectedFilePathUri(String) with NetUtils.toURI(String). Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/1542ec12 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/1542ec12 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/1542ec12 Branch: refs/heads/master Commit: 1542ec121cce478bccd7f51fec64c59d61bb9115 Parents: 55c787f Author: ggregory <[email protected]> Authored: Fri Sep 18 08:38:42 2015 -0700 Committer: ggregory <[email protected]> Committed: Fri Sep 18 08:38:42 2015 -0700 ---------------------------------------------------------------------- .../log4j/core/config/ConfigurationFactory.java | 3 +- .../logging/log4j/core/config/Configurator.java | 630 +++++++++---------- .../core/config/status/StatusConfiguration.java | 3 +- .../logging/log4j/core/util/FileUtils.java | 12 - .../logging/log4j/core/util/NetUtils.java | 26 + .../log4j/core/config/ConfiguratorTest.java | 47 ++ .../logging/log4j/core/util/FileUtilsTest.java | 18 - .../logging/log4j/core/util/NetUtilsTest.java | 57 ++ log4j-core/src/test/resources/log4j-list.xml | 29 + .../log4j/web/Log4jWebInitializerImpl.java | 532 ++++++++-------- src/changes/changes.xml | 3 + 11 files changed, 744 insertions(+), 616 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java index a6f5404..22327d8 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java @@ -42,6 +42,7 @@ import org.apache.logging.log4j.core.lookup.Interpolator; import org.apache.logging.log4j.core.lookup.StrSubstitutor; import org.apache.logging.log4j.core.util.FileUtils; import org.apache.logging.log4j.core.util.Loader; +import org.apache.logging.log4j.core.util.NetUtils; import org.apache.logging.log4j.core.util.ReflectionUtil; import org.apache.logging.log4j.status.StatusLogger; import org.apache.logging.log4j.util.LoaderUtil; @@ -394,7 +395,7 @@ public abstract class ConfigurationFactory extends ConfigurationBuilderFactory { if (configLocationStr != null) { ConfigurationSource source = null; try { - source = getInputFromUri(FileUtils.getCorrectedFilePathUri(configLocationStr)); + source = getInputFromUri(NetUtils.toURI(configLocationStr)); } catch (final Exception ex) { // Ignore the error and try as a String. LOGGER.catching(Level.DEBUG, ex); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java index c038397..fe6a5d5 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java @@ -1,318 +1,312 @@ -/* - * 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.config; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Map; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.impl.Log4jContextFactory; -import org.apache.logging.log4j.core.util.FileUtils; -import org.apache.logging.log4j.spi.LoggerContextFactory; -import org.apache.logging.log4j.status.StatusLogger; -import org.apache.logging.log4j.util.Strings; - -/** - * Initializes and configure the Logging system. This class provides several ways to construct a LoggerContext using - * the location of a configuration file, a context name, and various optional parameters. - */ -public final class Configurator { - - private static final String FQCN = Configurator.class.getName(); - - private static final Logger LOGGER = StatusLogger.getLogger(); - - private static Log4jContextFactory getFactory() { - final LoggerContextFactory factory = LogManager.getFactory(); - if (factory instanceof Log4jContextFactory) { - return (Log4jContextFactory) factory; - } else if (factory != null) { - LOGGER.error("LogManager returned an instance of {} which does not implement {}. Unable to initialize Log4j.", - factory.getClass().getName(), Log4jContextFactory.class.getName()); - return null; - } else { - LOGGER.fatal("LogManager did not return a LoggerContextFactory. This indicates something has gone terribly wrong!"); - return null; - } - } - - /** - * Initializes the Logging Context. - * @param loader The ClassLoader for the Context (or null). - * @param source The InputSource for the configuration. - * @return The LoggerContext. - */ - public static LoggerContext initialize(final ClassLoader loader, - final ConfigurationSource source) { - return initialize(loader, source, null); - } - - /** - * Initializes the Logging Context. - * @param loader The ClassLoader for the Context (or null). - * @param source The InputSource for the configuration. - * @param externalContext The external context to be attached to the LoggerContext. - * @return The LoggerContext. - */ - - public static LoggerContext initialize(final ClassLoader loader, - final ConfigurationSource source, - final Object externalContext) - { - - try { - final Log4jContextFactory factory = getFactory(); - return factory == null ? null : - factory.getContext(FQCN, loader, externalContext, false, source); - } catch (final Exception ex) { - LOGGER.error("There was a problem obtaining a LoggerContext using the configuration source [{}]", source, ex); - } - return null; - } - - /** - * Initializes the Logging Context. - * @param name The Context name. - * @param loader The ClassLoader for the Context (or null). - * @param configLocation The configuration for the logging context. - * @return The LoggerContext or null if an error occurred (check the status logger). - */ - public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation) { - return initialize(name, loader, configLocation, null); - - } - - /** - * Initializes the Logging Context. - * @param name The Context name. - * @param loader The ClassLoader for the Context (or null). - * @param configLocation The configuration for the logging context (or null, or blank). - * @param externalContext The external context to be attached to the LoggerContext - * @return The LoggerContext or null if an error occurred (check the status logger). - */ - public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation, - final Object externalContext) { - try { - final URI uri = Strings.isBlank(configLocation) ? null : FileUtils.getCorrectedFilePathUri(configLocation); - return initialize(name, loader, uri, externalContext); - } catch (final URISyntaxException ex) { - LOGGER.error("There was a problem parsing the configuration location [{}].", configLocation, ex); - } - return null; - } - - /** - * Initializes the Logging Context. - * @param name The Context name. - * @param loader The ClassLoader for the Context (or null). - * @param configLocation The configuration for the logging context. - * @return The LoggerContext. - */ - public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation) { - return initialize(name, loader, configLocation, null); - } - - /** - * Initializes the Logging Context. - * @param name The Context name. - * @param loader The ClassLoader for the Context (or null). - * @param configLocation The configuration for the logging context (or null). - * @param externalContext The external context to be attached to the LoggerContext - * @return The LoggerContext. - */ - public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation, - final Object externalContext) { - - try { - final Log4jContextFactory factory = getFactory(); - return factory == null ? null : - factory.getContext(FQCN, loader, externalContext, false, configLocation, name); - } catch (final Exception ex) { - LOGGER.error("There was a problem initializing the LoggerContext [{}] using configuration at [{}].", - name, configLocation, ex); - } - return null; - } - - /** - * Initializes the Logging Context. - * @param name The Context name. - * @param configLocation The configuration for the logging context. - * @return The LoggerContext or null if an error occurred (check the status logger). - */ - public static LoggerContext initialize(final String name, final String configLocation) { - return initialize(name, null, configLocation); - } - - /** - * Initializes the Logging Context. - * @param configuration The Configuration. - * @return The LoggerContext. - */ - public static LoggerContext initialize(Configuration configuration) { - return initialize(null, configuration, null); - } - - /** - * Initializes the Logging Context. - * @param loader The ClassLoader. - * @param configuration The Configuration. - * @return The LoggerContext. - */ - public static LoggerContext initialize(final ClassLoader loader, Configuration configuration) { - return initialize(loader, configuration, null); - } - - /** - * Initializes the Logging Context. - * @param loader The ClassLoader. - * @param configuration The Configuration. - * @param externalContext - The external context to be attached to the LoggerContext. - * @return The LoggerContext. - */ - public static LoggerContext initialize(final ClassLoader loader, Configuration configuration, final Object externalContext) { - try { - final Log4jContextFactory factory = getFactory(); - return factory == null ? null : - factory.getContext(FQCN, loader, externalContext, false, configuration); - } catch (final Exception ex) { - LOGGER.error("There was a problem initializing the LoggerContext using configuration {}", - configuration.getName(), ex); - } - return null; - } - - /** - * Sets the levels of <code>parentLogger</code> and all 'child' loggers to the given <code>level</code>. - * @param parentLogger the parent logger - * @param level the new level - */ - public static void setAllLevels(final String parentLogger, final Level level) { - // 1) get logger config - // 2) if exact match, use it, if not, create it. - // 3) set level on logger config - // 4) update child logger configs with level - // 5) update loggers - final LoggerContext loggerContext = LoggerContext.getContext(false); - final Configuration config = loggerContext.getConfiguration(); - boolean set = setLevel(parentLogger, level, config); - for (final Map.Entry<String, LoggerConfig> entry : config.getLoggers().entrySet()) { - if (entry.getKey().startsWith(parentLogger)) { - set |= setLevel(entry.getValue(), level); - } - } - if (set) { - loggerContext.updateLoggers(); - } - } - - private static boolean setLevel(final LoggerConfig loggerConfig, final Level level) { - final boolean set = !loggerConfig.getLevel().equals(level); - if (set) { - loggerConfig.setLevel(level); - } - return set; - } - - /** - * Sets logger levels. - * - * @param levelMap - * a levelMap where keys are level names and values are new - * Levels. - */ - public static void setLevel(final Map<String, Level> levelMap) { - final LoggerContext loggerContext = LoggerContext.getContext(false); - final Configuration config = loggerContext.getConfiguration(); - boolean set = false; - for (final Map.Entry<String, Level> entry : levelMap.entrySet()) { - final String loggerName = entry.getKey(); - final Level level = entry.getValue(); - set |= setLevel(loggerName, level, config); - } - if (set) { - loggerContext.updateLoggers(); - } - } - - /** - * Sets a logger's level. - * - * @param loggerName - * the logger name - * @param level - * the new level - */ - public static void setLevel(final String loggerName, final Level level) { - final LoggerContext loggerContext = LoggerContext.getContext(false); - if (Strings.isEmpty(loggerName)) { - setRootLevel(level); - } else { - if (setLevel(loggerName, level, loggerContext.getConfiguration())) { - loggerContext.updateLoggers(); - } - } - } - - private static boolean setLevel(final String loggerName, final Level level, final Configuration config) { - boolean set; - LoggerConfig loggerConfig = config.getLoggerConfig(loggerName); - if (!loggerName.equals(loggerConfig.getName())) { - // TODO Should additivity be inherited? - loggerConfig = new LoggerConfig(loggerName, level, true); - config.addLogger(loggerName, loggerConfig); - loggerConfig.setLevel(level); - set = true; - } else { - set = setLevel(loggerConfig, level); - } - return set; - } - - /** - * Sets the root logger's level. - * - * @param level - * the new level - */ - public static void setRootLevel(final Level level) { - final LoggerContext loggerContext = LoggerContext.getContext(false); - final LoggerConfig loggerConfig = loggerContext.getConfiguration().getRootLogger(); - if (!loggerConfig.getLevel().equals(level)) { - loggerConfig.setLevel(level); - loggerContext.updateLoggers(); - } - } - - /** - * Shuts down the given logging context. - * @param ctx the logging context to shut down, may be null. - */ - public static void shutdown(final LoggerContext ctx) { - if (ctx != null) { - ctx.stop(); - } - } - - private Configurator() { - // empty - } -} +/* + * 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.config; + +import java.net.URI; +import java.util.Map; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.impl.Log4jContextFactory; +import org.apache.logging.log4j.core.util.NetUtils; +import org.apache.logging.log4j.spi.LoggerContextFactory; +import org.apache.logging.log4j.status.StatusLogger; +import org.apache.logging.log4j.util.Strings; + +/** + * Initializes and configure the Logging system. This class provides several ways to construct a LoggerContext using + * the location of a configuration file, a context name, and various optional parameters. + */ +public final class Configurator { + + private static final String FQCN = Configurator.class.getName(); + + private static final Logger LOGGER = StatusLogger.getLogger(); + + private static Log4jContextFactory getFactory() { + final LoggerContextFactory factory = LogManager.getFactory(); + if (factory instanceof Log4jContextFactory) { + return (Log4jContextFactory) factory; + } else if (factory != null) { + LOGGER.error("LogManager returned an instance of {} which does not implement {}. Unable to initialize Log4j.", + factory.getClass().getName(), Log4jContextFactory.class.getName()); + return null; + } else { + LOGGER.fatal("LogManager did not return a LoggerContextFactory. This indicates something has gone terribly wrong!"); + return null; + } + } + + /** + * Initializes the Logging Context. + * @param loader The ClassLoader for the Context (or null). + * @param source The InputSource for the configuration. + * @return The LoggerContext. + */ + public static LoggerContext initialize(final ClassLoader loader, + final ConfigurationSource source) { + return initialize(loader, source, null); + } + + /** + * Initializes the Logging Context. + * @param loader The ClassLoader for the Context (or null). + * @param source The InputSource for the configuration. + * @param externalContext The external context to be attached to the LoggerContext. + * @return The LoggerContext. + */ + + public static LoggerContext initialize(final ClassLoader loader, + final ConfigurationSource source, + final Object externalContext) + { + + try { + final Log4jContextFactory factory = getFactory(); + return factory == null ? null : + factory.getContext(FQCN, loader, externalContext, false, source); + } catch (final Exception ex) { + LOGGER.error("There was a problem obtaining a LoggerContext using the configuration source [{}]", source, ex); + } + return null; + } + + /** + * Initializes the Logging Context. + * @param name The Context name. + * @param loader The ClassLoader for the Context (or null). + * @param configLocation The configuration for the logging context. + * @return The LoggerContext or null if an error occurred (check the status logger). + */ + public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation) { + return initialize(name, loader, configLocation, null); + + } + + /** + * Initializes the Logging Context. + * @param name The Context name. + * @param loader The ClassLoader for the Context (or null). + * @param configLocation The configuration for the logging context (or null, or blank). + * @param externalContext The external context to be attached to the LoggerContext + * @return The LoggerContext or null if an error occurred (check the status logger). + */ + public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation, + final Object externalContext) { + final URI uri = Strings.isBlank(configLocation) ? null : NetUtils.toURI(configLocation); + return initialize(name, loader, uri, externalContext); + } + + /** + * Initializes the Logging Context. + * @param name The Context name. + * @param loader The ClassLoader for the Context (or null). + * @param configLocation The configuration for the logging context. + * @return The LoggerContext. + */ + public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation) { + return initialize(name, loader, configLocation, null); + } + + /** + * Initializes the Logging Context. + * @param name The Context name. + * @param loader The ClassLoader for the Context (or null). + * @param configLocation The configuration for the logging context (or null). + * @param externalContext The external context to be attached to the LoggerContext + * @return The LoggerContext. + */ + public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation, + final Object externalContext) { + + try { + final Log4jContextFactory factory = getFactory(); + return factory == null ? null : + factory.getContext(FQCN, loader, externalContext, false, configLocation, name); + } catch (final Exception ex) { + LOGGER.error("There was a problem initializing the LoggerContext [{}] using configuration at [{}].", + name, configLocation, ex); + } + return null; + } + + /** + * Initializes the Logging Context. + * @param name The Context name. + * @param configLocation The configuration for the logging context. + * @return The LoggerContext or null if an error occurred (check the status logger). + */ + public static LoggerContext initialize(final String name, final String configLocation) { + return initialize(name, null, configLocation); + } + + /** + * Initializes the Logging Context. + * @param configuration The Configuration. + * @return The LoggerContext. + */ + public static LoggerContext initialize(Configuration configuration) { + return initialize(null, configuration, null); + } + + /** + * Initializes the Logging Context. + * @param loader The ClassLoader. + * @param configuration The Configuration. + * @return The LoggerContext. + */ + public static LoggerContext initialize(final ClassLoader loader, Configuration configuration) { + return initialize(loader, configuration, null); + } + + /** + * Initializes the Logging Context. + * @param loader The ClassLoader. + * @param configuration The Configuration. + * @param externalContext - The external context to be attached to the LoggerContext. + * @return The LoggerContext. + */ + public static LoggerContext initialize(final ClassLoader loader, Configuration configuration, final Object externalContext) { + try { + final Log4jContextFactory factory = getFactory(); + return factory == null ? null : + factory.getContext(FQCN, loader, externalContext, false, configuration); + } catch (final Exception ex) { + LOGGER.error("There was a problem initializing the LoggerContext using configuration {}", + configuration.getName(), ex); + } + return null; + } + + /** + * Sets the levels of <code>parentLogger</code> and all 'child' loggers to the given <code>level</code>. + * @param parentLogger the parent logger + * @param level the new level + */ + public static void setAllLevels(final String parentLogger, final Level level) { + // 1) get logger config + // 2) if exact match, use it, if not, create it. + // 3) set level on logger config + // 4) update child logger configs with level + // 5) update loggers + final LoggerContext loggerContext = LoggerContext.getContext(false); + final Configuration config = loggerContext.getConfiguration(); + boolean set = setLevel(parentLogger, level, config); + for (final Map.Entry<String, LoggerConfig> entry : config.getLoggers().entrySet()) { + if (entry.getKey().startsWith(parentLogger)) { + set |= setLevel(entry.getValue(), level); + } + } + if (set) { + loggerContext.updateLoggers(); + } + } + + private static boolean setLevel(final LoggerConfig loggerConfig, final Level level) { + final boolean set = !loggerConfig.getLevel().equals(level); + if (set) { + loggerConfig.setLevel(level); + } + return set; + } + + /** + * Sets logger levels. + * + * @param levelMap + * a levelMap where keys are level names and values are new + * Levels. + */ + public static void setLevel(final Map<String, Level> levelMap) { + final LoggerContext loggerContext = LoggerContext.getContext(false); + final Configuration config = loggerContext.getConfiguration(); + boolean set = false; + for (final Map.Entry<String, Level> entry : levelMap.entrySet()) { + final String loggerName = entry.getKey(); + final Level level = entry.getValue(); + set |= setLevel(loggerName, level, config); + } + if (set) { + loggerContext.updateLoggers(); + } + } + + /** + * Sets a logger's level. + * + * @param loggerName + * the logger name + * @param level + * the new level + */ + public static void setLevel(final String loggerName, final Level level) { + final LoggerContext loggerContext = LoggerContext.getContext(false); + if (Strings.isEmpty(loggerName)) { + setRootLevel(level); + } else { + if (setLevel(loggerName, level, loggerContext.getConfiguration())) { + loggerContext.updateLoggers(); + } + } + } + + private static boolean setLevel(final String loggerName, final Level level, final Configuration config) { + boolean set; + LoggerConfig loggerConfig = config.getLoggerConfig(loggerName); + if (!loggerName.equals(loggerConfig.getName())) { + // TODO Should additivity be inherited? + loggerConfig = new LoggerConfig(loggerName, level, true); + config.addLogger(loggerName, loggerConfig); + loggerConfig.setLevel(level); + set = true; + } else { + set = setLevel(loggerConfig, level); + } + return set; + } + + /** + * Sets the root logger's level. + * + * @param level + * the new level + */ + public static void setRootLevel(final Level level) { + final LoggerContext loggerContext = LoggerContext.getContext(false); + final LoggerConfig loggerConfig = loggerContext.getConfiguration().getRootLogger(); + if (!loggerConfig.getLevel().equals(level)) { + loggerConfig.setLevel(level); + loggerContext.updateLoggers(); + } + } + + /** + * Shuts down the given logging context. + * @param ctx the logging context to shut down, may be null. + */ + public static void shutdown(final LoggerContext ctx) { + if (ctx != null) { + ctx.stop(); + } + } + + private Configurator() { + // empty + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java index ce96d3f..16f5b08 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java @@ -29,6 +29,7 @@ import java.util.LinkedList; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.util.FileUtils; +import org.apache.logging.log4j.core.util.NetUtils; import org.apache.logging.log4j.status.StatusConsoleListener; import org.apache.logging.log4j.status.StatusListener; import org.apache.logging.log4j.status.StatusLogger; @@ -113,7 +114,7 @@ public class StatusConfiguration { if (name.equalsIgnoreCase("err")) { return System.err; } - final URI destUri = FileUtils.getCorrectedFilePathUri(name); + final URI destUri = NetUtils.toURI(name); final File output = FileUtils.fileFromUri(destUri); if (output == null) { // don't want any NPEs, no sir http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FileUtils.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FileUtils.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FileUtils.java index 54ac566..cab865c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FileUtils.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/FileUtils.java @@ -117,16 +117,4 @@ public final class FileUtils { throw new IOException("File " + dir + " exists and is not a directory. Unable to create directory."); } } - - /** - * Takes a given URI string which may contain backslashes (illegal in URIs) in it due to user input or variable - * substitution and returns a URI with the backslashes replaced with forward slashes. - * - * @param uri The URI string - * @return the URI. - * @throws URISyntaxException if instantiating the URI threw a {@code URISyntaxException}. - */ - public static URI getCorrectedFilePathUri(final String uri) throws URISyntaxException { - return new URI(WINDOWS_DIRECTORY_SEPARATOR.matcher(uri).replaceAll("/")); - } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/log4j-core/src/main/java/org/apache/logging/log4j/core/util/NetUtils.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/NetUtils.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/NetUtils.java index 41b6df4..e9c55f4 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/NetUtils.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/NetUtils.java @@ -16,9 +16,14 @@ */ package org.apache.logging.log4j.core.util; +import java.io.File; import java.net.InetAddress; +import java.net.MalformedURLException; import java.net.NetworkInterface; import java.net.SocketException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; import java.net.UnknownHostException; import java.util.Enumeration; @@ -73,4 +78,25 @@ public final class NetUtils { } } + /** + * Converts a URI string or file path to a URI object + * @param path the URI string or path + * @return the URI object + */ + public static URI toURI(final String path) { + try { + // Resolves absolute URI + return new URI(path); + } catch (final URISyntaxException e) { + // A file path or a Apache Commons VFS URL might contain blanks. + // A file path may start with a driver letter + try { + final URL url = new URL(path); + return new URI(url.getProtocol(), url.getHost(), url.getPath(), null); + } catch (MalformedURLException | URISyntaxException nestedEx) { + return new File(path).toURI(); + } + } + } + } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/log4j-core/src/test/java/org/apache/logging/log4j/core/config/ConfiguratorTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/ConfiguratorTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/ConfiguratorTest.java new file mode 100644 index 0000000..6ce49dc --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/ConfiguratorTest.java @@ -0,0 +1,47 @@ +/* + * 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.config; + +import java.io.File; + +import org.apache.logging.log4j.core.LoggerContext; +import org.junit.Assert; +import org.junit.Test; + +public class ConfiguratorTest { + + @Test + public void testInitializeFromAbsoluteFilePath() { + final String path = new File("src/test/resources/log4j-list.xml").getAbsolutePath(); + testInitializeFromFilePath(path); + } + + @Test + public void testInitializeFromRelativeFilePath() { + final String path = new File("src/test/resources/log4j-list.xml").toString(); + testInitializeFromFilePath(path); + } + + private void testInitializeFromFilePath(String path) { + final LoggerContext loggerContext = Configurator.initialize(getClass().getName(), null, path); + try { + Assert.assertNotNull(loggerContext.getConfiguration().getAppender("List")); + } finally { + loggerContext.stop(); + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/log4j-core/src/test/java/org/apache/logging/log4j/core/util/FileUtilsTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/FileUtilsTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/FileUtilsTest.java index fdf2265..4294423 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/FileUtilsTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/FileUtilsTest.java @@ -25,7 +25,6 @@ import static org.junit.Assert.assertTrue; import java.io.File; import java.net.URI; -import java.net.URISyntaxException; import org.junit.Test; @@ -87,21 +86,4 @@ public class FileUtilsTest { assertFalse("file does not exist", file.exists()); } - @Test - public void testGetCorrectedFilePathUriWithoutBackslashes() throws URISyntaxException { - final String config = "file:///path/to/something/on/unix"; - final URI uri = FileUtils.getCorrectedFilePathUri(config); - - assertNotNull("The URI should not be null.", uri); - assertEquals("The URI is not correct.", "file:///path/to/something/on/unix", uri.toString()); - } - - @Test - public void testGetCorrectedFilePathUriWithBackslashes() throws URISyntaxException { - final String config = "file:///D:\\path\\to\\something/on/windows"; - final URI uri = FileUtils.getCorrectedFilePathUri(config); - - assertNotNull("The URI should not be null.", uri); - assertEquals("The URI is not correct.", "file:///D:/path/to/something/on/windows", uri.toString()); - } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/log4j-core/src/test/java/org/apache/logging/log4j/core/util/NetUtilsTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/NetUtilsTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/NetUtilsTest.java new file mode 100644 index 0000000..8702d1f --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/NetUtilsTest.java @@ -0,0 +1,57 @@ +/* + * 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.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.junit.Test; + +public class NetUtilsTest { + + @Test + public void testToUriWithoutBackslashes() throws URISyntaxException { + final String config = "file:///path/to/something/on/unix"; + final URI uri = NetUtils.toURI(config); + + assertNotNull("The URI should not be null.", uri); + assertEquals("The URI is not correct.", "file:///path/to/something/on/unix", uri.toString()); + } + + @Test + public void testToUriWithBackslashes() throws URISyntaxException { + final String config = "file:///D:\\path\\to\\something/on/windows"; + final URI uri = NetUtils.toURI(config); + + assertNotNull("The URI should not be null.", uri); + assertEquals("The URI is not correct.", "file:///D:/path/to/something/on/windows", uri.toString()); + } + + @Test + public void testToUriWindowsAbsolutePath() throws URISyntaxException { + final String config = "D:\\path\\to\\something\\on\\windows"; + final URI uri = NetUtils.toURI(config); + + assertNotNull("The URI should not be null.", uri); + assertEquals("The URI is not correct.", "file:/D:/path/to/something/on/windows", uri.toString()); + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/log4j-core/src/test/resources/log4j-list.xml ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j-list.xml b/log4j-core/src/test/resources/log4j-list.xml new file mode 100644 index 0000000..c2a92c3 --- /dev/null +++ b/log4j-core/src/test/resources/log4j-list.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> +<Configuration status="WARN"> + <Appenders> + <List name="List"> + <PatternLayout pattern="[%-5level] %c{1.} %msg%n" /> + </List> + </Appenders> + <Loggers> + <Root level="debug"> + <AppenderRef ref="List" /> + </Root> + </Loggers> +</Configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jWebInitializerImpl.java ---------------------------------------------------------------------- diff --git a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jWebInitializerImpl.java b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jWebInitializerImpl.java index a7d70d2..0ed011b 100644 --- a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jWebInitializerImpl.java +++ b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jWebInitializerImpl.java @@ -1,266 +1,266 @@ -/* - * 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.web; - -import java.net.URI; -import java.net.URL; -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.servlet.ServletContext; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.core.AbstractLifeCycle; -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.core.util.FileUtils; -import org.apache.logging.log4j.core.util.Loader; -import org.apache.logging.log4j.core.util.NetUtils; -import org.apache.logging.log4j.core.util.SetUtils; -import org.apache.logging.log4j.spi.LoggerContextFactory; - -/** - * This class initializes and deinitializes Log4j no matter how the initialization occurs. - */ -final class Log4jWebInitializerImpl extends AbstractLifeCycle implements Log4jWebLifeCycle { - - private static final String WEB_INF = "/WEB-INF/"; - - private static final long serialVersionUID = 1L; - - static { - if (Loader.isClassAvailable("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."); - } - } - - private final Map<String, String> map = new ConcurrentHashMap<>(); - private final StrSubstitutor substitutor = new StrSubstitutor(new Interpolator(map)); - private final ServletContext servletContext; - - private String name; - private NamedContextSelector namedContextSelector; - private LoggerContext loggerContext; - - private Log4jWebInitializerImpl(final ServletContext servletContext) { - this.servletContext = servletContext; - this.map.put("hostName", NetUtils.getLocalHostname()); - } - - /** - * Initializes the Log4jWebLifeCycle attribute of a ServletContext. Those who wish to obtain this object should use - * the {@link org.apache.logging.log4j.web.WebLoggerContextUtils#getWebLifeCycle(javax.servlet.ServletContext)} - * method instead. - * - * @param servletContext - * the ServletContext to initialize - * @return a new Log4jWebLifeCycle - * @since 2.0.1 - */ - protected static Log4jWebInitializerImpl initialize(final ServletContext servletContext) { - final Log4jWebInitializerImpl initializer = new Log4jWebInitializerImpl(servletContext); - servletContext.setAttribute(SUPPORT_ATTRIBUTE, initializer); - return initializer; - } - - @Override - public synchronized void start() { - if (this.isStopped() || this.isStopping()) { - throw new IllegalStateException("Cannot start this Log4jWebInitializerImpl after it was stopped."); - } - - // only do this once - if (this.isInitialized()) { - super.setStarting(); - - 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".equalsIgnoreCase(this.servletContext - .getInitParameter(IS_LOG4J_CONTEXT_SELECTOR_NAMED)); - - if (isJndi) { - this.initializeJndi(location); - } else { - this.initializeNonJndi(location); - } - - this.servletContext.setAttribute(CONTEXT_ATTRIBUTE, this.loggerContext); - super.setStarted(); - } - } - - private void initializeJndi(final String location) { - final URI configLocation = getConfigURI(location); - - if (this.name == null) { - throw new IllegalStateException("A log4jContextName context parameter is required"); - } - - LoggerContext context; - final LoggerContextFactory factory = LogManager.getFactory(); - if (factory instanceof Log4jContextFactory) { - final ContextSelector selector = ((Log4jContextFactory) factory).getSelector(); - if (selector instanceof NamedContextSelector) { - this.namedContextSelector = (NamedContextSelector) selector; - context = this.namedContextSelector.locateContext(this.name, this.servletContext, configLocation); - ContextAnchor.THREAD_CONTEXT.set(context); - if (context.isInitialized()) { - context.start(); - } - ContextAnchor.THREAD_CONTEXT.remove(); - } else { - LOGGER.warn("Potential problem: Selector is not an instance of NamedContextSelector."); - return; - } - } else { - LOGGER.warn("Potential problem: LoggerContextFactory is not an instance of Log4jContextFactory."); - return; - } - this.loggerContext = context; - LOGGER.debug("Created logger context for [{}] using [{}].", this.name, context.getClass().getClassLoader()); - } - - private void initializeNonJndi(final String location) { - if (this.name == null) { - this.name = this.servletContext.getServletContextName(); - LOGGER.debug("Using the servlet context name \"{}\".", this.name); - } - - if (this.name == null && location == null) { - LOGGER.error("No Log4j context configuration provided. This is very unusual."); - return; - } - - final URI uri = getConfigURI(location); - this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), uri, this.servletContext); - } - - private URI getConfigURI(final String location) { - try { - String configLocation = location; - if (configLocation == null) { - final String[] paths = SetUtils.prefixSet(servletContext.getResourcePaths(WEB_INF), WEB_INF + "log4j2"); - LOGGER.debug("getConfigURI found resource paths {} in servletConext at [{}]", Arrays.toString(paths), WEB_INF); - if (paths.length == 1) { - configLocation = paths[0]; - } else if (paths.length > 1) { - final String prefix = WEB_INF + "log4j2-" + this.name + "."; - boolean found = false; - for (final String str : paths) { - if (str.startsWith(prefix)) { - configLocation = str; - found = true; - break; - } - } - if (!found) { - configLocation = paths[0]; - } - } - } - if (configLocation != null) { - final URL url = servletContext.getResource(configLocation); - if (url != null) { - final URI uri = url.toURI(); - LOGGER.debug("getConfigURI found resource [{}] in servletConext at [{}]", uri, configLocation); - return uri; - } - } - } catch (final Exception ex) { - // Just try passing the location. - } - if (location != null) { - try { - final URI correctedFilePathUri = FileUtils.getCorrectedFilePathUri(location); - LOGGER.debug("getConfigURI found [{}] in servletConext at [{}]", correctedFilePathUri, location); - return correctedFilePathUri; - } catch (final Exception e) { - LOGGER.error("Unable to convert configuration location [{}] to a URI", location, e); - } - } - return null; - } - - @Override - public synchronized void stop() { - if (!this.isStarted() && !this.isStopped()) { - throw new IllegalStateException("Cannot stop this Log4jWebInitializer because it has not started."); - } - - // only do this once - if (this.isStarted()) { - this.setStopping(); - if (this.loggerContext != null) { - LOGGER.debug("Removing LoggerContext for [{}].", this.name); - this.servletContext.removeAttribute(CONTEXT_ATTRIBUTE); - if (this.namedContextSelector != null) { - this.namedContextSelector.removeContext(this.name); - } - this.loggerContext.stop(); - this.loggerContext.setExternalContext(null); - this.loggerContext = null; - } - this.setStopped(); - } - } - - @Override - public void setLoggerContext() { - if (this.loggerContext != null) { - ContextAnchor.THREAD_CONTEXT.set(this.loggerContext); - } - } - - @Override - public void clearLoggerContext() { - ContextAnchor.THREAD_CONTEXT.remove(); - } - - @Override - public void wrapExecution(final Runnable runnable) { - this.setLoggerContext(); - - try { - runnable.run(); - } finally { - this.clearLoggerContext(); - } - } - - 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(); - } - } - -} +/* + * 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.web; + +import java.net.URI; +import java.net.URL; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.servlet.ServletContext; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.AbstractLifeCycle; +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.core.util.FileUtils; +import org.apache.logging.log4j.core.util.Loader; +import org.apache.logging.log4j.core.util.NetUtils; +import org.apache.logging.log4j.core.util.SetUtils; +import org.apache.logging.log4j.spi.LoggerContextFactory; + +/** + * This class initializes and deinitializes Log4j no matter how the initialization occurs. + */ +final class Log4jWebInitializerImpl extends AbstractLifeCycle implements Log4jWebLifeCycle { + + private static final String WEB_INF = "/WEB-INF/"; + + private static final long serialVersionUID = 1L; + + static { + if (Loader.isClassAvailable("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."); + } + } + + private final Map<String, String> map = new ConcurrentHashMap<>(); + private final StrSubstitutor substitutor = new StrSubstitutor(new Interpolator(map)); + private final ServletContext servletContext; + + private String name; + private NamedContextSelector namedContextSelector; + private LoggerContext loggerContext; + + private Log4jWebInitializerImpl(final ServletContext servletContext) { + this.servletContext = servletContext; + this.map.put("hostName", NetUtils.getLocalHostname()); + } + + /** + * Initializes the Log4jWebLifeCycle attribute of a ServletContext. Those who wish to obtain this object should use + * the {@link org.apache.logging.log4j.web.WebLoggerContextUtils#getWebLifeCycle(javax.servlet.ServletContext)} + * method instead. + * + * @param servletContext + * the ServletContext to initialize + * @return a new Log4jWebLifeCycle + * @since 2.0.1 + */ + protected static Log4jWebInitializerImpl initialize(final ServletContext servletContext) { + final Log4jWebInitializerImpl initializer = new Log4jWebInitializerImpl(servletContext); + servletContext.setAttribute(SUPPORT_ATTRIBUTE, initializer); + return initializer; + } + + @Override + public synchronized void start() { + if (this.isStopped() || this.isStopping()) { + throw new IllegalStateException("Cannot start this Log4jWebInitializerImpl after it was stopped."); + } + + // only do this once + if (this.isInitialized()) { + super.setStarting(); + + 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".equalsIgnoreCase(this.servletContext + .getInitParameter(IS_LOG4J_CONTEXT_SELECTOR_NAMED)); + + if (isJndi) { + this.initializeJndi(location); + } else { + this.initializeNonJndi(location); + } + + this.servletContext.setAttribute(CONTEXT_ATTRIBUTE, this.loggerContext); + super.setStarted(); + } + } + + private void initializeJndi(final String location) { + final URI configLocation = getConfigURI(location); + + if (this.name == null) { + throw new IllegalStateException("A log4jContextName context parameter is required"); + } + + LoggerContext context; + final LoggerContextFactory factory = LogManager.getFactory(); + if (factory instanceof Log4jContextFactory) { + final ContextSelector selector = ((Log4jContextFactory) factory).getSelector(); + if (selector instanceof NamedContextSelector) { + this.namedContextSelector = (NamedContextSelector) selector; + context = this.namedContextSelector.locateContext(this.name, this.servletContext, configLocation); + ContextAnchor.THREAD_CONTEXT.set(context); + if (context.isInitialized()) { + context.start(); + } + ContextAnchor.THREAD_CONTEXT.remove(); + } else { + LOGGER.warn("Potential problem: Selector is not an instance of NamedContextSelector."); + return; + } + } else { + LOGGER.warn("Potential problem: LoggerContextFactory is not an instance of Log4jContextFactory."); + return; + } + this.loggerContext = context; + LOGGER.debug("Created logger context for [{}] using [{}].", this.name, context.getClass().getClassLoader()); + } + + private void initializeNonJndi(final String location) { + if (this.name == null) { + this.name = this.servletContext.getServletContextName(); + LOGGER.debug("Using the servlet context name \"{}\".", this.name); + } + + if (this.name == null && location == null) { + LOGGER.error("No Log4j context configuration provided. This is very unusual."); + return; + } + + final URI uri = getConfigURI(location); + this.loggerContext = Configurator.initialize(this.name, this.getClassLoader(), uri, this.servletContext); + } + + private URI getConfigURI(final String location) { + try { + String configLocation = location; + if (configLocation == null) { + final String[] paths = SetUtils.prefixSet(servletContext.getResourcePaths(WEB_INF), WEB_INF + "log4j2"); + LOGGER.debug("getConfigURI found resource paths {} in servletConext at [{}]", Arrays.toString(paths), WEB_INF); + if (paths.length == 1) { + configLocation = paths[0]; + } else if (paths.length > 1) { + final String prefix = WEB_INF + "log4j2-" + this.name + "."; + boolean found = false; + for (final String str : paths) { + if (str.startsWith(prefix)) { + configLocation = str; + found = true; + break; + } + } + if (!found) { + configLocation = paths[0]; + } + } + } + if (configLocation != null) { + final URL url = servletContext.getResource(configLocation); + if (url != null) { + final URI uri = url.toURI(); + LOGGER.debug("getConfigURI found resource [{}] in servletConext at [{}]", uri, configLocation); + return uri; + } + } + } catch (final Exception ex) { + // Just try passing the location. + } + if (location != null) { + try { + final URI correctedFilePathUri = NetUtils.toURI(location); + LOGGER.debug("getConfigURI found [{}] in servletConext at [{}]", correctedFilePathUri, location); + return correctedFilePathUri; + } catch (final Exception e) { + LOGGER.error("Unable to convert configuration location [{}] to a URI", location, e); + } + } + return null; + } + + @Override + public synchronized void stop() { + if (!this.isStarted() && !this.isStopped()) { + throw new IllegalStateException("Cannot stop this Log4jWebInitializer because it has not started."); + } + + // only do this once + if (this.isStarted()) { + this.setStopping(); + if (this.loggerContext != null) { + LOGGER.debug("Removing LoggerContext for [{}].", this.name); + this.servletContext.removeAttribute(CONTEXT_ATTRIBUTE); + if (this.namedContextSelector != null) { + this.namedContextSelector.removeContext(this.name); + } + this.loggerContext.stop(); + this.loggerContext.setExternalContext(null); + this.loggerContext = null; + } + this.setStopped(); + } + } + + @Override + public void setLoggerContext() { + if (this.loggerContext != null) { + ContextAnchor.THREAD_CONTEXT.set(this.loggerContext); + } + } + + @Override + public void clearLoggerContext() { + ContextAnchor.THREAD_CONTEXT.remove(); + } + + @Override + public void wrapExecution(final Runnable runnable) { + this.setLoggerContext(); + + try { + runnable.run(); + } finally { + this.clearLoggerContext(); + } + } + + 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(); + } + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1542ec12/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 85cc20f..3779165 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -66,6 +66,9 @@ <action issue="LOG4J2-1114" dev="ggregory" type="update"> Add thread name to status logger layout. </action> + <action issue="LOG4J2-1123" dev="ggregory" type="fix" due-to="Gary Gregory"> + Core Configurator.initialize(String, ClassLoader, String) fails to work when config location is a file path. + </action> <action issue="LOG4J2-1117" dev="ggregory" type="fix" due-to="Marcus Thiesen"> OutputStreamManager in ConsoleAppender leaking managers. </action>
