diff --git a/.github/workflows/broken-links.yml b/.github/workflows/broken-links.yml index e2f3597..a37abe7 100644 --- a/.github/workflows/broken-links.yml +++ b/.github/workflows/broken-links.yml @@ -13,13 +13,13 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - run: mv .github/.lycheeignore .lycheeignore - name: Link Checker id: lychee - uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332 # v2 + uses: lycheeverse/lychee-action@5c4ee84814c983aa7164eaee476f014e53ff3963 # v2 with: fail: false # Don't fail on broken links, create an issue instead diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 9433b31..573b02b 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -20,7 +20,6 @@ on: - 'assets/**' env: - PRIMARY_MAVEN_MODULE: ${{ github.event.repository.name }} DEMO_MAVEN_MODULE: ${{ github.event.repository.name }}-demo jobs: @@ -35,7 +34,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up JDK uses: actions/setup-java@v4 @@ -77,7 +76,7 @@ jobs: distribution: [temurin] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up JDK uses: actions/setup-java@v4 @@ -100,7 +99,7 @@ jobs: distribution: [temurin] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up JDK uses: actions/setup-java@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5f8fb83..e415f67 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up JDK uses: actions/setup-java@v4 @@ -53,7 +53,7 @@ jobs: outputs: upload_url: ${{ steps.create-release.outputs.upload_url }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Configure Git run: | @@ -105,7 +105,7 @@ jobs: needs: [prepare-release] timeout-minutes: 60 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Init Git and pull run: | @@ -153,7 +153,7 @@ jobs: needs: [prepare-release] timeout-minutes: 15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Init Git and pull run: | @@ -184,7 +184,7 @@ jobs: needs: [publish-maven] timeout-minutes: 10 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Init Git and pull run: | diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index dc67287..f6c50a1 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: sparse-checkout: .github/labels.yml diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index 046be63..795bd6e 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up JDK uses: actions/setup-java@v4 diff --git a/.github/workflows/update-from-template.yml b/.github/workflows/update-from-template.yml index 65f56b0..e689fe9 100644 --- a/.github/workflows/update-from-template.yml +++ b/.github/workflows/update-from-template.yml @@ -36,7 +36,7 @@ jobs: update_branch_merged_commit: ${{ steps.manage-branches.outputs.update_branch_merged_commit }} create_update_branch_merged_pr: ${{ steps.manage-branches.outputs.create_update_branch_merged_pr }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: # Required because otherwise there are always changes detected when executing diff/rev-list fetch-depth: 0 @@ -183,7 +183,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: # Required because otherwise there are always changes detected when executing diff/rev-list fetch-depth: 0 diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml index b52c3e2..d43641c 100644 --- a/.idea/checkstyle-idea.xml +++ b/.idea/checkstyle-idea.xml @@ -1,7 +1,7 @@ - 10.21.0 + 10.26.1 JavaOnlyWithTests true true diff --git a/CHANGELOG.md b/CHANGELOG.md index eb5587e..7a3208d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,13 @@ +# 2.2.1 +* Windows NTFS junction fix + * Automatically disable it on Java 26+ as [JDK-8364277](https://bugs.openjdk.org/browse/JDK-8364277) is fixed there + * Backport changes from Java 25 to ensure compatibility and get performance improvements (JEP 486) +* Updated dependencies + # 2.2.0 * Added an explicit option for enabling the Windows NTFS junction fix: ``useWinNTFSJunctionFixIfApplicable`` #155 * Enabling it also requires adding ``--add-exports java.base/sun.nio.fs=ALL-UNNAMED`` or performance will be impacted by ~20x due to non-accessible file attributes cache - * This option is temporary and will be removed once the underlying JDK bug was fixed + * This option is temporary and will be removed once the [underlying JDK bug](https://bugs.openjdk.org/browse/JDK-8364277) was fixed * The default logger of ``AdvancedImageFromDockerFile`` now also includes ``dockerImageName`` to make it easier to distinguish between parallel builds # 2.1.1 diff --git a/pom.xml b/pom.xml index cb0573c..162df5e 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ com.puppycrawl.tools checkstyle - 10.26.1 + 11.0.0 diff --git a/testcontainers-advanced-imagebuilder-dummy-app/pom.xml b/testcontainers-advanced-imagebuilder-dummy-app/pom.xml index 450a54e..25af75f 100644 --- a/testcontainers-advanced-imagebuilder-dummy-app/pom.xml +++ b/testcontainers-advanced-imagebuilder-dummy-app/pom.xml @@ -82,7 +82,7 @@ com.puppycrawl.tools checkstyle - 10.26.1 + 11.0.0 diff --git a/testcontainers-advanced-imagebuilder/pom.xml b/testcontainers-advanced-imagebuilder/pom.xml index b7a4a0d..9d2a1dd 100644 --- a/testcontainers-advanced-imagebuilder/pom.xml +++ b/testcontainers-advanced-imagebuilder/pom.xml @@ -205,7 +205,7 @@ org.codehaus.mojo flatten-maven-plugin - 1.7.1 + 1.7.2 ossrh @@ -273,7 +273,7 @@ com.puppycrawl.tools checkstyle - 10.26.1 + 11.0.0 diff --git a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/FileTreeIterator.java b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/FileTreeIterator.java index ac13299..a6681b2 100644 --- a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/FileTreeIterator.java +++ b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/FileTreeIterator.java @@ -14,7 +14,7 @@ * limitations under the License. */ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,7 +74,6 @@ public class FileTreeIterator implements Iterator, Closeable * * @throws IllegalArgumentException if {@code maxDepth} is negative * @throws IOException if an I/O errors occurs opening the starting file - * @throws SecurityException if the security manager denies access to the starting file * @throws NullPointerException if {@code start} or {@code options} is {@code null} or the options array * contains a {@code null} element */ diff --git a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/FileTreeWalker.java b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/FileTreeWalker.java index 0a4651d..5770651 100644 --- a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/FileTreeWalker.java +++ b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/FileTreeWalker.java @@ -14,7 +14,7 @@ * limitations under the License. */ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -162,21 +162,8 @@ enum EventType /** * Events returned by the {@link #walk} and {@link #next} methods. */ - static class Event + record Event(EventType type, Path file, BasicFileAttributes attributes, IOException ioeException) { - private final EventType type; - private final Path file; - private final BasicFileAttributes attrs; - private final IOException ioe; - - private Event(final EventType type, final Path file, final BasicFileAttributes attrs, final IOException ioe) - { - this.type = type; - this.file = file; - this.attrs = attrs; - this.ioe = ioe; - } - Event(final EventType type, final Path file, final BasicFileAttributes attrs) { this(type, file, attrs, null); @@ -186,26 +173,6 @@ private Event(final EventType type, final Path file, final BasicFileAttributes a { this(type, file, null, ioe); } - - EventType type() - { - return this.type; - } - - Path file() - { - return this.file; - } - - BasicFileAttributes attributes() - { - return this.attrs; - } - - IOException ioeException() - { - return this.ioe; - } } /** @@ -307,16 +274,13 @@ private static BasicFileAttributes extractFromBasicFileAttributesHolder(final Pa * The * {@code canUseCached} argument determines whether this method can use cached attributes. */ - @SuppressWarnings("removal") private BasicFileAttributes getAttributes(final Path file, final boolean canUseCached) throws IOException { // if attributes are cached then use them if possible - if(canUseCached - && this.isBasicFileAttributesHolder(file) - && System.getSecurityManager() == null) + if(canUseCached && isBasicFileAttributesHolder(file)) { - final BasicFileAttributes cached = this.extractFromBasicFileAttributesHolder(file); + final BasicFileAttributes cached = extractFromBasicFileAttributesHolder(file); if(cached != null && (!this.followLinks || !cached.isSymbolicLink())) { return cached; @@ -337,7 +301,7 @@ private BasicFileAttributes getAttributes(final Path file, final boolean canUseC throw ioe; } - // attempt to get attrmptes without following links + // attempt to get attributes without following links attrs = Files.readAttributes( file, BasicFileAttributes.class, @@ -374,7 +338,7 @@ private boolean wouldLoop(final Path dir, final Object key) return true; } } - catch(final IOException | SecurityException x) + catch(final IOException e) { // ignore } @@ -386,13 +350,9 @@ private boolean wouldLoop(final Path dir, final Object key) /** * Visits the given file, returning the {@code Event} corresponding to that visit. *

