Repository: logging-log4j2
Updated Branches:
  refs/heads/master 91b599e7b -> 61e7a5427


Better error reporting.

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

Branch: refs/heads/master
Commit: 61e7a542793b0be05264805d75266bd050fd4519
Parents: 91b599e
Author: Gary Gregory <[email protected]>
Authored: Fri Sep 23 17:50:57 2016 -0700
Committer: Gary Gregory <[email protected]>
Committed: Fri Sep 23 17:50:57 2016 -0700

----------------------------------------------------------------------
 .../apache/log4j/config/InputStreamWrapper.java |  92 +++
 .../config/Log4j1ConfigurationConverter.java    |   4 +-
 .../log4j/config/Log4j1ConfigurationParser.java | 615 ++++++++++---------
 3 files changed, 403 insertions(+), 308 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/61e7a542/log4j-1.2-api/src/main/java/org/apache/log4j/config/InputStreamWrapper.java
----------------------------------------------------------------------
diff --git 
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/InputStreamWrapper.java 
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/InputStreamWrapper.java
new file mode 100644
index 0000000..29ea51a
--- /dev/null
+++ 
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/InputStreamWrapper.java
@@ -0,0 +1,92 @@
+/*
+ * 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 java.io.IOException;
+import java.io.InputStream;
+
+class InputStreamWrapper extends InputStream {
+
+    private final String description;
+    private final InputStream input;
+
+    public InputStreamWrapper(final InputStream input, final String 
description) {
+        this.input = input;
+        this.description = description;
+    }
+
+    @Override
+    public int available() throws IOException {
+        return input.available();
+    }
+
+    @Override
+    public void close() throws IOException {
+        input.close();
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        return input.equals(obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return input.hashCode();
+    }
+
+    @Override
+    public void mark(final int readlimit) {
+        input.mark(readlimit);
+    }
+
+    @Override
+    public boolean markSupported() {
+        return input.markSupported();
+    }
+
+    @Override
+    public int read() throws IOException {
+        return input.read();
+    }
+
+    @Override
+    public int read(final byte[] b) throws IOException {
+        return input.read(b);
+    }
+
+    @Override
+    public int read(final byte[] b, final int off, final int len) throws 
IOException {
+        return input.read(b, off, len);
+    }
+
+    @Override
+    public synchronized void reset() throws IOException {
+        input.reset();
+    }
+
+    @Override
+    public long skip(final long n) throws IOException {
+        return input.skip(n);
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + " [description=" + description + 
", input=" + input + "]";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/61e7a542/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationConverter.java
 
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationConverter.java
index c9c8bc5..e48e54c 100644
--- 
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationConverter.java
+++ 
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationConverter.java
@@ -142,7 +142,7 @@ public final class Log4j1ConfigurationConverter {
     }
 
     InputStream getInputStream() throws IOException {
-        return cla.pathIn == null ? System.in : 
Files.newInputStream(cla.pathIn);
+        return cla.pathIn == null ? System.in : new 
InputStreamWrapper(Files.newInputStream(cla.pathIn), cla.pathIn.toString());
     }
 
     OutputStream getOutputStream() throws IOException {
@@ -165,7 +165,7 @@ public final class Log4j1ConfigurationConverter {
                             newFile = lastIndex < 0 ? newFile + FILE_EXT_XML
                                     : newFile.substring(0, lastIndex) + 
FILE_EXT_XML;
                             final Path resolved = file.resolveSibling(newFile);
-                            try (final InputStream input = 
Files.newInputStream(file);
+                            try (final InputStream input = new 
InputStreamWrapper(Files.newInputStream(file), file.toString());
                                     final OutputStream output = 
Files.newOutputStream(resolved)) {
                                 try {
                                     convert(input, output);

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/61e7a542/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
index 16ab9c5..da9bc8f 100644
--- 
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
@@ -48,30 +48,26 @@ import org.apache.logging.log4j.status.StatusLogger;
  * From the Log4j 1.2 Javadocs:
  * </p>
  * <p>
- * All option values admit variable substitution. The syntax of variable
- * substitution is similar to that of Unix shells. The string between an 
opening
- * "${" and closing "}" is interpreted as a key. The value of the substituted
- * variable can be defined as a system property or in the configuration file
- * itself. The value of the key is first searched in the system properties, and
- * if not found there, it is then searched in the configuration file being
- * parsed. The corresponding value replaces the ${variableName} sequence. For
- * example, if java.home system property is set to /home/xyz, then every
- * occurrence of the sequence ${java.home} will be interpreted as /home/xyz.
+ * All option values admit variable substitution. The syntax of variable 
substitution is similar to that of Unix shells. The string between
+ * an opening "${" and closing "}" is interpreted as a key. The value of the 
substituted variable can be defined as a system property or in
+ * the configuration file itself. The value of the key is first searched in 
the system properties, and if not found there, it is then
+ * searched in the configuration file being parsed. The corresponding value 
replaces the ${variableName} sequence. For example, if java.home
+ * system property is set to /home/xyz, then every occurrence of the sequence 
${java.home} will be interpreted as /home/xyz.
  * </p>
  */
 public class Log4j1ConfigurationParser {
 
-       private static final String ROOTLOGGER = "rootLogger";
-       private static final String ROOTCATEGORY = "rootCategory";
-       private static final String TRUE = "true";
-       private static final String FALSE = "false";
-       
-       private final Properties properties = new Properties();
-       private StrSubstitutor strSubstitutorProperties;
-       private StrSubstitutor strSubstitutorSystem;
-       
-       private final ConfigurationBuilder<BuiltConfiguration> builder = 
ConfigurationBuilderFactory
-                       .newConfigurationBuilder();
+    private static final String ROOTLOGGER = "rootLogger";
+    private static final String ROOTCATEGORY = "rootCategory";
+    private static final String TRUE = "true";
+    private static final String FALSE = "false";
+
+    private final Properties properties = new Properties();
+    private StrSubstitutor strSubstitutorProperties;
+    private StrSubstitutor strSubstitutorSystem;
+
+    private final ConfigurationBuilder<BuiltConfiguration> builder = 
ConfigurationBuilderFactory
+            .newConfigurationBuilder();
 
     /**
      * Parses a Log4j 1.2 properties configuration file in ISO 8859-1 encoding 
into a ConfigurationBuilder.
@@ -84,7 +80,7 @@ public class Log4j1ConfigurationParser {
      * @throws ConfigurationException
      *             if the input does not contain a valid configuration
      */
-       public ConfigurationBuilder<BuiltConfiguration> 
buildConfigurationBuilder(final InputStream input)
+    public ConfigurationBuilder<BuiltConfiguration> 
buildConfigurationBuilder(final InputStream input)
             throws IOException {
         try {
             properties.load(input);
@@ -94,8 +90,9 @@ public class Log4j1ConfigurationParser {
             final String rootLoggerValue = getLog4jValue(ROOTLOGGER);
             if (rootCategoryValue == null && rootLoggerValue == null) {
                 // This is not a Log4j 1 properties configuration file.
-                throw new ConfigurationException(
-                        "Input does not contain a valid Log4j 1.x properties 
configuration: " + input);
+                warn("Missing " + ROOTCATEGORY + " or " + ROOTLOGGER + " in " 
+ input);
+                // throw new ConfigurationException(
+                // "Missing " + ROOTCATEGORY + " or " + ROOTLOGGER + " in " + 
input);
             }
             builder.setConfigurationName("Log4j1");
             // DEBUG
@@ -124,288 +121,294 @@ public class Log4j1ConfigurationParser {
         }
     }
 
-       private Map<String, String> buildClassToPropertyPrefixMap(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 buildAppender(final String appenderName, final String 
appenderClass) {
-               switch (appenderClass) {
-               case "org.apache.log4j.ConsoleAppender":
-                       buildConsoleAppender(appenderName);
-                       break;
-               case "org.apache.log4j.FileAppender":
-                       buildFileAppender(appenderName);
-                       break;
-               case "org.apache.log4j.DailyRollingFileAppender":
-                       buildDailyRollingFileAppender(appenderName);
-                       break;
-               case "org.apache.log4j.RollingFileAppender":
-                       buildRollingFileAppender(appenderName);
-                       break;
-               case "org.apache.log4j.varia.NullAppender":
-                       buildNullAppender(appenderName);
-                       break;
-               default:
-                       reportWarning("Unknown appender class: " + 
appenderClass + "; ignoring appender: " + appenderName);
-               }
-       }
-
-       private void buildConsoleAppender(final String appenderName) {
-               final AppenderComponentBuilder appenderBuilder = 
builder.newAppender(appenderName, ConsoleAppender.PLUGIN_NAME);
-               final String targetValue = getLog4jAppenderValue(appenderName, 
"Target", "System.out");
-               if (targetValue != null) {
-                       final ConsoleAppender.Target target;
-                       switch (targetValue) {
-                       case "System.out":
-                               target = ConsoleAppender.Target.SYSTEM_OUT;
-                               break;
-                       case "System.err":
-                               target = ConsoleAppender.Target.SYSTEM_ERR;
-                               break;
-                       default:
-                               reportWarning("Unknown value for console 
Target: " + targetValue);
-                               target = null;
-                       }
-                       if (target != null) {
-                               appenderBuilder.addAttribute("target", target);
-                       }
-               }
-               buildAttribute(appenderName, appenderBuilder, "Follow", 
"follow");
-               if (FALSE.equalsIgnoreCase(getLog4jAppenderValue(appenderName, 
"ImmediateFlush"))) {
-                       reportWarning("ImmediateFlush=false is not supported on 
Console appender");
-               }
-               buildAppenderLayout(appenderName, appenderBuilder);
-               builder.add(appenderBuilder);
-       }
-
-       private void buildFileAppender(final String appenderName) {
-               final AppenderComponentBuilder appenderBuilder = 
builder.newAppender(appenderName, FileAppender.PLUGIN_NAME);
-               buildFileAppender(appenderName, appenderBuilder);
-               builder.add(appenderBuilder);
-       }
-
-       private void buildFileAppender(final String appenderName, final 
AppenderComponentBuilder appenderBuilder) {
-               buildMandatoryAttribute(appenderName, appenderBuilder, "File", 
"fileName");
-               buildAttribute(appenderName, appenderBuilder, "Append", 
"append");
-               buildAttribute(appenderName, appenderBuilder, "BufferedIO", 
"bufferedIo");
-               buildAttribute(appenderName, appenderBuilder, "BufferSize", 
"bufferSize");
-               buildAttribute(appenderName, appenderBuilder, "ImmediateFlush", 
"immediateFlush");
-               buildAppenderLayout(appenderName, appenderBuilder);
-       }
-
-       private void buildDailyRollingFileAppender(final String appenderName) {
-               final AppenderComponentBuilder appenderBuilder = 
builder.newAppender(appenderName, RollingFileAppender.PLUGIN_NAME);
-               buildFileAppender(appenderName, appenderBuilder);
-               final String fileName = getLog4jAppenderValue(appenderName, 
"File");
-               final String datePattern = getLog4jAppenderValue(appenderName, 
"DatePattern", fileName + "'.'yyyy-MM-dd");
-               appenderBuilder.addAttribute("filePattern", fileName + "%d{" + 
datePattern + "}");
-               final ComponentBuilder<?> triggeringPolicy = 
builder.newComponent("Policies").addComponent(
-                               
builder.newComponent("TimeBasedTriggeringPolicy").addAttribute("modulate", 
true));
-               appenderBuilder.addComponent(triggeringPolicy);
-               appenderBuilder.addComponent(
-                               
builder.newComponent("DefaultRolloverStrategy").addAttribute("max", 
Integer.MAX_VALUE));
-               builder.add(appenderBuilder);
-       }
-
-       private void buildRollingFileAppender(final String appenderName) {
-               final AppenderComponentBuilder appenderBuilder = 
builder.newAppender(appenderName, RollingFileAppender.PLUGIN_NAME);
-               buildFileAppender(appenderName, appenderBuilder);
-               final String fileName = getLog4jAppenderValue(appenderName, 
"File");
-               appenderBuilder.addAttribute("filePattern", fileName + ".%i");
-               final String maxFileSizeString = 
getLog4jAppenderValue(appenderName, "MaxFileSize", "10485760");
-               final String maxBackupIndexString = 
getLog4jAppenderValue(appenderName, "MaxBackupIndex", "1");
-               final ComponentBuilder<?> triggeringPolicy = 
builder.newComponent("Policies").addComponent(
-                               
builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", 
maxFileSizeString));
-               appenderBuilder.addComponent(triggeringPolicy);
-               appenderBuilder.addComponent(
-                               
builder.newComponent("DefaultRolloverStrategy").addAttribute("max", 
maxBackupIndexString));
-               builder.add(appenderBuilder);
-       }
-
-       private void buildAttribute(final String componentName, final 
ComponentBuilder componentBuilder,
-                       final String sourceAttributeName, final String 
targetAttributeName) {
-               final String attributeValue = 
getLog4jAppenderValue(componentName, sourceAttributeName);
-               if (attributeValue != null) {
-                       componentBuilder.addAttribute(targetAttributeName, 
attributeValue);
-               }
-       }
-
-       private void buildAttributeWithDefault(final String componentName, 
final ComponentBuilder componentBuilder,
-                       final String sourceAttributeName, final String 
targetAttributeName, final String defaultValue) {
-               final String attributeValue = 
getLog4jAppenderValue(componentName, sourceAttributeName, defaultValue);
-               componentBuilder.addAttribute(targetAttributeName, 
attributeValue);
-       }
-
-       private void buildMandatoryAttribute(final String componentName, final 
ComponentBuilder componentBuilder,
-                       final String sourceAttributeName, final String 
targetAttributeName) {
-               final String attributeValue = 
getLog4jAppenderValue(componentName, sourceAttributeName);
-               if (attributeValue != null) {
-                       componentBuilder.addAttribute(targetAttributeName, 
attributeValue);
-               } else {
-                       reportWarning("Missing " + sourceAttributeName + " for 
" + componentName);
-               }
-       }
-
-       private void buildNullAppender(String appenderName) {
-               final AppenderComponentBuilder appenderBuilder = 
builder.newAppender(appenderName, NullAppender.PLUGIN_NAME);
-               builder.add(appenderBuilder);
-       }
-
-       private void buildAppenderLayout(final String name, final 
AppenderComponentBuilder appenderBuilder) {
-               final String layoutClass = getLog4jAppenderValue(name, 
"layout", null);
-               if (layoutClass != null) {
-                       switch (layoutClass) {
-                       case "org.apache.log4j.PatternLayout":
-                       case "org.apache.log4j.EnhancedPatternLayout": {
-                               final String pattern = 
getLog4jAppenderValue(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(pattern));
-                               break;
-                       }
-                       case "org.apache.log4j.SimpleLayout": {
-                               appenderBuilder.add(newPatternLayout("%level - 
%m%n"));
-                               break;
-                       }
-                       case "org.apache.log4j.TTCCLayout": {
-                               String pattern = "%r ";
-                               if 
(Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.ThreadPrinting", 
TRUE))) {
-                                       pattern += "[%t] ";
-                               }
-                               pattern += "%p ";
-                               if 
(Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.CategoryPrefixing", 
TRUE))) {
-                                       pattern += "%c ";
-                               }
-                               if 
(Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.ContextPrinting", 
TRUE))) {
-                                       pattern += "%notEmpty{%ndc }";
-                               }
-                               pattern += "- %m%n";
-                               appenderBuilder.add(newPatternLayout(pattern));
-                               break;
-                       }
-                       case "org.apache.log4j.HTMLLayout": {
-                               final LayoutComponentBuilder htmlLayout = 
builder.newLayout("HtmlLayout");
-                               htmlLayout.addAttribute("title", 
getLog4jAppenderValue(name, "layout.Title", "Log4J Log Messages"));
-                               htmlLayout.addAttribute("locationInfo",
-                                               
Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.LocationInfo", 
FALSE)));
-                               appenderBuilder.add(htmlLayout);
-                               break;
-                       }
-                       case "org.apache.log4j.xml.XMLLayout": {
-                               final LayoutComponentBuilder xmlLayout = 
builder.newLayout("Log4j1XmlLayout");
-                               xmlLayout.addAttribute("locationInfo",
-                                               
Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.LocationInfo", 
FALSE)));
-                               xmlLayout.addAttribute("properties",
-                                               
Boolean.parseBoolean(getLog4jAppenderValue(name, "layout.Properties", FALSE)));
-                               appenderBuilder.add(xmlLayout);
-                               break;
-                       }
-                       default:
-                               reportWarning("Unknown layout class: " + 
layoutClass);
-                       }
-               }
-       }
-
-       private LayoutComponentBuilder newPatternLayout(final String pattern) {
-               final LayoutComponentBuilder layoutBuilder = 
builder.newLayout("PatternLayout");
-               if (pattern != null) {
-                       layoutBuilder.addAttribute("pattern", pattern);
-               }
-               return layoutBuilder;
-       }
-
-       private String[] buildRootLogger(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);
-               final RootLoggerComponentBuilder loggerBuilder = 
builder.newRootLogger(rootLoggerLevel);
-               for (final String appender : sortedAppenderNames) {
-                       loggerBuilder.add(builder.newAppenderRef(appender));
-               }
-               builder.add(loggerBuilder);
-               return sortedAppenderNames;
-       }
-
-       private void buildLoggers(final String prefix) {
-               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 String appenderName, final 
String attributeName) {
-               return getProperty("log4j.appender." + appenderName + "." + 
attributeName);
-       }
-
-       private String getProperty(final String key) {
-               final String value = properties.getProperty(key);
-               final String sysValue = strSubstitutorSystem.replace(value);
-               return strSubstitutorProperties.replace(sysValue);
-       }
-
-       private String getProperty(final String key, String defaultValue) {
-               final String value = getProperty(key);
-               return value == null ? defaultValue : value;
-       }
-
-       private String getLog4jAppenderValue(final String appenderName, final 
String attributeName,
-                       final String defaultValue) {
-               return getProperty("log4j.appender." + appenderName + "." + 
attributeName, defaultValue);
-       }
-
-       private String getLog4jValue(final String key) {
-               return getProperty("log4j." + key);
-       }
-
-       private void reportWarning(final String msg) {
-               StatusLogger.getLogger().warn("Log4j 1 configuration parser: " 
+ msg);
-       }
+    private void warn(String string) {
+        System.err.println(string);
+    }
+
+    private Map<String, String> buildClassToPropertyPrefixMap(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 buildAppender(final String appenderName, final String 
appenderClass) {
+        switch (appenderClass) {
+        case "org.apache.log4j.ConsoleAppender":
+            buildConsoleAppender(appenderName);
+            break;
+        case "org.apache.log4j.FileAppender":
+            buildFileAppender(appenderName);
+            break;
+        case "org.apache.log4j.DailyRollingFileAppender":
+            buildDailyRollingFileAppender(appenderName);
+            break;
+        case "org.apache.log4j.RollingFileAppender":
+            buildRollingFileAppender(appenderName);
+            break;
+        case "org.apache.log4j.varia.NullAppender":
+            buildNullAppender(appenderName);
+            break;
+        default:
+            reportWarning("Unknown appender class: " + appenderClass + "; 
ignoring appender: " + appenderName);
+        }
+    }
+
+    private void buildConsoleAppender(final String appenderName) {
+        final AppenderComponentBuilder appenderBuilder = 
builder.newAppender(appenderName, ConsoleAppender.PLUGIN_NAME);
+        final String targetValue = getLog4jAppenderValue(appenderName, 
"Target", "System.out");
+        if (targetValue != null) {
+            final ConsoleAppender.Target target;
+            switch (targetValue) {
+            case "System.out":
+                target = ConsoleAppender.Target.SYSTEM_OUT;
+                break;
+            case "System.err":
+                target = ConsoleAppender.Target.SYSTEM_ERR;
+                break;
+            default:
+                reportWarning("Unknown value for console Target: " + 
targetValue);
+                target = null;
+            }
+            if (target != null) {
+                appenderBuilder.addAttribute("target", target);
+            }
+        }
+        buildAttribute(appenderName, appenderBuilder, "Follow", "follow");
+        if (FALSE.equalsIgnoreCase(getLog4jAppenderValue(appenderName, 
"ImmediateFlush"))) {
+            reportWarning("ImmediateFlush=false is not supported on Console 
appender");
+        }
+        buildAppenderLayout(appenderName, appenderBuilder);
+        builder.add(appenderBuilder);
+    }
+
+    private void buildFileAppender(final String appenderName) {
+        final AppenderComponentBuilder appenderBuilder = 
builder.newAppender(appenderName, FileAppender.PLUGIN_NAME);
+        buildFileAppender(appenderName, appenderBuilder);
+        builder.add(appenderBuilder);
+    }
+
+    private void buildFileAppender(final String appenderName, final 
AppenderComponentBuilder appenderBuilder) {
+        buildMandatoryAttribute(appenderName, appenderBuilder, "File", 
"fileName");
+        buildAttribute(appenderName, appenderBuilder, "Append", "append");
+        buildAttribute(appenderName, appenderBuilder, "BufferedIO", 
"bufferedIo");
+        buildAttribute(appenderName, appenderBuilder, "BufferSize", 
"bufferSize");
+        buildAttribute(appenderName, appenderBuilder, "ImmediateFlush", 
"immediateFlush");
+        buildAppenderLayout(appenderName, appenderBuilder);
+    }
+
+    private void buildDailyRollingFileAppender(final String appenderName) {
+        final AppenderComponentBuilder appenderBuilder = 
builder.newAppender(appenderName,
+                RollingFileAppender.PLUGIN_NAME);
+        buildFileAppender(appenderName, appenderBuilder);
+        final String fileName = getLog4jAppenderValue(appenderName, "File");
+        final String datePattern = getLog4jAppenderValue(appenderName, 
"DatePattern", fileName + "'.'yyyy-MM-dd");
+        appenderBuilder.addAttribute("filePattern", fileName + "%d{" + 
datePattern + "}");
+        final ComponentBuilder<?> triggeringPolicy = 
builder.newComponent("Policies")
+                
.addComponent(builder.newComponent("TimeBasedTriggeringPolicy").addAttribute("modulate",
 true));
+        appenderBuilder.addComponent(triggeringPolicy);
+        appenderBuilder
+                
.addComponent(builder.newComponent("DefaultRolloverStrategy").addAttribute("max",
 Integer.MAX_VALUE));
+        builder.add(appenderBuilder);
+    }
+
+    private void buildRollingFileAppender(final String appenderName) {
+        final AppenderComponentBuilder appenderBuilder = 
builder.newAppender(appenderName,
+                RollingFileAppender.PLUGIN_NAME);
+        buildFileAppender(appenderName, appenderBuilder);
+        final String fileName = getLog4jAppenderValue(appenderName, "File");
+        appenderBuilder.addAttribute("filePattern", fileName + ".%i");
+        final String maxFileSizeString = getLog4jAppenderValue(appenderName, 
"MaxFileSize", "10485760");
+        final String maxBackupIndexString = 
getLog4jAppenderValue(appenderName, "MaxBackupIndex", "1");
+        final ComponentBuilder<?> triggeringPolicy = 
builder.newComponent("Policies").addComponent(
+                
builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", 
maxFileSizeString));
+        appenderBuilder.addComponent(triggeringPolicy);
+        appenderBuilder.addComponent(
+                
builder.newComponent("DefaultRolloverStrategy").addAttribute("max", 
maxBackupIndexString));
+        builder.add(appenderBuilder);
+    }
+
+    private void buildAttribute(final String componentName, final 
ComponentBuilder componentBuilder,
+            final String sourceAttributeName, final String 
targetAttributeName) {
+        final String attributeValue = getLog4jAppenderValue(componentName, 
sourceAttributeName);
+        if (attributeValue != null) {
+            componentBuilder.addAttribute(targetAttributeName, attributeValue);
+        }
+    }
+
+    private void buildAttributeWithDefault(final String componentName, final 
ComponentBuilder componentBuilder,
+            final String sourceAttributeName, final String 
targetAttributeName, final String defaultValue) {
+        final String attributeValue = getLog4jAppenderValue(componentName, 
sourceAttributeName, defaultValue);
+        componentBuilder.addAttribute(targetAttributeName, attributeValue);
+    }
+
+    private void buildMandatoryAttribute(final String componentName, final 
ComponentBuilder componentBuilder,
+            final String sourceAttributeName, final String 
targetAttributeName) {
+        final String attributeValue = getLog4jAppenderValue(componentName, 
sourceAttributeName);
+        if (attributeValue != null) {
+            componentBuilder.addAttribute(targetAttributeName, attributeValue);
+        } else {
+            reportWarning("Missing " + sourceAttributeName + " for " + 
componentName);
+        }
+    }
+
+    private void buildNullAppender(String appenderName) {
+        final AppenderComponentBuilder appenderBuilder = 
builder.newAppender(appenderName, NullAppender.PLUGIN_NAME);
+        builder.add(appenderBuilder);
+    }
+
+    private void buildAppenderLayout(final String name, final 
AppenderComponentBuilder appenderBuilder) {
+        final String layoutClass = getLog4jAppenderValue(name, "layout", null);
+        if (layoutClass != null) {
+            switch (layoutClass) {
+            case "org.apache.log4j.PatternLayout":
+            case "org.apache.log4j.EnhancedPatternLayout": {
+                final String pattern = getLog4jAppenderValue(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(pattern));
+                break;
+            }
+            case "org.apache.log4j.SimpleLayout": {
+                appenderBuilder.add(newPatternLayout("%level - %m%n"));
+                break;
+            }
+            case "org.apache.log4j.TTCCLayout": {
+                String pattern = "%r ";
+                if (Boolean.parseBoolean(getLog4jAppenderValue(name, 
"layout.ThreadPrinting", TRUE))) {
+                    pattern += "[%t] ";
+                }
+                pattern += "%p ";
+                if (Boolean.parseBoolean(getLog4jAppenderValue(name, 
"layout.CategoryPrefixing", TRUE))) {
+                    pattern += "%c ";
+                }
+                if (Boolean.parseBoolean(getLog4jAppenderValue(name, 
"layout.ContextPrinting", TRUE))) {
+                    pattern += "%notEmpty{%ndc }";
+                }
+                pattern += "- %m%n";
+                appenderBuilder.add(newPatternLayout(pattern));
+                break;
+            }
+            case "org.apache.log4j.HTMLLayout": {
+                final LayoutComponentBuilder htmlLayout = 
builder.newLayout("HtmlLayout");
+                htmlLayout.addAttribute("title", getLog4jAppenderValue(name, 
"layout.Title", "Log4J Log Messages"));
+                htmlLayout.addAttribute("locationInfo",
+                        Boolean.parseBoolean(getLog4jAppenderValue(name, 
"layout.LocationInfo", FALSE)));
+                appenderBuilder.add(htmlLayout);
+                break;
+            }
+            case "org.apache.log4j.xml.XMLLayout": {
+                final LayoutComponentBuilder xmlLayout = 
builder.newLayout("Log4j1XmlLayout");
+                xmlLayout.addAttribute("locationInfo",
+                        Boolean.parseBoolean(getLog4jAppenderValue(name, 
"layout.LocationInfo", FALSE)));
+                xmlLayout.addAttribute("properties",
+                        Boolean.parseBoolean(getLog4jAppenderValue(name, 
"layout.Properties", FALSE)));
+                appenderBuilder.add(xmlLayout);
+                break;
+            }
+            default:
+                reportWarning("Unknown layout class: " + layoutClass);
+            }
+        }
+    }
+
+    private LayoutComponentBuilder newPatternLayout(final String pattern) {
+        final LayoutComponentBuilder layoutBuilder = 
builder.newLayout("PatternLayout");
+        if (pattern != null) {
+            layoutBuilder.addAttribute("pattern", pattern);
+        }
+        return layoutBuilder;
+    }
+
+    private String[] buildRootLogger(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);
+        final RootLoggerComponentBuilder loggerBuilder = 
builder.newRootLogger(rootLoggerLevel);
+        for (final String appender : sortedAppenderNames) {
+            loggerBuilder.add(builder.newAppenderRef(appender));
+        }
+        builder.add(loggerBuilder);
+        return sortedAppenderNames;
+    }
+
+    private void buildLoggers(final String prefix) {
+        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 String appenderName, final 
String attributeName) {
+        return getProperty("log4j.appender." + appenderName + "." + 
attributeName);
+    }
+
+    private String getProperty(final String key) {
+        final String value = properties.getProperty(key);
+        final String sysValue = strSubstitutorSystem.replace(value);
+        return strSubstitutorProperties.replace(sysValue);
+    }
+
+    private String getProperty(final String key, String defaultValue) {
+        final String value = getProperty(key);
+        return value == null ? defaultValue : value;
+    }
+
+    private String getLog4jAppenderValue(final String appenderName, final 
String attributeName,
+            final String defaultValue) {
+        return getProperty("log4j.appender." + appenderName + "." + 
attributeName, defaultValue);
+    }
+
+    private String getLog4jValue(final String key) {
+        return getProperty("log4j." + key);
+    }
+
+    private void reportWarning(final String msg) {
+        StatusLogger.getLogger().warn("Log4j 1 configuration parser: " + msg);
+    }
 
 }

Reply via email to