From 1d2b764d48e21316942ed3805a1aa8b79650302a Mon Sep 17 00:00:00 2001 From: Michael Osipov <1983-01-06@gmx.net> Date: Sun, 19 Dec 2021 14:58:04 +0100 Subject: [PATCH] Respect the order entries in a JAR file The insertion order did not take into account that META-INF/ and/or META-INF/MANIFEST.MF can or should come first. The code has added it META-INF/ to directories, thus the actual order of a JAR file was: META-INF/MANIFEST.MF META-INF/ META-INF/maven which does not make sense. Test supplied by: Plamen Totev This closes #189 --- .../archiver/zip/ConcurrentJarCreator.java | 34 ++++++++++--------- .../archiver/jar/BaseJarArchiverTest.java | 9 +++-- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/codehaus/plexus/archiver/zip/ConcurrentJarCreator.java b/src/main/java/org/codehaus/plexus/archiver/zip/ConcurrentJarCreator.java index a0b37a58c..3a1c0f81d 100644 --- a/src/main/java/org/codehaus/plexus/archiver/zip/ConcurrentJarCreator.java +++ b/src/main/java/org/codehaus/plexus/archiver/zip/ConcurrentJarCreator.java @@ -44,12 +44,12 @@ public class ConcurrentJarCreator private final boolean compressAddedZips; - private final ScatterZipOutputStream directories; - private final ScatterZipOutputStream metaInfDir; private final ScatterZipOutputStream manifest; + private final ScatterZipOutputStream directories; + private final ScatterZipOutputStream synchronousEntries; private final ParallelScatterZipCreator parallelScatterZipCreator; @@ -123,9 +123,9 @@ public ConcurrentJarCreator( boolean compressAddedZips, int nThreads ) throws IO { this.compressAddedZips = compressAddedZips; ScatterGatherBackingStoreSupplier defaultSupplier = new DeferredSupplier( 100000000 / nThreads ); - directories = createDeferred( defaultSupplier ); - manifest = createDeferred( defaultSupplier ); metaInfDir = createDeferred( defaultSupplier ); + manifest = createDeferred( defaultSupplier ); + directories = createDeferred( defaultSupplier ); synchronousEntries = createDeferred( defaultSupplier ); parallelScatterZipCreator = new ParallelScatterZipCreator( Executors.newFixedThreadPool( nThreads ), defaultSupplier ); @@ -152,20 +152,10 @@ public void addArchiveEntry( final ZipArchiveEntry zipArchiveEntry, final InputS { throw new IllegalArgumentException( "Method must be set on the supplied zipArchiveEntry" ); } - if ( zipArchiveEntry.isDirectory() && !zipArchiveEntry.isUnixSymlink() ) - { - final ByteArrayInputStream payload = new ByteArrayInputStream( new byte[] - { - } ); - - directories.addArchiveEntry( createZipArchiveEntryRequest( zipArchiveEntry, createInputStreamSupplier( - payload ) ) ); - - payload.close(); - } - else if ( "META-INF".equals( zipArchiveEntry.getName() ) || "META-INF/".equals( zipArchiveEntry.getName() ) ) + if ( "META-INF".equals( zipArchiveEntry.getName() ) || "META-INF/".equals( zipArchiveEntry.getName() ) ) { InputStream payload = source.get(); + // TODO This should be enforced because META-INF non-directory does not make any sense?! if ( zipArchiveEntry.isDirectory() ) { zipArchiveEntry.setMethod( ZipEntry.STORED ); @@ -178,6 +168,7 @@ else if ( "META-INF".equals( zipArchiveEntry.getName() ) || "META-INF/".equals( else if ( "META-INF/MANIFEST.MF".equals( zipArchiveEntry.getName() ) ) { InputStream payload = source.get(); + // TODO This should be enforced because META-INF/MANIFEST as non-file does not make any sense?! if ( zipArchiveEntry.isDirectory() ) { zipArchiveEntry.setMethod( ZipEntry.STORED ); @@ -187,6 +178,17 @@ else if ( "META-INF/MANIFEST.MF".equals( zipArchiveEntry.getName() ) ) payload.close(); } + else if ( zipArchiveEntry.isDirectory() && !zipArchiveEntry.isUnixSymlink() ) + { + final ByteArrayInputStream payload = new ByteArrayInputStream( new byte[] + { + } ); + + directories.addArchiveEntry( createZipArchiveEntryRequest( zipArchiveEntry, createInputStreamSupplier( + payload ) ) ); + + payload.close(); + } else if ( addInParallel ) { parallelScatterZipCreator.addArchiveEntry( createEntrySupplier( zipArchiveEntry, source ) ); diff --git a/src/test/java/org/codehaus/plexus/archiver/jar/BaseJarArchiverTest.java b/src/test/java/org/codehaus/plexus/archiver/jar/BaseJarArchiverTest.java index abf0d582a..c76b842dd 100644 --- a/src/test/java/org/codehaus/plexus/archiver/jar/BaseJarArchiverTest.java +++ b/src/test/java/org/codehaus/plexus/archiver/jar/BaseJarArchiverTest.java @@ -26,9 +26,11 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -55,8 +57,11 @@ public void testCreateJar() // verify that the JAR file is created and contains the expected files try ( ZipFile resultingArchive = new ZipFile( jarFile ) ) { - // verify that the JAR file contains manifest file - assertNotNull( resultingArchive.getEntry( "META-INF/MANIFEST.MF" ) ); + // verify that the JAR file contains manifest directory and file + // and that those are the first two entries. + Enumeration resultingEntries = resultingArchive.entries(); + assertEquals( "META-INF/", resultingEntries.nextElement().getName() ); + assertEquals( "META-INF/MANIFEST.MF", resultingEntries.nextElement().getName() ); // verify the JAR contains the class and it is not corrupted ZipEntry classFileEntry = resultingArchive.getEntry( "com/example/app/Main.class" );