This is an automated email from the ASF dual-hosted git repository.
pkarwasz pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/logging-log4j-transform.git
The following commit(s) were added to refs/heads/main by this push:
new b018a8e Refactor properties v2 parser to use `PropertiesSubset`
b018a8e is described below
commit b018a8e6071584f13b11484be3f9a981bcc0b415
Author: Piotr P. Karwasz <[email protected]>
AuthorDate: Mon Dec 16 17:15:26 2024 +0100
Refactor properties v2 parser to use `PropertiesSubset`
The `PropertiesV1ConfigurationParser` uses the `PropertiesSubset`
abstraction to pass subsets of properties between methods, while keeping track
of the global name of each property.
We refactor the `PropertiesV2ConfigurationParser` to use the same
abstraction, which allows us to eliminate many helper methods in
`PropertiesUtils`.
---
.../converter/config/internal/PropertiesUtils.java | 44 +--
.../internal/v1/AbstractComponentParser.java | 2 +-
.../v1/PropertiesV1ConfigurationParser.java | 2 +-
.../v1/appender/AbstractAppenderParser.java | 2 +-
.../internal/v1/filter/DenyAllFilterParser.java | 2 +-
.../internal/v1/filter/LevelMatchFilterParser.java | 2 +-
.../internal/v1/filter/LevelRangeFilterParser.java | 2 +-
.../v1/filter/StringMatchFilterParser.java | 2 +-
.../v1/layout/EnhancedPatternLayoutParser.java | 2 +-
.../internal/v1/layout/HtmlLayoutParser.java | 2 +-
.../internal/v1/layout/PatternLayoutParser.java | 2 +-
.../internal/v1/layout/SimpleLayoutParser.java | 2 +-
.../internal/v1/layout/TTCCLayoutParser.java | 2 +-
.../v2/PropertiesV2ConfigurationParser.java | 297 ++++++++++-----------
.../config/spi/{v1 => }/PropertiesSubset.java | 2 +-
.../config/spi/v1/Log4j1ComponentParser.java | 1 +
16 files changed, 182 insertions(+), 186 deletions(-)
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/PropertiesUtils.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/PropertiesUtils.java
index d2e3fdf..8b0663c 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/PropertiesUtils.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/PropertiesUtils.java
@@ -16,33 +16,20 @@
*/
package org.apache.logging.converter.config.internal;
-import java.util.Map;
+import java.util.Comparator;
import java.util.Properties;
import java.util.stream.Stream;
import org.apache.logging.converter.config.ConfigurationConverterException;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.jspecify.annotations.Nullable;
public final class PropertiesUtils {
- public static @Nullable String getAndRemove(Properties properties, String
key) {
- return (String) properties.remove(key);
- }
-
public static String getLastComponent(String name) {
int idx = name.lastIndexOf('.');
return idx == -1 ? name : name.substring(idx + 1);
}
- public static Properties extractSubset(Properties properties, String
prefix) {
- Properties subset =
org.apache.logging.log4j.util.PropertiesUtil.extractSubset(properties, prefix);
- String value = getAndRemove(properties, prefix);
- if (value != null) {
- subset.setProperty("", value);
- }
- return subset;
- }
-
public static @Nullable String extractProperty(PropertiesSubset subset,
String key) {
return (String) subset.getProperties().remove(key);
}
@@ -51,25 +38,24 @@ public final class PropertiesUtils {
Properties parentProperties = parentSubset.getProperties();
Properties properties =
org.apache.logging.log4j.util.PropertiesUtil.extractSubset(parentProperties,
childPrefix);
- String value = getAndRemove(parentProperties, childPrefix);
+ String value = (String) parentProperties.remove(childPrefix);
if (value != null) {
properties.setProperty("", value);
}
return PropertiesSubset.of(addPrefixes(parentSubset.getPrefix(),
childPrefix), properties);
}
- public static Map<String, Properties> partitionOnCommonPrefixes(Properties
properties) {
- return
org.apache.logging.log4j.util.PropertiesUtil.partitionOnCommonPrefixes(properties,
true);
- }
-
public static Stream<PropertiesSubset>
partitionOnCommonPrefixes(PropertiesSubset parentSubset) {
String parentPrefix = parentSubset.getPrefix();
String effectivePrefix = parentPrefix.isEmpty() ? parentPrefix :
parentPrefix + ".";
- return
org.apache.logging.log4j.util.PropertiesUtil.partitionOnCommonPrefixes(
+ Stream<PropertiesSubset> partitioned =
org.apache.logging.log4j.util.PropertiesUtil.partitionOnCommonPrefixes(
parentSubset.getProperties(), true)
.entrySet()
.stream()
- .map(entry -> PropertiesSubset.of(effectivePrefix +
entry.getKey(), entry.getValue()));
+ .map(entry -> PropertiesSubset.of(effectivePrefix +
entry.getKey(), entry.getValue()))
+ .sorted(Comparator.comparing(PropertiesSubset::getPrefix));
+ parentSubset.getProperties().clear();
+ return partitioned;
}
private static String addPrefixes(String left, String right) {
@@ -94,5 +80,19 @@ public final class PropertiesUtils {
}
}
+ /**
+ * @return {@code true} if the subset contains no properties.
+ */
+ public static boolean isEmpty(PropertiesSubset subset) {
+ return subset.getProperties().isEmpty();
+ }
+
+ /**
+ * @return {@code true} if the subset contains some properties.
+ */
+ public static boolean isNotEmpty(PropertiesSubset subset) {
+ return !isEmpty(subset);
+ }
+
private PropertiesUtils() {}
}
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/AbstractComponentParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/AbstractComponentParser.java
index 2eb6ecc..cb9c148 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/AbstractComponentParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/AbstractComponentParser.java
@@ -32,9 +32,9 @@ import
org.apache.logging.converter.config.internal.PropertiesUtils;
import org.apache.logging.converter.config.internal.StringUtils;
import org.apache.logging.converter.config.internal.XmlUtils;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ComponentParser;
import org.apache.logging.converter.config.spi.v1.Log4j1ParserContext;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/PropertiesV1ConfigurationParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/PropertiesV1ConfigurationParser.java
index 75ee813..a0e8b12 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/PropertiesV1ConfigurationParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/PropertiesV1ConfigurationParser.java
@@ -35,7 +35,7 @@ import
org.apache.logging.converter.config.internal.ComponentUtils.Configuration
import org.apache.logging.converter.config.internal.PropertiesUtils;
import org.apache.logging.converter.config.spi.ConfigurationNode;
import org.apache.logging.converter.config.spi.ConfigurationParser;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
@ServiceProvider(value = ConfigurationParser.class, resolution =
Resolution.MANDATORY)
public class PropertiesV1ConfigurationParser extends
AbstractV1ConfigurationParser {
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/appender/AbstractAppenderParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/appender/AbstractAppenderParser.java
index 28fb08c..0da9ce0 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/appender/AbstractAppenderParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/appender/AbstractAppenderParser.java
@@ -27,8 +27,8 @@ import
org.apache.logging.converter.config.internal.ComponentUtils.Configuration
import org.apache.logging.converter.config.internal.PropertiesUtils;
import org.apache.logging.converter.config.internal.v1.AbstractComponentParser;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ParserContext;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.jspecify.annotations.Nullable;
import org.w3c.dom.Element;
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/DenyAllFilterParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/DenyAllFilterParser.java
index d8c2b75..02b6a4a 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/DenyAllFilterParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/DenyAllFilterParser.java
@@ -24,8 +24,8 @@ import java.util.function.Supplier;
import org.apache.logging.converter.config.internal.ComponentUtils;
import org.apache.logging.converter.config.internal.v1.AbstractComponentParser;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ComponentParser;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.w3c.dom.Element;
/**
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/LevelMatchFilterParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/LevelMatchFilterParser.java
index acf54bc..e45ffaf 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/LevelMatchFilterParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/LevelMatchFilterParser.java
@@ -25,8 +25,8 @@ import java.util.function.Supplier;
import org.apache.logging.converter.config.internal.ComponentUtils;
import
org.apache.logging.converter.config.internal.ComponentUtils.ConfigurationNodeBuilder;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ComponentParser;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.w3c.dom.Element;
/**
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/LevelRangeFilterParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/LevelRangeFilterParser.java
index d668738..5a384ec 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/LevelRangeFilterParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/LevelRangeFilterParser.java
@@ -25,8 +25,8 @@ import java.util.function.Supplier;
import org.apache.logging.converter.config.internal.ComponentUtils;
import
org.apache.logging.converter.config.internal.ComponentUtils.ConfigurationNodeBuilder;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ComponentParser;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.w3c.dom.Element;
/**
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/StringMatchFilterParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/StringMatchFilterParser.java
index 0098881..cf92d39 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/StringMatchFilterParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/filter/StringMatchFilterParser.java
@@ -26,8 +26,8 @@ import
org.apache.logging.converter.config.ConfigurationConverterException;
import org.apache.logging.converter.config.internal.ComponentUtils;
import
org.apache.logging.converter.config.internal.ComponentUtils.ConfigurationNodeBuilder;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ComponentParser;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.jspecify.annotations.Nullable;
import org.w3c.dom.Element;
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/EnhancedPatternLayoutParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/EnhancedPatternLayoutParser.java
index 7603a53..f8c8503 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/EnhancedPatternLayoutParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/EnhancedPatternLayoutParser.java
@@ -20,8 +20,8 @@ import aQute.bnd.annotation.spi.ServiceProvider;
import java.lang.invoke.MethodHandle;
import java.util.Map;
import org.apache.logging.converter.config.internal.v1.AbstractComponentParser;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ComponentParser;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.w3c.dom.Element;
/**
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/HtmlLayoutParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/HtmlLayoutParser.java
index 83fed36..0961daa 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/HtmlLayoutParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/HtmlLayoutParser.java
@@ -24,8 +24,8 @@ import
org.apache.logging.converter.config.internal.ComponentUtils;
import org.apache.logging.converter.config.internal.StringUtils;
import org.apache.logging.converter.config.internal.v1.AbstractComponentParser;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ComponentParser;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.w3c.dom.Element;
/**
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/PatternLayoutParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/PatternLayoutParser.java
index 6c02d66..3715bb3 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/PatternLayoutParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/PatternLayoutParser.java
@@ -23,8 +23,8 @@ import java.util.function.Supplier;
import org.apache.logging.converter.config.internal.ComponentUtils;
import org.apache.logging.converter.config.internal.v1.AbstractComponentParser;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ComponentParser;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.w3c.dom.Element;
/**
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/SimpleLayoutParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/SimpleLayoutParser.java
index 2795d6f..2d65905 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/SimpleLayoutParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/SimpleLayoutParser.java
@@ -24,8 +24,8 @@ import java.util.function.Supplier;
import org.apache.logging.converter.config.internal.ComponentUtils;
import org.apache.logging.converter.config.internal.v1.AbstractComponentParser;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ComponentParser;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.w3c.dom.Element;
/**
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/TTCCLayoutParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/TTCCLayoutParser.java
index f37d93c..0d9fd71 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/TTCCLayoutParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v1/layout/TTCCLayoutParser.java
@@ -26,8 +26,8 @@ import
org.apache.logging.converter.config.internal.ComponentUtils.Configuration
import org.apache.logging.converter.config.internal.StringUtils;
import org.apache.logging.converter.config.internal.v1.AbstractComponentParser;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.converter.config.spi.v1.Log4j1ComponentParser;
-import org.apache.logging.converter.config.spi.v1.PropertiesSubset;
import org.jspecify.annotations.Nullable;
import org.w3c.dom.Element;
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v2/PropertiesV2ConfigurationParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v2/PropertiesV2ConfigurationParser.java
index 85fc653..afe4a76 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v2/PropertiesV2ConfigurationParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v2/PropertiesV2ConfigurationParser.java
@@ -17,24 +17,29 @@
package org.apache.logging.converter.config.internal.v2;
import static
org.apache.logging.converter.config.internal.ComponentUtils.newNodeBuilder;
-import static org.apache.logging.log4j.util.PropertiesUtil.extractSubset;
-import static
org.apache.logging.log4j.util.PropertiesUtil.partitionOnCommonPrefixes;
+import static
org.apache.logging.converter.config.internal.PropertiesUtils.extractProperty;
+import static
org.apache.logging.converter.config.internal.PropertiesUtils.extractSubset;
+import static
org.apache.logging.converter.config.internal.PropertiesUtils.isNotEmpty;
+import static
org.apache.logging.converter.config.internal.PropertiesUtils.partitionOnCommonPrefixes;
import aQute.bnd.annotation.Resolution;
import aQute.bnd.annotation.spi.ServiceProvider;
import java.io.IOException;
import java.io.InputStream;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.Collection;
+import java.util.Objects;
import java.util.Properties;
-import java.util.TreeMap;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.apache.logging.converter.config.ConfigurationConverterException;
+import org.apache.logging.converter.config.internal.ComponentUtils;
import
org.apache.logging.converter.config.internal.ComponentUtils.ConfigurationNodeBuilder;
+import org.apache.logging.converter.config.internal.PropertiesUtils;
import org.apache.logging.converter.config.spi.ConfigurationNode;
import org.apache.logging.converter.config.spi.ConfigurationParser;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.apache.logging.log4j.util.Strings;
-import org.jspecify.annotations.Nullable;
@ServiceProvider(value = ConfigurationParser.class, resolution =
Resolution.MANDATORY)
public class PropertiesV2ConfigurationParser implements ConfigurationParser {
@@ -48,8 +53,6 @@ public class PropertiesV2ConfigurationParser implements
ConfigurationParser {
private static final String TYPE_ATTRIBUTE = "type";
private static final String VALUE_ATTRIBUTE = "value";
- private static final String ROOT_LOGGER_NAME = "root";
-
private static final String APPENDERS_PLUGIN_NAME = "Appenders";
private static final String CONFIGURATION_PLUGIN_NAME = "Configuration";
private static final String CUSTOM_LEVEL_PLUGIN_NAME = "CustomLevel";
@@ -57,7 +60,6 @@ public class PropertiesV2ConfigurationParser implements
ConfigurationParser {
private static final String APPENDER_REF_PLUGIN_NAME = "AppenderRef";
private static final String ASYNC_LOGGER_PLUGIN_NAME = "AsyncLogger";
private static final String ASYNC_ROOT_PLUGIN_NAME = "AsyncRoot";
- private static final String FILTERS_PLUGIN_NAME = "Filters";
private static final String LOGGER_PLUGIN_NAME = "Logger";
private static final String LOGGERS_PLUGIN_NAME = "Loggers";
private static final String PROPERTIES_PLUGIN_NAME = "Properties";
@@ -65,6 +67,8 @@ public class PropertiesV2ConfigurationParser implements
ConfigurationParser {
private static final String ROOT_PLUGIN_NAME = "Root";
private static final String SCRIPTS_PLUGIN_NAME = "Scripts";
+ private static final String COMMA_SEPARATOR = "\\s*,\\s*";
+
@Override
public String getInputFormat() {
return LOG4J_V2_PROPERTIES_FORMAT;
@@ -77,107 +81,104 @@ public class PropertiesV2ConfigurationParser implements
ConfigurationParser {
@Override
public ConfigurationNode parse(InputStream inputStream) throws IOException
{
- Properties rootProperties = new Properties();
- rootProperties.load(inputStream);
+ Properties props = new Properties();
+ props.load(inputStream);
+ PropertiesSubset rootProperties = PropertiesSubset.of("", props);
ConfigurationNodeBuilder builder =
newNodeBuilder().setPluginName(CONFIGURATION_PLUGIN_NAME);
- for (final String key : rootProperties.stringPropertyNames()) {
- if (!key.contains(".")) {
- builder.addAttribute(key, remove(rootProperties, key));
- }
- }
-
- Properties propertyPlaceholders = extractSubset(rootProperties,
"property");
- if (!propertyPlaceholders.isEmpty()) {
+ PropertiesSubset propertyPlaceholders = extractSubset(rootProperties,
"property");
+ if (isNotEmpty(propertyPlaceholders)) {
builder.addChild(processPropertyPlaceholders(propertyPlaceholders));
}
- Map<String, Properties> scripts =
extractSubsetAndPartition(rootProperties, "script");
- if (!scripts.isEmpty()) {
- builder.addChild(processScripts(scripts));
+ PropertiesSubset scriptProperties = extractSubset(rootProperties,
"script");
+ if (isNotEmpty(scriptProperties)) {
+ builder.addChild(processScripts(scriptProperties));
}
+ PropertiesUtils.throwIfNotEmpty(scriptProperties);
- Properties customLevels = extractSubset(rootProperties, "customLevel");
- if (!customLevels.isEmpty()) {
+ PropertiesSubset customLevels = extractSubset(rootProperties,
"customLevel");
+ if (isNotEmpty(customLevels)) {
builder.addChild(processCustomLevels(customLevels));
}
-
- Map<String, Properties> filters =
extractSubsetAndPartition(rootProperties, "filter", "filters");
+ PropertiesUtils.throwIfNotEmpty(customLevels);
+
+ // Filters
+ PropertiesSubset filtersProperties = extractSubset(rootProperties,
"filter");
+ String filterNames = extractProperty(rootProperties, "filters");
+ final Stream<? extends PropertiesSubset> filtersStream = filterNames
!= null
+ ? partitionOnGivenPrefixes(filtersProperties, filterNames)
+ : partitionOnCommonPrefixes(filtersProperties);
+ Collection<ConfigurationNode> filters =
+ filtersStream.map(p -> processGenericComponent("filter",
p)).collect(Collectors.toList());
if (!filters.isEmpty()) {
- builder.addChild(processFilters("", filters));
- }
-
- Map<String, Properties> appenders =
extractSubsetAndPartition(rootProperties, "appender", "appenders");
- if (!appenders.isEmpty()) {
- builder.addChild(processAppenders(appenders));
+ builder.addChild(wrapFilters(filters));
}
+ PropertiesUtils.throwIfNotEmpty(filtersProperties);
+
+ // Appenders
+ PropertiesSubset appendersProperties = extractSubset(rootProperties,
"appender");
+ String appenderNames = extractProperty(rootProperties, "appenders");
+ final Stream<? extends PropertiesSubset> appendersStream =
appenderNames != null
+ ? partitionOnGivenPrefixes(appendersProperties, appenderNames)
+ : partitionOnCommonPrefixes(appendersProperties);
+ Collection<ConfigurationNode> appenders = appendersStream
+ .map(PropertiesV2ConfigurationParser::processAppender)
+ .collect(Collectors.toList());
+ builder.addChild(createAppenders(appenders));
+ PropertiesUtils.throwIfNotEmpty(appendersProperties);
ConfigurationNodeBuilder loggersBuilder =
newNodeBuilder().setPluginName(LOGGERS_PLUGIN_NAME);
// 1. Start with the root logger
- Properties rootLoggerProperties = extractSubset(rootProperties,
"rootLogger");
- String rootLoggerProperty = rootProperties.getProperty("rootLogger");
- if (rootLoggerProperty != null) {
- rootLoggerProperties.put("", rootLoggerProperty);
- }
+ PropertiesSubset rootLoggerProperties = extractSubset(rootProperties,
"rootLogger");
loggersBuilder.addChild(processRootLogger(rootLoggerProperties));
+ PropertiesUtils.throwIfNotEmpty(rootLoggerProperties);
// 2. The remaining loggers
- Map<String, Properties> loggers =
extractSubsetAndPartition(rootProperties, "logger", "loggers");
- for (Map.Entry<String, Properties> entry : loggers.entrySet()) {
- if (!ROOT_LOGGER_NAME.equals(entry.getKey())) {
- loggersBuilder.addChild(processLogger(entry.getKey(),
entry.getValue()));
- }
- }
+ PropertiesSubset loggersProperties = extractSubset(rootProperties,
"logger");
+ String loggersName = extractProperty(rootProperties, "loggers");
+ final Stream<? extends PropertiesSubset> loggersStream = loggersName
!= null
+ ? partitionOnGivenPrefixes(loggersProperties, loggersName)
+ : partitionOnCommonPrefixes(loggersProperties);
+
loggersStream.map(PropertiesV2ConfigurationParser::processLogger).forEach(loggersBuilder::addChild);
+ PropertiesUtils.throwIfNotEmpty(loggersProperties);
// Add the `Loggers` plugin
builder.addChild(loggersBuilder.get());
- return builder.get();
- }
-
- private static Map<String, Properties>
extractSubsetAndPartition(Properties rootProperties, String prefix) {
- return new
TreeMap<>(partitionOnCommonPrefixes(extractSubset(rootProperties, prefix)));
- }
-
- private static Map<String, Properties> extractSubsetAndPartition(
- Properties rootProperties, String prefix, String keysProperty) {
- String keysList = rootProperties.getProperty(keysProperty);
- if (keysList != null) {
- String[] keys = keysList.split(",", -1);
- Map<String, Properties> result = new LinkedHashMap<>();
- for (final String untrimmedKey : keys) {
- String key = untrimmedKey.trim();
- result.put(key, extractSubset(rootProperties, prefix + "." +
key));
+ // Extract attributes of Configuration
+ for (final String key :
rootProperties.getProperties().stringPropertyNames()) {
+ if (!key.contains(".")) {
+ builder.addAttribute(key, extractProperty(rootProperties,
key));
}
- return result;
}
- return extractSubsetAndPartition(rootProperties, prefix);
+ PropertiesUtils.throwIfNotEmpty(rootProperties);
+ return builder.get();
}
- private static ConfigurationNode processPropertyPlaceholders(final
Properties propertyPlaceholders) {
+ private static ConfigurationNode
processPropertyPlaceholders(PropertiesSubset propertyPlaceholders) {
+ Properties props = propertyPlaceholders.getProperties();
ConfigurationNodeBuilder builder =
newNodeBuilder().setPluginName(PROPERTIES_PLUGIN_NAME);
- for (final String key : propertyPlaceholders.stringPropertyNames()) {
+ for (final String key : props.stringPropertyNames()) {
ConfigurationNodeBuilder builder1 = newNodeBuilder()
.setPluginName(PROPERTY_PLUGIN_NAME)
.addAttribute(NAME_ATTRIBUTE, key)
- .addAttribute(VALUE_ATTRIBUTE,
propertyPlaceholders.getProperty(key));
+ .addAttribute(VALUE_ATTRIBUTE, props.getProperty(key));
builder.addChild(builder1.get());
}
return builder.get();
}
- private ConfigurationNode processScripts(Map<String, Properties> scripts) {
+ private ConfigurationNode processScripts(PropertiesSubset scripts) {
ConfigurationNodeBuilder builder =
newNodeBuilder().setPluginName(SCRIPTS_PLUGIN_NAME);
- for (final Map.Entry<String, Properties> entry : scripts.entrySet()) {
- String scriptPrefix = "script." + entry.getKey();
- Properties scriptProperties = entry.getValue();
- builder.addChild(processGenericComponent(scriptPrefix, "Script",
scriptProperties));
- }
+ partitionOnCommonPrefixes(scripts)
+ .forEach(script ->
builder.addChild(processGenericComponent("script", script)));
return builder.get();
}
- private ConfigurationNode processCustomLevels(Properties customLevels) {
+ private ConfigurationNode processCustomLevels(PropertiesSubset
customLevels) {
ConfigurationNodeBuilder builder =
newNodeBuilder().setPluginName(CUSTOM_LEVELS_PLUGIN_NAME);
- for (final String key : customLevels.stringPropertyNames()) {
- String value = validateInteger("customLevel." + key,
customLevels.getProperty(key));
+ for (final String key :
customLevels.getProperties().stringPropertyNames()) {
+ String value =
+ validateInteger("customLevel." + key,
Objects.requireNonNull(extractProperty(customLevels, key)));
ConfigurationNodeBuilder builder1 = newNodeBuilder()
.setPluginName(CUSTOM_LEVEL_PLUGIN_NAME)
.addAttribute(NAME_ATTRIBUTE, key)
@@ -196,84 +197,75 @@ public class PropertiesV2ConfigurationParser implements
ConfigurationParser {
}
}
- private static ConfigurationNode processFilters(String prefix, Map<String,
Properties> filters) {
- if (filters.size() == 1) {
- return processFilter(prefix, filters.entrySet().iterator().next());
- }
- ConfigurationNodeBuilder builder =
newNodeBuilder().setPluginName(FILTERS_PLUGIN_NAME);
- for (final Map.Entry<String, Properties> filterEntry :
filters.entrySet()) {
- builder.addChild(processFilter(prefix, filterEntry));
- }
- return builder.get();
- }
-
- private static ConfigurationNode processFilter(String prefix,
Map.Entry<String, ? extends Properties> filterEntry) {
- String actualPrefix = prefix.isEmpty() ? prefix : prefix + ".";
- String filterPrefix = actualPrefix + "filter." + filterEntry.getKey();
- Properties filterProperties = filterEntry.getValue();
- return processGenericComponent(filterPrefix, "Filter",
filterProperties);
- }
-
- private static ConfigurationNode processAppenders(Map<String, Properties>
appenders) {
+ private static ConfigurationNode createAppenders(Iterable<? extends
ConfigurationNode> appenders) {
ConfigurationNodeBuilder builder =
newNodeBuilder().setPluginName(APPENDERS_PLUGIN_NAME);
- for (Map.Entry<String, Properties> entry : appenders.entrySet()) {
- builder.addChild(processAppender(entry.getKey(),
entry.getValue()));
+ for (ConfigurationNode appender : appenders) {
+ builder.addChild(appender);
}
return builder.get();
}
- private static ConfigurationNode processAppender(String key, Properties
properties) {
- String appenderPrefix = "appender." + key;
+ private static ConfigurationNode processAppender(PropertiesSubset
properties) {
ConfigurationNodeBuilder builder = newNodeBuilder()
.setPluginName(getRequiredAttribute(
- properties, TYPE_ATTRIBUTE, () -> "No type attribute
provided for Appender " + appenderPrefix))
+ properties,
+ TYPE_ATTRIBUTE,
+ () -> "No type attribute provided for Appender " +
properties.getPrefix()))
.addAttribute(
NAME_ATTRIBUTE,
getRequiredAttribute(
properties,
NAME_ATTRIBUTE,
- () -> "No name attribute provided for Appender
" + appenderPrefix));
-
- addFiltersToComponent(appenderPrefix, properties, builder);
- processRemainingProperties(appenderPrefix, properties, builder);
+ () -> "No name attribute provided for Appender
" + properties.getPrefix()));
+ addFiltersToComponent(properties, builder);
+ processRemainingProperties(properties, builder);
return builder.get();
}
- private static ConfigurationNode processLogger(String key, Properties
properties) {
+ private static ConfigurationNode processLogger(PropertiesSubset
properties) {
ConfigurationNodeBuilder builder = newNodeBuilder()
- .addAttribute(LEVEL_AND_REFS_ATTRIBUTE, remove(properties, ""))
+ .addAttribute(LEVEL_AND_REFS_ATTRIBUTE,
extractProperty(properties, ""))
.addAttribute(
NAME_ATTRIBUTE,
getRequiredAttribute(
- properties, NAME_ATTRIBUTE, () -> "No name
attribute provided for Logger " + key));
+ properties,
+ NAME_ATTRIBUTE,
+ () -> "No name attribute provided for Logger "
+ properties.getPrefix()));
- String type = remove(properties, TYPE_ATTRIBUTE);
+ String type = extractProperty(properties, TYPE_ATTRIBUTE);
if (ASYNC_LOGGER_PLUGIN_NAME.equalsIgnoreCase(type)) {
builder.setPluginName(ASYNC_LOGGER_PLUGIN_NAME);
} else if (type != null) {
- throw new ConfigurationConverterException("Unknown logger type `"
+ type + "` for logger " + key);
+ throw new ConfigurationConverterException(
+ "Unknown logger type `" + type + "` for logger " +
properties.getPrefix());
} else {
builder.setPluginName(LOGGER_PLUGIN_NAME);
}
- String prefix = "logger." + key;
- addAppenderRefsToComponent(prefix, properties, builder);
- addFiltersToComponent(prefix, properties, builder);
- processRemainingProperties(prefix, properties, builder);
+ addAppenderRefsToComponent(properties, builder);
+ addFiltersToComponent(properties, builder);
+ processRemainingProperties(properties, builder);
return builder.get();
}
- private static void addAppenderRefsToComponent(
- String prefix, Properties properties, ConfigurationNodeBuilder
builder) {
- Map<String, Properties> appenderRefs =
extractSubsetAndPartition(properties, "appenderRef");
- for (final Map.Entry<String, Properties> entry :
appenderRefs.entrySet()) {
- builder.addChild(processAppenderRef(prefix + ".appenderRef." +
entry.getKey(), entry.getValue()));
+ private static ConfigurationNode wrapFilters(Collection<? extends
ConfigurationNode> filters) {
+ if (filters.isEmpty()) {
+ throw new IllegalArgumentException("No filters provided");
}
+ return filters.size() > 1
+ ? ComponentUtils.newCompositeFilter(filters)
+ : filters.iterator().next();
}
- private static ConfigurationNode processAppenderRef(String prefix,
Properties properties) {
+ private static void addAppenderRefsToComponent(PropertiesSubset
properties, ConfigurationNodeBuilder builder) {
+ PropertiesSubset appenderRefProperties = extractSubset(properties,
"appenderRef");
+ partitionOnCommonPrefixes(appenderRefProperties).forEach(p ->
builder.addChild(processAppenderRef(p)));
+ PropertiesUtils.throwIfNotEmpty(appenderRefProperties);
+ }
+
+ private static ConfigurationNode processAppenderRef(PropertiesSubset
properties) {
ConfigurationNodeBuilder builder = newNodeBuilder()
.setPluginName(APPENDER_REF_PLUGIN_NAME)
.addAttribute(
@@ -281,31 +273,32 @@ public class PropertiesV2ConfigurationParser implements
ConfigurationParser {
getRequiredAttribute(
properties,
REF_ATTRIBUTE,
- () -> "No ref attribute provided for
AppenderRef " + prefix));
+ () -> "No ref attribute provided for
AppenderRef " + properties.getPrefix()));
- String level = Strings.trimToNull(remove(properties, "level"));
+ String level = Strings.trimToNull(extractProperty(properties,
"level"));
if (level != null) {
builder.addAttribute("level", level);
}
-
- addFiltersToComponent(prefix, properties, builder);
- processRemainingProperties(prefix, properties, builder);
-
+ addFiltersToComponent(properties, builder);
+ processRemainingProperties(properties, builder);
return builder.get();
}
- private static void addFiltersToComponent(String prefix, Properties
properties, ConfigurationNodeBuilder builder) {
- Map<String, Properties> filters =
extractSubsetAndPartition(properties, "filter");
+ private static void addFiltersToComponent(PropertiesSubset properties,
ConfigurationNodeBuilder builder) {
+ PropertiesSubset filtersProperties = extractSubset(properties,
"filter");
+ Collection<ConfigurationNode> filters =
partitionOnCommonPrefixes(filtersProperties)
+ .map(p -> processGenericComponent("filter", p))
+ .collect(Collectors.toList());
if (!filters.isEmpty()) {
- builder.addChild(processFilters(prefix, filters));
+ builder.addChild(wrapFilters(filters));
}
}
- private static ConfigurationNode processRootLogger(Properties properties) {
+ private static ConfigurationNode processRootLogger(PropertiesSubset
properties) {
ConfigurationNodeBuilder builder =
- newNodeBuilder().addAttribute(LEVEL_AND_REFS_ATTRIBUTE,
remove(properties, ""));
+ newNodeBuilder().addAttribute(LEVEL_AND_REFS_ATTRIBUTE,
extractProperty(properties, ""));
- String type = remove(properties, TYPE_ATTRIBUTE);
+ String type = extractProperty(properties, TYPE_ATTRIBUTE);
if (ASYNC_ROOT_PLUGIN_NAME.equalsIgnoreCase(type)) {
builder.setPluginName(ASYNC_ROOT_PLUGIN_NAME);
} else if (type != null) {
@@ -314,62 +307,64 @@ public class PropertiesV2ConfigurationParser implements
ConfigurationParser {
builder.setPluginName(ROOT_PLUGIN_NAME);
}
- String prefix = "rootLogger";
- addAppenderRefsToComponent(prefix, properties, builder);
- addFiltersToComponent(prefix, properties, builder);
- processRemainingProperties(prefix, properties, builder);
+ addAppenderRefsToComponent(properties, builder);
+ addFiltersToComponent(properties, builder);
+ processRemainingProperties(properties, builder);
return builder.get();
}
- private static @Nullable String remove(final Properties properties, final
String key) {
- return (String) properties.remove(key);
- }
-
/**
* Standard mapping between a properties file and node tree.
* <p>
* The component must have a {@code type} attribute.
* </p>
*
- * @param prefix Prefix of all the properties in the global prefix file.
Used only for the exception message.
* @param componentCategory Type of expected component. Used only for the
exception message.
* @param properties Component properties with names relative to {@code
prefix}.
*/
- private static ConfigurationNode processGenericComponent(
- String prefix, String componentCategory, Properties properties) {
+ private static ConfigurationNode processGenericComponent(String
componentCategory, PropertiesSubset properties) {
ConfigurationNodeBuilder builder = newNodeBuilder();
builder.setPluginName(getRequiredAttribute(
properties,
TYPE_ATTRIBUTE,
- () -> "No type attribute provided for " + componentCategory +
" " + prefix));
- processRemainingProperties(prefix, properties, builder);
+ () -> "No type attribute provided for " + componentCategory +
" " + properties.getPrefix()));
+ processRemainingProperties(properties, builder);
return builder.get();
}
- private static void processRemainingProperties(
- String prefix, Properties properties, ConfigurationNodeBuilder
builder) {
- while (!properties.isEmpty()) {
- String propertyName =
properties.stringPropertyNames().iterator().next();
+ private static void processRemainingProperties(PropertiesSubset
properties, ConfigurationNodeBuilder builder) {
+ while (isNotEmpty(properties)) {
+ String propertyName =
+
properties.getProperties().stringPropertyNames().iterator().next();
int index = propertyName.indexOf('.');
if (index > 0) {
String localPrefix = propertyName.substring(0, index);
- String globalPrefix = prefix + "." + propertyName.substring(0,
index);
- Properties componentProperties = extractSubset(properties,
localPrefix);
- builder.addChild(processGenericComponent(globalPrefix,
"component", componentProperties));
+ PropertiesSubset componentProperties =
extractSubset(properties, localPrefix);
+ builder.addChild(processGenericComponent("component",
componentProperties));
} else {
- builder.addAttribute(propertyName, remove(properties,
propertyName));
+ builder.addAttribute(propertyName, extractProperty(properties,
propertyName));
}
}
}
private static String getRequiredAttribute(
- Properties properties, String propertyName, Supplier<String>
errorMessageSupplier) {
- String value = remove(properties, propertyName);
+ PropertiesSubset properties, String propertyName, Supplier<String>
errorMessageSupplier) {
+ String value = extractProperty(properties, propertyName);
if (Strings.isEmpty(value)) {
throw new
ConfigurationConverterException(errorMessageSupplier.get());
}
return value;
}
+
+ private static Stream<PropertiesSubset>
partitionOnGivenPrefixes(PropertiesSubset properties, String prefixes) {
+ Stream.Builder<PropertiesSubset> builder = Stream.builder();
+ for (String prefix : prefixes.split(COMMA_SEPARATOR, -1)) {
+ if (!prefix.isEmpty()) {
+ builder.add(extractSubset(properties, prefix));
+ }
+ }
+ return builder.build();
+ }
}
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/spi/v1/PropertiesSubset.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/spi/PropertiesSubset.java
similarity index 97%
rename from
log4j-converter-config/src/main/java/org/apache/logging/converter/config/spi/v1/PropertiesSubset.java
rename to
log4j-converter-config/src/main/java/org/apache/logging/converter/config/spi/PropertiesSubset.java
index 64d823c..7945ac7 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/spi/v1/PropertiesSubset.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/spi/PropertiesSubset.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.logging.converter.config.spi.v1;
+package org.apache.logging.converter.config.spi;
import java.util.AbstractMap;
import java.util.Map;
diff --git
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/spi/v1/Log4j1ComponentParser.java
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/spi/v1/Log4j1ComponentParser.java
index a3c544c..c7ec27d 100644
---
a/log4j-converter-config/src/main/java/org/apache/logging/converter/config/spi/v1/Log4j1ComponentParser.java
+++
b/log4j-converter-config/src/main/java/org/apache/logging/converter/config/spi/v1/Log4j1ComponentParser.java
@@ -18,6 +18,7 @@ package org.apache.logging.converter.config.spi.v1;
import org.apache.logging.converter.config.ConfigurationConverterException;
import org.apache.logging.converter.config.spi.ConfigurationNode;
+import org.apache.logging.converter.config.spi.PropertiesSubset;
import org.w3c.dom.Element;
public interface Log4j1ComponentParser {