diff --git a/CHANGELOG.md b/CHANGELOG.md index 182ac1e..eb5587e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 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 +* The default logger of ``AdvancedImageFromDockerFile`` now also includes ``dockerImageName`` to make it easier to distinguish between parallel builds + # 2.1.1 * Addresses a JDK bug which results in a crash or "infinite" loop when encountering recursive NTFS junctions on Windows #155 diff --git a/pom.xml b/pom.xml index a84f5d9..ac991bf 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ software.xdev testcontainers-advanced-imagebuilder-root - 2.1.2-SNAPSHOT + 2.2.0-SNAPSHOT pom diff --git a/testcontainers-advanced-imagebuilder-demo/pom.xml b/testcontainers-advanced-imagebuilder-demo/pom.xml index baa8899..30c81c6 100644 --- a/testcontainers-advanced-imagebuilder-demo/pom.xml +++ b/testcontainers-advanced-imagebuilder-demo/pom.xml @@ -7,11 +7,11 @@ software.xdev testcontainers-advanced-imagebuilder-root - 2.1.2-SNAPSHOT + 2.2.0-SNAPSHOT testcontainers-advanced-imagebuilder-demo - 2.1.2-SNAPSHOT + 2.2.0-SNAPSHOT jar diff --git a/testcontainers-advanced-imagebuilder-dummy-app/pom.xml b/testcontainers-advanced-imagebuilder-dummy-app/pom.xml index b81da89..c9a8f71 100644 --- a/testcontainers-advanced-imagebuilder-dummy-app/pom.xml +++ b/testcontainers-advanced-imagebuilder-dummy-app/pom.xml @@ -6,7 +6,7 @@ software.xdev testcontainers-advanced-imagebuilder-dummy-app - 2.1.2-SNAPSHOT + 2.2.0-SNAPSHOT jar diff --git a/testcontainers-advanced-imagebuilder/pom.xml b/testcontainers-advanced-imagebuilder/pom.xml index 0795ada..c795d05 100644 --- a/testcontainers-advanced-imagebuilder/pom.xml +++ b/testcontainers-advanced-imagebuilder/pom.xml @@ -6,7 +6,7 @@ software.xdev testcontainers-advanced-imagebuilder - 2.1.2-SNAPSHOT + 2.2.0-SNAPSHOT jar testcontainers-advanced-imagebuilder diff --git a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/AdvancedImageFromDockerFile.java b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/AdvancedImageFromDockerFile.java index 5516e48..f35ab4c 100644 --- a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/AdvancedImageFromDockerFile.java +++ b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/AdvancedImageFromDockerFile.java @@ -96,8 +96,8 @@ public class AdvancedImageFromDockerFile StringsTrait, DockerfileTrait { - protected static final Logger LOGGER = LoggerFactory.getLogger(AdvancedImageFromDockerFile.class); protected final String dockerImageName; + protected final Logger defaultLogger; protected final boolean deleteOnExit; protected final Map transferables = new HashMap<>(); @@ -121,6 +121,7 @@ public class AdvancedImageFromDockerFile protected Optional target = Optional.empty(); protected final Set> buildImageCmdModifiers = new LinkedHashSet<>(); protected Set externalDependencyImageNames = Collections.emptySet(); + protected boolean useWinNTFSJunctionFixIfApplicable; @SuppressWarnings("checkstyle:MagicNumber") public AdvancedImageFromDockerFile() @@ -134,9 +135,18 @@ public AdvancedImageFromDockerFile(final String dockerImageName) } public AdvancedImageFromDockerFile(final String dockerImageName, final boolean deleteOnExit) + { + this( + dockerImageName, + deleteOnExit, + LoggerFactory.getLogger(AdvancedImageFromDockerFile.class.getName() + "." + dockerImageName)); + } + + public AdvancedImageFromDockerFile(final String dockerImageName, final boolean deleteOnExit, final Logger logger) { this.dockerImageName = dockerImageName; this.deleteOnExit = deleteOnExit; + this.defaultLogger = logger; } @Override @@ -355,7 +365,8 @@ protected void configure(final BuildImageCmd buildImageCmd) this.preGitIgnoreLines, this.ignoreFileLineFilter, this.postGitIgnoreLines, - alwaysIncludePaths); + alwaysIncludePaths, + this.useWinNTFSJunctionFixIfApplicable); this.log().info( "{}x files will be transferred (determination took {}ms)", @@ -489,7 +500,7 @@ protected boolean canImageNameBePulled(final String imageName) protected Logger log() { - return LOGGER; + return this.defaultLogger; } public AdvancedImageFromDockerFile withBuildArg(final String key, final String value) @@ -599,4 +610,17 @@ public AdvancedImageFromDockerFile withBuildImageCmdModifier(final Consumer + * See {@link software.xdev.testcontainers.imagebuilder.transfer.java.nio.file.winntfs} for details + *

