You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2012/09/03 02:03:27 UTC

svn commit: r1380097 - in /logging/log4j/log4j2/trunk: core/src/main/java/org/apache/logging/log4j/core/ core/src/main/java/org/apache/logging/log4j/core/config/ core/src/main/java/org/apache/logging/log4j/core/config/plugins/ core/src/main/java/org/ap...

Author: rgoers
Date: Mon Sep  3 00:03:26 2012
New Revision: 1380097

URL: http://svn.apache.org/viewvc?rev=1380097&view=rev
Log:
Fix LOG4J2-75 - Add ability to specify configruation file in Log4jContextListener. Fix automatic reconfiguration

Added:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Reconfigurable.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/Log4jContextListener.java
      - copied, changed from r1374809, logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/ContextListener.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/javaee/
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/javaee/Log4jContextListenerTest.java
    logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-config.xml
      - copied, changed from r1374809, logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-perf.xml
Removed:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/ContextListener.java
Modified:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Logger.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/BaseConfiguration.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationListener.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/FileConfigurationMonitor.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/XMLConfiguration.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/plugins/ResolverUtil.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/FileUtils.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/JNDIContextFilter.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/XMLConfigurationPropsTest.java
    logging/log4j/log4j2/trunk/src/changes/changes.xml

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Logger.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Logger.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Logger.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/Logger.java Mon Sep  3 00:03:26 2012
@@ -112,6 +112,7 @@ public class Logger extends AbstractLogg
         if (data == null) {
             data = new SimpleMessage("");
         }
+        config.config.getConfigurationMonitor().checkConfiguration();
         config.loggerConfig.log(name, marker, fqcn, level, data, t);
     }
 
