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/05/13 07:42:28 UTC

svn commit: r1337783 - in /logging/log4j/log4j2/trunk: core/src/main/java/org/apache/logging/log4j/core/appender/ core/src/main/java/org/apache/logging/log4j/core/appender/rewrite/ core/src/main/java/org/apache/logging/log4j/core/appender/routing/ core...

Author: rgoers
Date: Sun May 13 05:42:27 2012
New Revision: 1337783

URL: http://svn.apache.org/viewvc?rev=1337783&view=rev
Log:
Add filtering on appender-refs.

Added:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/AppenderRef.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/AppenderRefLevelTest.java
      - copied, changed from r1332056, logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java
    logging/log4j/log4j2/trunk/core/src/test/resources/log4j-reference-level.xml
      - copied, changed from r1332056, logging/log4j/log4j2/trunk/core/src/test/resources/log4j-test1.xml
Removed:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/plugins/AppenderRefPlugin.java
Modified:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FailoverAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FailoversPlugin.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rewrite/RewriteAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/routing/Route.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/AppenderControl.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/DefaultConfiguration.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/filter/BurstFilter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/MapFilter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/MarkerFilter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/ThresholdFilter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/TimeFilter.java
    logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing.json
    logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing.xml
    logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing2.json
    logging/log4j/log4j2/trunk/src/site/xdoc/manual/architecture.xml
    logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml
    logging/log4j/log4j2/trunk/src/site/xdoc/manual/filters.xml

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FailoverAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FailoverAppender.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FailoverAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FailoverAppender.java Sun May 13 05:42:27 2012
@@ -21,6 +21,7 @@ import org.apache.logging.log4j.core.App
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.AppenderControl;
+import org.apache.logging.log4j.core.config.AppenderRef;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
@@ -64,14 +65,14 @@ public final class FailoverAppender exte
         Map<String, Appender> map = config.getAppenders();
         int errors = 0;
         if (map.containsKey(primaryRef)) {
-            primary = new AppenderControl(map.get(primaryRef));
+            primary = new AppenderControl(map.get(primaryRef), null, null);
         } else {
             LOGGER.error("Unable to locate primary Appender " + primaryRef);
             ++errors;
         }
         for (String name : failovers) {
             if (map.containsKey(name)) {
-                failoverAppenders.add(new AppenderControl(map.get(name)));
+                failoverAppenders.add(new AppenderControl(map.get(name), null, null));
             } else {
                 LOGGER.error("Failover appender " + name + " is not configured");
             }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FailoversPlugin.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FailoversPlugin.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FailoversPlugin.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/FailoversPlugin.java Sun May 13 05:42:27 2012
@@ -17,6 +17,7 @@
 package org.apache.logging.log4j.core.appender;
 
 import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.config.AppenderRef;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginElement;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
@@ -42,11 +43,15 @@ public final class FailoversPlugin {
      * @return The appender references.
      */
     @PluginFactory
-    public static String[] createFailovers(@PluginElement("appender-ref") String[] refs) {
+    public static String[] createFailovers(@PluginElement("appender-ref") AppenderRef[] refs) {
 
         if (refs == null) {
-            logger.error("failovers must contain an appender-refernce");
+            logger.error("failovers must contain an appender-reference");
         }
-        return refs;
+        String[] arr = new String[refs.length];
+        for (int i=0; i < refs.length; ++i) {
+            arr[i] = refs[i].getRef();
+        }
+        return arr;
     }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rewrite/RewriteAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rewrite/RewriteAppender.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rewrite/RewriteAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rewrite/RewriteAppender.java Sun May 13 05:42:27 2012
@@ -16,11 +16,14 @@
  */
 package org.apache.logging.log4j.core.appender.rewrite;
 
+import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Lifecycle;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.appender.AppenderBase;
 import org.apache.logging.log4j.core.config.AppenderControl;
+import org.apache.logging.log4j.core.config.AppenderRef;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
@@ -40,9 +43,9 @@ public final class RewriteAppender exten
     private final Configuration config;
     private ConcurrentMap<String, AppenderControl> appenders = new ConcurrentHashMap<String, AppenderControl>();
     private final RewritePolicy rewritePolicy;
-    private final String[] appenderRefs;
+    private final AppenderRef[] appenderRefs;
 
-    private RewriteAppender(String name, Filter filter, boolean handleException, String[] appenderRefs,
+    private RewriteAppender(String name, Filter filter, boolean handleException, AppenderRef[] appenderRefs,
                             RewritePolicy rewritePolicy, Configuration config) {
         super(name, filter, null, handleException);
         this.config = config;
@@ -53,10 +56,11 @@ public final class RewriteAppender exten
     @Override
     public void start() {
         Map<String, Appender> map = config.getAppenders();
-        for (String ref : appenderRefs) {
-            Appender appender = map.get(ref);
+        for (AppenderRef ref : appenderRefs) {
+            String name = ref.getRef();
+            Appender appender = map.get(name);
             if (appender != null) {
-                appenders.put(ref, new AppenderControl(appender));
+                appenders.put(name, new AppenderControl(appender, ref.getLevel(), null));
             } else {
                 LOGGER.error("Appender " + ref + " cannot be located. Reference ignored");
             }
@@ -68,9 +72,7 @@ public final class RewriteAppender exten
     public void stop() {
         super.stop();
         for (AppenderControl control : appenders.values()) {
-            if (control instanceof AppenderWrapper) {
-                control.getAppender().stop();
-            }
+            control.getAppender().stop();
         }
     }
 
@@ -100,7 +102,7 @@ public final class RewriteAppender exten
     @PluginFactory
     public static RewriteAppender createAppender(@PluginAttr("name") String name,
                                           @PluginAttr("suppressExceptions") String suppress,
-                                          @PluginElement("appender-ref") String[] appenderRefs,
+                                          @PluginElement("appender-ref") AppenderRef[] appenderRefs,
                                           @PluginConfiguration Configuration config,
                                           @PluginElement("rewritePolicy") RewritePolicy rewritePolicy,
                                           @PluginElement("filter") Filter filter) {
@@ -117,17 +119,4 @@ public final class RewriteAppender exten
         }
         return new RewriteAppender(name, filter, handleExceptions, appenderRefs, rewritePolicy, config);
     }
-
-    /**
-     * Wrap the AppenderControl simply so it can be used here.
-     */
-    private static class AppenderWrapper extends AppenderControl {
-        /**
-         * Constructor.
-         * @param appender The Appender to wrap.
-         */
-        public AppenderWrapper(Appender appender) {
-            super(appender);
-        }
-    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/routing/Route.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/routing/Route.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/routing/Route.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/routing/Route.java Sun May 13 05:42:27 2012
@@ -91,7 +91,7 @@ public final class Route {
      * @return A Route.
      */
     @PluginFactory
-    public static Route createRoute(@PluginAttr("appender-ref") String appenderRef,
+    public static Route createRoute(@PluginAttr("ref") String appenderRef,
                                     @PluginAttr("key") String key,
                                     @PluginNode Node node) {
         if (node != null && node.hasChildren()) {

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java Sun May 13 05:42:27 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.core.appender.routing;
 
+import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.LogEvent;
@@ -73,7 +74,7 @@ public final class RoutingAppender exten
                             LOGGER.error("Duplicate route " + key + " is ignored");
                         }
                     } else {
-                        appenders.put(key, new AppenderControl(appender));
+                        appenders.put(key, new AppenderControl(appender, null, null));
                     }
                 } else {
                     LOGGER.error("Appender " + route.getAppenderRef() + " cannot be located. Route ignored");
@@ -87,9 +88,7 @@ public final class RoutingAppender exten
     public void stop() {
         super.stop();
         for (AppenderControl control : appenders.values()) {
-            if (control instanceof AppenderWrapper) {
-                control.getAppender().stop();
-            }
+            control.getAppender().stop();
         }
     }
 
@@ -135,7 +134,7 @@ public final class RoutingAppender exten
             if (app == null) {
                 return null;
             }
-            control = new AppenderWrapper(app);
+            control = new AppenderControl(app, null, null);
             appenders.put(key, control);
             if (defaultRoute) {
                 appenders.put(DEFAULT_KEY, control);
@@ -194,13 +193,4 @@ public final class RoutingAppender exten
         }
         return new RoutingAppender(name, filter, handleExceptions, routes, rewritePolicy, config);
     }
-
-    /**
-     * Wrapper to allow AppenderControl to be used here.
-     */
-    private static class AppenderWrapper extends AppenderControl {
-        public AppenderWrapper(Appender appender) {
-            super(appender);
-        }
-    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/AppenderControl.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/AppenderControl.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/AppenderControl.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/AppenderControl.java Sun May 13 05:42:27 2012
@@ -16,27 +16,37 @@
  */
 package org.apache.logging.log4j.core.config;
 
+import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Lifecycle;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.appender.AppenderRuntimeException;
+import org.apache.logging.log4j.core.filter.Filterable;
 import org.apache.logging.log4j.core.filter.Filtering;
 
 /**
  * Wraps appenders with details the appender implementation shouldn't need to know about.
  */
-public class AppenderControl {
+public class AppenderControl extends Filterable {
 
     private ThreadLocal<AppenderControl> recursive = new ThreadLocal<AppenderControl>();
 
     private final Appender appender;
 
+    private final Level level;
+    private final int intLevel;
+
     /**
      * Constructor.
      * @param appender The target Appender.
      */
-    public AppenderControl(Appender appender) {
+    public AppenderControl(Appender appender, Level level, Filter filter) {
+        super(filter);
         this.appender = appender;
+        this.level = level;
+        this.intLevel = level == null ? Level.ALL.intLevel() : level.intLevel();
+        startFilter();
     }
 
     /**
@@ -52,6 +62,17 @@ public class AppenderControl {
      * @param event The event to process.
      */
     public void callAppender(LogEvent event) {
+        if (getFilter() != null) {
+            Filter.Result r = getFilter().filter(event);
+            if (r == Filter.Result.DENY) {
+                return;
+            }
+        }
+        if (level != null) {
+            if (intLevel < event.getLevel().intLevel()) {
+                return;
+            }
+        }
         if (recursive.get() != null) {
             appender.getHandler().error("Recursive call to appender " + appender.getName());
             return;

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/AppenderRef.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/AppenderRef.java?rev=1337783&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/AppenderRef.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/AppenderRef.java Sun May 13 05:42:27 2012
@@ -0,0 +1,82 @@
+/*
+ * 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.Level;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttr;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.status.StatusLogger;
+
+/**
+ * An Appender reference.
+ */
+@Plugin(name = "appender-ref", type = "Core", printObject = true)
+public class AppenderRef {
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    private final String ref;
+    private final Level level;
+    private final Filter filter;
+
+    private AppenderRef(String ref, Level level, Filter filter) {
+        this.ref = ref;
+        this.level = level;
+        this.filter = filter;
+    }
+
+    public String getRef() {
+        return ref;
+    }
+
+    public Level getLevel() {
+        return level;
+    }
+
+    public Filter getFilter() {
+        return filter;
+    }
+
+    /**
+     * Create an Appender reference.
+     * @param ref The name of the Appender.
+     * @return The name of the Appender.
+     */
+    @PluginFactory
+    public static AppenderRef createAppenderRef(@PluginAttr("ref") String ref,
+                                                @PluginAttr("level") String level,
+                                                @PluginElement("filters") Filter filter) {
+
+        if (ref == null) {
+            LOGGER.error("Appender references must contain a reference");
+            return null;
+        }
+        Level l = null;
+
+        if (level != null) {
+            l = Level.toLevel(level.toUpperCase(), null);
+            if (l == null) {
+                LOGGER.error("Invalid level " + level + " on Appender reference " + ref);
+            }
+        }
+
+        return new AppenderRef(ref, l, filter);
+    }
+}

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=1337783&r1=1337782&r2=1337783&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 Sun May 13 05:42:27 2012
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.core.config;
 
+import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Filter;
@@ -188,12 +189,12 @@ public class BaseConfiguration extends F
         for (Map.Entry<String, LoggerConfig> entry : loggers.entrySet()) {
             LoggerConfig l = entry.getValue();
             l.setConfigurationMonitor(monitor);
-            for (String ref : l.getAppenderRefs()) {
-                Appender app = appenders.get(ref);
+            for (AppenderRef ref : l.getAppenderRefs()) {
+                Appender app = appenders.get(ref.getRef());
                 if (app != null) {
-                    l.addAppender(app);
+                    l.addAppender(app, ref.getLevel(), ref.getFilter());
                 } else {
-                    LOGGER.error("Unable to locate appender " + ref + " for logger " + l.getName());
+                    LOGGER.error("Unable to locate appender " + ref.getRef() + " for logger " + l.getName());
                 }
             }
 
@@ -281,11 +282,11 @@ public class BaseConfiguration extends F
         appenders.putIfAbsent(name, appender);
         LoggerConfig lc = getLoggerConfig(name);
         if (lc.getName().equals(name)) {
-            lc.addAppender(appender);
+            lc.addAppender(appender, null, null);
         } else {
             LoggerConfig nlc = new LoggerConfig(name, lc.getLevel(), lc.isAdditive());
             nlc.setConfigurationMonitor(monitor);
-            nlc.addAppender(appender);
+            nlc.addAppender(appender, null, null);
             nlc.setParent(lc);
             loggers.putIfAbsent(name, nlc);
             setParents();
@@ -599,6 +600,12 @@ public class BaseConfiguration extends F
                         if (parms[index] != null) {
                             break;
                         }
+                        if (list.size() > 0 && !parmClass.isAssignableFrom(list.get(0).getClass())) {
+                            LOGGER.error("Attempted to assign List containing class " +
+                                list.get(0).getClass().getName() + " to array of type " + parmClass +
+                                " for attribute " + name);
+                            break;
+                        }
                         Object[] array = (Object[]) Array.newInstance(parmClass, list.size());
                         int i = 0;
                         for (Object obj : list) {

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfiguration.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfiguration.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfiguration.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfiguration.java Sun May 13 05:42:27 2012
@@ -50,7 +50,7 @@ public class DefaultConfiguration extend
         Appender appender = ConsoleAppender.createAppender(layout, null, "SYSTEM_OUT", "Console", "true");
         addAppender(appender);
         LoggerConfig root = getRootLogger();
-        root.addAppender(appender);
+        root.addAppender(appender, null, null);
 
         String l = System.getProperty(DEFAULT_LEVEL);
         Level level = (l != null && Level.valueOf(l) != null) ? Level.valueOf(l) : Level.ERROR;

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=1337783&r1=1337782&r2=1337783&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 Sun May 13 05:42:27 2012
@@ -22,6 +22,7 @@ import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Lifecycle;
 import org.apache.logging.log4j.core.filter.Filterable;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.core.LogEvent;
@@ -35,10 +36,16 @@ import org.apache.logging.log4j.message.
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Logger object that is created via configuration.
@@ -48,7 +55,7 @@ public class LoggerConfig extends Filter
 
     private static final Logger LOGGER = StatusLogger.getLogger();
 
-    private List<String> appenderRefs = new ArrayList<String>();
+    private List<AppenderRef> appenderRefs = new ArrayList<AppenderRef>();
     private Map<String, AppenderControl> appenders = new ConcurrentHashMap<String, AppenderControl>();
     private final String name;
     private LogEventFactory logEventFactory;
@@ -56,6 +63,10 @@ public class LoggerConfig extends Filter
     private boolean additive = true;
     private LoggerConfig parent;
     private ConfigurationMonitor monitor = new DefaultConfigurationMonitor();
+    private AtomicInteger counter = new AtomicInteger();
+    private boolean shutdown = false;
+    private static final int MAX_RETRIES = 3;
+    private static final long WAIT_TIME = 1000;
 
     /**
      * Default constructor.
@@ -79,7 +90,7 @@ public class LoggerConfig extends Filter
         this.additive = additive;
     }
 
-    protected LoggerConfig(String name, List<String> appenders, Filter filter, Level level,
+    protected LoggerConfig(String name, List<AppenderRef> appenders, Filter filter, Level level,
                            boolean additive) {
         super(filter);
         this.logEventFactory = this;
@@ -131,8 +142,8 @@ public class LoggerConfig extends Filter
      * Add an Appender to the LoggerConfig.
      * @param appender The Appender to add.
      */
-    public void addAppender(Appender appender) {
-        appenders.put(appender.getName(), new AppenderControl(appender));
+    public void addAppender(Appender appender, Level level, Filter filter) {
+        appenders.put(appender.getName(), new AppenderControl(appender, level, filter));
     }
 
     /**
@@ -140,7 +151,10 @@ public class LoggerConfig extends Filter
      * @param name The name of the Appender.
      */
     public void removeAppender(String name) {
-        appenders.remove(name);
+        AppenderControl ctl = appenders.remove(name);
+        if (ctl != null) {
+            cleanupFilter(ctl);
+        }
     }
 
     /**
@@ -159,14 +173,31 @@ public class LoggerConfig extends Filter
      * Remove all Appenders.
      */
     protected void clearAppenders() {
-        appenders.clear();
+        waitForCompletion();
+        Collection<AppenderControl> controls = appenders.values();
+        Iterator<AppenderControl> iterator = controls.iterator();
+        while (iterator.hasNext()) {
+            AppenderControl ctl = iterator.next();
+            iterator.remove();
+            cleanupFilter(ctl);
+        }
+    }
+
+    private void cleanupFilter(AppenderControl ctl) {
+        Filter filter = ctl.getFilter();
+        if (filter != null) {
+            ctl.removeFilter(filter);
+            if (filter instanceof Lifecycle) {
+                ((Lifecycle) filter).stop();
+            }
+        }
     }
 
     /**
      * Return the Appender references.
      * @return a List of all the Appender names attached to this LoggerConfig.
      */
-    public List<String> getAppenderRefs() {
+    public List<AppenderRef> getAppenderRefs() {
         return appenderRefs;
     }
 
@@ -233,19 +264,52 @@ public class LoggerConfig extends Filter
     }
 
     /**
+     * Wait for all log events to complete before shutting down this loggerConfig.
+     */
+    private synchronized void waitForCompletion() {
+        if (shutdown) {
+            return;
+        }
+        shutdown = true;
+        int retries = 0;
+        while (counter.get() > 0) {
+            try {
+                wait(WAIT_TIME * (retries + 1));
+            } catch (InterruptedException ie) {
+                if (++retries > MAX_RETRIES) {
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
      * Logs an event.
      * @param event Yhe log event.
      */
     public void log(LogEvent event) {
-        monitor.checkConfiguration();
-        if (isFiltered(event)) {
-            return;
-        }
 
-        callAppenders(event);
+        counter.incrementAndGet();
+        try {
+            monitor.checkConfiguration();
+            if (isFiltered(event)) {
+                return;
+            }
+
+            callAppenders(event);
+
+            if (additive && parent != null) {
+                parent.log(event);
+            }
+        } finally {
+            if (counter.decrementAndGet() == 0) {
+                synchronized(this) {
+                    if (shutdown) {
+                        notifyAll();
+                    }
+                }
 
-        if (additive && parent != null) {
-            parent.log(event);
+            }
         }
     }
 
@@ -288,14 +352,14 @@ public class LoggerConfig extends Filter
     public static LoggerConfig createLogger(@PluginAttr("additivity") String additivity,
                                             @PluginAttr("level") String loggerLevel,
                                             @PluginAttr("name") String loggerName,
-                                            @PluginElement("appender-ref") String[] refs,
+                                            @PluginElement("appender-ref") AppenderRef[] refs,
                                             @PluginElement("filters") Filter filter) {
         if (loggerName == null) {
             LOGGER.error("Loggers cannot be configured without a name");
             return null;
         }
 
-        List<String> appenderRefs = Arrays.asList(refs);
+        List<AppenderRef> appenderRefs = Arrays.asList(refs);
         Level level = loggerLevel == null ? Level.ERROR : Level.valueOf(loggerLevel.toUpperCase());
         String name = loggerName.equals("root") ? "" : loggerName;
         boolean additive = additivity == null ? true : Boolean.parseBoolean(additivity);
@@ -312,9 +376,9 @@ public class LoggerConfig extends Filter
         @PluginFactory
         public static LoggerConfig createLogger(@PluginAttr("additivity") String additivity,
                                             @PluginAttr("level") String loggerLevel,
-                                            @PluginElement("appender-ref") String[] refs,
+                                            @PluginElement("appender-ref") AppenderRef[] refs,
                                             @PluginElement("filters") Filter filter) {
-            List<String> appenderRefs = Arrays.asList(refs);
+            List<AppenderRef> appenderRefs = Arrays.asList(refs);
             Level level = loggerLevel == null ? Level.ERROR : Level.valueOf(loggerLevel.toUpperCase());
             boolean additive = additivity == null ? true : Boolean.parseBoolean(additivity);
 

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/BurstFilter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/BurstFilter.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/BurstFilter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/BurstFilter.java Sun May 13 05:42:27 2012
@@ -219,8 +219,8 @@ public final class BurstFilter extends F
                                            @PluginAttr("maxBurst") String maxBurst,
                                            @PluginAttr("onmatch") String match,
                                            @PluginAttr("onmismatch") String mismatch) {
-        Result onMatch = match == null ? null : Result.valueOf(match);
-        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch);
+        Result onMatch = match == null ? null : Result.valueOf(match.toUpperCase());
+        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch.toUpperCase());
         Level lvl = Level.toLevel(level, Level.WARN);
         float eventRate = rate == null ? DEFAULT_RATE : Float.parseFloat(rate);
         if (eventRate <= 0) {

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java Sun May 13 05:42:27 2012
@@ -119,8 +119,8 @@ public final class DynamicThresholdFilte
                                                       @PluginAttr("defaultThreshold") String level,
                                                       @PluginAttr("onmatch") String match,
                                                       @PluginAttr("onmismatch") String mismatch) {
-        Result onMatch = match == null ? null : Result.valueOf(match);
-        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch);
+        Result onMatch = match == null ? null : Result.valueOf(match.toUpperCase());
+        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch.toUpperCase());
         Map<String, Level> map = new HashMap<String, Level>();
         for (ValueLevelPair pair : pairs) {
             map.put(pair.getKey(), pair.getLevel());

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/MapFilter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/MapFilter.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/MapFilter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/MapFilter.java Sun May 13 05:42:27 2012
@@ -131,8 +131,8 @@ public class MapFilter extends FilterBas
             return null;
         }
         boolean isAnd = oper == null || !oper.equalsIgnoreCase("or");
-        Result onMatch = match == null ? null : Result.valueOf(match);
-        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch);
+        Result onMatch = match == null ? null : Result.valueOf(match.toUpperCase());
+        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch.toUpperCase());
         return new MapFilter(map, isAnd, onMatch, onMismatch);
     }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/MarkerFilter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/MarkerFilter.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/MarkerFilter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/MarkerFilter.java Sun May 13 05:42:27 2012
@@ -84,8 +84,8 @@ public final class MarkerFilter extends 
             return null;
         }
         Marker m = MarkerManager.getMarker(marker);
-        Result onMatch = match == null ? null : Result.valueOf(match);
-        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch);
+        Result onMatch = match == null ? null : Result.valueOf(match.toUpperCase());
+        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch.toUpperCase());
 
         return new MarkerFilter(m, onMatch, onMismatch);
     }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java Sun May 13 05:42:27 2012
@@ -109,8 +109,8 @@ public final class RegexFilter extends F
             LOGGER.error("RegexFilter caught exception compiling pattern: " + regex + " cause: " + ex.getMessage());
             return null;
         }
-        Result onMatch = match == null ? null : Result.valueOf(match);
-        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch);
+        Result onMatch = match == null ? null : Result.valueOf(match.toUpperCase());
+        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch.toUpperCase());
 
         return new RegexFilter(raw, pattern, onMatch, onMismatch);
     }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java Sun May 13 05:42:27 2012
@@ -140,8 +140,8 @@ public final class StructuredDataFilter 
             return null;
         }
         boolean isAnd = oper == null || !oper.equalsIgnoreCase("or");
-        Result onMatch = match == null ? null : Result.valueOf(match);
-        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch);
+        Result onMatch = match == null ? null : Result.valueOf(match.toUpperCase());
+        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch.toUpperCase());
         return new StructuredDataFilter(map, isAnd, onMatch, onMismatch);
     }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java Sun May 13 05:42:27 2012
@@ -158,8 +158,8 @@ public class ThreadContextMapFilter exte
             return null;
         }
         boolean isAnd = oper == null || !oper.equalsIgnoreCase("or");
-        Result onMatch = match == null ? null : Result.valueOf(match);
-        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch);
+        Result onMatch = match == null ? null : Result.valueOf(match.toUpperCase());
+        Result onMismatch = mismatch == null ? null : Result.valueOf(mismatch.toUpperCase());
         return new ThreadContextMapFilter(map, isAnd, onMatch, onMismatch);
     }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/ThresholdFilter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/ThresholdFilter.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/ThresholdFilter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/ThresholdFilter.java Sun May 13 05:42:27 2012
@@ -81,8 +81,8 @@ public final class ThresholdFilter exten
                                                @PluginAttr("onMatch") String match,
                                                @PluginAttr("onMismatch") String mismatch) {
         Level level = loggerLevel == null ? Level.ERROR : Level.toLevel(loggerLevel.toUpperCase());
-        Result onMatch = match == null ? Result.NEUTRAL : Result.valueOf(match);
-        Result onMismatch = mismatch == null ? Result.DENY : Result.valueOf(mismatch);
+        Result onMatch = match == null ? Result.NEUTRAL : Result.valueOf(match.toUpperCase());
+        Result onMismatch = mismatch == null ? Result.DENY : Result.valueOf(mismatch.toUpperCase());
 
         return new ThresholdFilter(level, onMatch, onMismatch);
     }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/TimeFilter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/TimeFilter.java?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/TimeFilter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/filter/TimeFilter.java Sun May 13 05:42:27 2012
@@ -126,8 +126,8 @@ public final class TimeFilter extends Fi
             }
         }
         TimeZone timezone = (tz == null) ? TimeZone.getDefault() : TimeZone.getTimeZone(tz);
-        Result onMatch = match == null ? Result.NEUTRAL : Result.valueOf(match);
-        Result onMismatch = mismatch == null ? Result.DENY : Result.valueOf(mismatch);
+        Result onMatch = match == null ? Result.NEUTRAL : Result.valueOf(match.toUpperCase());
+        Result onMismatch = mismatch == null ? Result.DENY : Result.valueOf(mismatch.toUpperCase());
 
         return new TimeFilter(s, e, timezone, onMatch, onMismatch);
     }

Copied: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/AppenderRefLevelTest.java (from r1332056, logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/AppenderRefLevelTest.java?p2=logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/AppenderRefLevelTest.java&p1=logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java&r1=1332056&r2=1337783&rev=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/AppenderRefLevelTest.java Sun May 13 05:42:27 2012
@@ -17,14 +17,16 @@
 package org.apache.logging.log4j.core;
 
 import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.MarkerManager;
 import org.apache.logging.log4j.ThreadContext;
-import org.apache.logging.log4j.test.appender.ListAppender;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
-import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.message.StructuredDataMessage;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.test.appender.ListAppender;
 import org.junit.AfterClass;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -38,11 +40,12 @@ import static org.junit.Assert.assertTru
 /**
  *
  */
-public class LoggerTest {
+public class AppenderRefLevelTest {
 
-    private static final String CONFIG = "log4j-test2.xml";
+    private static final String CONFIG = "log4j-reference-level.xml";
     private static Configuration config;
-    private static ListAppender app;
+    private static ListAppender app1;
+    private static ListAppender app2;
     private static LoggerContext ctx;
 
     @BeforeClass
@@ -51,9 +54,10 @@ public class LoggerTest {
         ctx = (LoggerContext) LogManager.getContext(false);
         config = ctx.getConfiguration();
         for (Map.Entry<String, Appender> entry : config.getAppenders().entrySet()) {
-            if (entry.getKey().equals("List")) {
-                app = (ListAppender) entry.getValue();
-                break;
+            if (entry.getKey().equals("LIST1")) {
+                app1 = (ListAppender) entry.getValue();
+            } else if (entry.getKey().equals("LIST2")) {
+                app2 = (ListAppender) entry.getValue();
             }
         }
     }
@@ -65,96 +69,55 @@ public class LoggerTest {
         StatusLogger.getLogger().reset();
     }
 
-    org.apache.logging.log4j.Logger logger = LogManager.getLogger("LoggerTest");
-
-    @Test
-    public void basicFlow() {
-        logger.entry();
-        logger.exit();
-        List<LogEvent> events = app.getEvents();
-        assertTrue("Incorrect number of events. Expected 2, actual " + events.size(), events.size() == 2);
-        app.clear();
-    }
-
-    @Test
-    public void simpleFlow() {
-        logger.entry(CONFIG);
-        logger.exit(0);
-        List<LogEvent> events = app.getEvents();
-        assertTrue("Incorrect number of events. Expected 2, actual " + events.size(), events.size() == 2);
-        app.clear();
-    }
-
-    @Test
-    public void throwing() {
-        logger.throwing(new IllegalArgumentException("Test Exception"));
-        List<LogEvent> events = app.getEvents();
-        assertTrue("Incorrect number of events. Expected 1, actual " + events.size(), events.size() == 1);
-        app.clear();
-    }
-
-    @Test
-    public void catching() {
-        try {
-            throw new NullPointerException();
-        } catch (Exception e) {
-            logger.catching(e);
-        }
-        List<LogEvent> events = app.getEvents();
-        assertTrue("Incorrect number of events. Expected 1, actual " + events.size(), events.size() == 1);
-        app.clear();
+    org.apache.logging.log4j.Logger logger1 = LogManager.getLogger("org.apache.logging.log4j.test1");
+    org.apache.logging.log4j.Logger logger2 = LogManager.getLogger("org.apache.logging.log4j.test2");
+    org.apache.logging.log4j.Logger logger3 = LogManager.getLogger("org.apache.logging.log4j.test3");
+    Marker testMarker = MarkerManager.getMarker("TEST");
+
+    @Before
+    public void before() {
+        app1.clear();
+        app2.clear();
     }
 
     @Test
-    public void debug() {
-        logger.debug("Debug message");
-        List<LogEvent> events = app.getEvents();
+    public void logger1() {
+        logger1.entry();
+        logger1.debug("debug message");
+        logger1.error("Test Message");
+        logger1.info("Info Message");
+        logger1.warn("warn Message");
+        logger1.exit();
+        List<LogEvent> events = app1.getEvents();
+        assertTrue("Incorrect number of events. Expected 6, actual " + events.size(), events.size() == 6);
+        events = app2.getEvents();
         assertTrue("Incorrect number of events. Expected 1, actual " + events.size(), events.size() == 1);
-        app.clear();
     }
 
     @Test
-    public void debugObject() {
-        logger.debug(new Date());
-        List<LogEvent> events = app.getEvents();
-        assertTrue("Incorrect number of events. Expected 1, actual " + events.size(), events.size() == 1);
-        app.clear();
-    }
-
-    @Test
-    public void debugWithParms() {
-        logger.debug("Hello, {}", "World");
-        List<LogEvent> events = app.getEvents();
-        assertTrue("Incorrect number of events. Expected 1, actual " + events.size(), events.size() == 1);
-        app.clear();
-    }
-
-    @Test
-    public void mdc() {
-
-        ThreadContext.put("TestYear", new Integer(2010).toString());
-        logger.debug("Debug message");
-        ThreadContext.clear();
-        logger.debug("Debug message");
-        List<LogEvent> events = app.getEvents();
+    public void logger2() {
+        logger2.entry();
+        logger2.debug("debug message");
+        logger2.error("Test Message");
+        logger2.info("Info Message");
+        logger2.warn("warn Message");
+        logger2.exit();
+        List<LogEvent> events = app1.getEvents();
         assertTrue("Incorrect number of events. Expected 2, actual " + events.size(), events.size() == 2);
-        app.clear();
+        events = app2.getEvents();
+        assertTrue("Incorrect number of events. Expected 4, actual " + events.size(), events.size() == 4);
     }
 
     @Test
-    public void structuredData() {
-        ThreadContext.put("loginId", "JohnDoe");
-        ThreadContext.put("ipAddress", "192.168.0.120");
-        ThreadContext.put("locale", Locale.US.getDisplayName());
-        StructuredDataMessage msg = new StructuredDataMessage("Audit@18060", "Transfer Complete", "Transfer");
-        msg.put("ToAccount", "123456");
-        msg.put("FromAccount", "123457");
-        msg.put("Amount", "200.00");
-        logger.info(MarkerManager.getMarker("EVENT"), msg);
-        ThreadContext.clear();
-        List<LogEvent> events = app.getEvents();
-        assertTrue("Incorrect number of events. Expected 1, actual " + events.size(), events.size() == 1);
-        app.clear();
+    public void logger3() {
+        logger3.entry();
+        logger3.debug(testMarker, "debug message");
+        logger3.error("Test Message");
+        logger3.info(testMarker, "Info Message");
+        logger3.warn("warn Message");
+        logger3.exit();
+        List<LogEvent> events = app1.getEvents();
+        assertTrue("Incorrect number of events. Expected 4, actual " + events.size(), events.size() == 4);
     }
 }
 

Copied: logging/log4j/log4j2/trunk/core/src/test/resources/log4j-reference-level.xml (from r1332056, logging/log4j/log4j2/trunk/core/src/test/resources/log4j-test1.xml)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j-reference-level.xml?p2=logging/log4j/log4j2/trunk/core/src/test/resources/log4j-reference-level.xml&p1=logging/log4j/log4j2/trunk/core/src/test/resources/log4j-test1.xml&r1=1332056&r2=1337783&rev=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j-test1.xml (original)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j-reference-level.xml Sun May 13 05:42:27 2012
@@ -17,37 +17,29 @@
 
 -->
 <configuration status="warn" name="XMLConfigTest" packages="org.apache.logging.log4j.test">
-  <properties>
-    <property name="filename">target/test.log</property>
-  </properties>
-  <ThresholdFilter level="debug"/>
-
   <appenders>
     <Console name="STDOUT">
       <PatternLayout pattern="%m%n"/>
     </Console>
-    <File name="File" fileName="${filename}" bufferedIO="false">
-      <PatternLayout>
-        <pattern>%d %p %C{1.} [%t] %m%n</pattern>
-      </PatternLayout>
-    </File>
-    <List name="List">
-      <filters>
-        <ThresholdFilter level="error"/>
-      </filters>
-    </List>
+    <List name="LIST1"/>
+    <List name="LIST2"/>
   </appenders>
 
   <loggers>
-    <logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
-        <ThreadContextMapFilter>
-          <KeyValuePair key="test" value="123"/>
-        </ThreadContextMapFilter>
-      <appender-ref ref="STDOUT"/>
+    <logger name="org.apache.logging.log4j.test1" level="trace" additivity="false">
+      <appender-ref ref="LIST1" level="trace"/>
+      <appender-ref ref="LIST2" level="error"/>
     </logger>>
 
     <logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
-      <appender-ref ref="File"/>
+      <appender-ref ref="LIST1" level="WARN"/>
+      <appender-ref ref="LIST2" level="debug"/>
+    </logger>>
+
+    <logger name="org.apache.logging.log4j.test3" level="trace" additivity="false">
+      <appender-ref ref="LIST1" level="trace">
+          <MarkerFilter marker="TEST" onmatch="deny" onmismatch="accept"/>
+      </appender-ref>
     </logger>>
 
     <root level="error">

Modified: logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing.json
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing.json?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing.json (original)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing.json Sun May 13 05:42:27 2012
@@ -37,8 +37,8 @@
                 "SizeBasedTriggeringPolicy": { "size": "500" }
               }
             },
-            { "appender-ref": "STDOUT", "key": "Audit"},
-            { "appender-ref": "List", "key": "Service"}
+            { "ref": "STDOUT", "key": "Audit"},
+            { "ref": "List", "key": "Service"}
           ]
         }
       }

Modified: logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing.xml?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing.xml (original)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing.xml Sun May 13 05:42:27 2012
@@ -40,8 +40,8 @@
             <SizeBasedTriggeringPolicy size="500" />
           </RollingFile>
         </Route>
-        <Route appender-ref="STDOUT" key="Audit"/>
-        <Route appender-ref="List" key="Service"/>
+        <Route ref="STDOUT" key="Audit"/>
+        <Route ref="List" key="Service"/>
       </Routes>
     </Routing>
   </appenders>

Modified: logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing2.json
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing2.json?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing2.json (original)
+++ logging/log4j/log4j2/trunk/core/src/test/resources/log4j-routing2.json Sun May 13 05:42:27 2012
@@ -34,8 +34,8 @@
                   "SizeBasedTriggeringPolicy": { "size": "500" }
                 }
               },
-              { "appender-ref": "STDOUT", "key": "Audit"},
-              { "appender-ref": "List", "key": "Service"}
+              { "ref": "STDOUT", "key": "Audit"},
+              { "ref": "List", "key": "Service"}
             ]
           }
         }

Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/architecture.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/architecture.xml?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/xdoc/manual/architecture.xml (original)
+++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/architecture.xml Sun May 13 05:42:27 2012
@@ -490,8 +490,9 @@
           <p>In addition to the automatic log Level filtering that takes place as described in the previous
             section, Log4j provides
             <a href="../log4j2-core/apidocs/org/apache/logging/log4j/core/Filter.html">Filter</a>s that can
