Split Log4j1 config factory into tiny factory and separate parser
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/74da11ee Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/74da11ee Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/74da11ee Branch: refs/heads/LOG4J2-1010&LOG4J2-1447-injectable-contextdata&better-datastructure Commit: 74da11ee8b2ce39925b16dd89c846be18c1b9e0f Parents: 71f0762 Author: Mikael Ståldal <mik...@staldal.nu> Authored: Sun Aug 21 12:03:01 2016 +0200 Committer: Mikael Ståldal <mik...@staldal.nu> Committed: Sun Aug 21 12:05:37 2016 +0200 ---------------------------------------------------------------------- .../config/Log4j1ConfigurationFactory.java | 311 +------------------ .../log4j/config/Log4j1ConfigurationParser.java | 301 ++++++++++++++++++ 2 files changed, 313 insertions(+), 299 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/74da11ee/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java ---------------------------------------------------------------------- diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java index 7fbb729..2ca2ac1 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java @@ -16,45 +16,17 @@ */ package org.apache.log4j.config; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.core.appender.ConsoleAppender; -import org.apache.logging.log4j.core.appender.ConsoleAppender.Target; import org.apache.logging.log4j.core.config.Configuration; +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.builder.api.AppenderComponentBuilder; import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder; -import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder; -import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder; import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; -import org.apache.logging.log4j.status.StatusLogger; + +import java.io.IOException; /** - * Experimental ConfigurationFactory for Log4j 1.2 properties files. - * <p> - * Currently supports: - * </p> - * <ul> - * <li>log4j.debug</li> - * <li>log4j.rootLogger</li> - * <li>log4j.logger</li> - * <li>log4j.appender</li> - * <li>org.apache.log4j.ConsoleAppender</li> - * <ul> - * <li>Follow</li> - * <li>Target</li> - * <li>layout</li> - * </ul> - * </ul> + * Experimental ConfigurationFactory for Log4j 1.2 properties configuration files. */ // TODO // @Plugin(name = "Log4j1ConfigurationFactory", category = ConfigurationFactory.CATEGORY) @@ -63,282 +35,23 @@ import org.apache.logging.log4j.status.StatusLogger; // @Order(50) public class Log4j1ConfigurationFactory extends ConfigurationFactory { - private Map<String, String> buildClassToPropertyPrefixMap(final Properties properties, - final String[] sortedAppenderNames) { - final String prefix = "log4j.appender."; - final int preLength = prefix.length(); - final Map<String, String> map = new HashMap<>(sortedAppenderNames.length); - for (final Entry<Object, Object> entry : properties.entrySet()) { - final Object keyObj = entry.getKey(); - if (keyObj != null) { - final String key = keyObj.toString(); - if (key.startsWith(prefix)) { - if (key.indexOf('.', preLength) < 0) { - final String name = key.substring(preLength); - if (Arrays.binarySearch(sortedAppenderNames, name) >= 0) { - final Object value = entry.getValue(); - if (value != null) { - map.put(name, value.toString()); - } - } - } - } - } - } - return map; - } - - private void buildConsoleAppender(final Properties properties, final String name, - final ConfigurationBuilder<BuiltConfiguration> builder) { - final AppenderComponentBuilder appenderBuilder = builder.newAppender(name, "Console"); - buildConsoleAppenderTarget(properties, name, builder, appenderBuilder); - buildAppenderLayout(properties, name, builder, appenderBuilder); - buildConsoleAppenderFollow(properties, name, builder, appenderBuilder); - builder.add(appenderBuilder); - } - - private void buildAppenderLayout(final Properties properties, final String name, - final ConfigurationBuilder<BuiltConfiguration> builder, final AppenderComponentBuilder appenderBuilder) { - final String layoutValue = getLog4jAppenderValue(properties, name, "layout", null); - if (layoutValue != null) { - switch (layoutValue) { - case "org.apache.log4j.PatternLayout": - case "org.apache.log4j.EnhancedPatternLayout": { - final String pattern = getLog4jAppenderValue(properties, name, "layout.ConversionPattern", null) - - // Log4j 2's %x (NDC) is not compatible with Log4j 1's %x - // Log4j 1: "foo bar baz" - // Log4j 2: "[foo, bar, baz]" - // Use %ndc to get the Log4j 1 format - .replace("%x", "%ndc") - - // Log4j 2's %X (MDC) is not compatible with Log4j 1's %X - // Log4j 1: "{{foo,bar}{hoo,boo}}" - // Log4j 2: "{foo=bar,hoo=boo}" - // Use %properties to get the Log4j 1 format - .replace("%X", "%properties"); - - appenderBuilder.add(newPatternLayout(builder, pattern)); - break; - } - case "org.apache.log4j.SimpleLayout": { - appenderBuilder.add(newPatternLayout(builder, "%level - %m%n")); - break; - } - case "org.apache.log4j.TTCCLayout": { - String pattern = "%r "; - if (Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.ThreadPrinting", "true"))) { - pattern += "[%t] "; - } - pattern += "%p "; - if (Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.CategoryPrefixing", "true"))) { - pattern += "%c "; - } - if (Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.ContextPrinting", "true"))) { - pattern += "%notEmpty{%ndc }"; - } - pattern += "- %m%n"; - appenderBuilder.add(newPatternLayout(builder, pattern)); - break; - } - case "org.apache.log4j.HTMLLayout": { - LayoutComponentBuilder htmlLayout = builder.newLayout("HtmlLayout"); - htmlLayout.addAttribute("title", - getLog4jAppenderValue(properties, name, "layout.Title", "Log4J Log Messages")); - htmlLayout.addAttribute("locationInfo", - Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.LocationInfo", "false"))); - appenderBuilder.add(htmlLayout); - break; - } - case "org.apache.log4j.xml.XMLLayout": { - LayoutComponentBuilder xmlLayout = builder.newLayout("Log4j1XmlLayout"); - xmlLayout.addAttribute("locationInfo", - Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.LocationInfo", "false"))); - xmlLayout.addAttribute("properties", - Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.Properties", "false"))); - appenderBuilder.add(xmlLayout); - break; - } - default: - reportWarning("Unsupported layout: " + layoutValue); - } - } - } - - private LayoutComponentBuilder newPatternLayout(final ConfigurationBuilder<BuiltConfiguration> builder, - final String pattern) { - final LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout"); - if (pattern != null) { - layoutBuilder.addAttribute("pattern", pattern); - } - return layoutBuilder; - } - - private void buildConsoleAppenderTarget(final Properties properties, final String name, - final ConfigurationBuilder<BuiltConfiguration> builder, final AppenderComponentBuilder appenderBuilder) { - final String value = getLog4jAppenderValue(properties, name, "Target", "System.out"); - if (value != null) { - final Target target; - switch (value) { - case "System.out": - target = ConsoleAppender.Target.SYSTEM_OUT; - break; - case "System.err": - target = ConsoleAppender.Target.SYSTEM_ERR; - break; - default: - reportWarning("Unknow value for console Target: " + value); - target = null; - } - if (target != null) { - appenderBuilder.addAttribute("target", target); - } - } - } - - private void buildConsoleAppenderFollow(final Properties properties, final String name, - final ConfigurationBuilder<BuiltConfiguration> builder, final AppenderComponentBuilder appenderBuilder) { - final String value = getLog4jAppenderValue(properties, name, "Follow", "false"); - if (value != null) { - appenderBuilder.addAttribute("follow", Boolean.valueOf(value).booleanValue()); - } - } - - Configuration createConfiguration(final String configName, final URI configLocation, - final ConfigurationBuilder<BuiltConfiguration> builder) throws IOException { - builder.setConfigurationName(configName); - final Properties properties = load(configLocation); - if (properties == null) { - return null; - } - // DEBUG - final String debugValue = getLog4jValue(properties, "debug"); - if (Boolean.valueOf(debugValue)) { - builder.setStatusLevel(Level.DEBUG); - } - // Root - final String[] sortedAppenderNamesC = buildRootLogger(builder, getRootCategoryValue(properties)); - final String[] sortedAppenderNamesL = buildRootLogger(builder, getRootLoggerValue(properties)); - final String[] sortedAppenderNames = sortedAppenderNamesL.length > 0 ? sortedAppenderNamesL - : sortedAppenderNamesC; - // Appenders - final Map<String, String> classNameToProperty = buildClassToPropertyPrefixMap(properties, sortedAppenderNames); - for (final Entry<String, String> entry : classNameToProperty.entrySet()) { - final String appenderName = entry.getKey(); - switch (entry.getValue()) { - case "org.apache.log4j.ConsoleAppender": - buildConsoleAppender(properties, appenderName, builder); - break; - default: - reportWarning("Ignoring appender " + appenderName - + "; consider porting your configuration file to the current Log4j format."); - } - } - // Loggers - buildLoggers(properties, "log4j.category.", builder); - buildLoggers(properties, "log4j.logger.", builder); - return builder.build(); - } - - private String[] buildRootLogger(final ConfigurationBuilder<BuiltConfiguration> builder, - final String rootLoggerValue) { - if (rootLoggerValue == null) { - return new String[0]; - } - final String[] rootLoggerParts = rootLoggerValue.split("\\s*,\\s*"); - final Level rootLoggerLevel = rootLoggerParts.length > 0 ? Level.valueOf(rootLoggerParts[0]) : Level.ERROR; - final String[] sortedAppenderNames = Arrays.copyOfRange(rootLoggerParts, 1, rootLoggerParts.length); - Arrays.sort(sortedAppenderNames); - RootLoggerComponentBuilder loggerBuilder = builder.newRootLogger(rootLoggerLevel); - for (String appender : sortedAppenderNames) { - loggerBuilder.add(builder.newAppenderRef(appender)); - } - builder.add(loggerBuilder); - return sortedAppenderNames; - } - - private void buildLoggers(final Properties properties, final String prefix, - final ConfigurationBuilder<BuiltConfiguration> builder) { - final int preLength = prefix.length(); - for (final Entry<Object, Object> entry : properties.entrySet()) { - final Object keyObj = entry.getKey(); - if (keyObj != null) { - final String key = keyObj.toString(); - if (key.startsWith(prefix)) { - final String name = key.substring(preLength); - final Object value = entry.getValue(); - if (value != null) { - builder.add(builder.newLogger(name, Level.valueOf(value.toString()))); - } - } - } - } - - } + private static final String[] SUFFIXES = {".properties"}; @Override public Configuration getConfiguration(final ConfigurationSource source) { - return getConfiguration(source.toString(), null); - } - - @Override - public Configuration getConfiguration(final String name, final URI configLocation) { + final ConfigurationBuilder<BuiltConfiguration> builder; try { - return createConfiguration(name, configLocation, newConfigurationBuilder()); - } catch (final IOException e) { - StatusLogger.getLogger().error(e); - return null; + builder = new Log4j1ConfigurationParser().buildConfigurationBuilder(source.getInputStream()); + } catch (IOException e) { + throw new ConfigurationException("Unable to load " + source.toString(), e); } - } - - private String getLog4jAppenderValue(final Properties properties, final String appenderName, - final String attributeName, final String defaultValue) { - return properties.getProperty("log4j.appender." + appenderName + "." + attributeName, defaultValue); - } - - private String getLog4jValue(final Properties properties, final String key) { - return properties.getProperty("log4j." + key); - } - - private String getRootCategoryValue(final Properties properties) { - return getLog4jValue(properties, "rootCategory"); - } - - private String getRootLoggerValue(final Properties properties) { - return getLog4jValue(properties, "rootLogger"); + if (builder == null) return null; + return builder.build(); } @Override protected String[] getSupportedTypes() { - return new String[] { "*.properties", ".xml" }; - } - - private Properties load(final URI uri) throws IOException { - final Properties properties = toProperties(uri); - final String rootCategoryValue = getRootCategoryValue(properties); - final String rootLoggerValue = getRootLoggerValue(properties); - if (rootCategoryValue == null && rootLoggerValue == null) { - // This is not a Log4j 1 properties file. - return null; - } - return properties; + return SUFFIXES; } - private void reportWarning(final String msg) { - StatusLogger.getLogger().warn("Log4j version 1 to 2 configuration bridge: " + msg); - - } - - private Properties toProperties(final URI uri) throws IOException { - final Properties properties; - try (InputStream in = uri.toURL().openStream()) { - properties = new Properties(); - if (uri.toString().endsWith(".xml")) { - properties.loadFromXML(in); - } else { - properties.load(in); - } - } - return properties; - } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/74da11ee/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationParser.java ---------------------------------------------------------------------- diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationParser.java b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationParser.java new file mode 100644 index 0000000..f98f909 --- /dev/null +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationParser.java @@ -0,0 +1,301 @@ +/* + * 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.log4j.config; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.appender.ConsoleAppender; +import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder; +import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder; +import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory; +import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder; +import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder; +import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; +import org.apache.logging.log4j.status.StatusLogger; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +/** + * Experimental parser for Log4j 1.2 properties configuration files. + * <p> + * Currently supports: + * </p> + * <ul> + * <li>log4j.debug</li> + * <li>log4j.rootLogger</li> + * <li>log4j.logger</li> + * <li>log4j.appender</li> + * <li>org.apache.log4j.ConsoleAppender</li> + * <ul> + * <li>Follow</li> + * <li>Target</li> + * <li>layout</li> + * </ul> + * </ul> + */ +public class Log4j1ConfigurationParser { + + /** + * Parse a Log4j 1.2 properties configuration file into a ConfigurationBuilder. + * + * @param input InputStream to read from, will not be closed. + * @return the populated ConfigurationBuilder + * @throws IOException if unable to read the input + */ + public ConfigurationBuilder<BuiltConfiguration> buildConfigurationBuilder(InputStream input) throws IOException { + final ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder(); + builder.setConfigurationName("Log4j1"); + final Properties properties = new Properties(); + properties.load(input); + final String rootCategoryValue = getRootCategoryValue(properties); + final String rootLoggerValue = getRootLoggerValue(properties); + if (rootCategoryValue == null && rootLoggerValue == null) { + // This is not a Log4j 1 properties configuration file. + return null; + } + // DEBUG + final String debugValue = getLog4jValue(properties, "debug"); + if (Boolean.valueOf(debugValue)) { + builder.setStatusLevel(Level.DEBUG); + } + // Root + final String[] sortedAppenderNamesC = buildRootLogger(builder, getRootCategoryValue(properties)); + final String[] sortedAppenderNamesL = buildRootLogger(builder, getRootLoggerValue(properties)); + final String[] sortedAppenderNames = sortedAppenderNamesL.length > 0 ? sortedAppenderNamesL + : sortedAppenderNamesC; + // Appenders + final Map<String, String> classNameToProperty = buildClassToPropertyPrefixMap(properties, sortedAppenderNames); + for (final Map.Entry<String, String> entry : classNameToProperty.entrySet()) { + final String appenderName = entry.getKey(); + switch (entry.getValue()) { + case "org.apache.log4j.ConsoleAppender": + buildConsoleAppender(properties, appenderName, builder); + break; + default: + reportWarning("Ignoring appender " + appenderName + + "; consider porting your configuration file to the current Log4j format."); + } + } + // Loggers + buildLoggers(properties, "log4j.category.", builder); + buildLoggers(properties, "log4j.logger.", builder); + return builder; + } + + private Map<String, String> buildClassToPropertyPrefixMap(final Properties properties, + final String[] sortedAppenderNames) { + final String prefix = "log4j.appender."; + final int preLength = prefix.length(); + final Map<String, String> map = new HashMap<>(sortedAppenderNames.length); + for (final Map.Entry<Object, Object> entry : properties.entrySet()) { + final Object keyObj = entry.getKey(); + if (keyObj != null) { + final String key = keyObj.toString(); + if (key.startsWith(prefix)) { + if (key.indexOf('.', preLength) < 0) { + final String name = key.substring(preLength); + if (Arrays.binarySearch(sortedAppenderNames, name) >= 0) { + final Object value = entry.getValue(); + if (value != null) { + map.put(name, value.toString()); + } + } + } + } + } + } + return map; + } + + private void buildConsoleAppender(final Properties properties, final String name, + final ConfigurationBuilder<BuiltConfiguration> builder) { + final AppenderComponentBuilder appenderBuilder = builder.newAppender(name, "Console"); + buildConsoleAppenderTarget(properties, name, builder, appenderBuilder); + buildAppenderLayout(properties, name, builder, appenderBuilder); + buildConsoleAppenderFollow(properties, name, builder, appenderBuilder); + builder.add(appenderBuilder); + } + + private void buildAppenderLayout(final Properties properties, final String name, + final ConfigurationBuilder<BuiltConfiguration> builder, final AppenderComponentBuilder appenderBuilder) { + final String layoutValue = getLog4jAppenderValue(properties, name, "layout", null); + if (layoutValue != null) { + switch (layoutValue) { + case "org.apache.log4j.PatternLayout": + case "org.apache.log4j.EnhancedPatternLayout": { + final String pattern = getLog4jAppenderValue(properties, name, "layout.ConversionPattern", null) + + // Log4j 2's %x (NDC) is not compatible with Log4j 1's %x + // Log4j 1: "foo bar baz" + // Log4j 2: "[foo, bar, baz]" + // Use %ndc to get the Log4j 1 format + .replace("%x", "%ndc") + + // Log4j 2's %X (MDC) is not compatible with Log4j 1's %X + // Log4j 1: "{{foo,bar}{hoo,boo}}" + // Log4j 2: "{foo=bar,hoo=boo}" + // Use %properties to get the Log4j 1 format + .replace("%X", "%properties"); + + appenderBuilder.add(newPatternLayout(builder, pattern)); + break; + } + case "org.apache.log4j.SimpleLayout": { + appenderBuilder.add(newPatternLayout(builder, "%level - %m%n")); + break; + } + case "org.apache.log4j.TTCCLayout": { + String pattern = "%r "; + if (Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.ThreadPrinting", "true"))) { + pattern += "[%t] "; + } + pattern += "%p "; + if (Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.CategoryPrefixing", "true"))) { + pattern += "%c "; + } + if (Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.ContextPrinting", "true"))) { + pattern += "%notEmpty{%ndc }"; + } + pattern += "- %m%n"; + appenderBuilder.add(newPatternLayout(builder, pattern)); + break; + } + case "org.apache.log4j.HTMLLayout": { + LayoutComponentBuilder htmlLayout = builder.newLayout("HtmlLayout"); + htmlLayout.addAttribute("title", + getLog4jAppenderValue(properties, name, "layout.Title", "Log4J Log Messages")); + htmlLayout.addAttribute("locationInfo", + Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.LocationInfo", "false"))); + appenderBuilder.add(htmlLayout); + break; + } + case "org.apache.log4j.xml.XMLLayout": { + LayoutComponentBuilder xmlLayout = builder.newLayout("Log4j1XmlLayout"); + xmlLayout.addAttribute("locationInfo", + Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.LocationInfo", "false"))); + xmlLayout.addAttribute("properties", + Boolean.parseBoolean(getLog4jAppenderValue(properties, name, "layout.Properties", "false"))); + appenderBuilder.add(xmlLayout); + break; + } + default: + reportWarning("Unsupported layout: " + layoutValue); + } + } + } + + private LayoutComponentBuilder newPatternLayout(final ConfigurationBuilder<BuiltConfiguration> builder, + final String pattern) { + final LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout"); + if (pattern != null) { + layoutBuilder.addAttribute("pattern", pattern); + } + return layoutBuilder; + } + + private void buildConsoleAppenderTarget(final Properties properties, final String name, + final ConfigurationBuilder<BuiltConfiguration> builder, final AppenderComponentBuilder appenderBuilder) { + final String value = getLog4jAppenderValue(properties, name, "Target", "System.out"); + if (value != null) { + final ConsoleAppender.Target target; + switch (value) { + case "System.out": + target = ConsoleAppender.Target.SYSTEM_OUT; + break; + case "System.err": + target = ConsoleAppender.Target.SYSTEM_ERR; + break; + default: + reportWarning("Unknow value for console Target: " + value); + target = null; + } + if (target != null) { + appenderBuilder.addAttribute("target", target); + } + } + } + + private void buildConsoleAppenderFollow(final Properties properties, final String name, + final ConfigurationBuilder<BuiltConfiguration> builder, final AppenderComponentBuilder appenderBuilder) { + final String value = getLog4jAppenderValue(properties, name, "Follow", "false"); + if (value != null) { + appenderBuilder.addAttribute("follow", Boolean.valueOf(value).booleanValue()); + } + } + + private String[] buildRootLogger(final ConfigurationBuilder<BuiltConfiguration> builder, + final String rootLoggerValue) { + if (rootLoggerValue == null) { + return new String[0]; + } + final String[] rootLoggerParts = rootLoggerValue.split("\\s*,\\s*"); + final Level rootLoggerLevel = rootLoggerParts.length > 0 ? Level.valueOf(rootLoggerParts[0]) : Level.ERROR; + final String[] sortedAppenderNames = Arrays.copyOfRange(rootLoggerParts, 1, rootLoggerParts.length); + Arrays.sort(sortedAppenderNames); + RootLoggerComponentBuilder loggerBuilder = builder.newRootLogger(rootLoggerLevel); + for (String appender : sortedAppenderNames) { + loggerBuilder.add(builder.newAppenderRef(appender)); + } + builder.add(loggerBuilder); + return sortedAppenderNames; + } + + private void buildLoggers(final Properties properties, final String prefix, + final ConfigurationBuilder<BuiltConfiguration> builder) { + final int preLength = prefix.length(); + for (final Map.Entry<Object, Object> entry : properties.entrySet()) { + final Object keyObj = entry.getKey(); + if (keyObj != null) { + final String key = keyObj.toString(); + if (key.startsWith(prefix)) { + final String name = key.substring(preLength); + final Object value = entry.getValue(); + if (value != null) { + builder.add(builder.newLogger(name, Level.valueOf(value.toString()))); + } + } + } + } + + } + + private String getLog4jAppenderValue(final Properties properties, final String appenderName, + final String attributeName, final String defaultValue) { + return properties.getProperty("log4j.appender." + appenderName + "." + attributeName, defaultValue); + } + + private String getLog4jValue(final Properties properties, final String key) { + return properties.getProperty("log4j." + key); + } + + private String getRootCategoryValue(final Properties properties) { + return getLog4jValue(properties, "rootCategory"); + } + + private String getRootLoggerValue(final Properties properties) { + return getLog4jValue(properties, "rootLogger"); + } + + private void reportWarning(final String msg) { + StatusLogger.getLogger().warn("Log4j 1 configuration parser: " + msg); + } + +}