-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a Configuration Converter API (#142)
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
- Loading branch information
Showing
45 changed files
with
3,234 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
~ 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. | ||
--> | ||
<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"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>org.apache.logging.log4j</groupId> | ||
<artifactId>log4j-transform-parent</artifactId> | ||
<version>${revision}</version> | ||
<relativePath>../log4j-transform-parent</relativePath> | ||
</parent> | ||
|
||
<artifactId>log4j-converter-config</artifactId> | ||
<name>Apache Log4j Configuration Converter</name> | ||
<description>Converts various logging configuration formats to the Log4j Core 2.x format.</description> | ||
|
||
<properties> | ||
<!-- This artifact is an API: we need to generate its Javadoc --> | ||
<maven.javadoc.skip>false</maven.javadoc.skip> | ||
|
||
<!-- Remove after first release --> | ||
<bnd.baseline.fail.on.missing>false</bnd.baseline.fail.on.missing> | ||
|
||
<!-- Dependencies --> | ||
<jackson.version>2.18.1</jackson.version> | ||
<txw2.version>4.0.5</txw2.version> | ||
</properties> | ||
|
||
<dependencyManagement> | ||
<dependencies> | ||
|
||
<dependency> | ||
<groupId>com.fasterxml.jackson</groupId> | ||
<artifactId>jackson-bom</artifactId> | ||
<version>${jackson.version}</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
|
||
</dependencies> | ||
</dependencyManagement> | ||
|
||
<dependencies> | ||
|
||
<dependency> | ||
<groupId>org.apache.logging.log4j</groupId> | ||
<artifactId>log4j-api</artifactId> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.jspecify</groupId> | ||
<artifactId>jspecify</artifactId> | ||
</dependency> | ||
|
||
<!-- Used in the JSON configuration format --> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-databind</artifactId> | ||
</dependency> | ||
|
||
<!-- Used in the v3 Properties configuration format --> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.dataformat</groupId> | ||
<artifactId>jackson-dataformat-properties</artifactId> | ||
</dependency> | ||
|
||
<!-- Used in the YAML configuration format --> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.dataformat</groupId> | ||
<artifactId>jackson-dataformat-yaml</artifactId> | ||
</dependency> | ||
|
||
<!-- Used in the XML configuration format --> | ||
<dependency> | ||
<groupId>org.glassfish.jaxb</groupId> | ||
<artifactId>txw2</artifactId> | ||
<version>${txw2.version}</version> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter-api</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter-params</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.assertj</groupId> | ||
<artifactId>assertj-core</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
</dependencies> | ||
</project> |
58 changes: 58 additions & 0 deletions
58
...rter-config/src/main/java/org/apache/logging/converter/config/ConfigurationConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* 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.logging.converter.config; | ||
|
||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
import java.util.Set; | ||
import org.apache.logging.converter.config.internal.DefaultConfigurationConverter; | ||
|
||
/** | ||
* Service class to convert between different logging configuration formats. | ||
*/ | ||
public interface ConfigurationConverter { | ||
|
||
/** | ||
* A default implementation of {@link ConfigurationConverter} that uses {@link java.util.ServiceLoader} to load additional formats. | ||
* @see org.apache.logging.converter.config.spi.ConfigurationMapper | ||
*/ | ||
static ConfigurationConverter getInstance() { | ||
return DefaultConfigurationConverter.INSTANCE; | ||
} | ||
|
||
/** | ||
* Converts a logging configuration file from one format to another. | ||
* | ||
* @param inputStream The input configuration file, never {@code null}. | ||
* @param inputFormat The input format. Must be one of the formats returned by {@link #getSupportedInputFormats()}. | ||
* @param outputStream The output configuration file, never {@code null}. | ||
* @param outputFormat The output format. Must be one of the formats returned by {@link #getSupportedOutputFormats()}. | ||
* @throws ConfigurationConverterException If any kind of error occurs during the conversion process. | ||
*/ | ||
void convert(InputStream inputStream, String inputFormat, OutputStream outputStream, String outputFormat) | ||
throws ConfigurationConverterException; | ||
|
||
/** | ||
* Returns the list of supported input formats. | ||
*/ | ||
Set<String> getSupportedInputFormats(); | ||
|
||
/** | ||
* Returns the list of supported output formats. | ||
*/ | ||
Set<String> getSupportedOutputFormats(); | ||
} |
33 changes: 33 additions & 0 deletions
33
...ig/src/main/java/org/apache/logging/converter/config/ConfigurationConverterException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* 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.logging.converter.config; | ||
|
||
/** | ||
* Exception thrown by {@link ConfigurationConverter}, when a problem occurs during the conversion. | ||
*/ | ||
public class ConfigurationConverterException extends RuntimeException { | ||
|
||
private static final long serialVersionUID = 1L; | ||
|
||
public ConfigurationConverterException(final String message) { | ||
super(message); | ||
} | ||
|
||
public ConfigurationConverterException(final String message, final Throwable cause) { | ||
super(message, cause); | ||
} | ||
} |
156 changes: 156 additions & 0 deletions
156
...ter-config/src/main/java/org/apache/logging/converter/config/internal/ComponentUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/* | ||
* 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.logging.converter.config.internal; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.TreeMap; | ||
import java.util.function.Supplier; | ||
import org.apache.logging.converter.config.ConfigurationConverterException; | ||
import org.apache.logging.converter.config.spi.ConfigurationNode; | ||
import org.jspecify.annotations.Nullable; | ||
|
||
public final class ComponentUtils { | ||
|
||
public static ConfigurationNodeBuilder newNodeBuilder() { | ||
return new ConfigurationNodeBuilder(); | ||
} | ||
|
||
public static ConfigurationNode createThresholdFilter(String level) { | ||
return newNodeBuilder() | ||
.setPluginName("ThresholdFilter") | ||
.addAttribute("level", level) | ||
.build(); | ||
} | ||
|
||
public static ConfigurationNode createCompositeFilter(Iterable<? extends ConfigurationNode> filters) { | ||
ConfigurationNodeBuilder builder = newNodeBuilder().setPluginName("Filters"); | ||
filters.forEach(builder::addChild); | ||
return builder.build(); | ||
} | ||
|
||
private ComponentUtils() {} | ||
|
||
public static class ConfigurationNodeBuilder implements Supplier<ConfigurationNode> { | ||
|
||
private @Nullable String pluginName; | ||
private final Map<String, String> attributes = new TreeMap<>(); | ||
private final List<ConfigurationNode> children = new ArrayList<>(); | ||
|
||
protected ConfigurationNodeBuilder() {} | ||
|
||
public ConfigurationNodeBuilder setPluginName(String pluginName) { | ||
this.pluginName = pluginName; | ||
return this; | ||
} | ||
|
||
public ConfigurationNodeBuilder addAttribute(String key, @Nullable String value) { | ||
if (value != null) { | ||
attributes.put(key, value); | ||
} | ||
return this; | ||
} | ||
|
||
public ConfigurationNodeBuilder addAttribute(String key, boolean value) { | ||
attributes.put(key, String.valueOf(value)); | ||
return this; | ||
} | ||
|
||
public ConfigurationNodeBuilder addChild(ConfigurationNode child) { | ||
children.add(child); | ||
return this; | ||
} | ||
|
||
public ConfigurationNode build() { | ||
if (pluginName == null) { | ||
throw new ConfigurationConverterException("No plugin name specified"); | ||
} | ||
return new ConfigurationNodeImpl(pluginName, attributes, children); | ||
} | ||
|
||
@Override | ||
public ConfigurationNode get() { | ||
return build(); | ||
} | ||
} | ||
|
||
private static final class ConfigurationNodeImpl implements ConfigurationNode { | ||
|
||
private final String pluginName; | ||
private final Map<String, String> attributes; | ||
private final List<ConfigurationNode> children; | ||
|
||
private ConfigurationNodeImpl( | ||
final String pluginName, | ||
final Map<String, String> attributes, | ||
final Collection<ConfigurationNode> children) { | ||
this.pluginName = pluginName; | ||
this.attributes = Collections.unmodifiableMap(new TreeMap<>(attributes)); | ||
this.children = Collections.unmodifiableList(new ArrayList<>(children)); | ||
} | ||
|
||
@Override | ||
public String getPluginName() { | ||
return pluginName; | ||
} | ||
|
||
@Override | ||
public Map<String, String> getAttributes() { | ||
return attributes; | ||
} | ||
|
||
@Override | ||
public List<? extends ConfigurationNode> getChildren() { | ||
return children; | ||
} | ||
|
||
private static void formatTo(ConfigurationNode node, StringBuilder builder, int indent) { | ||
String indentation = getIndentation(indent); | ||
builder.append(indentation).append("<").append(node.getPluginName()); | ||
for (final Map.Entry<String, String> entry : node.getAttributes().entrySet()) { | ||
builder.append(" ") | ||
.append(entry.getKey()) | ||
.append("=\"") | ||
.append(entry.getValue()) | ||
.append("\""); | ||
} | ||
builder.append(">\n"); | ||
for (ConfigurationNode child : node.getChildren()) { | ||
formatTo(child, builder, indent + 1); | ||
builder.append('\n'); | ||
} | ||
builder.append(indentation) | ||
.append("</") | ||
.append(node.getPluginName()) | ||
.append(">"); | ||
} | ||
|
||
private static String getIndentation(int indent) { | ||
return String.join("", Collections.nCopies(indent, " ")); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
StringBuilder builder = new StringBuilder(); | ||
formatTo(this, builder, 0); | ||
return builder.toString(); | ||
} | ||
} | ||
} |
Oops, something went wrong.