diff --git a/pom.xml b/pom.xml
index 3376419fc..caf778d61 100644
--- a/pom.xml
+++ b/pom.xml
@@ -97,6 +97,12 @@
1.9
runtime
+
+ com.github.luben
+ zstd-jni
+ 1.5.2-3
+ runtime
+
com.google.code.findbugs
jsr305
diff --git a/src/main/java/org/codehaus/plexus/archiver/manager/DefaultArchiverManager.java b/src/main/java/org/codehaus/plexus/archiver/manager/DefaultArchiverManager.java
index 5eea03035..884fd2dbe 100644
--- a/src/main/java/org/codehaus/plexus/archiver/manager/DefaultArchiverManager.java
+++ b/src/main/java/org/codehaus/plexus/archiver/manager/DefaultArchiverManager.java
@@ -110,6 +110,7 @@ String getFileExtention( @Nonnull File file )
if ( "gz".equals( archiveExt )
|| "bz2".equals( archiveExt )
|| "xz".equals( archiveExt )
+ || "zst".equals( archiveExt )
|| "snappy".equals( archiveExt ) )
{
String[] tokens = StringUtils.split( path, "." );
diff --git a/src/main/java/org/codehaus/plexus/archiver/tar/PlexusIoTarZstdFileResourceCollection.java b/src/main/java/org/codehaus/plexus/archiver/tar/PlexusIoTarZstdFileResourceCollection.java
new file mode 100644
index 000000000..aa084c10d
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/archiver/tar/PlexusIoTarZstdFileResourceCollection.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2022 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.plexus.archiver.tar;
+
+import javax.inject.Named;
+import java.io.File;
+
+/**
+ * Alias for {@link PlexusIoTarFileResourceCollection}
+ */
+@Named( "tar.zst" )
+public class PlexusIoTarZstdFileResourceCollection extends PlexusIoTarFileResourceCollection
+{
+
+ public PlexusIoTarZstdFileResourceCollection()
+ {
+ }
+
+ @Override
+ protected TarFile newTarFile( File file )
+ {
+ return new ZstdTarFile( file );
+ }
+
+}
diff --git a/src/main/java/org/codehaus/plexus/archiver/tar/TarArchiver.java b/src/main/java/org/codehaus/plexus/archiver/tar/TarArchiver.java
index 8166a1f35..f63e0e5f4 100644
--- a/src/main/java/org/codehaus/plexus/archiver/tar/TarArchiver.java
+++ b/src/main/java/org/codehaus/plexus/archiver/tar/TarArchiver.java
@@ -31,6 +31,7 @@
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
+import org.apache.commons.compress.compressors.zstandard.ZstdCompressorOutputStream;
import org.codehaus.plexus.archiver.AbstractArchiver;
import org.codehaus.plexus.archiver.ArchiveEntry;
import org.codehaus.plexus.archiver.ArchiverException;
@@ -484,7 +485,8 @@ public enum TarCompressionMethod
gzip,
bzip2,
snappy,
- xz
+ xz,
+ zstd
}
@@ -507,6 +509,10 @@ else if ( TarCompressionMethod.xz.equals( tarCompressionMethod ) )
{
return new XZCompressorOutputStream( bufferedOutputStream( ostream ) );
}
+ else if ( TarCompressionMethod.zstd.equals( tarCompressionMethod ) )
+ {
+ return new ZstdCompressorOutputStream( bufferedOutputStream( ostream ) );
+ }
return ostream;
}
diff --git a/src/main/java/org/codehaus/plexus/archiver/tar/TarUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/tar/TarUnArchiver.java
index 9e68cfdf3..d88c3dd11 100644
--- a/src/main/java/org/codehaus/plexus/archiver/tar/TarUnArchiver.java
+++ b/src/main/java/org/codehaus/plexus/archiver/tar/TarUnArchiver.java
@@ -30,6 +30,7 @@
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
+import org.apache.commons.compress.compressors.zstandard.ZstdCompressorInputStream;
import org.codehaus.plexus.archiver.AbstractUnArchiver;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.util.Streams;
@@ -159,6 +160,10 @@ else if ( compression == UntarCompressionMethod.XZ )
{
return new XZCompressorInputStream( istream );
}
+ else if ( compression == UntarCompressionMethod.ZSTD )
+ {
+ return new ZstdCompressorInputStream( istream );
+ }
return istream;
}
@@ -172,7 +177,8 @@ public enum UntarCompressionMethod
GZIP( "gzip" ),
BZIP2( "bzip2" ),
SNAPPY( "snappy" ),
- XZ( "xz" );
+ XZ( "xz" ),
+ ZSTD( "zstd" );
final String value;
diff --git a/src/main/java/org/codehaus/plexus/archiver/tar/TarZstdUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/tar/TarZstdUnArchiver.java
new file mode 100644
index 000000000..b144ccfcc
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/archiver/tar/TarZstdUnArchiver.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2022 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.plexus.archiver.tar;
+
+import javax.inject.Named;
+import java.io.File;
+
+/**
+ * Extract files in tar with zstd compression
+ */
+@Named( "tar.zst" )
+public class TarZstdUnArchiver extends TarUnArchiver
+{
+
+ public TarZstdUnArchiver()
+ {
+ setupCompressionMethod();
+ }
+
+ public TarZstdUnArchiver( File sourceFile )
+ {
+ super( sourceFile );
+
+ setupCompressionMethod();
+ }
+
+ private final void setupCompressionMethod()
+ {
+ setCompression( UntarCompressionMethod.ZSTD );
+ }
+
+}
diff --git a/src/main/java/org/codehaus/plexus/archiver/tar/ZstdTarFile.java b/src/main/java/org/codehaus/plexus/archiver/tar/ZstdTarFile.java
new file mode 100644
index 000000000..9a65686c8
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/archiver/tar/ZstdTarFile.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2022 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.plexus.archiver.tar;
+
+import org.codehaus.plexus.archiver.zstd.ZstdUnArchiver;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Extension of {@link org.codehaus.plexus.archiver.tar.TarFile} for zst compressed files.
+ */
+public class ZstdTarFile extends TarFile
+{
+
+ public ZstdTarFile( File file )
+ {
+ super( file );
+ }
+
+ @Override
+ protected InputStream getInputStream( File file ) throws IOException
+ {
+ return ZstdUnArchiver.getZstdInputStream( super.getInputStream( file ) );
+ }
+
+}
diff --git a/src/main/java/org/codehaus/plexus/archiver/zstd/PlexusIoZstdResourceCollection.java b/src/main/java/org/codehaus/plexus/archiver/zstd/PlexusIoZstdResourceCollection.java
new file mode 100644
index 000000000..84a9d0e62
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/archiver/zstd/PlexusIoZstdResourceCollection.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2022 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.plexus.archiver.zstd;
+
+import javax.inject.Named;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+
+import org.codehaus.plexus.archiver.util.Streams;
+import org.codehaus.plexus.components.io.attributes.FileAttributes;
+import org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributes;
+import org.codehaus.plexus.components.io.resources.PlexusIoCompressedFileResourceCollection;
+
+/**
+ * Implementation of {@link org.codehaus.plexus.components.io.resources.PlexusIoResourceCollection} for
+ * zstd compressed files.
+ */
+@Named( "zst" )
+public class PlexusIoZstdResourceCollection extends PlexusIoCompressedFileResourceCollection
+{
+
+ @Override
+ protected PlexusIoResourceAttributes getAttributes( File file ) throws IOException
+ {
+ return new FileAttributes( file, new HashMap(), new HashMap() );
+ }
+
+ @Override
+ protected String getDefaultExtension()
+ {
+ return ".zst";
+ }
+
+ @Override
+ protected InputStream getInputStream( File file ) throws IOException
+ {
+ return ZstdUnArchiver.getZstdInputStream( Streams.fileInputStream( file ) );
+ }
+
+}
diff --git a/src/main/java/org/codehaus/plexus/archiver/zstd/ZstdArchiver.java b/src/main/java/org/codehaus/plexus/archiver/zstd/ZstdArchiver.java
new file mode 100644
index 000000000..f2484d746
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/archiver/zstd/ZstdArchiver.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2022 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.plexus.archiver.zstd;
+
+import javax.inject.Named;
+
+import java.io.IOException;
+import org.codehaus.plexus.archiver.AbstractArchiver;
+import org.codehaus.plexus.archiver.ArchiveEntry;
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.archiver.ResourceIterator;
+import org.codehaus.plexus.archiver.exceptions.EmptyArchiveException;
+
+/**
+ * Zstd archiver.
+ */
+@Named( "zst" )
+public class ZstdArchiver extends AbstractArchiver
+{
+
+ private final ZstdCompressor compressor = new ZstdCompressor();
+
+ public ZstdArchiver()
+ {
+ }
+
+ /**
+ * Set compression level
+ */
+ public void setLevel( Integer level )
+ throws ArchiverException
+ {
+ compressor.setLevel( level );
+ }
+
+ @Override
+ protected void execute() throws ArchiverException, IOException
+ {
+ if ( !checkForced() )
+ {
+ return;
+ }
+
+ ResourceIterator iter = getResources();
+ if ( !iter.hasNext() )
+ {
+ throw new EmptyArchiveException( "archive cannot be empty" );
+ }
+ ArchiveEntry entry = iter.next();
+ if ( iter.hasNext() )
+ {
+ throw new ArchiverException( "There is more than one file in input." );
+ }
+ compressor.setSource( entry.getResource() );
+ compressor.setDestFile( getDestFile() );
+ compressor.compress();
+ }
+
+ @Override
+ public boolean isSupportingForced()
+ {
+ return true;
+ }
+
+ @Override
+ protected void close() throws IOException
+ {
+ compressor.close();
+ }
+
+ @Override
+ protected String getArchiveType()
+ {
+ return "zstd";
+ }
+
+}
diff --git a/src/main/java/org/codehaus/plexus/archiver/zstd/ZstdCompressor.java b/src/main/java/org/codehaus/plexus/archiver/zstd/ZstdCompressor.java
new file mode 100644
index 000000000..4dc06d2ea
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/archiver/zstd/ZstdCompressor.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2022 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.plexus.archiver.zstd;
+
+import org.apache.commons.compress.compressors.zstandard.ZstdCompressorOutputStream;
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.archiver.util.Compressor;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+
+import static org.codehaus.plexus.archiver.util.Streams.bufferedOutputStream;
+import static org.codehaus.plexus.archiver.util.Streams.fileOutputStream;
+
+/**
+ * Zstd compression
+ */
+public class ZstdCompressor extends Compressor
+{
+
+ private Integer level;
+
+ private ZstdCompressorOutputStream zstdOut;
+
+ public ZstdCompressor()
+ {
+ }
+
+ public void setLevel( Integer level )
+ {
+ this.level = level;
+ }
+
+ @Override
+ public void compress() throws ArchiverException
+ {
+ try
+ {
+ BufferedOutputStream outStream = bufferedOutputStream( fileOutputStream( getDestFile() ) );
+ if (level == null)
+ {
+ zstdOut = new ZstdCompressorOutputStream( outStream );
+ }
+ else
+ {
+ zstdOut = new ZstdCompressorOutputStream( outStream, level );
+ }
+ compress( getSource(), zstdOut);
+ }
+ catch ( IOException ioe )
+ {
+ throw new ArchiverException( "Problem creating zstd " + ioe.getMessage(), ioe );
+ }
+ }
+
+ @Override
+ public void close()
+ {
+ try
+ {
+ if ( this.zstdOut != null )
+ {
+ this.zstdOut.close();
+ zstdOut = null;
+ }
+ }
+ catch ( final IOException e )
+ {
+ throw new ArchiverException( "Failure closing target.", e );
+ }
+ }
+
+}
diff --git a/src/main/java/org/codehaus/plexus/archiver/zstd/ZstdUnArchiver.java b/src/main/java/org/codehaus/plexus/archiver/zstd/ZstdUnArchiver.java
new file mode 100644
index 000000000..7dcf6c1f5
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/archiver/zstd/ZstdUnArchiver.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2022 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.plexus.archiver.zstd;
+
+import org.apache.commons.compress.compressors.zstandard.ZstdCompressorInputStream;
+import org.codehaus.plexus.archiver.AbstractUnArchiver;
+import org.codehaus.plexus.archiver.ArchiverException;
+
+import javax.annotation.Nonnull;
+import javax.inject.Named;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.codehaus.plexus.archiver.util.Streams.bufferedInputStream;
+import static org.codehaus.plexus.archiver.util.Streams.bufferedOutputStream;
+import static org.codehaus.plexus.archiver.util.Streams.copyFully;
+import static org.codehaus.plexus.archiver.util.Streams.fileInputStream;
+import static org.codehaus.plexus.archiver.util.Streams.fileOutputStream;
+
+/**
+ * Unarchiver for zstd-compressed files.
+ */
+@Named( "zst" )
+public class ZstdUnArchiver extends AbstractUnArchiver
+{
+
+ private static final String OPERATION_ZSTD = "zstd";
+
+ public ZstdUnArchiver()
+ {
+ }
+
+ public ZstdUnArchiver( File source )
+ {
+ super( source );
+ }
+
+ @Override
+ protected void execute() throws ArchiverException
+ {
+ if ( getSourceFile().lastModified() > getDestFile().lastModified() )
+ {
+ getLogger().info( "Expanding " + getSourceFile().getAbsolutePath() + " to "
+ + getDestFile().getAbsolutePath() );
+
+ copyFully( getZstdInputStream( bufferedInputStream( fileInputStream( getSourceFile(), OPERATION_ZSTD) ) ),
+ bufferedOutputStream( fileOutputStream( getDestFile(), OPERATION_ZSTD) ), OPERATION_ZSTD);
+
+ }
+ }
+
+ public static @Nonnull
+ ZstdCompressorInputStream getZstdInputStream( InputStream in )
+ throws ArchiverException
+ {
+ try
+ {
+ return new ZstdCompressorInputStream( in );
+ }
+ catch ( IOException ioe )
+ {
+ throw new ArchiverException( "Trouble creating Zstd compressor, invalid file ?", ioe );
+ }
+ }
+
+ @Override
+ protected void execute( String path, File outputDirectory ) throws ArchiverException
+ {
+ throw new UnsupportedOperationException( "Targeted execution not supported in zstd format" );
+ }
+
+}
diff --git a/src/site/apt/index.apt b/src/site/apt/index.apt
index 747c47982..f12f3c60a 100644
--- a/src/site/apt/index.apt
+++ b/src/site/apt/index.apt
@@ -24,6 +24,7 @@ Plexus Archiver
| | {{{./xref/org/codehaus/plexus/archiver/jar/JarArchiver.html}<<>>}},
| | {{{./xref/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiver.html}<<>>}},
| | {{{./xref/org/codehaus/plexus/archiver/snappy/SnappyArchiver.html}<<>>}},
+| | {{{./xref/org/codehaus/plexus/archiver/zstandard/ZstdArchiver.html}<<>>}},
| | {{{./xref/org/codehaus/plexus/archiver/tar/TarArchiver.html}<<>>}},
| | {{{./xref/org/codehaus/plexus/archiver/war/WarArchiver.html}<<>>}},
| | {{{./xref/org/codehaus/plexus/archiver/zip/ZipArchiver.html}<<>>}}.
@@ -34,11 +35,13 @@ Plexus Archiver
| | {{{./xref/org/codehaus/plexus/archiver/xz.XZUnArchiver.html}<<>>}},
| | {{{./xref/org/codehaus/plexus/archiver/gzip.GZipUnArchiver.html}<<>>}},
| | {{{./xref/org/codehaus/plexus/archiver/snappy.SnappyUnArchiver.html}<<>>}},
+| | {{{./xref/org/codehaus/plexus/archiver/zstandard.ZstdUnArchiver.html}<<>>}},
| | {{{./xref/org/codehaus/plexus/archiver/tar.TarUnArchiver.html}<<>>}},
| | {{{./xref/org/codehaus/plexus/archiver/zip.ZipUnArchiver.html}<<>>}}
| | (also available as <<>>, <<>>, <<>>, <<>>, <<>>, <<>>, <<>>, <<>>, <<>>, <<>>),
| | {{{./xref/org/codehaus/plexus/archiver/tar.TarGZipUnArchiver.html}<<>>}} or <<>>,
| | {{{./xref/org/codehaus/plexus/archiver/tar.TarBZip2UnArchiver.html}<<>>}} or <<>>,
| | {{{./xref/org/codehaus/plexus/archiver/tar.TarXZUnArchiver.html}<<>>}} or <<>>,
+| | {{{./xref/org/codehaus/plexus/archiver/tar.TarZstdUnArchiver.html}<<>>}},
| | {{{./xref/org/codehaus/plexus/archiver/tar.TarSnappyUnArchiver.html}<<>>}}.
*------------------+-----------------+
diff --git a/src/test/java/org/codehaus/plexus/archiver/tar/TarZstdUnArchiverTest.java b/src/test/java/org/codehaus/plexus/archiver/tar/TarZstdUnArchiverTest.java
new file mode 100644
index 000000000..061449647
--- /dev/null
+++ b/src/test/java/org/codehaus/plexus/archiver/tar/TarZstdUnArchiverTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2022 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.plexus.archiver.tar;
+
+import java.io.File;
+import org.codehaus.plexus.archiver.Archiver;
+import org.codehaus.plexus.archiver.TestSupport;
+import org.codehaus.plexus.archiver.UnArchiver;
+import org.codehaus.plexus.archiver.zstd.ZstdArchiver;
+import org.codehaus.plexus.util.FileUtils;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class TarZstdUnArchiverTest extends TestSupport
+{
+
+ @Test
+ public void testExtract()
+ throws Exception
+ {
+ TarArchiver tarArchiver = (TarArchiver) lookup( Archiver.class, "tar" );
+ tarArchiver.setLongfile( TarLongFileMode.posix );
+
+ String fileName1 = "TarBZip2UnArchiverTest1.txt";
+ String fileName2 = "TarBZip2UnArchiverTest2.txt";
+ File file1InTar = getTestFile( "target/output/" + fileName1 );
+ File file2InTar = getTestFile( "target/output/" + fileName2 );
+ file1InTar.delete();
+ file2InTar.delete();
+
+ assertFalse( file1InTar.exists() );
+ assertFalse( file2InTar.exists() );
+
+ File testZstdFile = getTestFile( "target/output/archive.tar.zst" );
+ if ( testZstdFile.exists() )
+ {
+ FileUtils.fileDelete( testZstdFile.getPath() );
+ }
+ assertFalse( testZstdFile.exists() );
+
+ tarArchiver.addFile( getTestFile( "src/test/resources/manifests/manifest1.mf" ), fileName1 );
+ tarArchiver.addFile( getTestFile( "src/test/resources/manifests/manifest2.mf" ), fileName2, 0664 );
+ tarArchiver.setDestFile( getTestFile( "target/output/archive.tar" ) );
+ tarArchiver.createArchive();
+
+ ZstdArchiver zstdArchiver = (ZstdArchiver) lookup( Archiver.class, "zst" );
+
+ zstdArchiver.setDestFile( testZstdFile );
+ zstdArchiver.addFile( getTestFile( "target/output/archive.tar" ), "dontcare" );
+ zstdArchiver.createArchive();
+
+ assertTrue( testZstdFile.exists() );
+
+ TarZstdUnArchiver tarZstdUnArchiver = (TarZstdUnArchiver) lookup( UnArchiver.class, "tar.zst" );
+
+ tarZstdUnArchiver.setDestDirectory( getTestFile( "target/output" ) );
+ tarZstdUnArchiver.setSourceFile( testZstdFile );
+ tarZstdUnArchiver.extract();
+
+ assertTrue( file1InTar.exists() );
+ assertTrue( file2InTar.exists() );
+
+ assertEquals( testZstdFile, tarZstdUnArchiver.getSourceFile() );
+ }
+
+ @Test
+ public void testLookup() throws Exception
+ {
+ assertNotNull( lookup( UnArchiver.class, "tar.zst" ) );
+ }
+
+}
diff --git a/src/test/java/org/codehaus/plexus/archiver/zstd/ZstdArchiverTest.java b/src/test/java/org/codehaus/plexus/archiver/zstd/ZstdArchiverTest.java
new file mode 100644
index 000000000..eed3367e2
--- /dev/null
+++ b/src/test/java/org/codehaus/plexus/archiver/zstd/ZstdArchiverTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2022 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.plexus.archiver.zstd;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import org.codehaus.plexus.archiver.Archiver;
+import org.codehaus.plexus.archiver.BasePlexusArchiverTest;
+import org.codehaus.plexus.archiver.exceptions.EmptyArchiveException;
+import org.codehaus.plexus.archiver.zip.ZipArchiver;
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.IOUtil;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class ZstdArchiverTest extends BasePlexusArchiverTest
+{
+
+ @Test
+ public void testCreateArchive()
+ throws Exception
+ {
+ ZipArchiver zipArchiver = (ZipArchiver) lookup( Archiver.class, "zip" );
+ zipArchiver.addDirectory( getTestFile( "src" ) );
+ zipArchiver.setDestFile( getTestFile( "target/output/archiveForxz.zip" ) );
+ zipArchiver.createArchive();
+
+ ZstdArchiver archiver = (ZstdArchiver) lookup( Archiver.class, "zst" );
+ String[] inputFiles = new String[ 1 ];
+ inputFiles[0] = "archiveForxz.zip";
+
+ File targetOutputFile = getTestFile( "target/output/archive.zst" );
+ if ( targetOutputFile.exists() )
+ {
+ FileUtils.fileDelete( targetOutputFile.getPath() );
+ }
+ assertFalse( targetOutputFile.exists() );
+
+ archiver.addDirectory( getTestFile( "target/output" ), inputFiles, null );
+ archiver.setDestFile( targetOutputFile );
+ archiver.createArchive();
+
+ assertTrue( targetOutputFile.exists() );
+ }
+
+ @Test
+ public void testCreateEmptyArchive()
+ throws Exception
+ {
+ ZstdArchiver archiver = (ZstdArchiver) lookup( Archiver.class, "zst" );
+ archiver.setDestFile( getTestFile( "target/output/empty.zst" ) );
+ try
+ {
+ archiver.createArchive();
+
+ fail( "Creating empty archive should throw EmptyArchiveException" );
+ }
+ catch ( EmptyArchiveException ignore )
+ {
+ }
+ }
+
+ @Test
+ public void testCreateResourceCollection() throws Exception
+ {
+ final File pomFile = new File( "pom.xml" );
+ final File zstFile = new File( "target/output/pom.xml.zst" );
+ ZstdArchiver zstdArchiver = (ZstdArchiver) lookup( Archiver.class, "zst" );
+ zstdArchiver.setDestFile( zstFile );
+ zstdArchiver.addFile( pomFile, "pom.xml" );
+ FileUtils.removePath( zstFile.getPath() );
+ zstdArchiver.createArchive();
+
+ System.out.println( "Created: " + zstFile.getAbsolutePath() );
+
+ final File zipFile = new File( "target/output/pomxz.zip" );
+ ZipArchiver zipArchiver = (ZipArchiver) lookup( Archiver.class, "zip" );
+ zipArchiver.setDestFile( zipFile );
+ zipArchiver.addArchivedFileSet( zstFile, "prfx/" );
+ FileUtils.removePath( zipFile.getPath() );
+ zipArchiver.createArchive();
+
+ final ZipFile juZipFile = new ZipFile( zipFile );
+ final ZipEntry zipEntry = juZipFile.getEntry( "prfx/target/output/pom.xml" );
+ final InputStream archivePom = juZipFile.getInputStream( zipEntry );
+ final InputStream pom = Files.newInputStream( pomFile.toPath() );
+
+ assertTrue( Arrays.equals( IOUtil.toByteArray( pom ), IOUtil.toByteArray( archivePom ) ) );
+ archivePom.close();
+ pom.close();
+ juZipFile.close();
+ }
+
+ /**
+ * Tests the .std archiver is forced set to true, and after that
+ * tests the behavior when the forced is set to false.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testZstIsForcedBehaviour() throws Exception
+ {
+ ZstdArchiver zstdArchiver = (ZstdArchiver) createArchiver( "zst" );
+
+ assertTrue( zstdArchiver.isSupportingForced() );
+ zstdArchiver.createArchive();
+
+ final long creationTime = zstdArchiver.getDestFile().lastModified();
+
+ waitUntilNewTimestamp( zstdArchiver.getDestFile(), creationTime );
+
+ zstdArchiver = (ZstdArchiver) createArchiver( "zst" );
+
+ zstdArchiver.setForced( true );
+ zstdArchiver.createArchive();
+
+ final long firstRunTime = zstdArchiver.getDestFile().lastModified();
+
+ assertFalse( creationTime == firstRunTime );
+
+ zstdArchiver = (ZstdArchiver) createArchiver( "zst" );
+
+ zstdArchiver.setForced( false );
+ zstdArchiver.createArchive();
+
+ final long secondRunTime = zstdArchiver.getDestFile().lastModified();
+
+ assertEquals( firstRunTime, secondRunTime );
+ }
+
+}