-            be applied before control is passed to any LoggerConfig, after control is pased to a LoggerConfig
-            but before calling any Appenders, and on each Appender. In a manner very similar to firewall filters,
+            be applied before control is passed to any LoggerConfig, after control is passed to a LoggerConfig
+            but before calling any Appenders, after control is passed to a LoggerConfig but before calling a
+            specific Appender, and on each Appender. In a manner very similar to firewall filters,
             each Filter can return one of three results, Accept, Deny or Neutral. A response of Accept means
             that no other Filters should be called and the event should progress. A response of Deny means
             the event should be immediately ignored and control should be returned to the caller. A response

Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml (original)
+++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml Sun May 13 05:42:27 2012
@@ -569,13 +569,15 @@
           </p>
           <h4>Configuring Filters</h4>
           <p>
-            Log4j allows a filter to be specified in any of 3 places:
+            Log4j allows a filter to be specified in any of 4 places:
             <ol>
               <li>At the same level as the appenders, loggers and properties elements. These filters can accept
               or reject events before they have been passed to a LoggerConfig.</li>
               <li>In a logger element. These filters can accept or reject events for specific loggers.</li>
               <li>In an appender element. These filters can prevent or cause events to be processed by
                 the appender.</li>
+              <li>In an appender reference element. These filters are used to determine if a Logger should route
+                the event to an appender.</li>
             </ol>
           </p>
           <p>
