Skip to content

Commit abe16cb

Browse files
committed
Adds a Configuration Converter API
Adds an API to perform automatic conversions between different logging configuration file formats and a basic implementation. The implementation supports the following configuration file formats: - Log4j Core 2 XML, - Log4j Core 2 JSON, - Log4j Core 2 YAML, - Log4j Core 2 Properties (read-only), - Log4j Core 3 Properties. The API is extensible through `ServiceLoader` and allows integrators to provide support for additional configuration file formats. Read-only support for the Log4j 1 Properties and Log4j 1 XML configuration formats will be provided in a separate PR. **Note**: Currently the API is only accessible from Java code. Its main purpose is to provide a "Migrate Log4j 1.x to Log4j Core 2.x", a "Migrate Logback to Log4j Core 2.x" and a "Migrate JUL to Log4j Core 2.x" [OpenRewrite recipe](https://docs.openrewrite.org/recipes/java/logging/log4j). A `picocli`-based `log4j-transform-cli` tool to access all the goodies in this repository, will be provided later. Closes apache/logging-log4j2#2080
1 parent 7bea740 commit abe16cb

36 files changed

+2810
-30
lines changed

log4j-codegen/pom.xml

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,6 @@
4343

4444
<dependencies>
4545

46-
<dependency>
47-
<groupId>org.osgi</groupId>
48-
<artifactId>org.osgi.annotation.bundle</artifactId>
49-
<scope>provided</scope>
50-
</dependency>
51-
52-
<dependency>
53-
<groupId>org.osgi</groupId>
54-
<artifactId>org.osgi.annotation.versioning</artifactId>
55-
<scope>provided</scope>
56-
</dependency>
57-
58-
<dependency>
59-
<groupId>com.github.spotbugs</groupId>
60-
<artifactId>spotbugs-annotations</artifactId>
61-
<scope>provided</scope>
62-
</dependency>
63-
6446
<!-- Compile dependencies: the artifact is shaded, so limit these. -->
6547
<dependency>
6648
<groupId>info.picocli</groupId>

log4j-converter-config/pom.xml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Licensed to the Apache Software Foundation (ASF) under one or more
4+
~ contributor license agreements. See the NOTICE file distributed with
5+
~ this work for additional information regarding copyright ownership.
6+
~ The ASF licenses this file to you under the Apache License, Version 2.0
7+
~ (the "License"); you may not use this file except in compliance with
8+
~ the License. You may obtain a copy of the License at
9+
~
10+
~ http://www.apache.org/licenses/LICENSE-2.0
11+
~
12+
~ Unless required by applicable law or agreed to in writing, software
13+
~ distributed under the License is distributed on an "AS IS" BASIS,
14+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
~ See the License for the specific language governing permissions and
16+
~ limitations under the License.
17+
-->
18+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
19+
<modelVersion>4.0.0</modelVersion>
20+
<parent>
21+
<groupId>org.apache.logging.log4j</groupId>
22+
<artifactId>log4j-transform-parent</artifactId>
23+
<version>${revision}</version>
24+
<relativePath>../log4j-transform-parent</relativePath>
25+
</parent>
26+
27+
<artifactId>log4j-converter-config</artifactId>
28+
<name>Apache Log4j Configuration converter</name>
29+
<description>Converts various logging configuration formats to the Log4j Core 2.x format.</description>
30+
31+
<properties>
32+
<!-- Remove after first release -->
33+
<bnd.baseline.fail.on.missing>false</bnd.baseline.fail.on.missing>
34+
35+
<!-- Dependencies -->
36+
<jackson.version>2.18.1</jackson.version>
37+
<txw2.version>4.0.5</txw2.version>
38+
</properties>
39+
40+
<dependencyManagement>
41+
<dependencies>
42+
43+
<dependency>
44+
<groupId>com.fasterxml.jackson</groupId>
45+
<artifactId>jackson-bom</artifactId>
46+
<version>${jackson.version}</version>
47+
<type>pom</type>
48+
<scope>import</scope>
49+
</dependency>
50+
51+
</dependencies>
52+
</dependencyManagement>
53+
54+
<dependencies>
55+
56+
<dependency>
57+
<groupId>org.apache.logging.log4j</groupId>
58+
<artifactId>log4j-api</artifactId>
59+
</dependency>
60+
61+
<dependency>
62+
<groupId>org.jspecify</groupId>
63+
<artifactId>jspecify</artifactId>
64+
</dependency>
65+
66+
<!-- Used in the JSON configuration format -->
67+
<dependency>
68+
<groupId>com.fasterxml.jackson.core</groupId>
69+
<artifactId>jackson-databind</artifactId>
70+
</dependency>
71+
72+
<!-- Used in the v3 Properties configuration format -->
73+
<dependency>
74+
<groupId>com.fasterxml.jackson.dataformat</groupId>
75+
<artifactId>jackson-dataformat-properties</artifactId>
76+
</dependency>
77+
78+
<!-- Used in the YAML configuration format -->
79+
<dependency>
80+
<groupId>com.fasterxml.jackson.dataformat</groupId>
81+
<artifactId>jackson-dataformat-yaml</artifactId>
82+
</dependency>
83+
84+
<!-- Used in the XML configuration format -->
85+
<dependency>
86+
<groupId>org.glassfish.jaxb</groupId>
87+
<artifactId>txw2</artifactId>
88+
<version>${txw2.version}</version>
89+
</dependency>
90+
91+
<dependency>
92+
<groupId>org.junit.jupiter</groupId>
93+
<artifactId>junit-jupiter-api</artifactId>
94+
<scope>test</scope>
95+
</dependency>
96+
97+
<dependency>
98+
<groupId>org.junit.jupiter</groupId>
99+
<artifactId>junit-jupiter-params</artifactId>
100+
<scope>test</scope>
101+
</dependency>
102+
103+
<dependency>
104+
<groupId>org.assertj</groupId>
105+
<artifactId>assertj-core</artifactId>
106+
<scope>test</scope>
107+
</dependency>
108+
109+
</dependencies>
110+
</project>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.logging.converter.config;
18+
19+
import java.io.InputStream;
20+
import java.io.OutputStream;
21+
import java.util.Set;
22+
import org.apache.logging.converter.config.internal.DefaultConfigurationConverter;
23+
24+
/**
25+
* Service class to convert between different logging configuration formats.
26+
*/
27+
public interface ConfigurationConverter {
28+
29+
/**
30+
* A default implementation of {@link ConfigurationConverter} that uses {@link java.util.ServiceLoader} to load additional formats.
31+
* @see org.apache.logging.converter.config.spi.ConfigurationMapper
32+
*/
33+
static ConfigurationConverter newInstance() {
34+
return new DefaultConfigurationConverter();
35+
}
36+
37+
/**
38+
* Converts a logging configuration file from one format to another.
39+
*
40+
* @param inputStream The input configuration file, never {@code null}.
41+
* @param inputFormat The input format. Must be one of the formats returned by {@link #getSupportedInputFormats()}.
42+
* @param outputStream The output configuration file, never {@code null}.
43+
* @param outputFormat The output format. Must be one of the formats returned by {@link #getSupportedOutputFormats()}.
44+
* @throws ConfigurationConverterException If any kind of error occurs during the conversion process.
45+
*/
46+
void convert(InputStream inputStream, String inputFormat, OutputStream outputStream, String outputFormat)
47+
throws ConfigurationConverterException;
48+
49+
/**
50+
* Returns the list of supported input formats.
51+
*/
52+
Set<String> getSupportedInputFormats();
53+
54+
/**
55+
* Returns the list of supported output formats.
56+
*/
57+
Set<String> getSupportedOutputFormats();
58+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.logging.converter.config;
18+
19+
/**
20+
* Exception thrown by {@link ConfigurationConverter}, when a problem occurs during the conversion.
21+
*/
22+
public class ConfigurationConverterException extends RuntimeException {
23+
24+
private static final long serialVersionUID = 1L;
25+
26+
public ConfigurationConverterException(final String message) {
27+
super(message);
28+
}
29+
30+
public ConfigurationConverterException(final String message, final Throwable cause) {
31+
super(message, cause);
32+
}
33+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.logging.converter.config.internal;
18+
19+
import java.util.ArrayList;
20+
import java.util.Collection;
21+
import java.util.Collections;
22+
import java.util.List;
23+
import java.util.Map;
24+
import java.util.TreeMap;
25+
import java.util.function.Supplier;
26+
import org.apache.logging.converter.config.ConfigurationConverterException;
27+
import org.apache.logging.converter.config.spi.ConfigurationNode;
28+
import org.jspecify.annotations.Nullable;
29+
30+
public final class ConfigurationNodeImpl implements ConfigurationNode {
31+
32+
private final String pluginName;
33+
private final Map<String, String> attributes = new TreeMap<>();
34+
private final List<ConfigurationNode> children = new ArrayList<>();
35+
36+
public static NodeBuilder newNodeBuilder() {
37+
return new NodeBuilder();
38+
}
39+
40+
private ConfigurationNodeImpl(
41+
final String pluginName,
42+
final Map<String, String> attributes,
43+
final Collection<ConfigurationNode> children) {
44+
this.pluginName = pluginName;
45+
this.attributes.putAll(attributes);
46+
this.children.addAll(children);
47+
}
48+
49+
@Override
50+
public String getPluginName() {
51+
return pluginName;
52+
}
53+
54+
@Override
55+
public Map<String, String> getAttributes() {
56+
return Collections.unmodifiableMap(attributes);
57+
}
58+
59+
@Override
60+
public List<? extends ConfigurationNode> getChildren() {
61+
return Collections.unmodifiableList(children);
62+
}
63+
64+
private static void formatTo(ConfigurationNode node, StringBuilder builder, int indent) {
65+
String indentation = getIndentation(indent);
66+
builder.append(indentation).append("<").append(node.getPluginName());
67+
for (final Map.Entry<String, String> entry : node.getAttributes().entrySet()) {
68+
builder.append(" ")
69+
.append(entry.getKey())
70+
.append("=\"")
71+
.append(entry.getValue())
72+
.append("\"");
73+
}
74+
builder.append(">\n");
75+
for (ConfigurationNode child : node.getChildren()) {
76+
formatTo(child, builder, indent + 1);
77+
builder.append('\n');
78+
}
79+
builder.append(indentation).append("</").append(node.getPluginName()).append(">");
80+
}
81+
82+
private static String getIndentation(int indent) {
83+
return String.join("", Collections.nCopies(indent, " "));
84+
}
85+
86+
@Override
87+
public String toString() {
88+
StringBuilder builder = new StringBuilder();
89+
formatTo(this, builder, 0);
90+
return builder.toString();
91+
}
92+
93+
public static final class NodeBuilder implements Supplier<ConfigurationNode> {
94+
95+
private @Nullable String pluginName;
96+
private final Map<String, String> attributes = new TreeMap<>();
97+
private final List<ConfigurationNode> children = new ArrayList<>();
98+
99+
private NodeBuilder() {}
100+
101+
public NodeBuilder setPluginName(String pluginName) {
102+
this.pluginName = pluginName;
103+
return this;
104+
}
105+
106+
public NodeBuilder addAttribute(String key, @Nullable String value) {
107+
if (value != null) {
108+
attributes.put(key, value);
109+
}
110+
return this;
111+
}
112+
113+
public NodeBuilder addChild(ConfigurationNode child) {
114+
children.add(child);
115+
return this;
116+
}
117+
118+
public ConfigurationNode build() {
119+
if (pluginName == null) {
120+
throw new ConfigurationConverterException("No plugin name specified");
121+
}
122+
return new ConfigurationNodeImpl(pluginName, attributes, children);
123+
}
124+
125+
@Override
126+
public ConfigurationNode get() {
127+
return build();
128+
}
129+
}
130+
}

0 commit comments

Comments
 (0)