This is an automated email from the ASF dual-hosted git repository. vy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/logging-log4j-tools.git
commit 20e56e8123455f932e9ba8902b1b203247fb252c Author: Volkan Yazıcı <[email protected]> AuthorDate: Wed Jan 25 15:08:49 2023 +0100 Add tests for `MavenChangesImporter` --- log4j-changelog/README.adoc | 15 ++++- log4j-changelog/pom.xml | 12 ++++ .../logging/log4j/changelog/ChangelogEntry.java | 4 +- .../logging/log4j/changelog/ChangelogRelease.java | 4 +- .../changelog/importer/MavenChangesImporter.java | 13 +++- .../importer/MavenChangesImporterArgs.java | 21 +++++- .../logging/log4j/changelog/util/StringUtils.java | 13 ++++ .../logging/log4j/changelog/util/XmlUtils.java | 42 +++++++++++- .../logging/log4j/changelog/util/XmlWriter.java | 68 ++++++++++++------- .../logging/log4j/changelog/FileTestUtils.java | 75 +++++++++++++++++++++ .../log4j/changelog/MavenChangesImporterTest.java | 43 ++++++++++++ log4j-changelog/src/test/resources/1-changes.xml | 78 ++++++++++++++++++++++ ...Add_getExplicitLevel_method_to_LoggerConfig.xml | 25 +++++++ ...ConsoleListener_use_SimpleLogger_internally.xml | 25 +++++++ ..._InstantFormatter_against_delegate_failures.xml | 26 ++++++++ .../test/resources/2-imported/2.17.2/.release.xml} | 33 +-------- ...s_initialized_if_the_LoggerFactory_is_provi.xml | 26 ++++++++ ...ContextDataInjector_initialization_deadlock.xml | 25 +++++++ ..._Spring_Boot_Lookup_requires_the_log4j_spri.xml | 25 +++++++ .../test/resources/2-imported/2.18.0/.release.xml} | 33 +-------- ...erStrategy_should_use_the_current_time_when.xml | 25 +++++++ ...lloverStrategy_was_not_detecting_the_correc.xml | 25 +++++++ ...se_Paths_get_to_avoid_circular_file_systems.xml | 25 +++++++ log4j-tools-parent/pom.xml | 14 ++++ 24 files changed, 597 insertions(+), 98 deletions(-) diff --git a/log4j-changelog/README.adoc b/log4j-changelog/README.adoc index 1e13468..9e30d70 100644 --- a/log4j-changelog/README.adoc +++ b/log4j-changelog/README.adoc @@ -89,7 +89,10 @@ A typical `.release.xml` looks as follows: ---- $ cat src/changelog/2.19.0/release.xml <?xml version="1.0" encoding="UTF-8"?> -<release date="2022-09-09" version="2.19.0"/> +<release xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + date="2022-09-09" version="2.19.0"/> ---- A typical changelog entry file looks as follows: @@ -98,7 +101,10 @@ A typical changelog entry file looks as follows: ---- $ cat src/changelog/.2.x.x/LOG4J2-3628_new_changelog_infra.xml <?xml version="1.0" encoding="UTF-8"?> -<entry type="fixed"> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="fixed"> <issue id="LOG4J2-3556" link="https://issues.apache.org/jira/browse/LOG4J2-3556"/> <author id="vy"/> <author name="Arthur Gavlyukovskiy"/> @@ -161,7 +167,10 @@ A sample _changelog entry_ file is shared below. .`src/changelog/LOG4J2-3556_JsonTemplateLayout_stack_trace_truncation_fix.xml` file contents [source,xml] ---- -<entry type="fixed"> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="fixed"> <issue id="LOG4J2-3556" link="https://issues.apache.org/jira/browse/LOG4J2-3556"/> <author id="vy"/> <author name="Arthur Gavlyukovskiy"/> diff --git a/log4j-changelog/pom.xml b/log4j-changelog/pom.xml index 6e336be..53f0d77 100644 --- a/log4j-changelog/pom.xml +++ b/log4j-changelog/pom.xml @@ -43,6 +43,18 @@ <artifactId>freemarker</artifactId> </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <scope>test</scope> + </dependency> + </dependencies> </project> diff --git a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/ChangelogEntry.java b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/ChangelogEntry.java index f31d36a..88a42f2 100644 --- a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/ChangelogEntry.java +++ b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/ChangelogEntry.java @@ -112,12 +112,10 @@ public final class ChangelogEntry { } public void writeToXmlFile(final Path path) { - XmlWriter.toFile(path, document -> { + XmlWriter.toFile(path, "entry", (document, entryElement) -> { // Create the `entry` root element - final Element entryElement = document.createElement("entry"); entryElement.setAttribute("type", type.toXmlAttribute()); - document.appendChild(entryElement); // Create the `issue` elements issues.forEach(issue -> { diff --git a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/ChangelogRelease.java b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/ChangelogRelease.java index 2369ba7..b33765b 100644 --- a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/ChangelogRelease.java +++ b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/ChangelogRelease.java @@ -35,11 +35,9 @@ public final class ChangelogRelease { } public void writeToXmlFile(final Path path) { - XmlWriter.toFile(path, document -> { - final Element releaseElement = document.createElement("release"); + XmlWriter.toFile(path, "release", (document, releaseElement) -> { releaseElement.setAttribute("version", version); releaseElement.setAttribute("date", date); - document.appendChild(releaseElement); }); } diff --git a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/importer/MavenChangesImporter.java b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/importer/MavenChangesImporter.java index 318f0c9..33074f8 100644 --- a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/importer/MavenChangesImporter.java +++ b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/importer/MavenChangesImporter.java @@ -32,6 +32,10 @@ public final class MavenChangesImporter { public static void main(final String[] mainArgs) { final MavenChangesImporterArgs args = MavenChangesImporterArgs.fromSystemProperties(); + performImport(args); + } + + public static void performImport(final MavenChangesImporterArgs args) { final MavenChanges mavenChanges = MavenChanges.readFromFile(args.changesXmlFile); mavenChanges.releases.forEach(release -> { if ("TBD".equals(release.date)) { @@ -81,11 +85,14 @@ public final class MavenChangesImporter { } final String sanitizedDescription = action .description - .substring(0, Math.min(action.description.length(), 60)) .replaceAll("[^A-Za-z0-9]", "_") .replaceAll("_+", "_") - .replaceAll("[^A-Za-z0-9]$", ""); - actionRelativeFileBuilder.append(sanitizedDescription); + .replaceAll("^[^A-Za-z0-9]*", "") + .replaceAll("[^A-Za-z0-9]*$", ""); + final String shortenedSanitizedDescription = sanitizedDescription.length() > 60 + ? sanitizedDescription.substring(0, 60) + : sanitizedDescription; + actionRelativeFileBuilder.append(shortenedSanitizedDescription); actionRelativeFileBuilder.append(".xml"); return actionRelativeFileBuilder.toString(); } diff --git a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/importer/MavenChangesImporterArgs.java b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/importer/MavenChangesImporterArgs.java index fd9f631..515180b 100644 --- a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/importer/MavenChangesImporterArgs.java +++ b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/importer/MavenChangesImporterArgs.java @@ -17,11 +17,12 @@ package org.apache.logging.log4j.changelog.importer; import java.nio.file.Path; +import java.util.Objects; import static org.apache.logging.log4j.changelog.util.PropertyUtils.requireNonBlankIntProperty; import static org.apache.logging.log4j.changelog.util.PropertyUtils.requireNonBlankPathProperty; -final class MavenChangesImporterArgs { +public final class MavenChangesImporterArgs { public static final String CHANGELOG_DIRECTORY_PROPERTY_NAME = "log4j.changelog.directory"; @@ -35,10 +36,26 @@ final class MavenChangesImporterArgs { final int releaseVersionMajor; - private MavenChangesImporterArgs(final Path changelogDirectory, final Path changesXmlFile, final int releaseVersionMajor) { + public MavenChangesImporterArgs( + final Path changelogDirectory, + final Path changesXmlFile, + final int releaseVersionMajor) { + + // Check arguments + Objects.requireNonNull(changelogDirectory, "changelogDirectory"); + Objects.requireNonNull(changesXmlFile, "changesXmlFile"); + if (releaseVersionMajor < 0) { + final String message = String.format( + "was expecting `releaseVersionMajor >= 0`, found: %d", + releaseVersionMajor); + throw new IllegalArgumentException(message); + } + + // Set fields this.changelogDirectory = changelogDirectory; this.changesXmlFile = changesXmlFile; this.releaseVersionMajor = releaseVersionMajor; + } static MavenChangesImporterArgs fromSystemProperties() { diff --git a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/StringUtils.java b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/StringUtils.java index 1a084c2..ea5953a 100644 --- a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/StringUtils.java +++ b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/StringUtils.java @@ -31,4 +31,17 @@ public final class StringUtils { return input == null || input.matches("\\s*"); } + public static String repeat(final String input, final int count) { + if (count < 0) { + final String message = String.format("was expecting `count >= 0`, found: %d", count); + throw new IllegalArgumentException(message); + } + final int length = Math.multiplyExact(input.length(), count); + final StringBuilder stringBuilder = new StringBuilder(length); + for (int i = 0; i < count; i++) { + stringBuilder.append(input); + } + return stringBuilder.toString(); + } + } diff --git a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/XmlUtils.java b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/XmlUtils.java index 0a9ad6a..a438442 100644 --- a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/XmlUtils.java +++ b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/XmlUtils.java @@ -16,18 +16,36 @@ */ package org.apache.logging.log4j.changelog.util; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import java.io.InputStream; final class XmlUtils { + static final String XML_NAMESPACE = "http://logging.apache.org/log4j/changelog"; + + static final String XML_SCHEMA_LOCATION = "https://logging.apache.org/log4j/changelog-0.1.0.xsd"; + private XmlUtils() {} + static DocumentBuilderFactory createDocumentBuilderFactory() { + final DocumentBuilderFactory dbf = createSecureDocumentBuilderFactory(); + final Schema schema = readSchema(); + dbf.setSchema(schema); + dbf.setValidating(true); + return dbf; + } + /** * @return a {@link DocumentBuilderFactory} instance configured with certain XXE protection measures * @see <a href="https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxp-documentbuilderfactory-saxparserfactory-and-dom4j">XML External Entity Prevention Cheat Sheet</a> */ - static DocumentBuilderFactory createDocumentBuilderFactory() { + private static DocumentBuilderFactory createSecureDocumentBuilderFactory() { final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); String feature = null; try { @@ -68,4 +86,26 @@ final class XmlUtils { return dbf; } + private static Schema readSchema() { + + // Read the schema file resource + final String schemaFileName = "/log4j-changelog.xsd"; + final InputStream schemaInputStream = XmlUtils.class.getResourceAsStream(schemaFileName); + if (schemaInputStream == null) { + final String message = String.format("could not find the schema file resource: `%s`", schemaFileName); + throw new RuntimeException(message); + } + + // Read the schema + try { + final StreamSource schemaSource = new StreamSource(schemaInputStream); + final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + return schemaFactory.newSchema(schemaSource); + } catch (final Exception error) { + final String message = String.format("failed to load schema from file resource: `%s`", schemaFileName); + throw new RuntimeException(message, error); + } + + } + } diff --git a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/XmlWriter.java b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/XmlWriter.java index 7577ed5..3af34c4 100644 --- a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/XmlWriter.java +++ b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/util/XmlWriter.java @@ -20,7 +20,7 @@ import java.io.StringWriter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; -import java.util.function.Consumer; +import java.util.function.BiConsumer; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -34,14 +34,18 @@ import edu.umd.cs.findbugs.annotations.Nullable; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.w3c.dom.Comment; import org.w3c.dom.Document; +import org.w3c.dom.Element; public final class XmlWriter { private XmlWriter() {} - public static void toFile(final Path filepath, final Consumer<Document> documentConsumer) { + public static void toFile( + final Path filepath, + final String rootElementName, + final BiConsumer<Document, Element> documentConsumer) { try { - final String xml = toString(documentConsumer); + final String xml = toString(rootElementName, documentConsumer); final byte[] xmlBytes = xml.getBytes(CharsetUtils.CHARSET); @Nullable final Path filepathParent = filepath.getParent(); @@ -55,7 +59,7 @@ public final class XmlWriter { } } - public static String toString(final Consumer<Document> documentConsumer) { + public static String toString(final String rootElementName, final BiConsumer<Document, Element> documentConsumer) { try { // Create the document @@ -66,28 +70,35 @@ public final class XmlWriter { final Document document = documentBuilder.newDocument(); document.setXmlStandalone(true); final Comment licenseComment = document.createComment("\n" + - " Licensed to the Apache Software Foundation (ASF) under one or more\n" + - " contributor license agreements. See the NOTICE file distributed with\n" + - " this work for additional information regarding copyright ownership.\n" + - " The ASF licenses this file to You under the Apache License, Version 2.0\n" + - " (the \"License\"); you may not use this file except in compliance with\n" + - " the License. You may obtain a copy of the License at\n" + + " Licensed to the Apache Software Foundation (ASF) under one or more\n" + + " contributor license agreements. See the NOTICE file distributed with\n" + + " this work for additional information regarding copyright ownership.\n" + + " The ASF licenses this file to You under the Apache License, Version 2.0\n" + + " (the \"License\"); you may not use this file except in compliance with\n" + + " the License. You may obtain a copy of the License at\n" + "\n" + - " http://www.apache.org/licenses/LICENSE-2.0\n" + + " https://www.apache.org/licenses/LICENSE-2.0\n" + "\n" + - " Unless required by applicable law or agreed to in writing, software\n" + - " distributed under the License is distributed on an \"AS IS\" BASIS,\n" + - " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + - " See the License for the specific language governing permissions and\n" + - " limitations under the License." + + " Unless required by applicable law or agreed to in writing, software\n" + + " distributed under the License is distributed on an \"AS IS\" BASIS,\n" + + " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + + " See the License for the specific language governing permissions and\n" + + " limitations under the License." + "\n"); document.appendChild(licenseComment); - // Execute request changes - documentConsumer.accept(document); + // Create the root element + final Element rootElement = document.createElement(rootElementName); + document.appendChild(rootElement); + + // Apply requested changes + documentConsumer.accept(document, rootElement); +// rootElement.setAttribute("xmlns", XmlUtils.XML_NAMESPACE); +// rootElement.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); +// rootElement.setAttribute("xsi:schemaLocation", XmlUtils.XML_NAMESPACE + " "+ XmlUtils.XML_SCHEMA_LOCATION); // Serialize the document - return serializeXmlDocument(document); + return serializeXmlDocument(document, rootElementName); } catch (final Exception error) { throw new RuntimeException("failed writing XML", error); @@ -95,7 +106,8 @@ public final class XmlWriter { } @SuppressFBWarnings({"XXE_DTD_TRANSFORM_FACTORY", "XXE_XSLT_TRANSFORM_FACTORY"}) - private static String serializeXmlDocument(final Document document) throws Exception { + private static String serializeXmlDocument(final Document document, final String rootElementName) throws Exception { + final Transformer transformer = TransformerFactory.newInstance().newTransformer(); final StreamResult result = new StreamResult(new StringWriter()); final DOMSource source = new DOMSource(document); @@ -103,10 +115,20 @@ public final class XmlWriter { transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); transformer.transform(source, result); - return result.getWriter().toString() - // Life is too short to solve DOM transformer issues decently + + // Life is too short to solve DOM transformer issues decently + final String xml = result.getWriter().toString(); + final String padding = StringUtils.repeat(" ", rootElementName.length() + 2); + return xml .replace("?><!--", "?>\n<!--") - .replace("--><", "-->\n<"); + .replace("--><", "-->\n<") + .replaceFirst( + '<' + rootElementName + " (.+>\n)", + ('<' + rootElementName + " xmlns=\"" + XmlUtils.XML_NAMESPACE + "\"\n" + + padding + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + + padding + "xsi:schemaLocation=\"" + XmlUtils.XML_NAMESPACE + " "+ XmlUtils.XML_SCHEMA_LOCATION + "\"\n" + + padding + "$1")); + } } diff --git a/log4j-changelog/src/test/java/org/apache/logging/log4j/changelog/FileTestUtils.java b/log4j-changelog/src/test/java/org/apache/logging/log4j/changelog/FileTestUtils.java new file mode 100644 index 0000000..d67ff40 --- /dev/null +++ b/log4j-changelog/src/test/java/org/apache/logging/log4j/changelog/FileTestUtils.java @@ -0,0 +1,75 @@ +/* + * 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.log4j.changelog; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +final class FileTestUtils { + + private FileTestUtils() {} + + static void assertDirectoryContentMatches(final Path actualPath, final Path expectedPath) { + + // Compare file paths + final Map<String, Path> actualContents = directoryContents(actualPath); + final Map<String, Path> expectedContents = directoryContents(expectedPath); + final Set<String> relativeFilePaths = expectedContents.keySet(); + assertThat(actualContents).containsOnlyKeys(relativeFilePaths); + + // Compare file contents + relativeFilePaths.forEach(relativeFilePath -> { + final Path actualFilePath = actualContents.get(relativeFilePath); + final Path expectedFilePath = expectedContents.get(relativeFilePath); + if (!Files.isDirectory(actualFilePath) || !Files.isDirectory(expectedFilePath)) { + assertThat(actualFilePath).hasSameTextualContentAs(expectedFilePath, StandardCharsets.UTF_8); + } + }); + + } + + private static Map<String, Path> directoryContents(final Path root) { + final int rootPathLength = root.toAbsolutePath().toString().length(); + try (final Stream<Path> paths = Files.walk(root)) { + return paths + .filter(path -> !root.equals(path)) + .collect(Collectors.toMap( + path -> path.toAbsolutePath().toString().substring(rootPathLength + 1), + Function.identity(), + (oldPath, newPath) -> { + final String message = String.format( + "paths `%s` and `%s` have conflicting keys", + oldPath, newPath); + throw new IllegalStateException(message); + }, + TreeMap::new)); + } catch (final IOException error) { + final String message = String.format("failed walking directory: `%s`", root); + throw new UncheckedIOException(message, error); + } + } + +} diff --git a/log4j-changelog/src/test/java/org/apache/logging/log4j/changelog/MavenChangesImporterTest.java b/log4j-changelog/src/test/java/org/apache/logging/log4j/changelog/MavenChangesImporterTest.java new file mode 100644 index 0000000..ffaef0d --- /dev/null +++ b/log4j-changelog/src/test/java/org/apache/logging/log4j/changelog/MavenChangesImporterTest.java @@ -0,0 +1,43 @@ +/* + * 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.log4j.changelog; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.logging.log4j.changelog.importer.MavenChangesImporter; +import org.apache.logging.log4j.changelog.importer.MavenChangesImporterArgs; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.CleanupMode; +import org.junit.jupiter.api.io.TempDir; + +import static org.apache.logging.log4j.changelog.FileTestUtils.assertDirectoryContentMatches; + +class MavenChangesImporterTest { + + @Test + void output_should_match(@TempDir(cleanup = CleanupMode.ON_SUCCESS) final Path changelogDirectory) { + final MavenChangesImporterArgs args = new MavenChangesImporterArgs( + changelogDirectory, + Paths.get("src/test/resources/1-changes.xml"), + 2); + MavenChangesImporter.performImport(args); + assertDirectoryContentMatches(changelogDirectory, Paths.get("src/test/resources/2-imported")); + } + +} diff --git a/log4j-changelog/src/test/resources/1-changes.xml b/log4j-changelog/src/test/resources/1-changes.xml new file mode 100644 index 0000000..3a17e7c --- /dev/null +++ b/log4j-changelog/src/test/resources/1-changes.xml @@ -0,0 +1,78 @@ +<?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 + + https://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. +--> +<document xmlns="http://maven.apache.org/changes/1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/xsd/changes-1.0.0.xsd"> + + <properties> + <title>Changes</title> + </properties> + + <body> + + <release version="2.19.0" date="TBD" description="GA Release 2.19.0"> + + <action issue="LOG4J2-3584" dev="vy" type="fix"> + Make `StatusConsoleListener` use `SimpleLogger` internally + </action> + + <action issue="LOG4J2-3614" dev="vy" type="fix" due-to="strainu"> + Harden `InstantFormatter` against delegate failures + </action> + + <action issue="LOG4J2-3572" dev="rgoers" type="update"> + Add `getExplicitLevel` method to `LoggerConfig` + </action> + + </release> + + <release version="2.18.0" date="2022-06-28" description="GA Release 2.18.0"> + + <action issue="LOG4J2-3339" dev="rgoers" type="fix"> + `DirectWriteRolloverStrategy` should use the current time when creating files + </action> + + <action issue="LOG4J2-3527" dev="rgoers" type="add"> + Don't use `Paths.get()` to avoid circular file systems + </action> + + <action issue="LOG4J2-3490" dev="rgoers" type="remove"> + The `DirectWriteRolloverStrategy` was not detecting the correct index to use during startup + </action> + + </release> + + <release version="2.17.2" date="2022-02-23" description="GA Release 2.17.2"> + + <action issue="LOG4J2-3304" dev="rgoers" type="fix" due-to="francis-FY"> + Flag `LogManager` as initialized if the `LoggerFactory` is provided as a property + </action> + + <action issue="LOG4J2-3405" dev="rgoers" type="remove"> + Document that the Spring Boot Lookup requires the `log4j-spring-boot` dependency + </action> + + <action issue="LOG4J2-3333" dev="ckozak" type="remove"> + Fix `ThreadContextDataInjector` initialization deadlock + </action> + + </release> + + </body> + +</document> diff --git a/log4j-changelog/src/test/resources/2-imported/.2.x.x/LOG4J2-3572_Add_getExplicitLevel_method_to_LoggerConfig.xml b/log4j-changelog/src/test/resources/2-imported/.2.x.x/LOG4J2-3572_Add_getExplicitLevel_method_to_LoggerConfig.xml new file mode 100644 index 0000000..b135ac2 --- /dev/null +++ b/log4j-changelog/src/test/resources/2-imported/.2.x.x/LOG4J2-3572_Add_getExplicitLevel_method_to_LoggerConfig.xml @@ -0,0 +1,25 @@ +<?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 + + https://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. +--> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="changed"> + <issue id="LOG4J2-3572" link="https://issues.apache.org/jira/browse/LOG4J2-3572"/> + <author id="rgoers"/> + <description format="asciidoc">Add `getExplicitLevel` method to `LoggerConfig`</description> +</entry> diff --git a/log4j-changelog/src/test/resources/2-imported/.2.x.x/LOG4J2-3584_Make_StatusConsoleListener_use_SimpleLogger_internally.xml b/log4j-changelog/src/test/resources/2-imported/.2.x.x/LOG4J2-3584_Make_StatusConsoleListener_use_SimpleLogger_internally.xml new file mode 100644 index 0000000..7902947 --- /dev/null +++ b/log4j-changelog/src/test/resources/2-imported/.2.x.x/LOG4J2-3584_Make_StatusConsoleListener_use_SimpleLogger_internally.xml @@ -0,0 +1,25 @@ +<?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 + + https://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. +--> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="fixed"> + <issue id="LOG4J2-3584" link="https://issues.apache.org/jira/browse/LOG4J2-3584"/> + <author id="vy"/> + <description format="asciidoc">Make `StatusConsoleListener` use `SimpleLogger` internally</description> +</entry> diff --git a/log4j-changelog/src/test/resources/2-imported/.2.x.x/LOG4J2-3614_Harden_InstantFormatter_against_delegate_failures.xml b/log4j-changelog/src/test/resources/2-imported/.2.x.x/LOG4J2-3614_Harden_InstantFormatter_against_delegate_failures.xml new file mode 100644 index 0000000..34111cf --- /dev/null +++ b/log4j-changelog/src/test/resources/2-imported/.2.x.x/LOG4J2-3614_Harden_InstantFormatter_against_delegate_failures.xml @@ -0,0 +1,26 @@ +<?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 + + https://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. +--> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="fixed"> + <issue id="LOG4J2-3614" link="https://issues.apache.org/jira/browse/LOG4J2-3614"/> + <author id="vy"/> + <author name="strainu"/> + <description format="asciidoc">Harden `InstantFormatter` against delegate failures</description> +</entry> diff --git a/log4j-changelog/pom.xml b/log4j-changelog/src/test/resources/2-imported/2.17.2/.release.xml similarity index 52% copy from log4j-changelog/pom.xml copy to log4j-changelog/src/test/resources/2-imported/2.17.2/.release.xml index 6e336be..b46393f 100644 --- a/log4j-changelog/pom.xml +++ b/log4j-changelog/src/test/resources/2-imported/2.17.2/.release.xml @@ -15,34 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" +<release xmlns="http://logging.apache.org/log4j/changelog" 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> - <artifactId>log4j-tools-parent</artifactId> - <groupId>org.apache.logging.log4j</groupId> - <version>${revision}</version> - <relativePath>../log4j-tools-parent/pom.xml</relativePath> - </parent> - - <artifactId>log4j-changelog</artifactId> - - <dependencies> - - <dependency> - <groupId>com.github.spotbugs</groupId> - <artifactId>spotbugs-annotations</artifactId> - <scope>provided</scope> - </dependency> - - <dependency> - <groupId>org.freemarker</groupId> - <artifactId>freemarker</artifactId> - </dependency> - - </dependencies> - -</project> + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + date="2022-02-23" version="2.17.2"/> diff --git a/log4j-changelog/src/test/resources/2-imported/2.17.2/LOG4J2-3304_Flag_LogManager_as_initialized_if_the_LoggerFactory_is_provi.xml b/log4j-changelog/src/test/resources/2-imported/2.17.2/LOG4J2-3304_Flag_LogManager_as_initialized_if_the_LoggerFactory_is_provi.xml new file mode 100644 index 0000000..242b03e --- /dev/null +++ b/log4j-changelog/src/test/resources/2-imported/2.17.2/LOG4J2-3304_Flag_LogManager_as_initialized_if_the_LoggerFactory_is_provi.xml @@ -0,0 +1,26 @@ +<?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 + + https://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. +--> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="fixed"> + <issue id="LOG4J2-3304" link="https://issues.apache.org/jira/browse/LOG4J2-3304"/> + <author id="rgoers"/> + <author name="francis-FY"/> + <description format="asciidoc">Flag `LogManager` as initialized if the `LoggerFactory` is provided as a property</description> +</entry> diff --git a/log4j-changelog/src/test/resources/2-imported/2.17.2/LOG4J2-3333_Fix_ThreadContextDataInjector_initialization_deadlock.xml b/log4j-changelog/src/test/resources/2-imported/2.17.2/LOG4J2-3333_Fix_ThreadContextDataInjector_initialization_deadlock.xml new file mode 100644 index 0000000..cb4ea04 --- /dev/null +++ b/log4j-changelog/src/test/resources/2-imported/2.17.2/LOG4J2-3333_Fix_ThreadContextDataInjector_initialization_deadlock.xml @@ -0,0 +1,25 @@ +<?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 + + https://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. +--> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="removed"> + <issue id="LOG4J2-3333" link="https://issues.apache.org/jira/browse/LOG4J2-3333"/> + <author id="ckozak"/> + <description format="asciidoc">Fix `ThreadContextDataInjector` initialization deadlock</description> +</entry> diff --git a/log4j-changelog/src/test/resources/2-imported/2.17.2/LOG4J2-3405_Document_that_the_Spring_Boot_Lookup_requires_the_log4j_spri.xml b/log4j-changelog/src/test/resources/2-imported/2.17.2/LOG4J2-3405_Document_that_the_Spring_Boot_Lookup_requires_the_log4j_spri.xml new file mode 100644 index 0000000..6b213cb --- /dev/null +++ b/log4j-changelog/src/test/resources/2-imported/2.17.2/LOG4J2-3405_Document_that_the_Spring_Boot_Lookup_requires_the_log4j_spri.xml @@ -0,0 +1,25 @@ +<?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 + + https://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. +--> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="removed"> + <issue id="LOG4J2-3405" link="https://issues.apache.org/jira/browse/LOG4J2-3405"/> + <author id="rgoers"/> + <description format="asciidoc">Document that the Spring Boot Lookup requires the `log4j-spring-boot` dependency</description> +</entry> diff --git a/log4j-changelog/pom.xml b/log4j-changelog/src/test/resources/2-imported/2.18.0/.release.xml similarity index 52% copy from log4j-changelog/pom.xml copy to log4j-changelog/src/test/resources/2-imported/2.18.0/.release.xml index 6e336be..2f7068a 100644 --- a/log4j-changelog/pom.xml +++ b/log4j-changelog/src/test/resources/2-imported/2.18.0/.release.xml @@ -15,34 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" +<release xmlns="http://logging.apache.org/log4j/changelog" 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> - <artifactId>log4j-tools-parent</artifactId> - <groupId>org.apache.logging.log4j</groupId> - <version>${revision}</version> - <relativePath>../log4j-tools-parent/pom.xml</relativePath> - </parent> - - <artifactId>log4j-changelog</artifactId> - - <dependencies> - - <dependency> - <groupId>com.github.spotbugs</groupId> - <artifactId>spotbugs-annotations</artifactId> - <scope>provided</scope> - </dependency> - - <dependency> - <groupId>org.freemarker</groupId> - <artifactId>freemarker</artifactId> - </dependency> - - </dependencies> - -</project> + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + date="2022-06-28" version="2.18.0"/> diff --git a/log4j-changelog/src/test/resources/2-imported/2.18.0/LOG4J2-3339_DirectWriteRolloverStrategy_should_use_the_current_time_when.xml b/log4j-changelog/src/test/resources/2-imported/2.18.0/LOG4J2-3339_DirectWriteRolloverStrategy_should_use_the_current_time_when.xml new file mode 100644 index 0000000..8490b36 --- /dev/null +++ b/log4j-changelog/src/test/resources/2-imported/2.18.0/LOG4J2-3339_DirectWriteRolloverStrategy_should_use_the_current_time_when.xml @@ -0,0 +1,25 @@ +<?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 + + https://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. +--> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="fixed"> + <issue id="LOG4J2-3339" link="https://issues.apache.org/jira/browse/LOG4J2-3339"/> + <author id="rgoers"/> + <description format="asciidoc">`DirectWriteRolloverStrategy` should use the current time when creating files</description> +</entry> diff --git a/log4j-changelog/src/test/resources/2-imported/2.18.0/LOG4J2-3490_The_DirectWriteRolloverStrategy_was_not_detecting_the_correc.xml b/log4j-changelog/src/test/resources/2-imported/2.18.0/LOG4J2-3490_The_DirectWriteRolloverStrategy_was_not_detecting_the_correc.xml new file mode 100644 index 0000000..c60d17b --- /dev/null +++ b/log4j-changelog/src/test/resources/2-imported/2.18.0/LOG4J2-3490_The_DirectWriteRolloverStrategy_was_not_detecting_the_correc.xml @@ -0,0 +1,25 @@ +<?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 + + https://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. +--> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="removed"> + <issue id="LOG4J2-3490" link="https://issues.apache.org/jira/browse/LOG4J2-3490"/> + <author id="rgoers"/> + <description format="asciidoc">The `DirectWriteRolloverStrategy` was not detecting the correct index to use during startup</description> +</entry> diff --git a/log4j-changelog/src/test/resources/2-imported/2.18.0/LOG4J2-3527_Don_t_use_Paths_get_to_avoid_circular_file_systems.xml b/log4j-changelog/src/test/resources/2-imported/2.18.0/LOG4J2-3527_Don_t_use_Paths_get_to_avoid_circular_file_systems.xml new file mode 100644 index 0000000..d7e296b --- /dev/null +++ b/log4j-changelog/src/test/resources/2-imported/2.18.0/LOG4J2-3527_Don_t_use_Paths_get_to_avoid_circular_file_systems.xml @@ -0,0 +1,25 @@ +<?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 + + https://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. +--> +<entry xmlns="http://logging.apache.org/log4j/changelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.0.xsd" + type="added"> + <issue id="LOG4J2-3527" link="https://issues.apache.org/jira/browse/LOG4J2-3527"/> + <author id="rgoers"/> + <description format="asciidoc">Don't use `Paths.get()` to avoid circular file systems</description> +</entry> diff --git a/log4j-tools-parent/pom.xml b/log4j-tools-parent/pom.xml index 671e311..c2dbf46 100644 --- a/log4j-tools-parent/pom.xml +++ b/log4j-tools-parent/pom.xml @@ -52,7 +52,9 @@ <maven.site.deploy.skip>true</maven.site.deploy.skip> <!-- dependency versions --> + <assertj.version>3.24.0</assertj.version> <freemarker.version>2.3.32</freemarker.version> + <junit.version>5.9.2</junit.version> <maven-plugin.version>3.7.1</maven-plugin.version> <maven-plugin-api.version>3.8.7</maven-plugin-api.version> <spotbugs.version>4.7.3</spotbugs.version> @@ -68,12 +70,24 @@ <dependencyManagement> <dependencies> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>${assertj.version}</version> + </dependency> + <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>${freemarker.version}</version> </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>${junit.version}</version> + </dependency> + <dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId>