@@ -288,10 +289,12 @@ public class Logger extends AbstractLogg
         }
 
         protected void logEvent(LogEvent event) {
+            config.getConfigurationMonitor().checkConfiguration();
             loggerConfig.log(event);
         }
 
         boolean filter(Level level, Marker marker, String msg) {
+            config.getConfigurationMonitor().checkConfiguration();
             Filter filter = config.getFilter();
             if (filter != null) {
                 Filter.Result r = filter.filter(logger, level, marker, msg);
@@ -304,6 +307,7 @@ public class Logger extends AbstractLogg
         }
 
         boolean filter(Level level, Marker marker, String msg, Throwable t) {
+            config.getConfigurationMonitor().checkConfiguration();
             Filter filter = config.getFilter();
             if (filter != null) {
                 Filter.Result r = filter.filter(logger, level, marker, msg, t);
@@ -316,6 +320,7 @@ public class Logger extends AbstractLogg
         }
 
         boolean filter(Level level, Marker marker, String msg, Object p1) {
+            config.getConfigurationMonitor().checkConfiguration();
             Filter filter = config.getFilter();
             if (filter != null) {
                 Filter.Result r = filter.filter(logger, level, marker, msg, p1);
@@ -328,6 +333,7 @@ public class Logger extends AbstractLogg
         }
 
         boolean filter(Level level, Marker marker, String msg, Object p1, Object p2) {
+            config.getConfigurationMonitor().checkConfiguration();
             Filter filter = config.getFilter();
             if (filter != null) {
                 Filter.Result r = filter.filter(logger, level, marker, msg, p1, p2);
@@ -340,6 +346,7 @@ public class Logger extends AbstractLogg
         }
 
         boolean filter(Level level, Marker marker, String msg, Object p1, Object p2, Object p3) {
+            config.getConfigurationMonitor().checkConfiguration();
             Filter filter = config.getFilter();
             if (filter != null) {
                 Filter.Result r = filter.filter(logger, level, marker, msg, p1, p2, p3);
@@ -353,6 +360,7 @@ public class Logger extends AbstractLogg
 
         boolean filter(Level level, Marker marker, String msg, Object p1, Object p2, Object p3,
                        Object... params) {
+            config.getConfigurationMonitor().checkConfiguration();
             Filter filter = config.getFilter();
             if (filter != null) {
                 Filter.Result r = filter.filter(logger, level, marker, msg, p1, p2, p3, params);
@@ -365,6 +373,7 @@ public class Logger extends AbstractLogg
         }
 
         boolean filter(Level level, Marker marker, Object msg, Throwable t) {
+            config.getConfigurationMonitor().checkConfiguration();
             Filter filter = config.getFilter();
             if (filter != null) {
                 Filter.Result r = filter.filter(logger, level, marker, msg, t);
@@ -377,6 +386,7 @@ public class Logger extends AbstractLogg
         }
 
         boolean filter(Level level, Marker marker, Message msg, Throwable t) {
+            config.getConfigurationMonitor().checkConfiguration();
             Filter filter = config.getFilter();
             if (filter != null) {
                 Filter.Result r = filter.filter(logger, level, marker, msg, t);

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java Mon Sep  3 00:03:26 2012
@@ -21,6 +21,7 @@ import org.apache.logging.log4j.core.con
 import org.apache.logging.log4j.core.config.ConfigurationListener;
 import org.apache.logging.log4j.core.config.DefaultConfiguration;
 import org.apache.logging.log4j.core.config.NullConfiguration;
+import org.apache.logging.log4j.core.config.Reconfigurable;
 import org.apache.logging.log4j.status.StatusLogger;
 
 import java.io.File;
@@ -276,8 +277,15 @@ public class LoggerContext implements or
     /**
      * Cause a reconfiguration to take place when the underlying configuration file changes.
      */
-    public void onChange() {
-        reconfigure();
+    public synchronized void onChange(Reconfigurable reconfigurable) {
+        logger.debug("Reconfiguration started for context " + contextName);
+        Configuration config = reconfigurable.reconfigure();
+        if (config != null) {
+            setConfiguration(config);
+            logger.debug("Reconfiguration completed");
+        } else {
+            logger.debug("Reconfiguration failed");
+        }
     }
 
 

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/BaseConfiguration.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/BaseConfiguration.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/BaseConfiguration.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/BaseConfiguration.java Mon Sep  3 00:03:26 2012
@@ -185,11 +185,8 @@ public class BaseConfiguration extends F
             LOGGER.warn("No Root logger was configured, using default");
         }
 
-        root.setConfigurationMonitor(monitor);
-
         for (Map.Entry<String, LoggerConfig> entry : loggers.entrySet()) {
             LoggerConfig l = entry.getValue();
-            l.setConfigurationMonitor(monitor);
             for (AppenderRef ref : l.getAppenderRefs()) {
                 Appender app = appenders.get(ref.getRef());
                 if (app != null) {
@@ -269,6 +266,10 @@ public class BaseConfiguration extends F
         return subst;
     }
 
+    public ConfigurationMonitor getConfigurationMonitor() {
+        return monitor;
+    }
+
     /**
      * Associates an Appender with a LoggerConfig. This method is synchronized in case a Logger with the
      * same name is being updated at the same time.
@@ -286,7 +287,6 @@ public class BaseConfiguration extends F
             lc.addAppender(appender, null, null);
         } else {
             LoggerConfig nlc = new LoggerConfig(name, lc.getLevel(), lc.isAdditive());
-            nlc.setConfigurationMonitor(monitor);
             nlc.addAppender(appender, null, null);
             nlc.setParent(lc);
             loggers.putIfAbsent(name, nlc);
@@ -311,7 +311,6 @@ public class BaseConfiguration extends F
             lc.addFilter(filter);
         } else {
             LoggerConfig nlc = new LoggerConfig(name, lc.getLevel(), lc.isAdditive());
-            nlc.setConfigurationMonitor(monitor);
             nlc.addFilter(filter);
             nlc.setParent(lc);
             loggers.putIfAbsent(name, nlc);
@@ -335,7 +334,6 @@ public class BaseConfiguration extends F
             lc.setAdditive(additive);
         } else {
             LoggerConfig nlc = new LoggerConfig(name, lc.getLevel(), additive);
-            nlc.setConfigurationMonitor(monitor);
             nlc.setParent(lc);
             loggers.putIfAbsent(name, nlc);
             setParents();

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java Mon Sep  3 00:03:26 2012
@@ -73,4 +73,6 @@ public interface Configuration extends F
     Object getComponent(String name);
 
     void addComponent(String name, Object object);
+
+    ConfigurationMonitor getConfigurationMonitor();
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java Mon Sep  3 00:03:26 2012
@@ -199,12 +199,20 @@ public abstract class ConfigurationFacto
         if (configFile != null && configFile.exists() && configFile.canRead()) {
             try {
                 InputSource source = new InputSource(new FileInputStream(configFile));
-                source.setSystemId(configLocation.getPath());
+                source.setSystemId(configFile.getAbsolutePath());
                 return source;
             } catch (FileNotFoundException ex) {
                 LOGGER.error("Cannot locate file " + configLocation.getPath(), ex);
             }
         }
+        String scheme = configLocation.getScheme();
+        if (scheme == null || scheme.equals("classloader")) {
+            ClassLoader loader = this.getClass().getClassLoader();
+            InputSource source = getInputFromResource(configLocation.getPath(), loader);
+            if (source != null) {
+                return source;
+            }
+        }
         try {
             InputSource source = new InputSource(configLocation.toURL().openStream());
             source.setSystemId(configLocation.getPath());
@@ -213,6 +221,8 @@ public abstract class ConfigurationFacto
             LOGGER.error("Invalid URL " + configLocation.toString(), ex);
         } catch (IOException ex) {
             LOGGER.error("Unable to access " + configLocation.toString(), ex);
+        } catch (Exception ex){
+            LOGGER.error("Unable to access " + configLocation.toString(), ex);
         }
         return null;
     }
@@ -347,9 +357,16 @@ public abstract class ConfigurationFacto
                 }
             } else {
                 for (ConfigurationFactory factory : factories) {
-                    Configuration config = factory.getConfiguration(name, configLocation);
-                    if (config != null) {
-                        return config;
+                    String[] types = factory.getSupportedTypes();
+                    if (types != null) {
+                        for (String type : types) {
+                            if (type.equals("*") || configLocation.getPath().endsWith(type)) {
+                                Configuration config = factory.getConfiguration(name, configLocation);
+                                if (config != null) {
+                                    return config;
+                                }
+                            }
+                        }
                     }
                 }
             }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationListener.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationListener.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationListener.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationListener.java Mon Sep  3 00:03:26 2012
@@ -21,5 +21,5 @@ package org.apache.logging.log4j.core.co
  */
 public interface ConfigurationListener {
 
-    void onChange();
+    void onChange(Reconfigurable reconfigurable);
 }

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java?rev=1380097&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java Mon Sep  3 00:03:26 2012
@@ -0,0 +1,54 @@
+/*
+ * 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 org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.xml.sax.InputSource;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URL;
+
+/**
+ *
+ */
+public final class Configurator {
+
+    private Configurator() {
+    }
+
+    public static LoggerContext intitalize(String name, String configLocation) {
+
+        try {
+            LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+            URI uri = configLocation == null ? null : new URI(configLocation);
+            Configuration config = ConfigurationFactory.getInstance().getConfiguration(name, uri);
+            ctx.setConfiguration(config);
+            return ctx;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+    public static void shutdown() {
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        ctx.setConfiguration(new DefaultConfiguration());
+    }
+
+}

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/FileConfigurationMonitor.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/FileConfigurationMonitor.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/FileConfigurationMonitor.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/FileConfigurationMonitor.java Mon Sep  3 00:03:26 2012
@@ -27,7 +27,7 @@ public class FileConfigurationMonitor im
 
     private static final int MASK = 0x0f;
 
-    private static final int MIN_INTERVAL = 30;
+    private static final int MIN_INTERVAL = 5;
 
     private static final int MILLIS_PER_SECOND = 1000;
 
@@ -43,13 +43,17 @@ public class FileConfigurationMonitor im
 
     private volatile int counter = 0;
 
+    private Reconfigurable reconfigurable;
+
     /**
      * Constructor.
      * @param file The File to monitor.
      * @param listeners The List of ConfigurationListeners to notify upon a change.
      * @param interval The monitor interval in seconds. The minimum interval is 30 seconds.
      */
-    public FileConfigurationMonitor(File file, List<ConfigurationListener> listeners, int interval) {
+    public FileConfigurationMonitor(Reconfigurable reconfigurable, File file, List<ConfigurationListener> listeners,
+                                    int interval) {
+        this.reconfigurable = reconfigurable;
         this.file = file;
         this.lastModified = file.lastModified();
         this.listeners = listeners;
@@ -66,10 +70,10 @@ public class FileConfigurationMonitor im
                 long current = System.currentTimeMillis();
                 if (current >= nextCheck) {
                     nextCheck = current + interval;
-                    if (lastModified >= file.lastModified()) {
+                    if (file.lastModified() > lastModified) {
                         lastModified = file.lastModified();
                         for (ConfigurationListener listener : listeners) {
-                            listener.onChange();
+                            listener.onChange(reconfigurable);
                         }
                     }
                 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java Mon Sep  3 00:03:26 2012
@@ -31,6 +31,8 @@ import org.xml.sax.InputSource;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -41,7 +43,7 @@ import java.util.Map;
 /**
  * Creates a Node hierarchy from a JSON file.
  */
-public class JSONConfiguration extends BaseConfiguration {
+public class JSONConfiguration extends BaseConfiguration implements Reconfigurable {
 
     private static final String[] VERBOSE_CLASSES = new String[] {ResolverUtil.class.getName()};
 
@@ -53,7 +55,10 @@ public class JSONConfiguration extends B
 
     private List<String> messages = new ArrayList<String>();
 
+    private File configFile;
+
     public JSONConfiguration(InputSource source, File configFile) {
+        this.configFile = configFile;
         byte[] buffer;
 
         try {
@@ -88,7 +93,7 @@ public class JSONConfiguration extends B
                 } else if ("monitorInterval".equalsIgnoreCase(entry.getKey())) {
                     int interval = Integer.parseInt(getSubst().replace(entry.getValue()));
                     if (interval > 0 && configFile != null) {
-                        monitor = new FileConfigurationMonitor(configFile, listeners, interval);
+                        monitor = new FileConfigurationMonitor(this, configFile, listeners, interval);
                     }
                 }
             }
@@ -146,6 +151,19 @@ public class JSONConfiguration extends B
         }
     }
 
+    public Configuration reconfigure() {
+        if (configFile != null) {
+            try {
+                InputSource source = new InputSource(new FileInputStream(configFile));
+                source.setSystemId(configFile.getAbsolutePath());
+                return new JSONConfiguration(source, configFile);
+            } catch (FileNotFoundException ex) {
+                LOGGER.error("Cannot locate file " + configFile, ex);
+            }
+        }
+        return null;
+    }
+
     private Node constructNode(String name, Node parent, JsonNode jsonNode) {
         PluginType type = getPluginManager().getPluginType(name);
         Node node = new Node(parent, name, type);

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java Mon Sep  3 00:03:26 2012
@@ -61,7 +61,6 @@ public class LoggerConfig extends Filter
     private Level level;
     private boolean additive = true;
     private LoggerConfig parent;
-    private ConfigurationMonitor monitor = new DefaultConfigurationMonitor();
     private AtomicInteger counter = new AtomicInteger();
     private boolean shutdown = false;
 
@@ -100,19 +99,10 @@ public class LoggerConfig extends Filter
 
     @Override
     public Filter getFilter() {
-        monitor.checkConfiguration();
         return super.getFilter();
     }
 
     /**
-     * Set the ConfigurationMonitor that will detect configuration changes.
-     * @param monitor The ConfigurationMonitor.
-     */
-    public void setConfigurationMonitor(ConfigurationMonitor monitor) {
-        this.monitor = monitor;
-    }
-
-    /**
      * Return the name of the LoggerConfig.
      * @return the name of the LoggerConfig.
      */
@@ -291,7 +281,6 @@ public class LoggerConfig extends Filter
 
         counter.incrementAndGet();
         try {
-            monitor.checkConfiguration();
             if (isFiltered(event)) {
                 return;
             }

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Reconfigurable.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Reconfigurable.java?rev=1380097&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Reconfigurable.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/Reconfigurable.java Mon Sep  3 00:03:26 2012
@@ -0,0 +1,9 @@
+package org.apache.logging.log4j.core.config;
+
+/**
+ *  Interface to be implemented by Configurations that can be reconfigured at runtime.
+ */
+public interface Reconfigurable {
+
+    Configuration reconfigure();
+}

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/XMLConfiguration.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/XMLConfiguration.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/XMLConfiguration.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/XMLConfiguration.java Mon Sep  3 00:03:26 2012
@@ -44,6 +44,8 @@ import javax.xml.validation.Validator;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -54,7 +56,7 @@ import java.util.Map;
 /**
  * Creates a Node hierarchy from an XML file.
  */
-public class XMLConfiguration extends BaseConfiguration {
+public class XMLConfiguration extends BaseConfiguration implements Reconfigurable {
 
     private static final String[] VERBOSE_CLASSES = new String[] {ResolverUtil.class.getName()};
 
@@ -74,7 +76,10 @@ public class XMLConfiguration extends Ba
 
     private List<String> messages = new ArrayList<String>();
 
+    private File configFile;
+
     public XMLConfiguration(InputSource source, File configFile) {
+        this.configFile = configFile;
         byte[] buffer = null;
 
         try {
@@ -110,7 +115,7 @@ public class XMLConfiguration extends Ba
                 } else if ("monitorInterval".equalsIgnoreCase(entry.getKey())) {
                     int interval = Integer.parseInt(getSubst().replace(entry.getValue()));
                     if (interval > 0 && configFile != null) {
-                        monitor = new FileConfigurationMonitor(configFile, listeners, interval);
+                        monitor = new FileConfigurationMonitor(this, configFile, listeners, interval);
                     }
                 }
             }
@@ -189,6 +194,19 @@ public class XMLConfiguration extends Ba
         rootElement = null;
     }
 
+    public Configuration reconfigure() {
+        if (configFile != null) {
+            try {
+                InputSource source = new InputSource(new FileInputStream(configFile));
+                source.setSystemId(configFile.getAbsolutePath());
+                return new XMLConfiguration(source, configFile);
+            } catch (FileNotFoundException ex) {
+                LOGGER.error("Cannot locate file " + configFile, ex);
+            }
+        }
+        return null;
+    }
+
     private void constructHierarchy(Node node, Element element) {
         processAttributes(node, element);
         StringBuffer buffer = new StringBuffer();

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/plugins/ResolverUtil.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/plugins/ResolverUtil.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/plugins/ResolverUtil.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/plugins/ResolverUtil.java Mon Sep  3 00:03:26 2012
@@ -21,6 +21,7 @@ import org.apache.logging.log4j.status.S
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.net.URI;
@@ -78,6 +79,8 @@ public class ResolverUtil<T> {
     /** The set of matches being accumulated. */
     private Set<URI> resourceMatches = new HashSet<URI>();
 
+    private static final String VFSZIP = "vfszip";
+
     /**
      * The ClassLoader to use when looking for classes. If null then the ClassLoader returned
      * by Thread.currentThread().getContextClassLoader() will be used.
@@ -229,7 +232,8 @@ public class ResolverUtil<T> {
 
         while (urls.hasMoreElements()) {
             try {
-                String urlPath = urls.nextElement().getFile();
+                URL url = urls.nextElement();
+                String urlPath = url.getFile();
                 urlPath = URLDecoder.decode(urlPath, "UTF-8");
 
                 // If it's a file in a directory, trim the stupid file: spec
@@ -243,11 +247,19 @@ public class ResolverUtil<T> {
                 }
 
                 LOG.info("Scanning for classes in [" + urlPath + "] matching criteria: " + test);
-                File file = new File(urlPath);
-                if (file.isDirectory()) {
-                    loadImplementationsInDirectory(test, packageName, file);
+                // Check for a jar in a war in JBoss
+                if (VFSZIP.equals(url.getProtocol())) {
+                    String path = urlPath.substring(0, urlPath.length() - packageName.length() - 2);
+                    URL newURL = new URL(url.getProtocol(), url.getHost(), path);
+                    JarInputStream stream = new JarInputStream(newURL.openStream());
+                    loadImplementationsInJar(test, packageName, path, stream);
                 } else {
-                    loadImplementationsInJar(test, packageName, file);
+                    File file = new File(urlPath);
+                    if (file.isDirectory()) {
+                        loadImplementationsInDirectory(test, packageName, file);
+                    } else {
+                        loadImplementationsInJar(test, packageName, file);
+                    }
                 }
             } catch (IOException ioe) {
                 LOG.warn("could not read entries", ioe);
@@ -299,20 +311,42 @@ public class ResolverUtil<T> {
      * @param jarfile the jar file to be examined for classes
      */
     private void loadImplementationsInJar(Test test, String parent, File jarfile) {
+        JarInputStream jarStream;
+        try {
+            jarStream = new JarInputStream(new FileInputStream(jarfile));
+            loadImplementationsInJar(test, parent, jarfile.getPath(), jarStream);
+        } catch (FileNotFoundException ex) {
+            LOG.error("Could not search jar file '" + jarfile + "' for classes matching criteria: " +
+                test + " file not found");
+        } catch (IOException ioe) {
+            LOG.error("Could not search jar file '" + jarfile + "' for classes matching criteria: " +
+                test + " due to an IOException", ioe);
+        }
+    }
+
+    /**
+     * Finds matching classes within a jar files that contains a folder structure
+     * matching the package structure.  If the File is not a JarFile or does not exist a warning
+     * will be logged, but no error will be raised.
+     *
+     * @param test a Test used to filter the classes that are discovered
+     * @param parent the parent package under which classes must be in order to be considered
+     * @param stream The jar InputStream
+     */
+    private void loadImplementationsInJar(Test test, String parent, String path, JarInputStream stream) {
 
         try {
             JarEntry entry;
-            JarInputStream jarStream = new JarInputStream(new FileInputStream(jarfile));
 
-            while ((entry = jarStream.getNextJarEntry()) != null) {
+            while ((entry = stream.getNextJarEntry()) != null) {
                 String name = entry.getName();
                 if (!entry.isDirectory() && name.startsWith(parent) && isTestApplicable(test, name)) {
                     addIfMatching(test, name);
                 }
             }
         } catch (IOException ioe) {
-            LOG.error("Could not search jar file '" + jarfile + "' for classes matching criteria: " +
-                      test + " due to an IOException", ioe);
+            LOG.error("Could not search jar file '" + path + "' for classes matching criteria: " +
+                test + " due to an IOException", ioe);
         }
     }
 

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/FileUtils.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/FileUtils.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/FileUtils.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/helpers/FileUtils.java Mon Sep  3 00:03:26 2012
@@ -38,6 +38,8 @@ public final class FileUtils {
 
     private static Logger logger = StatusLogger.getLogger();
 
+
+
     private FileUtils() {
     }
 
@@ -49,9 +51,18 @@ public final class FileUtils {
      * @return the resulting file object
      */
     public static File fileFromURI(URI uri) {
-        if (uri == null || !uri.getScheme().equals(PROTOCOL_FILE) || !uri.getScheme().equals(JBOSS_FILE)) {
+        if (uri == null || (uri.getScheme() != null &&
+            (!PROTOCOL_FILE.equals(uri.getScheme()) && !JBOSS_FILE.equals(uri.getScheme())))) {
             return null;
         } else {
+            if (uri.getScheme() == null) {
+                try {
+                    uri = new File(uri.getPath()).toURI();
+                } catch (Exception ex) {
+                    logger.warn("Invalid URI " + uri);
+                    return null;
+                }
+            }
             try {
                 return new File(URLDecoder.decode(uri.toURL().getFile(), "UTF8"));
             } catch (MalformedURLException ex) {

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/JNDIContextFilter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/JNDIContextFilter.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/JNDIContextFilter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/JNDIContextFilter.java Mon Sep  3 00:03:26 2012
@@ -57,7 +57,7 @@ public class JNDIContextFilter implement
         if (name == null) {
             throw new UnavailableException("A context-name attribute is required");
         }
-        if (context.getAttribute(ContextListener.LOG4J_CONTEXT_ATTRIBUTE) == null) {
+        if (context.getAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE) == null) {
             LoggerContext ctx;
             LoggerContextFactory factory = LogManager.getFactory();
             if (factory instanceof Log4jContextFactory) {
@@ -71,7 +71,7 @@ public class JNDIContextFilter implement
             } else {
                 return;
             }
-            context.setAttribute(ContextListener.LOG4J_CONTEXT_ATTRIBUTE, ctx);
+            context.setAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE, ctx);
             created = true;
             context.log("Created context for " + name + " using " + ctx.getClass().getClassLoader());
         }
@@ -79,7 +79,7 @@ public class JNDIContextFilter implement
 
     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
         throws IOException, ServletException {
-        LoggerContext ctx = (LoggerContext) context.getAttribute(ContextListener.LOG4J_CONTEXT_ATTRIBUTE);
+        LoggerContext ctx = (LoggerContext) context.getAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE);
         if (ctx != null) {
             ContextAnchor.THREAD_CONTEXT.set(ctx);
             try {
@@ -93,10 +93,10 @@ public class JNDIContextFilter implement
     }
 
     public void destroy() {
-        LoggerContext ctx = (LoggerContext) context.getAttribute(ContextListener.LOG4J_CONTEXT_ATTRIBUTE);
+        LoggerContext ctx = (LoggerContext) context.getAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE);
         if (ctx != null && created) {
             context.log("Removing context for " + name);
-            context.removeAttribute(ContextListener.LOG4J_CONTEXT_ATTRIBUTE);
+            context.removeAttribute(Log4jContextListener.LOG4J_CONTEXT_ATTRIBUTE);
             if (selector != null) {
                 selector.removeContext(name);
             }

Copied: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/Log4jContextListener.java (from r1374809, logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/ContextListener.java)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/Log4jContextListener.java?p2=logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/Log4jContextListener.java&p1=logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/ContextListener.java&r1=1374809&r2=1380097&rev=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/ContextListener.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/javaee/Log4jContextListener.java Mon Sep  3 00:03:26 2012
@@ -17,6 +17,7 @@
 package org.apache.logging.log4j.core.javaee;
 
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configurator;
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
@@ -25,25 +26,33 @@ import javax.servlet.ServletContextListe
 /**
  * Saves the LoggerContext into the ServletContext as an attribute.
  */
-public class ContextListener implements ServletContextListener {
+public class Log4jContextListener implements ServletContextListener {
 
     /**
      * The name of the attribute to use to store the LoggerContext into the ServletContext.
      */
     public static final String LOG4J_CONTEXT_ATTRIBUTE = "Log4JContext";
 
+    public static final String LOG4J_CONFIG = "log4jConfiguration";
+
+    public static final String LOG4J_CONTEXT_NAME = "log4jContextName";
+
     public void contextInitialized(ServletContextEvent event) {
         ServletContext context = event.getServletContext();
-        LoggerContext ctx = new LoggerContext(context.getServletContextName(), context);
-        context.setAttribute(LOG4J_CONTEXT_ATTRIBUTE, ctx);
+        String locn = context.getInitParameter(LOG4J_CONFIG);
+        String name = context.getInitParameter(LOG4J_CONTEXT_NAME);
+        if (name == null) {
+            name = context.getServletContextName();
+        }
+        if (name == null && locn == null) {
+            context.log("No Log4j context configuration provided");
+            return;
+        }
+        context.setAttribute(LOG4J_CONTEXT_ATTRIBUTE, Configurator.intitalize(name, locn));
     }
 
     public void contextDestroyed(ServletContextEvent event) {
-        ServletContext context = event.getServletContext();
-        LoggerContext ctx = (LoggerContext) context.getAttribute(LOG4J_CONTEXT_ATTRIBUTE);
-        if (ctx != null) {
-            context.removeAttribute(LOG4J_CONTEXT_ATTRIBUTE);
-            ctx.stop();
-        }
+        event.getServletContext().removeAttribute(LOG4J_CONTEXT_ATTRIBUTE);
+        Configurator.shutdown();
     }
 }

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java?rev=1380097&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java (added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java Mon Sep  3 00:03:26 2012
@@ -0,0 +1,123 @@
+/*
+ * 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 org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Map;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ */
+public class TestConfigurator {
+
+    private static final String CONFIG_NAME = "ConfigTest";
+
+
+    @Test
+    public void testFromFile() throws Exception {
+        Configurator.intitalize("Test1", "target/test-classes/log4j2-config.xml");
+        Logger logger = LogManager.getLogger("org.apache.test.TestConfigurator");
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        Configuration config = ctx.getConfiguration();
+        assertNotNull("No configuration", config);
+        assertTrue("Incorrect Configuration. Expected " + CONFIG_NAME + " but found " + config.getName(),
+            CONFIG_NAME.equals(config.getName()));
+        Map<String, Appender> map = config.getAppenders();
+        assertNotNull("No Appenders", map != null && map.size() > 0);
+        assertTrue("Wrong configuration", map.containsKey("List"));
+        Configurator.shutdown();
+        config = ctx.getConfiguration();
+        assertTrue("Incorrect Configuration. Expected " + DefaultConfiguration.DEFAULT_NAME + " but found " +
+            config.getName(), DefaultConfiguration.DEFAULT_NAME.equals(config.getName()));
+    }
+
+    @Test
+    public void testFromClassPath() throws Exception {
+        Configurator.intitalize("Test1", "log4j2-config.xml");
+        Logger logger = LogManager.getLogger("org.apache.test.TestConfigurator");
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        Configuration config = ctx.getConfiguration();
+        assertNotNull("No configuration", config);
+        assertTrue("Incorrect Configuration. Expected " + CONFIG_NAME + " but found " + config.getName(),
+            CONFIG_NAME.equals(config.getName()));
+        Map<String, Appender> map = config.getAppenders();
+        assertNotNull("No Appenders", map != null && map.size() > 0);
+        assertTrue("Wrong configuration", map.containsKey("List"));
+        Configurator.shutdown();
+        config = ctx.getConfiguration();
+        assertTrue("Incorrect Configuration. Expected " + DefaultConfiguration.DEFAULT_NAME + " but found " +
+            config.getName(), DefaultConfiguration.DEFAULT_NAME.equals(config.getName()));
+    }
+
+    @Test
+    public void testByName() throws Exception {
+        Configurator.intitalize("-config", null);
+        Logger logger = LogManager.getLogger("org.apache.test.TestConfigurator");
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        Configuration config = ctx.getConfiguration();
+        assertNotNull("No configuration", config);
+        assertTrue("Incorrect Configuration. Expected " + CONFIG_NAME + " but found " + config.getName(),
+            CONFIG_NAME.equals(config.getName()));
+        Map<String, Appender> map = config.getAppenders();
+        assertNotNull("No Appenders", map != null && map.size() > 0);
+        assertTrue("Wrong configuration", map.containsKey("List"));
+        Configurator.shutdown();
+        config = ctx.getConfiguration();
+        assertTrue("Incorrect Configuration. Expected " + DefaultConfiguration.DEFAULT_NAME + " but found " +
+            config.getName(), DefaultConfiguration.DEFAULT_NAME.equals(config.getName()));
+    }
+
+    @Test
+    public void testReconfiguration() throws Exception {
+        File file = new File("target/test-classes/log4j2-config.xml");
+        file.setLastModified(System.currentTimeMillis() - 120000);
+        Configurator.intitalize("Test1", "target/test-classes/log4j2-config.xml");
+        Logger logger = LogManager.getLogger("org.apache.test.TestConfigurator");
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        Configuration config = ctx.getConfiguration();
+        assertNotNull("No configuration", config);
+        assertTrue("Incorrect Configuration. Expected " + CONFIG_NAME + " but found " + config.getName(),
+            CONFIG_NAME.equals(config.getName()));
+        Map<String, Appender> map = config.getAppenders();
+        assertNotNull("No Appenders", map != null && map.size() > 0);
+        assertTrue("Wrong configuration", map.containsKey("List"));
+
+        Thread.sleep(500);
+        file.setLastModified(System.currentTimeMillis());
+        for (int i = 0; i < 17; ++i) {
+            logger.debug("Test message " + i);
+        }
+        Configuration newConfig = ctx.getConfiguration();
+        assertTrue("Configuration not reset", newConfig != config);
+        Configurator.shutdown();
+        config = ctx.getConfiguration();
+        assertTrue("Incorrect Configuration. Expected " + DefaultConfiguration.DEFAULT_NAME + " but found " +
+            config.getName(), DefaultConfiguration.DEFAULT_NAME.equals(config.getName()));
+    }
+}

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/XMLConfigurationPropsTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/XMLConfigurationPropsTest.java?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/XMLConfigurationPropsTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/config/XMLConfigurationPropsTest.java Mon Sep  3 00:03:26 2012
@@ -16,25 +16,13 @@
  */
 package org.apache.logging.log4j.core.config;
 
-import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.filter.ThreadContextMapFilter;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import java.io.BufferedInputStream;
-import java.io.DataInputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.util.Iterator;
-import java.util.Map;
-
 import static org.junit.Assert.*;
 
 /**

Added: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/javaee/Log4jContextListenerTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/javaee/Log4jContextListenerTest.java?rev=1380097&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/javaee/Log4jContextListenerTest.java (added)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/javaee/Log4jContextListenerTest.java Mon Sep  3 00:03:26 2012
@@ -0,0 +1,230 @@
+/*
+ * 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.javaee;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.DefaultConfiguration;
+import org.junit.Test;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ */
+public class Log4jContextListenerTest {
+
+    private static final String CONFIG_NAME = "ConfigTest";
+
+    @Test
+    public void testFromFile() throws Exception {
+        MockServletContext context = new MockServletContext();
+        context.setInitParameter(Log4jContextListener.LOG4J_CONTEXT_NAME, "Test1");
+        context.setInitParameter(Log4jContextListener.LOG4J_CONFIG, "target/test-classes/log4j2-config.xml");
+        Log4jContextListener listener = new Log4jContextListener();
+        ServletContextEvent event = new ServletContextEvent(context);
+        listener.contextInitialized(event);
+        Logger logger = LogManager.getLogger("org.apache.test.TestConfigurator");
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        Configuration config = ctx.getConfiguration();
+        assertNotNull("No configuration", config);
+        assertTrue("Incorrect Configuration. Expected " + CONFIG_NAME + " but found " + config.getName(),
+            CONFIG_NAME.equals(config.getName()));
+        Map<String, Appender> map = config.getAppenders();
+        assertNotNull("No Appenders", map != null && map.size() > 0);
+        assertTrue("Wrong configuration", map.containsKey("List"));
+        listener.contextDestroyed(event);
+        config = ctx.getConfiguration();
+        assertTrue("Incorrect Configuration. Expected " + DefaultConfiguration.DEFAULT_NAME + " but found " +
+            config.getName(), DefaultConfiguration.DEFAULT_NAME.equals(config.getName()));
+    }
+
+    @Test
+    public void testFromClassPath() throws Exception {
+        MockServletContext context = new MockServletContext();
+        context.setInitParameter(Log4jContextListener.LOG4J_CONTEXT_NAME, "Test1");
+        context.setInitParameter(Log4jContextListener.LOG4J_CONFIG, "log4j2-config.xml");
+        Log4jContextListener listener = new Log4jContextListener();
+        ServletContextEvent event = new ServletContextEvent(context);
+        listener.contextInitialized(event);
+        Logger logger = LogManager.getLogger("org.apache.test.TestConfigurator");
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        Configuration config = ctx.getConfiguration();
+        assertNotNull("No configuration", config);
+        assertTrue("Incorrect Configuration. Expected " + CONFIG_NAME + " but found " + config.getName(),
+            CONFIG_NAME.equals(config.getName()));
+        Map<String, Appender> map = config.getAppenders();
+        assertNotNull("No Appenders", map != null && map.size() > 0);
+        assertTrue("Wrong configuration", map.containsKey("List"));
+        listener.contextDestroyed(event);
+        config = ctx.getConfiguration();
+        assertTrue("Incorrect Configuration. Expected " + DefaultConfiguration.DEFAULT_NAME + " but found " +
+            config.getName(), DefaultConfiguration.DEFAULT_NAME.equals(config.getName()));
+    }
+
+    @Test
+    public void testByName() throws Exception {
+        MockServletContext context = new MockServletContext();
+        context.setInitParameter(Log4jContextListener.LOG4J_CONTEXT_NAME, "-config");
+        Log4jContextListener listener = new Log4jContextListener();
+        ServletContextEvent event = new ServletContextEvent(context);
+        listener.contextInitialized(event);
+        Logger logger = LogManager.getLogger("org.apache.test.TestConfigurator");
+        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+        Configuration config = ctx.getConfiguration();
+        assertNotNull("No configuration", config);
+        assertTrue("Incorrect Configuration. Expected " + CONFIG_NAME + " but found " + config.getName(),
+            CONFIG_NAME.equals(config.getName()));
+        Map<String, Appender> map = config.getAppenders();
+        assertNotNull("No Appenders", map != null && map.size() > 0);
+        assertTrue("Wrong configuration", map.containsKey("List"));
+        listener.contextDestroyed(event);
+        config = ctx.getConfiguration();
+        assertTrue("Incorrect Configuration. Expected " + DefaultConfiguration.DEFAULT_NAME + " but found " +
+            config.getName(), DefaultConfiguration.DEFAULT_NAME.equals(config.getName()));
+    }
+
+
+    private class MockServletContext implements ServletContext {
+        private String name;
+
+        private Hashtable<String, String> params = new Hashtable<String, String>();
+
+        private Hashtable<String, Object> attrs = new Hashtable<String, Object>();
+
+
+        public ServletContext getContext(String s) {
+            return null;
+        }
+
+        public int getMajorVersion() {
+            return 0;
+        }
+
+        public int getMinorVersion() {
+            return 0;
+        }
+
+        public String getMimeType(String s) {
+            return null;
+        }
+
+        public Set getResourcePaths(String s) {
+            return null;
+        }
+
+        public URL getResource(String s) throws MalformedURLException {
+            return null;
+        }
+
+        public InputStream getResourceAsStream(String s) {
+            return null;
+        }
+
+        public RequestDispatcher getRequestDispatcher(String s) {
+            return null;
+        }
+
+        public RequestDispatcher getNamedDispatcher(String s) {
+            return null;
+        }
+
+        public Servlet getServlet(String s) throws ServletException {
+            return null;
+        }
+
+        public Enumeration getServlets() {
+            return null;
+        }
+
+        public Enumeration getServletNames() {
+            return null;
+        }
+
+        public void log(String s) {
+            System.out.println(s);
+        }
+
+        public void log(Exception e, String s) {
+            System.out.println(s);
+            e.printStackTrace();
+        }
+
+        public void log(String s, Throwable throwable) {
+            System.out.println(s);
+            throwable.printStackTrace();
+        }
+
+        public String getRealPath(String s) {
+            return null;
+        }
+
+        public String getServerInfo() {
+            return "Mock";
+        }
+
+        public void setInitParameter(String key, String value) {
+            params.put(key, value);
+        }
+
+        public String getInitParameter(String s) {
+            return params.get(s);
+        }
+
+        public Enumeration getInitParameterNames() {
+            return params.keys();
+        }
+
+        public Object getAttribute(String s) {
+            return attrs.get(s);
+        }
+
+        public Enumeration getAttributeNames() {
+            return attrs.keys();
+        }
+
+        public void setAttribute(String s, Object o) {
+            attrs.put(s, o);
+        }
+
+        public void removeAttribute(String s) {
+            attrs.remove(s);
+        }
+
+        public String getServletContextName() {
+            return null;
+        }
+    }
+}

Copied: logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-config.xml (from r1374809, logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-perf.xml)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-config.xml?p2=logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-config.xml&p1=logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-perf.xml&r1=1374809&r2=1380097&rev=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-perf.xml (original)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j2-config.xml Mon Sep  3 00:03:26 2012
@@ -16,17 +16,21 @@
  limitations under the License.
 
 -->
-<configuration packages="" name="XMLPerfTest" status="error">
+<configuration name="ConfigTest" status="error" packages="org.apache.logging.log4j.test"
+    monitorInterval="5">
   <appenders>
-    <File name="TestLogfile" fileName="target/testlog4j2.log" immediateFlush="false">
-      <PatternLayout>
-        <pattern>%d{ISO8601} %5p [%t] %c{1} %X{transactionId} - %m%n</pattern>
-      </PatternLayout>
-    </File>
+    <Console name="STDOUT">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+    <List name="List">
+    </List>
   </appenders>
   <loggers>
-    <root level="debug">
-      <appender-ref ref="TestLogfile"/>
+    <logger name="org.apache.test" level="trace" additivity="false">
+      <appender-ref ref="List"/>
+    </logger>
+    <root level="error">
+      <appender-ref ref="STDOUT"/>
     </root>
   </loggers>
 </configuration>
\ No newline at end of file

Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1380097&r1=1380096&r2=1380097&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Mon Sep  3 00:03:26 2012
@@ -23,6 +23,11 @@
 
   <body>
     <release version="2.0-alpha3" date="TBD" description="">
+      <action issue="LOG4J2-75" dev="rgoers" type="fix">
+        Enhanced Log4jContextListener to accept a configuration file location. Modified FileConfigurationMonitor
+        to monitor files configured that way. Fixed other reconfiguration related bugs. Tested in JBoss and
+        Tomcat.
+      </action>
       <action issue="LOG4J2-72" dev="rgoers" type="fix">
         NullPointerException in RollingFileManager when filePattern does not cause the file to be compressed.
       </action>