You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by vy...@apache.org on 2023/01/31 12:11:01 UTC

[logging-log4j-tools] branch windows-fixes updated: Fix Windows test problem

This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch windows-fixes
in repository https://gitbox.apache.org/repos/asf/logging-log4j-tools.git


The following commit(s) were added to refs/heads/windows-fixes by this push:
     new 3608645  Fix Windows test problem
3608645 is described below

commit 360864566ee9b37fc2584a77bd4461ca1816b94f
Author: Piotr P. Karwasz <pi...@karwasz.org>
AuthorDate: Mon Jan 30 23:35:54 2023 +0100

    Fix Windows test problem
    
    The Windows Freemarker failure has been fixed by restraining the
    templates to the `changelog` directory.
---
 CHANGELOG.adoc                                     |  2 +-
 .../changelog/exporter/ChangelogExporter.java      | 49 ++++++++++++++---
 .../log4j/changelog/exporter/FreeMarkerUtils.java  | 63 +++++++---------------
 .../logging/log4j/changelog/FileTestUtils.java     |  7 +--
 4 files changed, 64 insertions(+), 57 deletions(-)

diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 41693ae..3b10e63 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -17,7 +17,7 @@ limitations under the License.
 
 == Unreleased
 
-* Fixed Windows compatibility (for https://github.com/apache/logging-log4j-tools/issues/19[#19] by Volkan Yazıcı)
+* Fixed Windows compatibility (for https://github.com/apache/logging-log4j-tools/issues/19[#19] by Piotr P. Karwasz, Volkan Yazıcı)
 
 * Fixed unreleased directory order in `ChangelogExporter` (for https://github.com/apache/logging-log4j-tools/issues/17[#17] by Volkan Yazıcı)
 
diff --git a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/exporter/ChangelogExporter.java b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/exporter/ChangelogExporter.java
index 41d0021..a2341d8 100644
--- a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/exporter/ChangelogExporter.java
+++ b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/exporter/ChangelogExporter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.changelog.exporter;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.nio.file.Files;
@@ -64,6 +65,7 @@ public final class ChangelogExporter {
                 try {
                     exportRelease(
                             args.outputDirectory,
+                            args.changelogDirectory,
                             releaseDirectory,
                             changelogRelease,
                             releaseChangelogTemplateFile);
@@ -100,6 +102,7 @@ public final class ChangelogExporter {
                     System.out.format("exporting upcoming release directory: `%s`%n", upcomingReleaseDirectory);
                     exportRelease(
                             args.outputDirectory,
+                            args.changelogDirectory,
                             upcomingReleaseDirectory,
                             upcomingRelease,
                             upcomingReleaseChangelogTemplateFile);
@@ -107,8 +110,10 @@ public final class ChangelogExporter {
                 });
 
         // Export the release index
-        final Path changelogIndexTemplateFile = ChangelogFiles.indexTemplateFile(args.changelogDirectory);
-        exportIndex(args.outputDirectory, changelogReleases, changelogIndexTemplateFile);
+        exportIndex(
+                args.outputDirectory,
+                args.changelogDirectory,
+                changelogReleases);
 
     }
 
@@ -133,12 +138,19 @@ public final class ChangelogExporter {
 
     private static void exportRelease(
             final Path outputDirectory,
+            final Path changelogDirectory,
             final Path releaseDirectory,
             final ChangelogRelease changelogRelease,
             final Path releaseChangelogTemplateFile) {
-        final Map<ChangelogEntry.Type, List<ChangelogEntry>> changelogEntriesByType = readChangelogEntriesByType(releaseDirectory);
+        final Map<ChangelogEntry.Type, List<ChangelogEntry>> changelogEntriesByType =
+                readChangelogEntriesByType(releaseDirectory);
         try {
-            exportRelease(outputDirectory, changelogRelease, changelogEntriesByType, releaseChangelogTemplateFile);
+            exportRelease(
+                    outputDirectory,
+                    changelogDirectory,
+                    changelogRelease,
+                    changelogEntriesByType,
+                    releaseChangelogTemplateFile);
         } catch (final IOException error) {
             final String message = String.format("failed exporting release from directory `%s`", releaseDirectory);
             throw new UncheckedIOException(message, error);
@@ -160,6 +172,7 @@ public final class ChangelogExporter {
 
     private static void exportRelease(
             final Path outputDirectory,
+            final Path changelogDirectory,
             final ChangelogRelease release,
             final Map<ChangelogEntry.Type, List<ChangelogEntry>> entriesByType,
             final Path releaseChangelogTemplateFile)
@@ -169,7 +182,12 @@ public final class ChangelogExporter {
         final Map<String, Object> releaseChangelogTemplateData = new LinkedHashMap<>();
         releaseChangelogTemplateData.put("release", release);
         releaseChangelogTemplateData.put("entriesByType", entriesByType);
-        FreeMarkerUtils.render(releaseChangelogTemplateFile, releaseChangelogTemplateData, releaseChangelogFile);
+        final String releaseChangelogTemplateName = templateName(changelogDirectory, releaseChangelogTemplateFile);
+        FreeMarkerUtils.render(
+                changelogDirectory,
+                releaseChangelogTemplateName,
+                releaseChangelogTemplateData,
+                releaseChangelogFile);
     }
 
     private static ChangelogRelease upcomingRelease(final int versionMajor) {
@@ -179,8 +197,8 @@ public final class ChangelogExporter {
 
     private static void exportIndex(
             final Path outputDirectory,
-            final List<ChangelogRelease> changelogReleases,
-            final Path indexTemplateFile) {
+            final Path changelogDirectory,
+            final List<ChangelogRelease> changelogReleases) {
         final Object indexTemplateData = Collections.singletonMap(
                 "releases", IntStream
                         .range(0, changelogReleases.size())
@@ -195,8 +213,10 @@ public final class ChangelogExporter {
                             return (Object) changelogReleaseData;
                         })
                         .collect(Collectors.toList()));
+        final Path indexTemplateFile = ChangelogFiles.indexTemplateFile(changelogDirectory);
+        final String indexTemplateName = templateName(changelogDirectory, indexTemplateFile);
         final Path indexFile = outputDirectory.resolve("index.adoc");
-        FreeMarkerUtils.render(indexTemplateFile, indexTemplateData, indexFile);
+        FreeMarkerUtils.render(changelogDirectory, indexTemplateName, indexTemplateData, indexFile);
     }
 
     private static String releaseChangelogFileName(final ChangelogRelease changelogRelease) {
@@ -204,4 +224,17 @@ public final class ChangelogExporter {
         return String.format("%s.adoc", changelogRelease.version);
     }
 
+    /**
+     * Creates a FreeMarker template name from the given path, assuming that the provided changelog directory is the template folder.
+     * <p>
+     * {@link freemarker.cache.FileTemplateLoader} works against a template folder, hence the path relativization required.
+     * </p>
+     */
+    private static String templateName(final Path changelogDirectory, final Path path) {
+        final Path relativePath = changelogDirectory.relativize(path);
+        return File.pathSeparatorChar == '/'
+                ? relativePath.toString()
+                : relativePath.toString().replace('\\', '/');
+    }
+
 }
diff --git a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/exporter/FreeMarkerUtils.java b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/exporter/FreeMarkerUtils.java
index 116421b..5ab86d6 100644
--- a/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/exporter/FreeMarkerUtils.java
+++ b/log4j-changelog/src/main/java/org/apache/logging/log4j/changelog/exporter/FreeMarkerUtils.java
@@ -17,36 +17,35 @@
 package org.apache.logging.log4j.changelog.exporter;
 
 import java.io.BufferedWriter;
-import java.io.File;
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardOpenOption;
-import java.util.Arrays;
 
 import org.apache.logging.log4j.changelog.util.CharsetUtils;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import freemarker.cache.FileTemplateLoader;
-import freemarker.cache.MultiTemplateLoader;
-import freemarker.cache.TemplateLoader;
 import freemarker.template.*;
 
 final class FreeMarkerUtils {
 
     private FreeMarkerUtils() {}
 
-    private static final Configuration CONFIGURATION = createConfiguration();
-
-    private static Configuration createConfiguration() {
-        final Configuration configuration = new Configuration(Configuration.VERSION_2_3_29);
+    @SuppressFBWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME")
+    private static Configuration createConfiguration(final Path templateDirectory) {
+        final Version configurationVersion = Configuration.VERSION_2_3_29;
+        final Configuration configuration = new Configuration(configurationVersion);
         configuration.setDefaultEncoding(CharsetUtils.CHARSET_NAME);
         configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
-        final TemplateLoader templateLoader = createTemplateLoader();
-        configuration.setTemplateLoader(templateLoader);
+        try {
+            configuration.setTemplateLoader(new FileTemplateLoader(templateDirectory.toFile()));
+        } catch (final IOException error) {
+            throw new UncheckedIOException(error);
+        }
         final DefaultObjectWrapperBuilder objectWrapperBuilder =
-                new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_27);
+                new DefaultObjectWrapperBuilder(configurationVersion);
         objectWrapperBuilder.setExposeFields(true);
         final DefaultObjectWrapper objectWrapper = objectWrapperBuilder.build();
         configuration.setObjectWrapper(objectWrapper);
@@ -56,41 +55,15 @@ final class FreeMarkerUtils {
         return configuration;
     }
 
-    private static TemplateLoader createTemplateLoader() {
-        final File[] roots = File.listRoots();
-        if (roots.length == 0) {
-            throw new RuntimeException("could not find any filesystem roots");
-        } else if (roots.length == 1) {
-            return createFileTemplateLoader(roots[0]);
-        } else {
-            final TemplateLoader[] templateLoaders = Arrays
-                    .stream(roots)
-                    .map(FreeMarkerUtils::createFileTemplateLoader)
-                    .toArray(TemplateLoader[]::new);
-            return new MultiTemplateLoader(templateLoaders);
-        }
-    }
-
-    private static FileTemplateLoader createFileTemplateLoader(final File baseDir) {
-        try {
-            return new FileTemplateLoader(baseDir);
-        } catch (final IOException error) {
-            final String message =
-                    String.format("failed creating file template loader for base directory `%s`", baseDir);
-            throw new UncheckedIOException(message, error);
-        }
-    }
-
     @SuppressFBWarnings("TEMPLATE_INJECTION_FREEMARKER")
-    static void render(final Path templateFile, final Object templateData, final Path outputFile) {
-        // Since we are using `FileTemplateLoader`, template names refer to actual file paths.
-        // On Windows, this causes failures; FreeMarker doesn't allow backslashes in the template name.
-        // As a workaround, we are replacing backslashes with slashes.
-        final String templateName = File.separatorChar == '/'
-                ? templateFile.toAbsolutePath().toString()
-                : templateFile.toAbsolutePath().toString().replace('\\', '/');
+    static void render(
+            final Path templateDirectory,
+            final String templateName,
+            final Object templateData,
+            final Path outputFile) {
         try {
-            final Template template = CONFIGURATION.getTemplate(templateName);
+            final Configuration configuration = createConfiguration(templateDirectory);
+            final Template template = configuration.getTemplate(templateName);
             final Path outputFileParent = outputFile.getParent();
             if (outputFileParent != null) {
                 Files.createDirectories(outputFileParent);
@@ -105,7 +78,7 @@ final class FreeMarkerUtils {
         } catch (final Exception error) {
             final String message = String.format(
                     "failed rendering template `%s` to file `%s`",
-                    templateFile,
+                    templateName,
                     outputFile);
             throw new RuntimeException(message, error);
         }
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
index d67ff40..0722116 100644
--- 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
@@ -18,10 +18,11 @@ 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.Map;
+import java.util.Set;
+import java.util.TreeMap;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -45,7 +46,7 @@ final class FileTestUtils {
             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);
+                assertThat(actualFilePath).hasSameBinaryContentAs(expectedFilePath);
             }
         });