Index: core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java =================================================================== --- core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java (revision 1415539) +++ core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java (working copy) @@ -18,12 +18,14 @@ import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Filter; -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.appender.AbstractAppender; -import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy; -import org.apache.logging.log4j.core.config.AppenderControl; -import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.Node; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.appender.AbstractAppender; +import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy; +import org.apache.logging.log4j.core.appender.routing.Route; +import org.apache.logging.log4j.core.appender.routing.Routes; +import org.apache.logging.log4j.core.config.AppenderControl; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.Node; 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.PluginConfiguration; @@ -44,14 +46,15 @@ */ @Plugin(name = "Routing", type = "Core", elementType = "appender", printObject = true) public final class RoutingAppender extends AbstractAppender { - private static final String DEFAULT_KEY = "ROUTING_APPENDER_DEFAULT"; - private final Routes routes; - private final Configuration config; - private ConcurrentMap appenders = new ConcurrentHashMap(); - private final RewritePolicy rewritePolicy; - - private RoutingAppender(String name, Filter filter, boolean handleException, Routes routes, - RewritePolicy rewritePolicy, Configuration config) { + private static final String DEFAULT_KEY = "ROUTING_APPENDER_DEFAULT"; + private final Routes routes; + private final Configuration config; + private final ConcurrentMap appenders = new ConcurrentHashMap(); + private final RewritePolicy rewritePolicy; + private Route dynamicDefault; + + private RoutingAppender(String name, Filter filter, boolean handleException, Routes routes, + RewritePolicy rewritePolicy, Configuration config) { super(name, filter, null, handleException); this.routes = routes; this.config = config; @@ -105,64 +108,100 @@ control.callAppender(event); } } - - private synchronized AppenderControl getControl(String key, LogEvent event) { - AppenderControl control = appenders.get(key); - boolean defaultRoute = false; - if (control != null) { - return control; - } + + private synchronized AppenderControl getControl(String key, LogEvent event) { + AppenderControl control = appenders.get(key); + if (control != null) { + return control; + } Route route = null; for (Route r : routes.getRoutes()) { if (r.getAppenderRef() == null && key.equals(r.getKey())) { route = r; - break; - } - } - if (route == null) { - control = appenders.get(DEFAULT_KEY); - if (control != null) { - return control; - } - for (Route r : routes.getRoutes()) { - if (r.getAppenderRef() == null && r.getKey() == null) { - route = r; - defaultRoute = true; - break; - } - } - } - if (route != null) { - Appender app = createAppender(route, event); - if (app == null) { + break; + } + } + boolean defaultRoute = false; + if (route == null) { + if (dynamicDefault == null) { + control = appenders.get(DEFAULT_KEY); + if (control != null) { + return control; + } + for (Route r : routes.getRoutes()) { + if (r.getAppenderRef() == null && r.getKey() == null) { + route = r; + defaultRoute = true; + break; + } + } + } + else { + route = dynamicDefault; + } + } + + if (route != null) { + Appender app = createAppender(route, event); + if (app == null) { return null; } - control = new AppenderControl(app, null, null); - appenders.put(key, control); - if (defaultRoute) { - appenders.put(DEFAULT_KEY, control); - } - } - + control = new AppenderControl(app, null, null); + appenders.put(key, control); + if (defaultRoute) { + Node appenderNode = getAppenderNode(route); + // TODO: change something else, hack and also NPE possibility. Basically this is trying to find out of the appender name is dynamic or not. Don't know what the best way to do that is. + if (appenderNode != null && + appenderNode.getAttributes().get("name").contains("${")) { + dynamicDefault = route; + } + else { + appenders.put(DEFAULT_KEY, control); + } + } + } + return control; - } + } + + private Appender createAppender(Route route, LogEvent event) { + Node node = getAppenderNode(route); + if (node != null) { + node = clone(node, route.getNode()); + config.createConfiguration(node, event); + if (node.getObject() instanceof Appender) { + Appender app = (Appender) node.getObject(); + app.start(); + return (Appender) node.getObject(); + } + LOGGER.error("Unable to create Appender of type " + node.getName()); + return null; + } + LOGGER.error("No Appender was configured for route " + route.getKey()); + return null; + } + + private Node getAppenderNode(Route route) { + Node routeNode = route.getNode(); + for (Node node : routeNode.getChildren()) { + if (node.getType().getElementName().equals("appender")) { + return node; + } + } + return null; + } - private Appender createAppender(Route route, LogEvent event) { - Node routeNode = route.getNode(); - for (Node node : routeNode.getChildren()) { - if (node.getType().getElementName().equals("appender")) { - config.createConfiguration(node, event); - if (node.getObject() instanceof Appender) { - Appender app = (Appender) node.getObject(); - app.start(); - return (Appender) node.getObject(); - } - LOGGER.error("Unable to create Appender of type " + node.getName()); - return null; - } + private Node clone(final Node node, final Node parent) { + final Node clone = new Node(parent, node.getName(), node.getType()); + clone.setObject(node.getObject()); + clone.setValue(node.getValue()); + for (Node child : node.getChildren()) { + clone.getChildren().add(clone(child, clone)); } - LOGGER.error("No Appender was configured for route " + route.getKey()); - return null; + for (Map.Entry attr : node.getAttributes().entrySet()) { + clone.getAttributes().put(attr.getKey(), attr.getValue()); + } + return clone; } /**