Index: src/test/java/org/apache/logging/log4j/core/config/JSONConfigurationTest.java =================================================================== --- src/test/java/org/apache/logging/log4j/core/config/JSONConfigurationTest.java (revision 0) +++ src/test/java/org/apache/logging/log4j/core/config/JSONConfigurationTest.java (revision 0) @@ -0,0 +1,9 @@ +package org.apache.logging.log4j.core.config; + +public class JSONConfigurationTest extends AbstractConfigurationTest { + + @Override + public String getConfigFile() { + return "log4j-test1.json"; + } +} Index: src/test/java/org/apache/logging/log4j/core/config/YAMLConfigurationTest.java =================================================================== --- src/test/java/org/apache/logging/log4j/core/config/YAMLConfigurationTest.java (revision 0) +++ src/test/java/org/apache/logging/log4j/core/config/YAMLConfigurationTest.java (revision 0) @@ -0,0 +1,9 @@ +package org.apache.logging.log4j.core.config; + +public class YAMLConfigurationTest extends AbstractConfigurationTest{ + + @Override + public String getConfigFile() { + return "log4j-test1.yaml"; + } +} Index: src/test/java/org/apache/logging/log4j/core/config/AbstractConfigurationTest.java =================================================================== --- src/test/java/org/apache/logging/log4j/core/config/AbstractConfigurationTest.java (revision 0) +++ src/test/java/org/apache/logging/log4j/core/config/AbstractConfigurationTest.java (revision 0) @@ -0,0 +1,93 @@ +package org.apache.logging.log4j.core.config; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.Appender; +import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.filter.ThreadContextMapFilter; +import org.apache.logging.log4j.status.StatusLogger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.util.Iterator; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public abstract class AbstractConfigurationTest { + + public abstract String getConfigFile(); + + @Before + public void setUp() { + System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, getConfigFile()); + } + + @After + public void tearDown() { + System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY); + final LoggerContext ctx = (LoggerContext) LogManager.getContext(); + ctx.reconfigure(); + StatusLogger.getLogger().reset(); + } + + @Test + public void testConfiguredAppenders() { + final LoggerContext ctx = (LoggerContext) LogManager.getContext(); + final Configuration c = ctx.getConfiguration(); + final Map apps = c.getAppenders(); + assertNotNull(apps); + assertEquals(3, apps.size()); + } + + @Test + public void testLogger() { + final Logger logger = LogManager.getLogger("org.apache.logging.log4j.test1.Test"); + assertTrue(logger instanceof org.apache.logging.log4j.core.Logger); + final org.apache.logging.log4j.core.Logger l = (org.apache.logging.log4j.core.Logger) logger; + assertEquals(Level.DEBUG, l.getLevel()); + final int filterCount = l.filterCount(); + assertTrue("number of filters - " + filterCount, filterCount == 1); + final Iterator iter = l.getFilters(); + final Filter filter = iter.next(); + assertTrue(filter instanceof ThreadContextMapFilter); + final Map appenders = l.getAppenders(); + assertNotNull(appenders); + assertTrue("number of appenders = " + appenders.size(), appenders.size() == 1); + final Appender a = appenders.get("STDOUT"); + assertNotNull(a); + assertEquals(a.getName(), "STDOUT"); + } + + @Test + public void logToFile() throws Exception { + final FileOutputStream fos = new FileOutputStream("target/test.log", false); + fos.flush(); + fos.close(); + final Logger logger = LogManager.getLogger("org.apache.logging.log4j.test2.Test"); + logger.debug("This is a test"); + final BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream("target/test.log"))); + try { + int count = 0; + String str = ""; + while (is.ready()) { + str = is.readLine(); + ++count; + } + assertTrue("Incorrect count " + count, count == 1); + assertTrue("Bad data", str.endsWith("This is a test")); + } finally { + is.close(); + } + } + +} Index: src/test/resources/log4j-test1.json =================================================================== --- src/test/resources/log4j-test1.json (revision 0) +++ src/test/resources/log4j-test1.json (revision 0) @@ -0,0 +1,75 @@ +{ + "Configuration" : { + "status": "warn", + "name": "YAMLConfigTest", + "packages": "org.apache.logging.log4j.test", + + "properties" : { + "property" : { + "name" : "filename", + "value": "target/test.log" + } + }, + "thresholdFilter" : { + "level": "debug" + }, + "appenders" : { + "Console" : { + "name" : "STDOUT", + "PatternLayout" : { + "Pattern": "%m%n" + } + }, + "File" : { + "name": "File", + "fileName": "${filename}", + "bufferedIO": false, + "PatternLayout" : { + "Pattern": "%d %p %C{1.} [%t] %m%n" + } + }, + "List" : { + "name": "List", + "Filters": { + "ThresholdFilter" : { + "level" : "error" + } + } + } + }, + "Loggers" : { + "logger" : [ + { + "name" : "org.apache.logging.log4j.test1", + "level" : "debug", + "additivity" : false, + "ThreadContextMapFilter" : { + "KeyValuePair": { + "key" : "test", + "value" : 123 + } + }, + "AppenderRef" : { + "ref" : "STDOUT" + } + }, + { + "name" : "org.apache.logging.log4j.test2", + "level" : "debug", + "additivity" : false, + "AppenderRef" : { + "ref" : "File" + } + + } + ], + "Root" : { + "level" : "error", + "AppenderRef" : { + "ref" : "STDOUT" + } + + } + } + } +} \ No newline at end of file Index: src/test/resources/log4j-test1.yaml =================================================================== --- src/test/resources/log4j-test1.yaml (revision 0) +++ src/test/resources/log4j-test1.yaml (revision 0) @@ -0,0 +1,49 @@ +Configuration: + status: warn + name: YAMLConfigTest + packages: org.apache.logging.log4j.test + properties: + property: + name: filename + value: target/test.log + thresholdFilter: + level: debug + appenders: + Console: + name: STDOUT + PatternLayout: + Pattern: "%m%n" + File: + name: File + fileName: ${filename} + bufferedIO: false + PatternLayout: + Pattern: "%d %p %C{1.} [%t] %m%n" + List: + name: List + Filters: + ThresholdFilter: + level: error + + Loggers: + logger: + - + name: org.apache.logging.log4j.test1 + level: debug + additivity: false + ThreadContextMapFilter: + KeyValuePair: + key: test + value: 123 + AppenderRef: + ref: STDOUT + - + name: org.apache.logging.log4j.test2 + level: debug + additivity: false + AppenderRef: + ref: File + Root: + level: error + AppenderRef: + ref: STDOUT Index: src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java =================================================================== --- src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java (revision 1532078) +++ src/main/java/org/apache/logging/log4j/core/config/JSONConfiguration.java (working copy) @@ -72,7 +72,7 @@ buffer = toByteArray(configStream); configStream.close(); final InputStream is = new ByteArrayInputStream(buffer); - final ObjectMapper mapper = new ObjectMapper().configure(JsonParser.Feature.ALLOW_COMMENTS, true); + final ObjectMapper mapper = getObjectMapper(); root = mapper.readTree(is); if (root.size() == 1) { final Iterator i = root.elements(); @@ -158,6 +158,10 @@ } } + protected ObjectMapper getObjectMapper() { + return new ObjectMapper().configure(JsonParser.Feature.ALLOW_COMMENTS, true); + } + @Override public void stop() { super.stop(); Index: src/main/java/org/apache/logging/log4j/core/config/YAMLConfigurationFactory.java =================================================================== --- src/main/java/org/apache/logging/log4j/core/config/YAMLConfigurationFactory.java (revision 0) +++ src/main/java/org/apache/logging/log4j/core/config/YAMLConfigurationFactory.java (revision 0) @@ -0,0 +1,58 @@ +package org.apache.logging.log4j.core.config; + +import org.apache.logging.log4j.core.config.plugins.Plugin; + +import java.io.File; + +@Plugin(name = "YAMLConfigurationFactory", category = "ConfigurationFactory") +@Order(7) +public class YAMLConfigurationFactory extends ConfigurationFactory { + + /** + * The file extensions supported by this factory. + */ + public static final String[] SUFFIXES = new String[] {".yml", ".yaml"}; + + private static String[] dependencies = new String[] { + "com.fasterxml.jackson.databind.ObjectMapper", + "com.fasterxml.jackson.databind.JsonNode", + "com.fasterxml.jackson.core.JsonParser", + "com.fasterxml.jackson.dataformat.yaml.YAMLFactory" + }; + + private final File configFile = null; + + private boolean isActive; + + public YAMLConfigurationFactory() { + try { + for (final String item : dependencies) { + Class.forName(item); + } + } catch (final ClassNotFoundException ex) { + LOGGER.debug("Missing dependencies for Yaml support"); + isActive = false; + return; + } + isActive = true; + } + + @Override + protected boolean isActive() { + return isActive; + } + + @Override + public Configuration getConfiguration(final ConfigurationSource source) { + if (!isActive) { + return null; + } + return new YAMLConfiguration(source); + } + + @Override + public String[] getSupportedTypes() { + return SUFFIXES; + } + +} Index: src/main/java/org/apache/logging/log4j/core/config/YAMLConfiguration.java =================================================================== --- src/main/java/org/apache/logging/log4j/core/config/YAMLConfiguration.java (revision 0) +++ src/main/java/org/apache/logging/log4j/core/config/YAMLConfiguration.java (revision 0) @@ -0,0 +1,18 @@ +package org.apache.logging.log4j.core.config; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; + +public class YAMLConfiguration extends JSONConfiguration { + + public YAMLConfiguration(ConfigurationFactory.ConfigurationSource configSource) { + super(configSource); + } + + @Override + protected ObjectMapper getObjectMapper() { + return new ObjectMapper(new YAMLFactory()).configure(JsonParser.Feature.ALLOW_COMMENTS, true); + } + +} Index: pom.xml =================================================================== --- pom.xml (revision 1532078) +++ pom.xml (working copy) @@ -64,6 +64,11 @@ true + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + true + + org.fusesource.jansi jansi true