@@ -594,10 +596,6 @@
   <appenders>
     <Console name="STDOUT">
       <PatternLayout pattern="%m MDC%X%n"/>
-      <filters>
-        <MarkerFilter marker="FLOW" onMatch="DENY" onMismatch="NEUTRAL"/>
-        <MarkerFilter marker="EXCEPTION" onMatch="DENY" onMismatch="ACCEPT"/>
-      </filters>
     </Console>
     <Console name="FLOW">
       <PatternLayout pattern="%C{1}.%M %m %ex%n"/>
@@ -624,7 +622,12 @@
     </logger>>
 
     <logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
-      <appender-ref ref="File"/>
+      <appender-ref ref="File">
+        <ThreadContextMapFilter>
+          <KeyValuePair key="test" value="123"/>
+        </ThreadContextMapFilter>
+      </appender-ref>
+      <appender-ref ref="STDOUT" level="error"/>
     </logger>>
 
     <root level="trace">

Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/filters.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/filters.xml?rev=1337783&r1=1337782&r2=1337783&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/xdoc/manual/filters.xml (original)
+++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/filters.xml Sun May 13 05:42:27 2012
@@ -30,7 +30,7 @@
           one of 3 values - ACCEPT, DENY or NEUTRAL.
         </p>
         <p>
-          Filters may be configured in one of three locations;
+          Filters may be configured in one of four locations;
           <ol>
             <li>Context-wide Filters are configured directly in the configuration. Events that are
             rejected by these filters will not be passed to loggers for further processing. Once an
