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 2015/08/30 06:00:27 UTC

[1/2] logging-log4j2 git commit: LOG4J-952 - Add ConfigurationAssembler and PropertiesConfiguration support

Repository: logging-log4j2
Updated Branches:
  refs/heads/LOG4J2-952 [created] bf4afb3e3


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginBuilderAttributeVisitor.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginBuilderAttributeVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginBuilderAttributeVisitor.java
index 0856e46..bfd2c70 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginBuilderAttributeVisitor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginBuilderAttributeVisitor.java
@@ -49,7 +49,7 @@ public class PluginBuilderAttributeVisitor extends AbstractPluginVisitor<PluginB
         final String replacedValue = this.substitutor.replace(event, rawValue);
         final Object value = convert(replacedValue, null);
         final Object debugValue = this.annotation.sensitive() ? NameUtil.md5(value + this.getClass().getName()) : value;
-        StringBuilders.appendKeyDqValue(log, "name", debugValue);
+        StringBuilders.appendKeyDqValue(log, name, debugValue);
         return value;
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java
new file mode 100644
index 0000000..b5701b0
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java
@@ -0,0 +1,56 @@
+/*
+ * 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.properties;
+
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.Reconfigurable;
+import org.apache.logging.log4j.core.config.assembler.api.Component;
+import org.apache.logging.log4j.core.config.assembler.impl.AssembledConfiguration;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Configuration created from a properties file.
+ */
+public class PropertiesConfiguration extends AssembledConfiguration implements Reconfigurable {
+
+    private static final long serialVersionUID = 5198216024278070407L;
+
+    public PropertiesConfiguration(ConfigurationSource source, Component root) {
+        super(source, root);
+    }
+
+    @Override
+    public Configuration reconfigure() {
+        try {
+            final ConfigurationSource source = getConfigurationSource().resetInputStream();
+            if (source == null) {
+                return null;
+            }
+            final PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory();
+            final PropertiesConfiguration config = factory.getConfiguration(source);
+            return config.root.getComponents().size() == 0 ? null : config;
+        } catch (final IOException ex) {
+            LOGGER.error("Cannot locate file {}", getConfigurationSource(), ex);
+        }
+        return null;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationFactory.java
new file mode 100644
index 0000000..aa40697
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationFactory.java
@@ -0,0 +1,349 @@
+/*
+ * 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.properties;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.config.ConfigurationException;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.Order;
+import org.apache.logging.log4j.core.config.assembler.api.AppenderAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.AppenderRefAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.ComponentAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.ConfigurationAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.FilterAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.LayoutAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.LoggerAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.RootLoggerAssembler;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.util.PropertiesUtil;
+import org.apache.logging.log4j.util.Strings;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * Creates a PropertiesConfiguration from a properties file.
+ */
+@Plugin(name = "PropertiesConfigurationFactory", category = ConfigurationFactory.CATEGORY)
+@Order(8)
+public class PropertiesConfigurationFactory extends ConfigurationFactory {
+    private static final String STATUS_KEY = "status";
+    private static final String SHUTDOWN_HOOK = "shutdownHook";
+    private static final String VERBOSE = "verbose";
+    private static final String PACKAGES = "packages";
+    private static final String CONFIG_NAME = "name";
+    private static final String MONITOR_INTERVAL = "monitorInterval";
+    private static final String CONFIG_TYPE = "type";
+
+    @Override
+    protected String[] getSupportedTypes() {
+        return new String[] {".properties"};
+    }
+
+    @Override
+    public PropertiesConfiguration getConfiguration(ConfigurationSource source) {
+        final InputStream configStream = source.getInputStream();
+        Properties properties = new Properties();
+        try {
+            properties.load(configStream);
+        } catch (IOException ioe) {
+            throw new ConfigurationException("Unable to load " + source.toString(), ioe);
+        }
+        ConfigurationAssembler<PropertiesConfiguration> assembler = newConfiguration(PropertiesConfiguration.class);
+        String value = properties.getProperty(STATUS_KEY);
+        if (value != null) {
+            assembler.setStatusLevel(Level.toLevel(value, Level.ERROR));
+        } else {
+            assembler.setStatusLevel(Level.ERROR);
+        }
+        value = properties.getProperty(SHUTDOWN_HOOK);
+        if (value != null) {
+            assembler.setShutdownHook(value);
+        }
+        value = properties.getProperty(VERBOSE);
+        if (value != null) {
+            assembler.setVerbosity(value);
+        }
+        value = properties.getProperty(PACKAGES);
+        if (value != null) {
+            assembler.setPackages(value);
+        }
+        value = properties.getProperty(CONFIG_NAME);
+        if (value != null) {
+            assembler.setConfigurationName(value);
+        }
+        value = properties.getProperty(MONITOR_INTERVAL);
+        if (value != null) {
+            assembler.setMonitorInterval(value);
+        }
+        Properties props = PropertiesUtil.extractSubset(properties, "property");
+        for (String key : props.stringPropertyNames()) {
+            assembler.addProperty(key, props.getProperty(key));
+        }
+
+        Properties levelProps = PropertiesUtil.extractSubset(properties, "customLevel");
+        if (levelProps.size() > 0) {
+            for (String key : levelProps.stringPropertyNames()) {
+                assembler.add(assembler.newCustomLevel(key, Integer.parseInt(props.getProperty(key))));
+            }
+        }
+
+        String filterProp = properties.getProperty("filters");
+        if (filterProp != null) {
+            String[] filterNames = filterProp.split(",");
+            for (String filterName : filterNames) {
+                String name = filterName.trim();
+                assembler.add(createFilter(assembler, name, PropertiesUtil.extractSubset(properties, "filter." + name)));
+            }
+        }
+        String appenderProp = properties.getProperty("appenders");
+        if (appenderProp != null) {
+            String[] appenderNames = appenderProp.split(",");
+            for (String appenderName : appenderNames) {
+                String name = appenderName.trim();
+                assembler.add(
+                        createAppender(assembler, name, PropertiesUtil.extractSubset(properties, "appender." + name)));
+            }
+        }
+        String loggerProp = properties.getProperty("loggers");
+        if (appenderProp != null) {
+            String[] loggerNames = loggerProp.split(",");
+            for (String loggerName : loggerNames) {
+                String name = loggerName.trim();
+                if (!name.equals("root")) {
+                    assembler.add(
+                            createLogger(assembler, name, PropertiesUtil.extractSubset(properties, "logger." + name)));
+                }
+            }
+        }
+
+        props = PropertiesUtil.extractSubset(properties, "rootLogger");
+        if (props.size() > 0) {
+            assembler.add(createRootLogger(assembler, props));
+        }
+
+        return assembler.assemble();
+    }
+
+    private AppenderAssembler createAppender(ConfigurationAssembler<PropertiesConfiguration> assembler, String key, Properties properties) {
+        String name = properties.getProperty(CONFIG_NAME);
+        if (Strings.isEmpty(name)) {
+            throw new ConfigurationException("No name attribute provided for Appender " + key);
+        }
+        properties.remove(CONFIG_NAME);
+        String type = properties.getProperty(CONFIG_TYPE);
+        if (Strings.isEmpty(type)) {
+            throw new ConfigurationException("No type attribute provided for Appender " + key);
+        }
+        properties.remove(CONFIG_TYPE);
+        AppenderAssembler appenderAssembler = assembler.newAppender(name, type);
+        String filters = properties.getProperty("filters");
+        if (filters != null) {
+            properties.remove("filters");
+            String[] filterNames = filters.split(",");
+            for (String filterName : filterNames) {
+                filterName = filterName.trim();
+                Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
+                appenderAssembler.add(createFilter(assembler, filterName, filterProps));
+            }
+        }
+        Properties layoutProps = PropertiesUtil.extractSubset(properties, "layout");
+        if (layoutProps.size() > 0) {
+            appenderAssembler.add(createLayout(assembler, name, layoutProps));
+        }
+
+        processRemainingProperties(appenderAssembler, name, properties);
+        return appenderAssembler;
+    }
+
+    private FilterAssembler createFilter(ConfigurationAssembler<PropertiesConfiguration> assembler, String key, Properties properties) {
+        String type = properties.getProperty(CONFIG_TYPE);
+        if (Strings.isEmpty(type)) {
+            throw new ConfigurationException("No type attribute provided for Appender " + key);
+        }
+        properties.remove(CONFIG_TYPE);
+        String onMatch = properties.getProperty("onMatch");
+        if (onMatch != null) {
+            properties.remove("onMatch");
+        }
+        String onMisMatch = properties.getProperty("onMisMatch");
+        if (onMisMatch != null) {
+            properties.remove("onMisMatch");
+        }
+        FilterAssembler filterAssembler = assembler.newFilter(type, onMatch, onMisMatch);
+        processRemainingProperties(filterAssembler, key, properties);
+        return filterAssembler;
+    }
+
+    private AppenderRefAssembler createAppenderRef(ConfigurationAssembler<PropertiesConfiguration> assembler, String key, Properties properties) {
+        String ref = properties.getProperty("ref");
+        if (Strings.isEmpty(ref)) {
+            throw new ConfigurationException("No ref attribute provided for AppenderRef " + key);
+        }
+        properties.remove("ref");
+        AppenderRefAssembler appenderRefAssembler = assembler.newAppenderRef(ref);
+        String level = properties.getProperty("level");
+        if (!Strings.isEmpty(level)) {
+            appenderRefAssembler.addAttribute("level", level);
+        }
+        String filters = properties.getProperty("filters");
+        if (filters != null) {
+            properties.remove("filters");
+            String[] filterNames = filters.split(",");
+            for (String filterName : filterNames) {
+                filterName = filterName.trim();
+                Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
+                appenderRefAssembler.add(createFilter(assembler, filterName, filterProps));
+            }
+        }
+        return appenderRefAssembler;
+    }
+
+    private LoggerAssembler createLogger(ConfigurationAssembler<PropertiesConfiguration> assembler, String key, Properties properties) {
+        String name = properties.getProperty(CONFIG_NAME);
+        if (Strings.isEmpty(name)) {
+            throw new ConfigurationException("No name attribute provided for Logger " + key);
+        }
+        properties.remove(CONFIG_NAME);
+        String level = properties.getProperty("level");
+        if (level != null) {
+            properties.remove("level");
+        }
+        LoggerAssembler loggerAssembler;
+        String type = properties.getProperty(CONFIG_TYPE);
+        if (type != null) {
+            if (type.equalsIgnoreCase("asyncLogger")) {
+                loggerAssembler = assembler.newAsyncLogger(name, level);
+            } else {
+                throw new ConfigurationException("Unknown Logger type " + type + " for Logger " + name);
+            }
+        } else {
+            loggerAssembler = assembler.newLogger(name, level);
+        }
+        String appenderRefs = properties.getProperty("appenderRefs");
+        if (appenderRefs != null) {
+            properties.remove("appenderRefs");
+            String[] refNames = appenderRefs.split(",");
+            for (String appenderRef : refNames) {
+                appenderRef = appenderRef.trim();
+                Properties refProps = PropertiesUtil.extractSubset(properties, "appenderRef." + appenderRef);
+                loggerAssembler.add(createAppenderRef(assembler, appenderRef, refProps));
+            }
+        }
+        String filters = properties.getProperty("filters");
+        if (filters != null) {
+            properties.remove("filters");
+            String[] filterNames = filters.split(",");
+            for (String filterName : filterNames) {
+                filterName = filterName.trim();
+                Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
+                loggerAssembler.add(createFilter(assembler, filterName, filterProps));
+            }
+        }
+        String additivity = properties.getProperty("additivity");
+        if (!Strings.isEmpty(additivity)) {
+            loggerAssembler.addAttribute("additivity", additivity);
+        }
+        return loggerAssembler;
+    }
+
+    private RootLoggerAssembler createRootLogger(ConfigurationAssembler<PropertiesConfiguration> assembler, Properties properties) {
+        String level = properties.getProperty("level");
+        if (level != null) {
+            properties.remove("level");
+        }
+        RootLoggerAssembler loggerAssembler;
+        String type = properties.getProperty(CONFIG_TYPE);
+        if (type != null) {
+            if (type.equalsIgnoreCase("asyncRoot")) {
+                loggerAssembler = assembler.newAsyncRootLogger(level);
+            } else {
+                throw new ConfigurationException("Unknown Logger type for root logger" + type);
+            }
+        } else {
+            loggerAssembler = assembler.newRootLogger(level);
+        }
+        String appenderRefs = properties.getProperty("appenderRefs");
+        if (appenderRefs != null) {
+            properties.remove("appenderRefs");
+            String[] refNames = appenderRefs.split(",");
+            for (String appenderRef : refNames) {
+                appenderRef = appenderRef.trim();
+                Properties refProps = PropertiesUtil.extractSubset(properties, "appenderRef." + appenderRef);
+                loggerAssembler.add(createAppenderRef(assembler, appenderRef, refProps));
+            }
+        }
+        String filters = properties.getProperty("filters");
+        if (filters != null) {
+            properties.remove("filters");
+            String[] filterNames = filters.split(",");
+            for (String filterName : filterNames) {
+                filterName = filterName.trim();
+                Properties filterProps = PropertiesUtil.extractSubset(properties, "filter." + filterName);
+                loggerAssembler.add(createFilter(assembler, filterName, filterProps));
+            }
+        }
+        return loggerAssembler;
+    }
+
+    private LayoutAssembler createLayout(ConfigurationAssembler<PropertiesConfiguration> assembler, String appenderName, Properties properties) {
+        String type = properties.getProperty(CONFIG_TYPE);
+        if (Strings.isEmpty(type)) {
+            throw new ConfigurationException("No type attribute provided for Layout on Appender " + appenderName);
+        }
+        properties.remove(CONFIG_TYPE);
+        LayoutAssembler layoutAssembler = assembler.newLayout(type);
+        processRemainingProperties(layoutAssembler, appenderName, properties);
+        return layoutAssembler;
+    }
+
+    @SuppressWarnings("rawtypes")
+    private ComponentAssembler<?> createComponent(ComponentAssembler parent, String key, Properties properties) {
+        String name = properties.getProperty(CONFIG_NAME);
+        if (name != null) {
+            properties.remove(CONFIG_NAME);
+        }
+        String type = properties.getProperty(CONFIG_TYPE);
+        if (Strings.isEmpty(type)) {
+            throw new ConfigurationException("No type attribute provided for component " + key);
+        }
+        properties.remove(CONFIG_TYPE);
+        @SuppressWarnings("unchecked")
+        ComponentAssembler<?> componentAssembler = parent.getAssembler().newComponent(name, type);
+        processRemainingProperties(componentAssembler, name, properties);
+        return componentAssembler;
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    private void processRemainingProperties(ComponentAssembler assembler, String name, Properties properties) {
+        while (properties.size() > 0) {
+            String propertyName = properties.stringPropertyNames().iterator().next();
+
+            int index = propertyName.indexOf('.');
+            if (index > 0) {
+                String prefix = propertyName.substring(0, index);
+                Properties componentProperties = PropertiesUtil.extractSubset(properties, prefix);
+                assembler.addComponent(createComponent(assembler, prefix, componentProperties));
+            } else  {
+                assembler.addAttribute(propertyName, properties.getProperty(propertyName));
+                properties.remove(propertyName);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
index 34f47ce..e88faae 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
@@ -179,6 +179,33 @@ public class Log4jContextFactory implements LoggerContextFactory, ShutdownCallba
     }
 
     /**
+     * Loads the LoggerContext using the ContextSelector using the provided Configuration
+     * @param fqcn The fully qualified class name of the caller.
+     * @param loader The ClassLoader to use or null.
+     * @param externalContext An external context (such as a ServletContext) to be associated with the LoggerContext.
+     * @param currentContext If true returns the current Context, if false returns the Context appropriate
+     * for the caller if a more appropriate Context can be determined.
+     * @param configuration The Configuration.
+     * @return The LoggerContext.
+     */
+    public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
+            final boolean currentContext, final Configuration configuration) {
+        final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, null);
+        if (externalContext != null && ctx.getExternalContext() == null) {
+            ctx.setExternalContext(externalContext);
+        }
+        if (ctx.getState() == LifeCycle.State.INITIALIZED) {
+            ContextAnchor.THREAD_CONTEXT.set(ctx);
+            try {
+                ctx.start(configuration);
+            } finally {
+                ContextAnchor.THREAD_CONTEXT.remove();
+            }
+        }
+        return ctx;
+    }
+
+    /**
      * Loads the LoggerContext using the ContextSelector.
      * @param fqcn The fully qualified class name of the caller.
      * @param loader The ClassLoader to use or null.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/util/PropertiesUtil.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/PropertiesUtil.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/PropertiesUtil.java
new file mode 100644
index 0000000..c43ce93
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/PropertiesUtil.java
@@ -0,0 +1,42 @@
+package org.apache.logging.log4j.core.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ *
+ */
+public class PropertiesUtil {
+
+    /**
+     * Extracts properties that start with or are equals to the specific prefix and returns them in a
+     * new Properties object with the prefix removed.
+     * @param properties The Properties to evaluate.
+     * @param prefix The prefix to extract.
+     * @return The subset of properties.
+     */
+    public static Properties extractSubset(Properties properties, String prefix) {
+        Properties subset = new Properties();
+
+        if (prefix == null || prefix.length() == 0) {
+            return subset;
+        }
+
+        String prefixToMatch = prefix.charAt(prefix.length() - 1) != '.' ? prefix + '.' : prefix;
+
+        List<String> keys = new ArrayList<>();
+
+        for (String key : properties.stringPropertyNames()) {
+            if (key.startsWith(prefixToMatch)) {
+                subset.setProperty(key.substring(prefixToMatch.length()), properties.getProperty(key));
+                keys.add(key);
+            }
+        }
+        for (String key : keys) {
+            properties.remove(key);
+        }
+
+        return subset;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/PropertiesRoutingAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/PropertiesRoutingAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/PropertiesRoutingAppenderTest.java
new file mode 100644
index 0000000..2c02a92
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/PropertiesRoutingAppenderTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.appender.routing;
+
+import org.apache.logging.log4j.EventLogger;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.junit.CleanFiles;
+import org.apache.logging.log4j.junit.InitialLoggerContext;
+import org.apache.logging.log4j.message.StructuredDataMessage;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.List;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class PropertiesRoutingAppenderTest {
+    private static final String CONFIG = "log4j-routing.properties";
+    private static final String UNKNOWN_LOG_FILE = "target/rolling1/rollingtestProps-Unknown.log";
+    private static final String ALERT_LOG_FILE = "target/routing1/routingtestProps-Alert.log";
+    private static final String ACTIVITY_LOG_FILE = "target/routing1/routingtestProps-Activity.log";
+
+    private ListAppender app;
+
+    @Rule
+    public InitialLoggerContext init = new InitialLoggerContext(CONFIG);
+
+    @Rule
+    public CleanFiles files = new CleanFiles(UNKNOWN_LOG_FILE, ALERT_LOG_FILE, ACTIVITY_LOG_FILE);
+
+    @Before
+    public void setUp() throws Exception {
+        this.app = this.init.getListAppender("List");
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        this.app.clear();
+    }
+
+    @Test
+    public void routingTest() {
+        StructuredDataMessage msg = new StructuredDataMessage("Test", "This is a test", "Service");
+        EventLogger.logEvent(msg);
+        final List<LogEvent> list = app.getEvents();
+        assertNotNull("No events generated", list);
+        assertTrue("Incorrect number of events. Expected 1, got " + list.size(), list.size() == 1);
+        msg = new StructuredDataMessage("Test", "This is a test", "Alert");
+        EventLogger.logEvent(msg);
+        File file = new File(ALERT_LOG_FILE);
+        assertTrue("Alert file was not created", file.exists());
+        msg = new StructuredDataMessage("Test", "This is a test", "Activity");
+        EventLogger.logEvent(msg);
+        file = new File(ACTIVITY_LOG_FILE);
+        assertTrue("Activity file was not created", file.exists());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
index 0f87ff6..9bbecf8 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
@@ -30,6 +30,11 @@ import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.ConsoleAppender;
+import org.apache.logging.log4j.core.config.assembler.api.AppenderAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.ConfigurationAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.ConfigurationAssemblerFactory;
+import org.apache.logging.log4j.core.config.assembler.impl.AssembledConfiguration;
 import org.apache.logging.log4j.core.filter.CompositeFilter;
 import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.junit.After;
@@ -355,4 +360,30 @@ public class TestConfigurator {
         assertThat(config.getAppenders(), hasSize(equalTo(2)));
     }
 
+    @Test
+    public void testAssembler() throws Exception {
+        ConfigurationAssembler<AssembledConfiguration> assembler = ConfigurationAssemblerFactory.newConfiguration();
+        assembler.setStatusLevel(Level.ERROR);
+        assembler.setConfigurationName("AssemblyTest");
+        assembler.add(assembler.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL)
+                .addAttribute("level", Level.DEBUG));
+        AppenderAssembler appenderAssembler = assembler.newAppender("Stdout", "CONSOLE").addAttribute("target",
+                ConsoleAppender.Target.SYSTEM_OUT);
+        appenderAssembler.add(assembler.newLayout("PatternLayout").
+                addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
+        appenderAssembler.add(assembler.newFilter("MarkerFilter", Filter.Result.DENY,
+                Filter.Result.NEUTRAL).addAttribute("marker", "FLOW"));
+        assembler.add(appenderAssembler);
+        assembler.add(assembler.newLogger("org.apache.logging.log4j", Level.DEBUG).
+                add(assembler.newAppenderRef("Stdout")).
+                addAttribute("additivity", false));
+        assembler.add(assembler.newRootLogger(Level.ERROR).add(assembler.newAppenderRef("Stdout")));
+        ctx = Configurator.initialize(assembler.assemble());
+        final Configuration config = ctx.getConfiguration();
+        assertNotNull("No configuration", config);
+        assertEquals("Unexpected Configuration", "AssemblyTest", config.getName());
+        assertThat(config.getAppenders(), hasSize(equalTo(1)));
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/test/java/org/apache/logging/log4j/core/config/assembler/ConfigurationAssemblerTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/assembler/ConfigurationAssemblerTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/assembler/ConfigurationAssemblerTest.java
new file mode 100644
index 0000000..3e0ef2f
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/assembler/ConfigurationAssemblerTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.assembler;
+
+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.LifeCycle;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.logging.log4j.core.filter.ThresholdFilter;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class ConfigurationAssemblerTest {
+
+    @Test
+    public void doConfigure() throws Exception {
+        System.setProperty(ConfigurationFactory.CONFIGURATION_FACTORY_PROPERTY, "org.apache.logging.log4j.core.config.assembler.CustomConfigurationFactory");
+        Configuration config = ((LoggerContext)LogManager.getContext(false)).getConfiguration();
+        assertNotNull("No configuration created", config);
+        assertEquals("Incorrect State: " + config.getState(), config.getState(), LifeCycle.State.STARTED);
+        Map<String, Appender> appenders = config.getAppenders();
+        assertNotNull(appenders);
+        assertTrue("Incorrect number of Appenders: " + appenders.size(), appenders.size() == 1);
+        Map<String, LoggerConfig> loggers = config.getLoggers();
+        assertNotNull(loggers);
+        assertTrue("Incorrect number of LoggerConfigs: " + loggers.size(), loggers.size() == 2);
+        Filter filter = config.getFilter();
+        assertNotNull("No Filter", filter);
+        assertTrue("Not a Threshold Filter", filter instanceof ThresholdFilter);
+        Logger logger = LogManager.getLogger(getClass());
+        logger.info("Welcome to Log4j!");
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/test/java/org/apache/logging/log4j/core/config/assembler/CustomConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/assembler/CustomConfigurationFactory.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/assembler/CustomConfigurationFactory.java
new file mode 100644
index 0000000..21e7f65
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/assembler/CustomConfigurationFactory.java
@@ -0,0 +1,67 @@
+/*
+ * 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.assembler;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.appender.ConsoleAppender;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.assembler.api.AppenderAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.ConfigurationAssembler;
+import org.apache.logging.log4j.core.config.assembler.impl.AssembledConfiguration;
+
+import java.net.URI;
+
+/**
+ * Normally this would be a plugin. However, we don't want it used for everything so it will be defined
+ * via a system property.
+ */
+//@Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
+//@Order(50)
+public class CustomConfigurationFactory extends ConfigurationFactory {
+
+    @Override
+    protected String[] getSupportedTypes() {
+        return new String[] {"*"};
+    }
+
+    @Override
+    public Configuration getConfiguration(ConfigurationSource source) {
+        return getConfiguration(source.toString(), null);
+    }
+
+    @Override
+    public Configuration getConfiguration(final String name, final URI configLocation) {
+        ConfigurationAssembler<AssembledConfiguration> assembler = newConfiguration();
+        assembler.setStatusLevel(Level.ERROR);
+        assembler.add(assembler.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL)
+                .addAttribute("level", Level.DEBUG));
+        AppenderAssembler appenderAssembler = assembler.newAppender("Stdout", "CONSOLE").addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
+        appenderAssembler.add(assembler.newLayout("PatternLayout").
+                addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
+        appenderAssembler.add(assembler.newFilter("MarkerFilter", Filter.Result.DENY,
+                Filter.Result.NEUTRAL).addAttribute("marker", "FLOW"));
+        assembler.add(appenderAssembler);
+        assembler.add(assembler.newLogger("org.apache.logging.log4j", Level.DEBUG).
+                add(assembler.newAppenderRef("Stdout")).
+                addAttribute("additivity", false));
+        assembler.add(assembler.newRootLogger(Level.ERROR).add(assembler.newAppenderRef("Stdout")));
+        return assembler.assemble();
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java
new file mode 100644
index 0000000..6c78abb
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.properties;
+
+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.LifeCycle;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.logging.log4j.core.filter.ThresholdFilter;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class PropertiesConfigurationTest {
+
+    @Test
+    public void testPropertiesConfiguration() {
+        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "target/test-classes/log4j2-properties.properties");
+        Configuration config = ((LoggerContext)LogManager.getContext(false)).getConfiguration();
+        assertNotNull("No configuration created", config);
+        assertEquals("Incorrect State: " + config.getState(), config.getState(), LifeCycle.State.STARTED);
+        Map<String, Appender> appenders = config.getAppenders();
+        assertNotNull(appenders);
+        assertTrue("Incorrect number of Appenders: " + appenders.size(), appenders.size() == 1);
+        Map<String, LoggerConfig> loggers = config.getLoggers();
+        assertNotNull(loggers);
+        assertTrue("Incorrect number of LoggerConfigs: " + loggers.size(), loggers.size() == 2);
+        Filter filter = config.getFilter();
+        assertNotNull("No Filter", filter);
+        assertTrue("Not a Threshold Filter", filter instanceof ThresholdFilter);
+        Logger logger = LogManager.getLogger(getClass());
+        logger.info("Welcome to Log4j!");
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/RollingFilePropertiesTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/RollingFilePropertiesTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/RollingFilePropertiesTest.java
new file mode 100644
index 0000000..9607284
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/RollingFilePropertiesTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.properties;
+
+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.LifeCycle;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.logging.log4j.core.filter.ThresholdFilter;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class RollingFilePropertiesTest {
+    @Test
+    public void testPropertiesConfiguration() {
+        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "target/test-classes/log4j-rolling.properties");
+        Configuration config = ((LoggerContext) LogManager.getContext(false)).getConfiguration();
+        assertNotNull("No configuration created", config);
+        assertEquals("Incorrect State: " + config.getState(), config.getState(), LifeCycle.State.STARTED);
+        Map<String, Appender> appenders = config.getAppenders();
+        assertNotNull(appenders);
+        assertTrue("Incorrect number of Appenders: " + appenders.size(), appenders.size() == 3);
+        Map<String, LoggerConfig> loggers = config.getLoggers();
+        assertNotNull(loggers);
+        assertTrue("Incorrect number of LoggerConfigs: " + loggers.size(), loggers.size() == 2);
+        Filter filter = config.getFilter();
+        assertNotNull("No Filter", filter);
+        assertTrue("Not a Threshold Filter", filter instanceof ThresholdFilter);
+        Logger logger = LogManager.getLogger(getClass());
+        logger.info("Welcome to Log4j!");
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/test/java/org/apache/logging/log4j/core/util/PropertiesUtilTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/PropertiesUtilTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/PropertiesUtilTest.java
new file mode 100644
index 0000000..0fc6f20
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/PropertiesUtilTest.java
@@ -0,0 +1,25 @@
+package org.apache.logging.log4j.core.util;
+
+import org.junit.Test;
+
+import java.io.FileInputStream;
+import java.util.Properties;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class PropertiesUtilTest {
+
+    @Test
+    public void testSubset() throws Exception {
+        Properties props = new Properties();
+        props.load(new FileInputStream("target/test-classes/log4j2-properties.properties"));
+        Properties subset = PropertiesUtil.extractSubset(props, "appender.Stdout.filter.marker");
+        assertNotNull("No subset returned", subset);
+        assertTrue("Incorrect number of items. Expected 4, actual " + subset.size(), subset.size() == 4);
+        assertTrue("Missing propertu", subset.containsKey("type"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/test/resources/log4j-rolling.properties
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-rolling.properties b/log4j-core/src/test/resources/log4j-rolling.properties
new file mode 100644
index 0000000..17e4a60
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-rolling.properties
@@ -0,0 +1,62 @@
+# 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.
+
+status = error
+name = PropertiesConfigTest
+
+property.filename = target/rolling/rollingtest.log
+
+filters = threshold
+
+filter.threshold.type = ThresholdFilter
+filter.threshold.level = debug
+
+appenders = console, rolling, list
+
+appender.console.type = Console
+appender.console.name = STDOUT
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %m%n
+
+appender.rolling.type = RollingFile
+appender.rolling.name = RollingFile
+appender.rolling.fileName = ${filename}
+appender.rolling.filePattern = target/rolling2/test1-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz
+appender.rolling.layout.type = PatternLayout
+appender.rolling.layout.pattern = %d %p %C{1.} [%t] %m%n
+appender.rolling.policies.type = Policies
+appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
+appender.rolling.policies.time.interval = 2
+appender.rolling.policies.time.modulate = true
+appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
+appender.rolling.policies.size.size=100MB
+
+appender.list.type = List
+appender.list.name = List
+appender.list.filters = threshold
+appender.list.filter.threshold.type = ThresholdFilter
+appender.list.filter.threshold.level = error
+
+loggers = rolling
+
+logger.rolling.name = org.apache.logging.log4j.core.appender.rolling
+logger.rolling.level = debug
+logger.rolling.additivity = false
+logger.rolling.appenderRefs = rolling
+logger.rolling.appenderRef.rolling.ref = RollingFile
+
+rootLogger.level = info
+rootLogger.appenderRefs = stdout
+rootLogger.appenderRef.stdout.ref = STDOUT
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/test/resources/log4j-routing.properties
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-routing.properties b/log4j-core/src/test/resources/log4j-routing.properties
new file mode 100644
index 0000000..dc68cdc
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-routing.properties
@@ -0,0 +1,69 @@
+# 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.
+
+status = error
+name = RoutingTest
+
+property.filename = target/routing1/routingtestProps-$${sd:type}.log
+
+filters = threshold
+
+filter.threshold.type = ThresholdFilter
+filter.threshold.level = debug
+
+appenders = console, routing, list
+
+appender.console.type = Console
+appender.console.name = STDOUT
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %m%n
+
+appender.routing.type = Routing
+appender.routing.name = Routing
+appender.routing.routes.type = Routes
+appender.routing.routes.pattern = $${sd:type}
+appender.routing.routes.route1.type = Route
+appender.routing.routes.route1.rolling.type = RollingFile
+appender.routing.routes.route1.rolling.name = Routing-${sd:type}
+appender.routing.routes.route1.rolling.fileName = ${filename}
+appender.routing.routes.route1.rolling.filePattern = target/routing1/test1-${sd:type}.%i.log.gz
+appender.routing.routes.route1.rolling.layout.type = PatternLayout
+appender.routing.routes.route1.rolling.layout.pattern = %d %p %C{1.} [%t] %m%n
+appender.routing.routes.route1.rolling.policy.type = SizeBasedTriggeringPolicy
+appender.routing.routes.route1.rolling.policy.size = 500
+appender.routing.routes.route2.type = Route
+appender.routing.routes.route2.ref = STDOUT
+appender.routing.routes.route2.key = Audit
+appender.routing.routes.route3.type = Route
+appender.routing.routes.route3.ref = List
+appender.routing.routes.route3.key = Service
+
+appender.list.type = List
+appender.list.name = List
+appender.list.filters = threshold
+appender.list.filter.threshold.type = ThresholdFilter
+appender.list.filter.threshold.level = debug
+
+loggers = event
+
+logger.event.name = EventLogger
+logger.event.level = info
+logger.event.additivity = false
+logger.event.appenderRefs = routing
+logger.event.appenderRef.routing.ref = Routing
+
+rootLogger.level = error
+rootLogger.appenderRefs = stdout
+rootLogger.appenderRef.stdout.ref = STDOUT

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/test/resources/log4j2-properties.properties
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j2-properties.properties b/log4j-core/src/test/resources/log4j2-properties.properties
new file mode 100644
index 0000000..56afedf
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j2-properties.properties
@@ -0,0 +1,44 @@
+# 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.
+
+filters = Threshold
+
+filter.Threshold.type = ThresholdFilter
+filter.Threshold.level = DEBUG
+
+appenders = Stdout
+
+appender.Stdout.type = Console
+appender.Stdout.name = StdOut
+appender.Stdout.target = SYSTEM_OUT
+appender.Stdout.layout.type = PatternLayout
+appender.Stdout.layout.pattern = %d [%t] %-5level: %msg%n%throwable
+appender.Stdout.filters = marker
+appender.Stdout.filter.marker.type = MarkerFilter
+appender.Stdout.filter.marker.onMatch = DENY
+appender.Stdout.filter.marker.onMisMatch = NEUTRAL
+appender.Stdout.filter.marker.marker = FLOW
+
+loggers = log4j
+
+logger.log4j.name = org.apache.logging.log4j
+logger.log4j.appenderRefs = console
+logger.log4j.appenderRef.console.ref = StdOut
+logger.log4j.level = DEBUG
+logger.log4j.additivity = false
+
+rootLogger.appenderRefs = console
+rootLogger.appenderRef.console.ref = StdOut
+rootLogger.level = ERROR


[2/2] logging-log4j2 git commit: LOG4J-952 - Add ConfigurationAssembler and PropertiesConfiguration support

Posted by rg...@apache.org.
LOG4J-952 - Add ConfigurationAssembler and PropertiesConfiguration support


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/bf4afb3e
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/bf4afb3e
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/bf4afb3e

Branch: refs/heads/LOG4J2-952
Commit: bf4afb3e308edd9556b4dbc30f5764fc3f36ea5f
Parents: 920ebf7
Author: Ralph Goers <rg...@nextiva.com>
Authored: Sat Aug 29 15:47:53 2015 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Sat Aug 29 15:47:53 2015 -0700

----------------------------------------------------------------------
 .../core/config/AbstractConfiguration.java      |   5 +-
 .../log4j/core/config/ConfigurationFactory.java |   3 +-
 .../logging/log4j/core/config/Configurator.java |  40 ++-
 .../config/assembler/api/AppenderAssembler.java |  43 +++
 .../assembler/api/AppenderRefAssembler.java     |  30 ++
 .../core/config/assembler/api/Assembler.java    |  37 ++
 .../core/config/assembler/api/Component.java    |  80 +++++
 .../assembler/api/ComponentAssembler.java       |  94 +++++
 .../assembler/api/CompositeFilterAssembler.java |  30 ++
 .../assembler/api/ConfigurationAssembler.java   | 252 +++++++++++++
 .../api/ConfigurationAssemblerFactory.java      |  39 +++
 .../assembler/api/CustomLevelAssembler.java     |  24 ++
 .../config/assembler/api/FilterAssembler.java   |  24 ++
 .../config/assembler/api/LayoutAssembler.java   |  24 ++
 .../config/assembler/api/LoggerAssembler.java   |  37 ++
 .../assembler/api/RootLoggerAssembler.java      |  37 ++
 .../assembler/impl/AssembledConfiguration.java  | 141 ++++++++
 .../impl/DefaultAppenderAssembler.java          |  44 +++
 .../impl/DefaultAppenderRefAssembler.java       |  39 +++
 .../impl/DefaultComponentAssembler.java         | 127 +++++++
 .../impl/DefaultCompositeFilterAssembler.java   |  40 +++
 .../impl/DefaultConfigurationAssembler.java     | 318 +++++++++++++++++
 .../impl/DefaultCustomLevelAssembler.java       |  33 ++
 .../assembler/impl/DefaultFilterAssembler.java  |  34 ++
 .../assembler/impl/DefaultLayoutAssembler.java  |  30 ++
 .../assembler/impl/DefaultLoggerAssembler.java  |  63 ++++
 .../impl/DefaultRootLoggerAssembler.java        |  62 ++++
 .../visitors/PluginAttributeVisitor.java        |   2 +-
 .../visitors/PluginBuilderAttributeVisitor.java |   2 +-
 .../properties/PropertiesConfiguration.java     |  56 +++
 .../PropertiesConfigurationFactory.java         | 349 +++++++++++++++++++
 .../log4j/core/impl/Log4jContextFactory.java    |  27 ++
 .../logging/log4j/core/util/PropertiesUtil.java |  42 +++
 .../routing/PropertiesRoutingAppenderTest.java  |  79 +++++
 .../log4j/core/config/TestConfigurator.java     |  31 ++
 .../assembler/ConfigurationAssemblerTest.java   |  59 ++++
 .../assembler/CustomConfigurationFactory.java   |  67 ++++
 .../properties/PropertiesConfigurationTest.java |  60 ++++
 .../properties/RollingFilePropertiesTest.java   |  59 ++++
 .../log4j/core/util/PropertiesUtilTest.java     |  25 ++
 .../src/test/resources/log4j-rolling.properties |  62 ++++
 .../src/test/resources/log4j-routing.properties |  69 ++++
 .../test/resources/log4j2-properties.properties |  44 +++
 43 files changed, 2757 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index 2218166..aedd25b 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -469,8 +469,9 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
      * @return the Appender with the specified name or null if the Appender cannot be located.
      */
     @Override
-    public Appender getAppender(final String name) {
-        return appenders.get(name);
+    @SuppressWarnings("unchecked")
+    public <T extends Appender> T getAppender(final String name) {
+        return (T)appenders.get(name);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
index 14ea97b..7ff8a2b 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
@@ -35,6 +35,7 @@ import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.config.assembler.api.ConfigurationAssemblerFactory;
 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
 import org.apache.logging.log4j.core.lookup.Interpolator;
@@ -70,7 +71,7 @@ import org.apache.logging.log4j.util.Strings;
  * be called in their respective order. DefaultConfiguration is always called
  * last if no configuration has been returned.
  */
-public abstract class ConfigurationFactory {
+public abstract class ConfigurationFactory extends ConfigurationAssemblerFactory {
     /**
      * Allow the ConfigurationFactory class to be specified as a system property.
      */

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
index cb3d4ef..d654804 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
@@ -164,6 +164,44 @@ public final class Configurator {
     }
 
     /**
+     * Initializes the Logging Context.
+     * @param configuration The Configuration.
+     * @return The LoggerContext.
+     */
+    public static LoggerContext initialize(Configuration configuration) {
+        return initialize(null, configuration, null);
+    }
+
+    /**
+     * Initializes the Logging Context.
+     * @param loader The ClassLoader.
+     * @param configuration The Configuration.
+     * @return The LoggerContext.
+     */
+    public static LoggerContext initialize(final ClassLoader loader, Configuration configuration) {
+        return initialize(loader, configuration, null);
+    }
+
+    /**
+     * Initializes the Logging Context.
+     * @param loader The ClassLoader.
+     * @param configuration The Configuration.
+     * @param externalContext - The external context to be attached to the LoggerContext.
+     * @return The LoggerContext.
+     */
+    public static LoggerContext initialize(final ClassLoader loader, Configuration configuration, final Object externalContext) {
+        try {
+            final Log4jContextFactory factory = getFactory();
+            return factory == null ? null :
+                    factory.getContext(FQCN, loader, externalContext, false, configuration);
+        } catch (final Exception ex) {
+            LOGGER.error("There was a problem initializing the LoggerContext using configuration {}",
+                    configuration.getName(), ex);
+        }
+        return null;
+    }
+
+    /**
      * Sets the levels of <code>parentLogger</code> and all 'child' loggers to the given <code>level</level>.
      * @param parentLogger the parent logger
      * @param level the new level
@@ -198,7 +236,7 @@ public final class Configurator {
     /**
      * Sets a logger levels.
      * 
-     * @param level
+     * @param levelMap
      *            a levelMap where keys are level names and values are new
      *            Levels.
      */

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/AppenderAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/AppenderAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/AppenderAssembler.java
new file mode 100644
index 0000000..95d343a
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/AppenderAssembler.java
@@ -0,0 +1,43 @@
+/*
+ * 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.assembler.api;
+
+/**
+ * Assembler for constructing Appenders.
+ */
+public interface AppenderAssembler extends ComponentAssembler<AppenderAssembler> {
+
+    /**
+     * Add a Layout to the Appender component.
+     * @param assembler The LayoutAssembler with all of its attributes set.
+     * @return this Assembler.
+     */
+    AppenderAssembler add(LayoutAssembler assembler);
+
+    /**
+     * Add a Filter to the Appender component.
+     * @param assembler The FilterAssembler with all of its attributes and sub components set.
+     * @return this Assembler.
+     */
+    AppenderAssembler add(FilterAssembler assembler);
+
+    /**
+     * Return the name of the Appender.
+     * @return the name of the Appender.
+     */
+    String getName();
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/AppenderRefAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/AppenderRefAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/AppenderRefAssembler.java
new file mode 100644
index 0000000..c055faa
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/AppenderRefAssembler.java
@@ -0,0 +1,30 @@
+/*
+ * 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.assembler.api;
+
+/**
+ * Assembler for constructing AppenderRefs.
+ */
+public interface AppenderRefAssembler extends ComponentAssembler<AppenderRefAssembler>  {
+
+    /**
+     * Add a Filter to the Appender component.
+     * @param assembler The FilterAssembler with all of its attributes and sub components set.
+     * @return this Assembler.
+     */
+    AppenderRefAssembler add(FilterAssembler assembler);
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/Assembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/Assembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/Assembler.java
new file mode 100644
index 0000000..7cb9e39
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/Assembler.java
@@ -0,0 +1,37 @@
+/*
+ * 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.assembler.api;
+
+/**
+ * Gathers information in preparation for creating components. These assemblers are primarily useful for
+ * aggregating the information that will be used to create a Configuration.
+ *
+ * @param <T> the Component class this is a builder for.
+ */
+public interface Assembler<T> {
+
+    /**
+     * Builds the plugin object after all configuration has been set. This will use default values for any
+     * unspecified attributes for the plugin.
+     *
+     * @return the configured plugin instance.
+     * @throws org.apache.logging.log4j.core.config.ConfigurationException if there was an error building the plugin
+     * object.
+     */
+    T assemble();
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/Component.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/Component.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/Component.java
new file mode 100644
index 0000000..cd12b39
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/Component.java
@@ -0,0 +1,80 @@
+/*
+ * 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.assembler.api;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Container for assembling Configurations. This class is not normally directly manipulated by users
+ * of the Assembler API.
+ */
+public class Component {
+
+    private final Map<String, String> attributes = new HashMap<>();
+    private final List<Component> components = new ArrayList<>();
+    private final String pluginType;
+    private final String value;
+
+    public Component(String pluginType) {
+        this(pluginType, null, null);
+    }
+
+    public Component(String pluginType, String name) {
+        this(pluginType, name, null);
+    }
+
+    public Component(String pluginType, String name, String value) {
+        this.pluginType = pluginType;
+        this.value = value;
+        if (name != null && name.length() > 0) {
+            attributes.put("name", name);
+        }
+    }
+
+    public Component() {
+        this.pluginType = null;
+        this.value = null;
+    }
+
+
+    public String addAttribute(String key, String value) {
+        return attributes.put(key, value);
+    }
+
+    public void addComponent(Component component) {
+        components.add(component);
+    }
+
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    public List<Component> getComponents() {
+        return components;
+    }
+
+    public String getPluginType() {
+        return pluginType;
+    }
+
+    public String getValue() {
+        return value;
+    }
+ }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ComponentAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ComponentAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ComponentAssembler.java
new file mode 100644
index 0000000..3c21e5a
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ComponentAssembler.java
@@ -0,0 +1,94 @@
+/*
+ * 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.assembler.api;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.config.Configuration;
+
+/**
+ * Assembler for arbitrary components and the base class for the provided components.
+ */
+@SuppressWarnings("rawtypes")
+public interface ComponentAssembler<T extends ComponentAssembler> extends Assembler<Component> {
+
+    /**
+     * Add an attribute to the component.
+     * @param key The attribute key.
+     * @param value The value of the attribute.
+     * @return The ComponentAssembler.
+     */
+    T addAttribute(String key, String value);
+
+    /**
+     * Add a logging Level attribute to the component.
+     * @param key The attribute key.
+     * @param level The logging Level.
+     * @return The ComponentAssembler.
+     */
+    T addAttribute(String key, Level level);
+
+    /**
+     * Add an enumeration.
+     * @param key The attribute key.
+     * @param value The enumeration.
+     * @return The ComponentAssembler.
+     */
+    T addAttribute(String key, Enum<?> value);
+
+    /**
+     * Add an integer attribute.
+     * @param key The attribute key.
+     * @param value The integer value.
+     * @return The ComponentAssembler.
+     */
+    T addAttribute(String key, int value);
+
+    /**
+     * Add a boolean attribute.
+     * @param key The attribute key.
+     * @param value The integer value.
+     * @return The ComponentAssembler.
+     */
+    T addAttribute(String key, boolean value);
+
+    /**
+     * Add an Object attribute.
+     * @param key The attribute key.
+     * @param value The integer value.
+     * @return The ComponentAssembler.
+     */
+    T addAttribute(String key, Object value);
+
+    /**
+     * Add a sub component.
+     * @param assembler The Assembler for the subcomponent with all of its attributes and sub-components set.
+     * @return The ComponentAssembler.
+     */
+    T addComponent(ComponentAssembler<?> assembler);
+
+    /**
+     * Return the name of the component, if any.
+     * @return The components name or null if it doesn't have one.
+     */
+    String getName();
+
+    /**
+     * Retrieve the ConfigurationAssembler.
+     * @return The ConfiguratonAssembler.
+     */
+    ConfigurationAssembler<? extends Configuration> getAssembler();
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/CompositeFilterAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/CompositeFilterAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/CompositeFilterAssembler.java
new file mode 100644
index 0000000..4ab8f7e
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/CompositeFilterAssembler.java
@@ -0,0 +1,30 @@
+/*
+ * 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.assembler.api;
+
+/**
+ * Wraps multiple filter assemblers.
+ */
+public interface CompositeFilterAssembler extends ComponentAssembler<CompositeFilterAssembler> {
+
+    /**
+     * Add a FilterComponent.
+     * @param assembler The FilterAssembler with all of its attributes and sub-components set.
+     * @return The CompositeFilterAssembler.
+     */
+    CompositeFilterAssembler add(FilterAssembler assembler);
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ConfigurationAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ConfigurationAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ConfigurationAssembler.java
new file mode 100644
index 0000000..600515b
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ConfigurationAssembler.java
@@ -0,0 +1,252 @@
+/*
+ * 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.assembler.api;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+
+/**
+ * Interface for assembling logging configurations.
+ */
+public interface ConfigurationAssembler<T extends Configuration> extends Assembler<T> {
+
+    /**
+     * Set the name of the configuration.
+     *
+     * @param name the name of the {@link Configuration}. By default is {@code "Constructed"}.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> setConfigurationName(String name);
+
+    /**
+     * Set the configuration source, if one exists.
+     * @param configurationSource the ConfigurationSource.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> setConfigurationSource(ConfigurationSource configurationSource);
+
+    /**
+     * Set the level of the StatusLogger.
+     * @param level The logging level.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> setStatusLevel(Level level);
+
+    /**
+     * Set whether the logging should include constructing Plugins.
+     * @param verbosity "disable" will hide messages from plugin construction.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> setVerbosity(String verbosity);
+
+    /**
+     * Set the list of packages to search for plugins.
+     * @param packages The comma separated list of packages.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> setPackages(String packages);
+
+    /**
+     * Set whether the shutdown hook should be disabled.
+     * @param flag "disable" will prevent the shutdown hook from being set.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> setShutdownHook(String flag);
+
+    /**
+     * Sets the interval at which the configuration file should be checked for changes.
+     * @param intervalSeconds The number of seconds that should pass between checks of the configuration file.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> setMonitorInterval(String intervalSeconds);
+
+    /**
+     * Adds an AppenderComponent.
+     * @param assembler The AppenderAssembler with all of its attributes and sub components set.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> add(AppenderAssembler assembler);
+
+    /**
+     * Adds a CustomLevel component.
+     * @param assembler The CustomLevelAssembler with all of its attributes set.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> add(CustomLevelAssembler assembler);
+
+    /**
+     * Add a Logger component.
+     * @param assembler The LoggerAssembler with all of its attributes and sub components set.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> add(LoggerAssembler assembler);
+
+    /**
+     * Add the root Logger component.
+     * @param assembler The RootLoggerAssembler with all of its attributes and sub components set.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> add(RootLoggerAssembler assembler);
+
+    /**
+     * Add a Filter component.
+     * @param assembler the FilterAssembler with all of its attributes and sub components set.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> add(FilterAssembler assembler);
+
+    /**
+     * Add a Property key and value.
+     * @param key The property key.
+     * @param value The property value.
+     * @return this Assembler instance.
+     */
+    ConfigurationAssembler<T> addProperty(String key, String value);
+
+    /**
+     * Returns an Assembler for creating Appenders.
+     * @param name The name of the Appender.
+     * @param pluginName The Plugin type of the Appender.
+     * @return the AppenderAssembler.
+     */
+    AppenderAssembler newAppender(String name, String pluginName);
+
+
+    /**
+     * Returns an Assembler for creating AppenderRefs.
+     * @param ref The name of the Appender being referenced.
+     * @return the AppenderRefAssembler.
+     */
+    AppenderRefAssembler newAppenderRef(String ref);
+
+    /**
+     * Returns an Assembler for creating generic components.
+     * @param name The name of the component (may be null).
+     * @param pluginName The Plugin type of the component.
+     * @return The ComponentAssembler.
+     */
+    @SuppressWarnings("rawtypes")
+    ComponentAssembler newComponent(String name, String pluginName);
+
+    /**
+     * Returns an Assembler for creating generic components.
+     * @param name The name of the component (may be null).
+     * @param pluginName The Plugin type of the component.
+     * @param value The value of the component.
+     * @return The ComponentAssembler.
+     */
+    @SuppressWarnings("rawtypes")
+    ComponentAssembler<ComponentAssembler> newComponent(String name, String pluginName, String value);
+
+    /**
+     * Returns an Asssembler for creating CustomLevels
+     * @param name The name of the custom level.
+     * @param level The integer value to be assigned to the level.
+     * @return The CustomLevelAssembler.
+     */
+    CustomLevelAssembler newCustomLevel(String name, int level);
+
+    /**
+     * Returns an Asssembler for creating Filters.
+     * @param pluginName The Plugin type of the Filter.
+     * @param onMatch "ACCEPT", "DENY", or "NEUTRAL"
+     * @param onMisMatch "ACCEPT", "DENY", or "NEUTRAL"
+     * @return The FilterAssembler.
+     */
+    FilterAssembler newFilter(String pluginName, Filter.Result onMatch, Filter.Result onMisMatch);
+
+    /**
+     * Returns an Asssembler for creating Filters.
+     * @param pluginName The Plugin type of the Filter.
+     * @param onMatch "ACCEPT", "DENY", or "NEUTRAL"
+     * @param onMisMatch "ACCEPT", "DENY", or "NEUTRAL"
+     * @return The FilterAssembler.
+     */
+    FilterAssembler newFilter(String pluginName, String onMatch, String onMisMatch);
+
+    /**
+     * Returns an Assembler for creating Layouts.
+     * @param type The Plugin type of the Layout.
+     * @return The LayoutAssembler.
+     */
+    LayoutAssembler newLayout(String pluginName);
+
+    /**
+     * Returns an Assembler for creating Loggers.
+     * @param name The name of the Logger.
+     * @param level The logging Level to be assigned to the Logger.
+     * @return The LoggerAssembler.
+     */
+    LoggerAssembler newLogger(String name, Level level);
+
+
+    /**
+     * Returns an Assembler for creating Loggers.
+     * @param name The name of the Logger.
+     * @param level The logging Level to be assigned to the Logger.
+     * @return The LoggerAssembler.
+     */
+    LoggerAssembler newLogger(String name, String level);
+
+    /**
+     * Returns an Assembler for creating Async Loggers.
+     * @param name The name of the Logger.
+     * @param level The logging Level to be assigned to the Logger.
+     * @return The LoggerAssembler.
+     */
+    LoggerAssembler newAsyncLogger(String name, Level level);
+
+    /**
+     * Returns an Assembler for creating Async Loggers.
+     * @param name The name of the Logger.
+     * @param level The logging Level to be assigned to the Logger.
+     * @return The LoggerAssembler.
+     */
+    LoggerAssembler newAsyncLogger(String name, String level);
+
+    /**
+     * Returns an Assembler for creating the root Logger.
+     * @param level The logging Level to be assigned to the root Logger.
+     * @return The RootLoggerAssembler.
+     */
+    RootLoggerAssembler newRootLogger(Level level);
+
+    /**
+     * Returns an Assembler for creating the root Logger.
+     * @param level The logging Level to be assigned to the root Logger.
+     * @return The RootLoggerAssembler.
+     */
+    RootLoggerAssembler newRootLogger(String level);
+
+
+    /**
+     * Returns an Assembler for creating the async root Logger.
+     * @param level The logging Level to be assigned to the root Logger.
+     * @return The RootLoggerAssembler.
+     */
+    RootLoggerAssembler newAsyncRootLogger(Level level);
+
+
+    /**
+     * Returns an Assembler for creating the async root Logger.
+     * @param level The logging Level to be assigned to the root Logger.
+     * @return The RootLoggerAssembler.
+     */
+    RootLoggerAssembler newAsyncRootLogger(String level);
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ConfigurationAssemblerFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ConfigurationAssemblerFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ConfigurationAssemblerFactory.java
new file mode 100644
index 0000000..8c26425
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/ConfigurationAssemblerFactory.java
@@ -0,0 +1,39 @@
+/*
+ * 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.assembler.api;
+
+import org.apache.logging.log4j.core.config.assembler.impl.AssembledConfiguration;
+import org.apache.logging.log4j.core.config.assembler.impl.DefaultConfigurationAssembler;
+
+/**
+ *
+ */
+public class ConfigurationAssemblerFactory {
+
+    /**
+     * Returns the default ConfigurationAssembler to construct Log4j configurations.
+     * @return The ConfigurationAssembler.
+     */
+    public static ConfigurationAssembler<AssembledConfiguration> newConfiguration() {
+        return new DefaultConfigurationAssembler<>();
+    }
+
+    public static <T extends AssembledConfiguration> ConfigurationAssembler<T> newConfiguration(Class<T> clazz) {
+        return new DefaultConfigurationAssembler<T>(clazz);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/CustomLevelAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/CustomLevelAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/CustomLevelAssembler.java
new file mode 100644
index 0000000..c37ab9e
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/CustomLevelAssembler.java
@@ -0,0 +1,24 @@
+/*
+ * 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.assembler.api;
+
+/**
+ * Assembler for constructing Filters
+ */
+public interface CustomLevelAssembler extends ComponentAssembler<CustomLevelAssembler> {
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/FilterAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/FilterAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/FilterAssembler.java
new file mode 100644
index 0000000..cf95228
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/FilterAssembler.java
@@ -0,0 +1,24 @@
+/*
+ * 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.assembler.api;
+
+/**
+ * Assembler for constructing Filters
+ */
+public interface FilterAssembler extends ComponentAssembler<FilterAssembler> {
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/LayoutAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/LayoutAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/LayoutAssembler.java
new file mode 100644
index 0000000..954ea51
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/LayoutAssembler.java
@@ -0,0 +1,24 @@
+/*
+ * 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.assembler.api;
+
+/**
+ * Assembler for constructing Layouts
+ */
+public interface LayoutAssembler extends ComponentAssembler<LayoutAssembler> {
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/LoggerAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/LoggerAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/LoggerAssembler.java
new file mode 100644
index 0000000..fd6b673
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/LoggerAssembler.java
@@ -0,0 +1,37 @@
+/*
+ * 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.assembler.api;
+
+/**
+ * Assembler for constructing Loggers.
+ */
+public interface LoggerAssembler extends ComponentAssembler<LoggerAssembler> {
+
+    /**
+     * Add an Appender reference to the Logger component.
+     * @param assembler The AppenderRefAssembler with all of its attributes and sub-components set.
+     * @return this Assembler.
+     */
+    LoggerAssembler add(AppenderRefAssembler assembler);
+
+    /**
+     * Add a Filter to the Logger component.
+     * @param assembler The FilterAssembler with all of its attributes and sub-components set.
+     * @return this Assembler.
+     */
+    LoggerAssembler add(FilterAssembler assembler);
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/RootLoggerAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/RootLoggerAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/RootLoggerAssembler.java
new file mode 100644
index 0000000..dfd01ba
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/api/RootLoggerAssembler.java
@@ -0,0 +1,37 @@
+/*
+ * 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.assembler.api;
+
+/**
+ * Assembler for constructing the root Logger.
+ */
+public interface RootLoggerAssembler extends ComponentAssembler<RootLoggerAssembler> {
+
+    /**
+     * Add an Appender reference to the Logger component.
+     * @param assembler The AppenderRefAssembler with all of its attributes and sub-components set.
+     * @return this Assembler.
+     */
+    RootLoggerAssembler add(AppenderRefAssembler assembler);
+
+    /**
+     * Add a Filter to the Logger component.
+     * @param assembler The FilterAssembler with all of its attributes and sub-components set.
+     * @return this Assembler.
+     */
+    RootLoggerAssembler add(FilterAssembler assembler);
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/AssembledConfiguration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/AssembledConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/AssembledConfiguration.java
new file mode 100644
index 0000000..afdb259
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/AssembledConfiguration.java
@@ -0,0 +1,141 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.core.config.AbstractConfiguration;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.FileConfigurationMonitor;
+import org.apache.logging.log4j.core.config.Node;
+import org.apache.logging.log4j.core.config.Reconfigurable;
+import org.apache.logging.log4j.core.config.assembler.api.Component;
+import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
+import org.apache.logging.log4j.core.config.plugins.util.PluginType;
+import org.apache.logging.log4j.core.config.plugins.util.ResolverUtil;
+import org.apache.logging.log4j.core.config.status.StatusConfiguration;
+import org.apache.logging.log4j.core.util.Patterns;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This is the general version of the Configuration created by the Assembler. It may be extended to
+ * enhance its functionality.
+ */
+public class AssembledConfiguration extends AbstractConfiguration {
+    private static final long serialVersionUID = -3071897330997405132L;
+    private static final String[] VERBOSE_CLASSES = new String[] { ResolverUtil.class.getName() };
+    private final StatusConfiguration statusConfig;
+    protected Component root;
+    private Component loggersComponent;
+    private Component appendersComponent;
+    private Component filtersComponent;
+    private Component propertiesComponent;
+    private Component customLevelsComponent;
+
+    public AssembledConfiguration(ConfigurationSource source, Component rootComponent) {
+        super(source);
+        statusConfig = new StatusConfiguration().withVerboseClasses(VERBOSE_CLASSES).withStatus(getDefaultStatus());
+        for (Component component : rootComponent.getComponents()) {
+            switch (component.getPluginType()) {
+                case "Loggers": {
+                    loggersComponent = component;
+                    break;
+                }
+                case "Appenders": {
+                    appendersComponent = component;
+                    break;
+                }
+                case "Filters": {
+                    filtersComponent = component;
+                    break;
+                }
+                case "Properties": {
+                    propertiesComponent = component;
+                    break;
+                }
+                case "CustomLevels": {
+                    customLevelsComponent = component;
+                    break;
+                }
+            }
+        }
+        root = rootComponent;
+    }
+
+    @Override
+    public void setup() {
+        List<Node> children = rootNode.getChildren();
+        if (propertiesComponent.getComponents().size() > 0) {
+            children.add(convertToNode(rootNode, propertiesComponent));
+        }
+        if (customLevelsComponent.getComponents().size() > 0) {
+            children.add(convertToNode(rootNode, customLevelsComponent));
+        }
+        children.add(convertToNode(rootNode, loggersComponent));
+        children.add(convertToNode(rootNode, appendersComponent));
+        if (filtersComponent.getComponents().size() > 0) {
+            if (filtersComponent.getComponents().size() == 1) {
+                children.add(convertToNode(rootNode, filtersComponent.getComponents().get(0)));
+            } else {
+                children.add(convertToNode(rootNode, filtersComponent));
+            }
+        }
+        root = null;
+    }
+
+    public StatusConfiguration getStatusConfiguration() {
+        return statusConfig;
+    }
+
+    public void setPluginPackages(String packages) {
+        pluginPackages.addAll(Arrays.asList(packages.split(Patterns.COMMA_SEPARATOR)));
+    }
+
+    public void setShutdownHook(String flag) {
+        isShutdownHookEnabled = !"disable".equalsIgnoreCase(flag);
+    }
+
+    public void setMonitorInterval(int intervalSeconds) {
+        if (this instanceof Reconfigurable && intervalSeconds > 0) {
+            ConfigurationSource configSource = getConfigurationSource();
+            if (configSource != null) {
+                final File configFile = configSource.getFile();
+                if (intervalSeconds > 0 && configFile != null) {
+                    monitor = new FileConfigurationMonitor((Reconfigurable)this, configFile, listeners, intervalSeconds);
+                }
+            }
+        }
+    }
+
+    public PluginManager getPluginManager() {
+        return pluginManager;
+    }
+
+    protected Node convertToNode(Node parent, Component component) {
+        String name = component.getPluginType();
+        PluginType<?> pluginType = pluginManager.getPluginType(name);
+        Node node = new Node(parent, name, pluginType);
+        node.getAttributes().putAll(component.getAttributes());
+        node.setValue(component.getValue());
+        List<Node> children = node.getChildren();
+        for (Component child : component.getComponents()) {
+            children.add(convertToNode(node, child));
+        }
+        return node;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultAppenderAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultAppenderAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultAppenderAssembler.java
new file mode 100644
index 0000000..be94a88
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultAppenderAssembler.java
@@ -0,0 +1,44 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.assembler.api.AppenderAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.FilterAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.LayoutAssembler;
+
+/**
+ * Holds the Appender Component attributes and subcomponents.
+ */
+public class DefaultAppenderAssembler extends DefaultComponentAssembler<AppenderAssembler> implements AppenderAssembler {
+
+    public DefaultAppenderAssembler(DefaultConfigurationAssembler<? extends Configuration> assembler, String name, String type) {
+        super(assembler, name, type);
+    }
+
+    @Override
+    public AppenderAssembler add(LayoutAssembler assembler) {
+        addComponent(assembler);
+        return this;
+    }
+
+    @Override
+    public AppenderAssembler add(FilterAssembler assembler) {
+        addComponent(assembler);
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultAppenderRefAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultAppenderRefAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultAppenderRefAssembler.java
new file mode 100644
index 0000000..b91aa82
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultAppenderRefAssembler.java
@@ -0,0 +1,39 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.assembler.api.AppenderRefAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.FilterAssembler;
+
+/**
+ * Holds the Appender Component attributes and subcomponents.
+ */
+public class DefaultAppenderRefAssembler extends DefaultComponentAssembler<AppenderRefAssembler> implements AppenderRefAssembler {
+
+    public DefaultAppenderRefAssembler(DefaultConfigurationAssembler<? extends Configuration> assembler, String ref) {
+        super(assembler, "AppenderRef");
+        addAttribute("ref", ref);
+    }
+
+
+    @Override
+    public AppenderRefAssembler add(FilterAssembler assembler) {
+        addComponent(assembler);
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultComponentAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultComponentAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultComponentAssembler.java
new file mode 100644
index 0000000..a8851bd
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultComponentAssembler.java
@@ -0,0 +1,127 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.assembler.api.Component;
+import org.apache.logging.log4j.core.config.assembler.api.ComponentAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.ConfigurationAssembler;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Generic component that captures attributes and Components in preparation for assembling the Appender's
+ * Component.
+ */
+@SuppressWarnings("rawtypes")
+public class DefaultComponentAssembler<T extends ComponentAssembler> implements ComponentAssembler<T> {
+
+    private ConfigurationAssembler<? extends Configuration> assembler;
+    private String type;
+    private Map<String, String> attributes = new HashMap<>();
+    private List<Component> components = new ArrayList<>();
+    private String name;
+    private String value;
+
+    public DefaultComponentAssembler(ConfigurationAssembler<? extends Configuration> assembler, String type) {
+        this(assembler, null, type, null);
+    }
+
+    public DefaultComponentAssembler(ConfigurationAssembler<? extends Configuration> assembler, String name, String type) {
+        this(assembler, name, type, null);
+    }
+
+    public DefaultComponentAssembler(ConfigurationAssembler<? extends Configuration> assembler, String name, String type, String value) {
+        this.type = type;
+        this.assembler = assembler;
+        this.name = name;
+        this.value = value;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public T addAttribute(String key, Level level) {
+        attributes.put(key, level.toString());
+        return (T) this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public T addAttribute(String key, String value) {
+        attributes.put(key, value);
+        return (T) this;
+    }
+
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public T addAttribute(String key, Enum<?> value) {
+        attributes.put(key, value.name());
+        return (T) this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public T addAttribute(String key, int value) {
+        attributes.put(key, Integer.toString(value));
+        return (T) this;
+    }
+
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public T addAttribute(String key, boolean value) {
+        attributes.put(key, Boolean.toString(value));
+        return (T) this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public T addAttribute(String key, Object value) {
+        attributes.put(key, value.toString());
+        return (T) this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public T addComponent(ComponentAssembler<?> assembler) {
+        components.add(assembler.assemble());
+        return (T) this;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public ConfigurationAssembler<? extends Configuration> getAssembler() {
+        return assembler;
+    }
+
+    @Override
+    public Component assemble() {
+        Component component = new Component(type, name, value);
+        component.getAttributes().putAll(attributes);
+        component.getComponents().addAll(components);
+        return component;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultCompositeFilterAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultCompositeFilterAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultCompositeFilterAssembler.java
new file mode 100644
index 0000000..39f9c11
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultCompositeFilterAssembler.java
@@ -0,0 +1,40 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.assembler.api.CompositeFilterAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.FilterAssembler;
+
+/**
+ *
+ */
+public class DefaultCompositeFilterAssembler extends DefaultComponentAssembler<CompositeFilterAssembler> implements CompositeFilterAssembler {
+
+    public DefaultCompositeFilterAssembler(DefaultConfigurationAssembler<? extends Configuration> assembler, String onMatch, String onMisMatch) {
+        super(assembler, "Filters");
+        addAttribute("onMatch", onMatch);
+        addAttribute("onMisMatch", onMisMatch);
+    }
+
+    @Override
+    public CompositeFilterAssembler add(FilterAssembler assembler) {
+        addComponent(assembler);
+        return this;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultConfigurationAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultConfigurationAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultConfigurationAssembler.java
new file mode 100644
index 0000000..c72ef49
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultConfigurationAssembler.java
@@ -0,0 +1,318 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationException;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.assembler.api.AppenderAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.AppenderRefAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.Component;
+import org.apache.logging.log4j.core.config.assembler.api.ComponentAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.ConfigurationAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.CustomLevelAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.FilterAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.LayoutAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.LoggerAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.RootLoggerAssembler;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+/**
+ *
+ */
+public class DefaultConfigurationAssembler<T extends AssembledConfiguration> implements ConfigurationAssembler<T> {
+
+    private AssembledConfiguration configuration;
+
+    private final Component root = new Component();
+    private Component loggers;
+    private Component appenders;
+    private Component filters;
+    private Component properties;
+    private Component customLevels;
+    private final Class<?> clazz;
+    private ConfigurationSource source;
+    private int monitorInterval = 0;
+    private Level level = null;
+    private String verbosity = null;
+    private String packages = null;
+    private String shutdownFlag = null;
+    private String name = null;
+
+    /**
+     * The key with which Apache Log4j loads the selector class.
+     *
+     * @see <a href=
+     *      "http://logging.apache.org/log4j/2.0/manual/async.html">
+     *      Async Loggers</a>
+     */
+    private static final String LOG4J_ASYNC_LOGGERS = "Log4jContextSelector";
+
+    public DefaultConfigurationAssembler() {
+        this(AssembledConfiguration.class);
+        root.addAttribute("name", "Assembled");
+    }
+
+    public <T extends AssembledConfiguration> DefaultConfigurationAssembler(Class<T> clazz) {
+        if (clazz == null) {
+            throw new IllegalArgumentException("A Configuration class must be provided");
+        }
+        this.clazz = clazz;
+        List<Component> components = root.getComponents();
+        properties = new Component("Properties");
+        components.add(properties);
+        customLevels = new Component("CustomLevels");
+        components.add(customLevels);
+        filters = new Component("Filters");
+        components.add(filters);
+        appenders = new Component("Appenders");
+        components.add(appenders);
+        loggers = new Component("Loggers");
+        components.add(loggers);
+    }
+
+    /**
+     * Set the name of the configuration.
+     *
+     * @param name the name of the {@link Configuration}. By default is {@code "Assembled"}.
+     * @return this builder instance
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> setConfigurationName(String name) {
+        this.name = name;
+        return this;
+    }
+
+    /**
+     * Set the ConfigurationSource.
+     *
+     * @param configurationSource the {@link ConfigurationSource).}
+     * @return this builder instance
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> setConfigurationSource(ConfigurationSource configurationSource) {
+        source = configurationSource;
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> setMonitorInterval(String intervalSeconds) {
+        monitorInterval = Integer.parseInt(intervalSeconds);
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> setStatusLevel(Level level) {
+        this.level = level;
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> setVerbosity(String verbosity) {
+        this.verbosity = verbosity;
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> setPackages(String packages) {
+        this.packages = packages;
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> setShutdownHook(String flag) {
+        this.shutdownFlag = flag;
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> add(AppenderAssembler assembler) {
+        appenders.getComponents().add(assembler.assemble());
+        return this;
+    }
+
+    @Override
+    public ConfigurationAssembler<T> add(CustomLevelAssembler assembler) {
+        customLevels.getComponents().add(assembler.assemble());
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> add(LoggerAssembler assembler) {
+        loggers.getComponents().add(assembler.assemble());
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> add(RootLoggerAssembler assembler) {
+        for (Component c : loggers.getComponents()) {
+            if (c.getPluginType().equals("root")) {
+                throw new ConfigurationException("root Logger was previously defined");
+            }
+        }
+        loggers.getComponents().add(assembler.assemble());
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> add(FilterAssembler assembler) {
+        filters.getComponents().add(assembler.assemble());
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationAssembler<T> addProperty(String key, String value) {
+        properties.addComponent(newComponent(key, "Property", value).assemble());
+        return this;
+    }
+
+    @Override
+    public AppenderAssembler newAppender(String name, String type) {
+        return new DefaultAppenderAssembler(this, name, type);
+    }
+
+
+    @Override
+    public AppenderRefAssembler newAppenderRef(String ref) {
+        return new DefaultAppenderRefAssembler(this, ref);
+    }
+
+
+    @Override
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public ComponentAssembler<ComponentAssembler> newComponent(String name, String type) {
+        return new DefaultComponentAssembler(this, name, type);
+    }
+
+    @Override
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public ComponentAssembler<ComponentAssembler> newComponent(String name, String type, String value) {
+        return new DefaultComponentAssembler(this, name, type, value);
+    }
+
+    @Override
+    public CustomLevelAssembler newCustomLevel(String name, int level) {
+        return new DefaultCustomLevelAssembler(this, name, level);
+    }
+
+    @Override
+    @SuppressWarnings("rawtypes")
+    public FilterAssembler newFilter(String type, String onMatch, String onMisMatch) {
+        return new DefaultFilterAssembler(this, type, onMatch, onMisMatch);
+    }
+
+
+    @Override
+    @SuppressWarnings("rawtypes")
+    public FilterAssembler newFilter(String type, Filter.Result onMatch, Filter.Result onMisMatch) {
+        return new DefaultFilterAssembler(this, type, onMatch.name(), onMisMatch.name());
+    }
+
+    @Override
+    public LayoutAssembler newLayout(String type) {
+        return new DefaultLayoutAssembler(this, type);
+    }
+
+    @Override
+    public LoggerAssembler newLogger(String name, String level) {
+        return new DefaultLoggerAssembler(this, name, level);
+    }
+
+    @Override
+    public LoggerAssembler newLogger(String name, Level level) {
+        return new DefaultLoggerAssembler(this, name, level.toString());
+    }
+
+    @Override
+    public LoggerAssembler newAsyncLogger(String name, String level) {
+        return new DefaultLoggerAssembler(this, name, level, "AsyncLogger");
+    }
+
+    @Override
+    public LoggerAssembler newAsyncLogger(String name, Level level) {
+        return new DefaultLoggerAssembler(this, name, level.toString(), "AsyncLogger");
+    }
+
+    @Override
+    public RootLoggerAssembler newRootLogger(String level) {
+        return new DefaultRootLoggerAssembler(this, level);
+    }
+
+    @Override
+    public RootLoggerAssembler newRootLogger(Level level) {
+        return new DefaultRootLoggerAssembler(this, level.toString());
+    }
+
+    @Override
+    public RootLoggerAssembler newAsyncRootLogger(String level) {
+        return new DefaultRootLoggerAssembler(this, level, "AsyncRoot");
+    }
+
+    @Override
+    public RootLoggerAssembler newAsyncRootLogger(Level level) {
+        return new DefaultRootLoggerAssembler(this, level.toString(), "AsyncRoot");
+    }
+
+    @Override
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public T assemble() {
+        AssembledConfiguration configuration;
+        try {
+            if (source == null) {
+                source = ConfigurationSource.NULL_SOURCE;
+            }
+            Constructor constructor = clazz.getConstructor(ConfigurationSource.class, Component.class);
+            configuration = (AssembledConfiguration) constructor.newInstance(source, root);
+            configuration.setMonitorInterval(monitorInterval);
+            if (name != null) {
+                configuration.setName(name);
+            }
+            if (level != null) {
+                configuration.getStatusConfiguration().withStatus(level);
+            }
+            if (verbosity != null) {
+                configuration.getStatusConfiguration().withVerbosity(verbosity);
+            }
+            if (packages != null) {
+                configuration.setPluginPackages(packages);
+            }
+            if (shutdownFlag != null) {
+                configuration.setShutdownHook(shutdownFlag);
+            }
+        } catch (Exception ex) {
+            throw new IllegalArgumentException("Invalid Configuration class specified", ex);
+        }
+        configuration.getStatusConfiguration().initialize();
+        return (T)configuration;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultCustomLevelAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultCustomLevelAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultCustomLevelAssembler.java
new file mode 100644
index 0000000..8b5bfed
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultCustomLevelAssembler.java
@@ -0,0 +1,33 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.assembler.api.CustomLevelAssembler;
+
+/**
+ *
+ */
+public class DefaultCustomLevelAssembler extends DefaultComponentAssembler<CustomLevelAssembler> implements
+        CustomLevelAssembler {
+
+    public DefaultCustomLevelAssembler(DefaultConfigurationAssembler<? extends Configuration> assembler, String name,
+            int level) {
+        super(assembler, name, "CustomLevel");
+        addAttribute("level", Integer.toString(level));
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultFilterAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultFilterAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultFilterAssembler.java
new file mode 100644
index 0000000..4a2caad
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultFilterAssembler.java
@@ -0,0 +1,34 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.assembler.api.ComponentAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.FilterAssembler;
+
+/**
+ *
+ */
+public class DefaultFilterAssembler extends DefaultComponentAssembler<FilterAssembler> implements FilterAssembler {
+
+    public DefaultFilterAssembler(DefaultConfigurationAssembler<? extends Configuration> assembler, String type, String onMatch,
+            String onMisMatch) {
+        super(assembler, type);
+        addAttribute("onMatch", onMatch);
+        addAttribute("onMisMatch", onMisMatch);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultLayoutAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultLayoutAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultLayoutAssembler.java
new file mode 100644
index 0000000..08da646
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultLayoutAssembler.java
@@ -0,0 +1,30 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.assembler.api.LayoutAssembler;
+
+/**
+ *
+ */
+public class DefaultLayoutAssembler extends DefaultComponentAssembler<LayoutAssembler> implements LayoutAssembler {
+
+    public DefaultLayoutAssembler(DefaultConfigurationAssembler<? extends Configuration> assembler, String type) {
+        super(assembler, type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultLoggerAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultLoggerAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultLoggerAssembler.java
new file mode 100644
index 0000000..22a1e51
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultLoggerAssembler.java
@@ -0,0 +1,63 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.assembler.api.AppenderRefAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.FilterAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.LoggerAssembler;
+
+/**
+ *
+ */
+public class DefaultLoggerAssembler extends DefaultComponentAssembler<LoggerAssembler> implements LoggerAssembler {
+
+    /**
+     * Configure a logger.
+     * @param assembler
+     * @param name
+     * @param level
+     */
+    public DefaultLoggerAssembler(DefaultConfigurationAssembler<? extends Configuration> assembler, String name, String level) {
+        super(assembler, name, "Logger");
+        addAttribute("level", level);
+    }
+
+    /**
+     * Configure a logger.
+     * @param assembler
+     * @param name
+     * @param level
+     * @param type
+     */
+    public DefaultLoggerAssembler(DefaultConfigurationAssembler<? extends Configuration> assembler, String name, String level, String type) {
+        super(assembler, name, type);
+        addAttribute("level", level);
+    }
+
+    @Override
+    public LoggerAssembler add(AppenderRefAssembler assembler) {
+        addComponent(assembler);
+        return this;
+    }
+
+    @Override
+    public LoggerAssembler add(FilterAssembler assembler) {
+        addComponent(assembler);
+        return this;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultRootLoggerAssembler.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultRootLoggerAssembler.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultRootLoggerAssembler.java
new file mode 100644
index 0000000..d5ad8dd
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/assembler/impl/DefaultRootLoggerAssembler.java
@@ -0,0 +1,62 @@
+/*
+ * 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.assembler.impl;
+
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.assembler.api.AppenderRefAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.FilterAssembler;
+import org.apache.logging.log4j.core.config.assembler.api.RootLoggerAssembler;
+
+/**
+ *
+ */
+public class DefaultRootLoggerAssembler extends DefaultComponentAssembler<RootLoggerAssembler> implements RootLoggerAssembler {
+
+    /**
+     * Configure the root logger.
+     * @param assembler
+     * @param level
+     */
+    public DefaultRootLoggerAssembler(DefaultConfigurationAssembler<? extends Configuration> assembler, String level) {
+        super(assembler, "", "Root");
+        addAttribute("level", level);
+    }
+
+    /**
+     * Configure the root logger.
+     * @param assembler
+     * @param level
+     * @param type
+     */
+    public DefaultRootLoggerAssembler(DefaultConfigurationAssembler<? extends Configuration> assembler, String level, String type) {
+        super(assembler, "", type);
+        addAttribute("level", level);
+    }
+
+    @Override
+    public RootLoggerAssembler add(AppenderRefAssembler assembler) {
+        addComponent(assembler);
+        return this;
+    }
+
+
+    @Override
+    public RootLoggerAssembler add(FilterAssembler assembler) {
+        addComponent(assembler);
+        return this;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf4afb3e/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginAttributeVisitor.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginAttributeVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginAttributeVisitor.java
index 63e5cb5..acaea29 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginAttributeVisitor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visitors/PluginAttributeVisitor.java
@@ -44,7 +44,7 @@ public class PluginAttributeVisitor extends AbstractPluginVisitor<PluginAttribut
         final Object defaultValue = findDefaultValue(event);
         final Object value = convert(replacedValue, defaultValue);
         final Object debugValue = this.annotation.sensitive() ? NameUtil.md5(value + this.getClass().getName()) : value;
-        StringBuilders.appendKeyDqValue(log, "name", debugValue);
+        StringBuilders.appendKeyDqValue(log, name, debugValue);
         return value;
     }