You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2015/09/18 17:38:50 UTC

logging-log4j2 git commit: [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).

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 <gg...@apache.org>
Authored: Fri Sep 18 08:38:42 2015 -0700
Committer: ggregory <gg...@apache.org>
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>