Skip to content

Commit 1a75e20

Browse files
committed
Modify zip/jar archivers to add entries synchronously when needed
1 parent 59c7470 commit 1a75e20

File tree

5 files changed

+58
-14
lines changed

5 files changed

+58
-14
lines changed

src/main/java/org/codehaus/plexus/archiver/jar/JarArchiver.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ private void writeManifest( ConcurrentJarCreator zOut, Manifest manifest )
333333

334334
ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
335335
super.zipFile( createInputStreamSupplier( bais ), zOut, MANIFEST_NAME, System.currentTimeMillis(), null,
336-
DEFAULT_FILE_MODE, null );
336+
DEFAULT_FILE_MODE, null, false );
337337
super.initZipOutputStream( zOut );
338338
}
339339

@@ -435,15 +435,15 @@ private void createIndexList( ConcurrentJarCreator zOut )
435435
ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
436436

437437
super.zipFile( createInputStreamSupplier( bais ), zOut, INDEX_NAME, System.currentTimeMillis(), null,
438-
DEFAULT_FILE_MODE, null );
438+
DEFAULT_FILE_MODE, null, true );
439439
}
440440

441441
/**
442442
* Overridden from Zip class to deal with manifests and index lists.
443443
*/
444444
protected void zipFile( InputStreamSupplier is, ConcurrentJarCreator zOut, String vPath,
445445
long lastModified, File fromArchive,
446-
int mode, String symlinkDestination )
446+
int mode, String symlinkDestination, boolean addInParallel )
447447
throws IOException, ArchiverException
448448
{
449449
if ( MANIFEST_NAME.equalsIgnoreCase( vPath ) )
@@ -464,7 +464,7 @@ else if ( INDEX_NAME.equalsIgnoreCase( vPath ) && index )
464464
{
465465
rootEntries.addElement( vPath );
466466
}
467-
super.zipFile( is, zOut, vPath, lastModified, fromArchive, mode, symlinkDestination );
467+
super.zipFile( is, zOut, vPath, lastModified, fromArchive, mode, symlinkDestination, addInParallel );
468468
}
469469
}
470470

src/main/java/org/codehaus/plexus/archiver/zip/AbstractZipArchiver.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,14 @@ private void addParentDirs(ArchiveEntry archiveEntry, File baseDir, String entry
421421
* @param lastModified last modification time for the entry.
422422
* @param fromArchive the original archive we are copying this
423423
* @param symlinkDestination
424+
* @param addInParallel Indicates if the entry should be add in parallel.
425+
* If set to {@code false} it is added synchronously.
426+
* If the entry is symbolic link this parameter is ignored.
424427
*/
425428
@SuppressWarnings( { "JavaDoc" } )
426429
protected void zipFile( InputStreamSupplier in, ConcurrentJarCreator zOut, String vPath,
427430
long lastModified,
428-
File fromArchive, int mode, String symlinkDestination )
431+
File fromArchive, int mode, String symlinkDestination, boolean addInParallel )
429432
throws IOException, ArchiverException
430433
{
431434
getLogger().debug( "adding entry " + vPath );
@@ -446,11 +449,11 @@ protected void zipFile( InputStreamSupplier in, ConcurrentJarCreator zOut, Strin
446449
ZipEncoding enc = ZipEncodingHelper.getZipEncoding( getEncoding() );
447450
final byte[] bytes = enc.encode( symlinkDestination ).array();
448451
payload = new ByteArrayInputStream( bytes );
449-
zOut.addArchiveEntry( ze, createInputStreamSupplier( payload ) );
452+
zOut.addArchiveEntry( ze, createInputStreamSupplier( payload ), true );
450453
}
451454
else
452455
{
453-
zOut.addArchiveEntry( ze, wrappedRecompressor( ze, in ) );
456+
zOut.addArchiveEntry( ze, wrappedRecompressor( ze, in ), addInParallel );
454457
}
455458
}
456459
}
@@ -502,7 +505,8 @@ public InputStream get()
502505
};
503506
try
504507
{
505-
zipFile( in, zOut, vPath, resource.getLastModified(), null, entry.getMode(), symlinkTarget );
508+
zipFile( in, zOut, vPath, resource.getLastModified(), null, entry.getMode(), symlinkTarget,
509+
!entry.shouldAddSynchronously() );
506510
}
507511
catch ( IOException e )
508512
{
@@ -583,15 +587,15 @@ protected void zipDir( PlexusIoResource dir, ConcurrentJarCreator zOut, String v
583587

584588
if ( !isSymlink )
585589
{
586-
zOut.addArchiveEntry( ze, createInputStreamSupplier( new ByteArrayInputStream( "".getBytes() ) ) );
590+
zOut.addArchiveEntry( ze, createInputStreamSupplier( new ByteArrayInputStream( "".getBytes() ) ), true );
587591
}
588592
else
589593
{
590594
String symlinkDestination = ( (SymlinkDestinationSupplier) dir ).getSymlinkDestination();
591595
ZipEncoding enc = ZipEncodingHelper.getZipEncoding( encodingToUse );
592596
final byte[] bytes = enc.encode( symlinkDestination ).array();
593597
ze.setMethod( ZipArchiveEntry.DEFLATED );
594-
zOut.addArchiveEntry( ze, createInputStreamSupplier( new ByteArrayInputStream( bytes ) ) );
598+
zOut.addArchiveEntry( ze, createInputStreamSupplier( new ByteArrayInputStream( bytes ) ), true );
595599
}
596600
}
597601
}

