diff --git a/io/src/main/java/io/smallrye/common/io/archive/ArchiveBuilder.java b/io/src/main/java/io/smallrye/common/io/archive/ArchiveBuilder.java index f9756995..cd8a2413 100644 --- a/io/src/main/java/io/smallrye/common/io/archive/ArchiveBuilder.java +++ b/io/src/main/java/io/smallrye/common/io/archive/ArchiveBuilder.java @@ -1221,7 +1221,8 @@ public ArchiveBuilder addArchive(String name) throws IOException { * or the outer builder can be closed. *
* {@link ZipOption#ZIP64} applies to the outer entry (reserving ZIP64 space in the outer local - * file header). The inner builder inherits the same options as its defaults. + * file header). The inner builder inherits the same options as its defaults, with the exception of + * {@link ZipOption#ALLOW_DUPLICATE_ENTRIES}. * * @param name the entry name for the nested archive (must not be {@code null}) * @param options the options; may contain {@link ZipOption} values @@ -1272,7 +1273,8 @@ public ArchiveBuilder addArchive(String name, FileAttribute>... attrs) throws * or the outer builder can be closed. *
* {@link ZipOption#ZIP64} applies to the outer entry (reserving ZIP64 space in the outer local - * file header). The inner builder inherits the same options as its defaults. + * file header). The inner builder inherits the same options as its defaults, with the exception of + * {@link ZipOption#ALLOW_DUPLICATE_ENTRIES}. * {@link ZipOption#DEFLATED} is permitted here (unlike {@code addBufferedEntry}) and sets * the inner builder's default compression method; the outer entry is always STORED. *
@@ -1307,7 +1309,7 @@ public ArchiveBuilder addArchive(String name, Collection extends OpenOption> o // which triggers the close action for CRC/LFH patching on the outer entry return new ArchiveBuilder(nested, nested.filePosition(), innerMethod == PARSED_NO_METHOD ? METHOD_DEFLATE : innerMethod, zip64, - (parsed & PARSED_ALLOW_DUPLICATE_ENTRIES) != 0 || allowDuplicateEntries); + (parsed & PARSED_ALLOW_DUPLICATE_ENTRIES) != 0); } // ── Raw data methods ──────────────────────────────────────────────── diff --git a/io/src/test/java/io/smallrye/common/io/archive/ArchiveBuilderTests.java b/io/src/test/java/io/smallrye/common/io/archive/ArchiveBuilderTests.java index 1b832773..0859019f 100644 --- a/io/src/test/java/io/smallrye/common/io/archive/ArchiveBuilderTests.java +++ b/io/src/test/java/io/smallrye/common/io/archive/ArchiveBuilderTests.java @@ -2072,4 +2072,33 @@ public void testDuplicateNestedArchiveBlockedByDefault() throws Exception { }); } } + + /** + * Test that {@link ZipOption#ALLOW_DUPLICATE_ENTRIES} is not inherited by a nested archive, + * but can be specified explicitly on the nested archive if desired. + * + * @throws Exception if an unexpected error occurs + */ + @Test + public void testDuplicateOptionNotInheritedByNestedArchive() throws Exception { + Path file = tempDir.resolve("duplicate-nested-not-inherited.zip"); + // Outer archive has duplicates allowed + try (ArchiveBuilder builder = ArchiveBuilder.open(file, ZipOption.ALLOW_DUPLICATE_ENTRIES)) { + // Nested archive does NOT have duplicate options specified, so it should NOT allow duplicates + try (ArchiveBuilder inner = builder.addArchive("inner1.jar")) { + inner.addEntry("foo.txt", "foo".getBytes(StandardCharsets.UTF_8)); + assertThrows(IllegalArgumentException.class, () -> { + inner.addEntry("foo.txt", "bar".getBytes(StandardCharsets.UTF_8)); + }); + } + + // Nested archive explicitly has duplicate options specified, so it should allow duplicates + try (ArchiveBuilder inner = builder.addArchive("inner2.jar", ZipOption.ALLOW_DUPLICATE_ENTRIES)) { + inner.addEntry("foo.txt", "foo".getBytes(StandardCharsets.UTF_8)); + assertDoesNotThrow(() -> { + inner.addEntry("foo.txt", "bar".getBytes(StandardCharsets.UTF_8)); + }); + } + } + } }