@@ -43,6 +43,8 @@
             of the additivity setting.</li>
             <li>Appender Filters are used to determine if a specific Appender should handle the
             formatting and publication of the event.</li>
+            <li>Appender Reference Filters are used to determine if a Logger should route the event to
+            an appender.</li>
           </ol>
         </p>
         <a name="BurstFilter"/>
@@ -283,6 +285,62 @@
 </configuration>
   ]]></source>
           </p>
+          <p>
+            This sample configuration will exhibit the same behavior as the preceding example since the only
+          logger configured is the root.
+
+            <source><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<configuration status="warn" name="MyApp" packages="">
+  <appenders>
+    <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
+      <BurstFilter level="INFO" rate="16" maxBurst="100"/>
+      <PatternLayout>
+        <pattern>%d %p %C{1.} [%t] %m%n</pattern>
+      </PatternLayout>
+      <TimeBasedTriggeringPolicy />
+    </RollingFile>
+  </appenders>
+  <loggers>
+    <root level="error">
+      <MapFilter onMatch="ACCEPT" onMismatch="NEUTRAL" operator="or">
+        <KeyValuePair key="eventId" value="Login"/>
+        <KeyValuePari key="eventId" value="Logout"/>
+      </MapFilter>
+      <appender-ref ref="RollingFile">
+      </appender-ref>
+    </root>
+  </loggers>
+</configuration>
+  ]]></source>
+          </p>
+          <p>
+            This third sample configuration will exhibit the same behavior as the preceding examples since the only
+            logger configured is the root and the root is only configured with a single appender reference.
+
+            <source><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<configuration status="warn" name="MyApp" packages="">
+  <appenders>
+    <RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
+      <BurstFilter level="INFO" rate="16" maxBurst="100"/>
+      <PatternLayout>
+        <pattern>%d %p %C{1.} [%t] %m%n</pattern>
+      </PatternLayout>
+      <TimeBasedTriggeringPolicy />
+    </RollingFile>
+  </appenders>
+  <loggers>
+    <root level="error">
+      <appender-ref ref="RollingFile">
+        <MapFilter onMatch="ACCEPT" onMismatch="NEUTRAL" operator="or">
+          <KeyValuePair key="eventId" value="Login"/>
+          <KeyValuePari key="eventId" value="Logout"/>
+        </MapFilter>
+      </appender-ref>
+    </root>
+  </loggers>
+</configuration>
+  ]]></source>
+          </p>
         </subsection>
         <a name="MarkerFilter"/>
         <subsection name="MarkerFilter">