- * The {@code ignoreSecurityException} parameter determines whether any SecurityException should be ignored or not. - * If a SecurityException is thrown, and is ignored, then this method returns {@code null} to mean that there is no - * event corresponding to a visit to the file. - *

* The {@code canUseCached} parameter determines whether cached attributes for the file can be used or not. */ - private Event visit(final Path entry, final boolean ignoreSecurityException, final boolean canUseCached) + private Event visit(final Path entry, final boolean canUseCached) { // need the file attributes final BasicFileAttributes attrs; @@ -404,14 +364,6 @@ private Event visit(final Path entry, final boolean ignoreSecurityException, fin { return new Event(EventType.ENTRY, entry, ioe); } - catch(final SecurityException se) - { - if(ignoreSecurityException) - { - return null; - } - throw se; - } // at maximum depth or file is not a directory final int depth = this.stack.size(); @@ -439,14 +391,6 @@ private Event visit(final Path entry, final boolean ignoreSecurityException, fin { return new Event(EventType.ENTRY, entry, ioe); } - catch(final SecurityException se) - { - if(ignoreSecurityException) - { - return null; - } - throw se; - } // push a directory node to the stack and return an event this.stack.push(new DirectoryNode(entry, attrs.fileKey(), stream)); @@ -463,12 +407,9 @@ Event walk(final Path file) throw new IllegalStateException("Closed"); } - final Event ev = this.visit( + return this.visit( file, - false, // ignoreSecurityException false); // canUseCached - assert ev != null; - return ev; } /** @@ -483,61 +424,53 @@ Event next() } // continue iteration of the directory at the top of the stack - Event ev; - do + Path entry = null; + IOException ioe = null; + + // get next entry in the directory + if(!top.skipped()) { - Path entry = null; - IOException ioe = null; - - // get next entry in the directory - if(!top.skipped()) + final Iterator iterator = top.iterator(); + try { - final Iterator iterator = top.iterator(); - try + if(iterator.hasNext()) { - if(iterator.hasNext()) - { - entry = iterator.next(); - } - } - catch(final DirectoryIteratorException x) - { - ioe = x.getCause(); + entry = iterator.next(); } } - - // no next entry so close and pop directory, - // creating corresponding event - if(entry == null) + catch(final DirectoryIteratorException x) { - try + ioe = x.getCause(); + } + } + + // no next entry so close and pop directory, + // creating corresponding event + if(entry == null) + { + try + { + top.stream().close(); + } + catch(final IOException e) + { + if(ioe == null) { - top.stream().close(); + ioe = e; } - catch(final IOException e) + else { - if(ioe == null) - { - ioe = e; - } - else - { - ioe.addSuppressed(e); - } + ioe.addSuppressed(e); } - this.stack.pop(); - return new Event(EventType.END_DIRECTORY, top.directory(), ioe); } - - // visit the entry - ev = this.visit( - entry, - true, // ignoreSecurityException - true); // canUseCached + this.stack.pop(); + return new Event(EventType.END_DIRECTORY, top.directory(), ioe); } - while(ev == null); - return ev; + // visit the entry + return this.visit( + entry, + true); // canUseCached } /** diff --git a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/WinNTFSJunctionFiles.java b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/WinNTFSJunctionFiles.java index fd478ed..c343fb5 100644 --- a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/WinNTFSJunctionFiles.java +++ b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/WinNTFSJunctionFiles.java @@ -52,14 +52,27 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * @see software.xdev.testcontainers.imagebuilder.transfer.java.nio.file.winntfs */ public final class WinNTFSJunctionFiles { + private static final Logger LOG = LoggerFactory.getLogger(WinNTFSJunctionFiles.class); + + @SuppressWarnings("checkstyle:MagicNumber") public static boolean shouldBeApplied(final Path path) { + // JDK-8364277 was fixed in Java 26 + if(Runtime.version().feature() >= 26) + { + LOG.info("WindowsNTFSJunctionFix is no longer required " + + "as this is a Java version where JDK-8364277 is fixed"); + return false; + } try { final FileStore store = Files.getFileStore(path); diff --git a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/package-info.java b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/package-info.java index 1774ed0..aeac06a 100644 --- a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/package-info.java +++ b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/package-info.java @@ -14,16 +14,17 @@ * limitations under the License. */ /** - * This package was forked from the OpenJDK (as of 21.0.7) to resolve a crash/infinite loop when encountering + * This package was forked from the OpenJDK (25) to resolve a crash/infinite loop when encountering * * recursive NTFS junctions on Windows * . *

* Please note: - * Enabling it also requires adding ``--add-exports java.base/sun.nio.fs=ALL-UNNAMED`` or performance will be - * impacted by ~20x due non-accessible file attributes cache + * Enabling/Using it also requires adding --add-exports java.base/sun.nio.fs=ALL-UNNAMED as arguments + * or performance will be impacted by ~20x due non-accessible file attributes cache. *

* + * @see JDK-8364277 * @see NTFS junction */ package software.xdev.testcontainers.imagebuilder.transfer.java.nio.file.winntfs; diff --git a/testcontainers-advanced-imagebuilder/src/test/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/WinNTFSJunctionFilesTest.java b/testcontainers-advanced-imagebuilder/src/test/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/WinNTFSJunctionFilesTest.java index 2c8822d..f5fdf4e 100644 --- a/testcontainers-advanced-imagebuilder/src/test/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/WinNTFSJunctionFilesTest.java +++ b/testcontainers-advanced-imagebuilder/src/test/java/software/xdev/testcontainers/imagebuilder/transfer/java/nio/file/winntfs/WinNTFSJunctionFilesTest.java @@ -52,7 +52,7 @@ void junctionNoCrash(@TempDir final Path tempDir) throws IOException if(!WinNTFSJunctionFiles.shouldBeApplied(tempDir)) { - Assumptions.abort("Test is not applicable: Not WIN + NTFS"); + Assumptions.abort("Test is not applicable"); } final Path testFile = sub.resolve("test.txt");