+ */ + public AdvancedImageFromDockerFile withUseWinNTFSJunctionFixIfApplicable( + final boolean useWinNTFSJunctionFixIfApplicable) + { + this.useWinNTFSJunctionFixIfApplicable = useWinNTFSJunctionFixIfApplicable; + return this; + } } diff --git a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/DefaultTransferFilesCreator.java b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/DefaultTransferFilesCreator.java index a28c7a3..c23aa64 100644 --- a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/DefaultTransferFilesCreator.java +++ b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/DefaultTransferFilesCreator.java @@ -82,7 +82,8 @@ public Map determineFilesToTransfer( final Set preGitIgnoreLines, final Predicate ignoreFileLineFilter, final Set postGitIgnoreLines, - final Set alwaysIncludedRelativePaths) + final Set alwaysIncludedRelativePaths, + final boolean useWinNTFSJunctionFixIfApplicable) { try { @@ -100,7 +101,8 @@ public Map determineFilesToTransfer( return this.walkFilesAndDetermineTransfer( ignoreNode, - alwaysIncludedRelativePaths); + alwaysIncludedRelativePaths, + useWinNTFSJunctionFixIfApplicable); } catch(final IOException ioe) { @@ -133,9 +135,11 @@ protected IgnoreNode createIgnoreNode(final Set ignoreLines) protected Map walkFilesAndDetermineTransfer( final IgnoreNode ignoreNode, - final Set alwaysIncludedRelativePaths) throws IOException + final Set alwaysIncludedRelativePaths, + final boolean useWinNTFSJunctionFixIfApplicable) throws IOException { try(final Stream walk = findFiles( + useWinNTFSJunctionFixIfApplicable, this.baseDir, Integer.MAX_VALUE, // Ignore directories @@ -161,13 +165,14 @@ protected Map walkFilesAndDetermineTransfer( } protected static Stream findFiles( + final boolean useWinNTFSJunctionFixIfApplicable, final Path start, final int maxDepth, final BiPredicate matcher, final FileVisitOption... options) throws IOException { - return WinNTFSJunctionFiles.shouldBeApplied(start) + return useWinNTFSJunctionFixIfApplicable && WinNTFSJunctionFiles.shouldBeApplied(start) ? WinNTFSJunctionFiles.find(start, maxDepth, matcher, options) : Files.find(start, maxDepth, matcher, options); } diff --git a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/TransferFilesCreator.java b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/TransferFilesCreator.java index 90c1b10..b764e70 100644 --- a/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/TransferFilesCreator.java +++ b/testcontainers-advanced-imagebuilder/src/main/java/software/xdev/testcontainers/imagebuilder/transfer/TransferFilesCreator.java @@ -28,7 +28,8 @@ Map determineFilesToTransfer( Set preGitIgnoreLines, Predicate ignoreFileLineFilter, Set postGitIgnoreLines, - Set alwaysIncludedRelativePaths); + Set alwaysIncludedRelativePaths, + boolean useWinNTFSJunctionFixIfApplicable); InputStream getAllFilesToTransferAsTarInputStream( Map filesToTransfer, 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 459655c..0a4651d 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 @@ -55,6 +55,9 @@ import java.util.Collection; import java.util.Iterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Walks a file tree, generating a sequence of events corresponding to the files in the tree. @@ -240,43 +243,59 @@ IOException ioeException() } // region Reflect access BasicFileAttributesHolder - private boolean initializedBasicFileAttributesHolderClazz; - private Class basicFileAttributesHolderClazz; - private Method mBasicFileAttributesHolderGet; + private static boolean initializedBasicFileAttributesHolderClazz; + private static Class basicFileAttributesHolderClazz; + private static Method mBasicFileAttributesHolderGet; + private static boolean wasBasicFileAttributesHolderGetAccessSuccess; - private void initBasicFileAttributesHolderClazz() + private static void initBasicFileAttributesHolderClazz() { - if(!this.initializedBasicFileAttributesHolderClazz) + if(!initializedBasicFileAttributesHolderClazz) { try { - this.basicFileAttributesHolderClazz = Class.forName("sun.nio.fs.BasicFileAttributesHolder"); - this.mBasicFileAttributesHolderGet = this.basicFileAttributesHolderClazz.getMethod("get"); - this.mBasicFileAttributesHolderGet.setAccessible(true); + basicFileAttributesHolderClazz = Class.forName("sun.nio.fs.BasicFileAttributesHolder"); + mBasicFileAttributesHolderGet = basicFileAttributesHolderClazz.getMethod("get"); + mBasicFileAttributesHolderGet.setAccessible(true); } catch(final Exception ignored) { // Ignored } - this.initializedBasicFileAttributesHolderClazz = true; + initializedBasicFileAttributesHolderClazz = true; } } - private boolean isBasicFileAttributesHolder(final Path file) + private static boolean isBasicFileAttributesHolder(final Path file) { - this.initBasicFileAttributesHolderClazz(); + initBasicFileAttributesHolderClazz(); - return this.basicFileAttributesHolderClazz != null - && this.basicFileAttributesHolderClazz.isInstance(file); + return basicFileAttributesHolderClazz != null + && basicFileAttributesHolderClazz.isInstance(file); } - private BasicFileAttributes extractFromBasicFileAttributesHolder(final Path file) + private static BasicFileAttributes extractFromBasicFileAttributesHolder(final Path file) { try { - return (BasicFileAttributes)this.mBasicFileAttributesHolderGet.invoke(file); + final BasicFileAttributes attrs = (BasicFileAttributes)mBasicFileAttributesHolderGet.invoke(file); + wasBasicFileAttributesHolderGetAccessSuccess = true; + return attrs; + } + catch(final IllegalAccessException ex) + { + // Did we ever access it successfully? + if(!wasBasicFileAttributesHolderGetAccessSuccess) + { + basicFileAttributesHolderClazz = null; + mBasicFileAttributesHolderGet = null; + final Logger logger = LoggerFactory.getLogger(FileTreeWalker.class); + logger.warn("Failed to access BasicFileAttributesHolder", ex); + logger.warn("To fix this add '--add-exports java.base/sun.nio.fs=ALL-UNNAMED' as VM options"); + } + return null; } - catch(final IllegalAccessException | InvocationTargetException ignored) + catch(final InvocationTargetException ignored) { return null; } 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 cade447..1774ed0 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 @@ -18,6 +18,11 @@ * * 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 + *

* * @see NTFS junction */