src/main/java/org/codehaus/plexus/archiver/zip/ConcurrentJarCreator.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public class ConcurrentJarCreator {
3737
private final ScatterZipOutputStream directories;
3838
private final ScatterZipOutputStream metaInfDir;
3939
private final ScatterZipOutputStream manifest;
40+
private final ScatterZipOutputStream synchronousEntries;
4041

4142
private final ParallelScatterZipCreator parallelScatterZipCreator;
4243
private long zipCloseElapsed;
@@ -61,6 +62,7 @@ public ConcurrentJarCreator(int nThreads) throws IOException {
6162
directories = createDeferred(defaultSupplier);
6263
manifest = createDeferred(defaultSupplier);
6364
metaInfDir = createDeferred( defaultSupplier );
65+
synchronousEntries = createDeferred( defaultSupplier );
6466

6567
parallelScatterZipCreator = new ParallelScatterZipCreator(Executors.newFixedThreadPool(nThreads), defaultSupplier);
6668
}
@@ -72,10 +74,12 @@ public ConcurrentJarCreator(int nThreads) throws IOException {
7274
*
7375
* @param zipArchiveEntry The entry to add. Compression method
7476
* @param source The source input stream supplier
77+
* @param addInParallel Indicates if the entry should be add in parallel.
78+
* If set to {@code false} the entry is added synchronously.
7579
* @throws java.io.IOException
7680
*/
77-
78-
public void addArchiveEntry(final ZipArchiveEntry zipArchiveEntry, final InputStreamSupplier source) throws IOException {
81+
public void addArchiveEntry(final ZipArchiveEntry zipArchiveEntry, final InputStreamSupplier source,
82+
final boolean addInParallel) throws IOException {
7983
final int method = zipArchiveEntry.getMethod();
8084
if (method == -1) throw new IllegalArgumentException("Method must be set on the supplied zipArchiveEntry");
8185
if (zipArchiveEntry.isDirectory() && !zipArchiveEntry.isUnixSymlink()) {
@@ -93,8 +97,10 @@ public void addArchiveEntry(final ZipArchiveEntry zipArchiveEntry, final InputSt
9397
if (zipArchiveEntry.isDirectory()) zipArchiveEntry.setMethod(ZipEntry.STORED);
9498
manifest.addArchiveEntry(createZipArchiveEntryRequest(zipArchiveEntry, createInputStreamSupplier(payload)));
9599
payload.close();
96-
} else {
100+
} else if (addInParallel) {
97101
parallelScatterZipCreator.addArchiveEntry(zipArchiveEntry, source);
102+
} else {
103+
synchronousEntries.addArchiveEntry( createZipArchiveEntryRequest( zipArchiveEntry, source ) );
98104
}
99105
}
100106

@@ -110,12 +116,14 @@ public void writeTo(ZipArchiveOutputStream targetStream) throws IOException, Exe
110116
metaInfDir.writeTo( targetStream );
111117
manifest.writeTo(targetStream);
112118
directories.writeTo(targetStream);
119+
synchronousEntries.writeTo( targetStream );
113120
parallelScatterZipCreator.writeTo( targetStream);
114121
long startAt = System.currentTimeMillis();
115122
targetStream.close();
116123
zipCloseElapsed = System.currentTimeMillis() - startAt;
117124
manifest.close();
118125
directories.close();
126+
synchronousEntries.close();
119127
}
120128

121129
/**

src/test/java/org/codehaus/plexus/archiver/zip/ConcurrentJarCreatorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public InputStream get() {
7575
throw new RuntimeException(e);
7676
}
7777
}
78-
});
78+
}, true);
7979
}
8080

8181
}

src/test/java/org/codehaus/plexus/archiver/zip/ZipArchiverTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import org.codehaus.plexus.archiver.BasePlexusArchiverTest;
3535
import org.codehaus.plexus.archiver.UnArchiver;
3636
import org.codehaus.plexus.archiver.UnixStat;
37+
import org.codehaus.plexus.archiver.tar.TarArchiver;
38+
import org.codehaus.plexus.archiver.tar.TarFile;
3739
import org.codehaus.plexus.archiver.util.ArchiveEntryUtils;
3840
import org.codehaus.plexus.archiver.util.DefaultArchivedFileSet;
3941
import org.codehaus.plexus.archiver.util.DefaultFileSet;
@@ -675,6 +677,36 @@ public void testCreateResourceCollection()
675677
cmp2.close();
676678
}
677679

680+
public void testZipNonConcurrentResourceCollection()
681+
throws Exception
682+
{
683+
final File tarFile = getTestFile( "target/output/zip-non-concurrent.tar" );
684+
TarArchiver tarArchiver = (TarArchiver) lookup( Archiver.ROLE, "tar" );
685+
tarArchiver.setDestFile( tarFile );
686+
// We're testing concurrency issue so we need large amount of files
687+
for (int i = 0; i < 100; i++)
688+
{
689+
tarArchiver.addFile( getTestFile( "src/test/resources/manifests/manifest1.mf" ),
690+
"manifest1.mf" + i );
691+
// Directories are added separately so let's test them too
692+
tarArchiver.addFile( getTestFile( "src/test/resources/manifests/manifest2.mf" ),
693+
"subdir" + i + "/manifest2.mf" );
694+
}
695+
tarArchiver.createArchive();
696+
697+
final File zipFile = new File( "target/output/zip-non-concurrent.zip" );
698+
ZipArchiver zipArchive = getZipArchiver( zipFile );
699+
zipArchive.addArchivedFileSet( tarFile, "prfx/" );
700+
zipArchive.setEncoding( "UTF-8" );
701+
zipArchive.createArchive();
702+
703+
final TarFile cmp1 = new TarFile( tarFile );
704+
final ZipFile cmp2 = new ZipFile( zipFile );
705+
ArchiveFileComparator.assertEquals( cmp1, cmp2, "prfx/" );
706+
cmp1.close();
707+
cmp2.close();
708+
}
709+
678710
public void testDefaultUTF8()
679711
throws IOException
680712
{

0 commit comments

Comments
 (0)