diff --git a/src/main/java/org/rauschig/jarchivelib/Archiver.java b/src/main/java/org/rauschig/jarchivelib/Archiver.java
index 97a1582..03f1137 100644
--- a/src/main/java/org/rauschig/jarchivelib/Archiver.java
+++ b/src/main/java/org/rauschig/jarchivelib/Archiver.java
@@ -35,7 +35,7 @@ public interface Archiver {
*
* If the archive parameter has no file extension (e.g. "archive" instead of "archive.zip"), the concrete archiver
* implementation should append it according to its file format (.zip, .tar, .tar.gz, ...).
- *
+ *
* @param archive the name of the archive to create
* @param destination the destination directory where to place the created archive
* @param source the input file or directory to archive
@@ -65,7 +65,7 @@ public interface Archiver {
* Extracts the given archive file into the given destination directory.
*
* The destination is expected to be a writable directory.
- *
+ *
* @param archive the archive file to extract
* @param destination the directory to which to extract the files
* @throws IOException propagated I/O errors by {@code java.io}
@@ -86,7 +86,7 @@ public interface Archiver {
/**
* Reads the given archive file as an {@link ArchiveStream} which is used to access individual {@link ArchiveEntry}
* objects within the archive without extracting the archive onto the file system.
- *
+ *
* @param archive the archive file to stream
* @return a new archive stream for the given archive
* @throws IOException propagated I/O errors by {@code java.io}
@@ -96,8 +96,15 @@ public interface Archiver {
/**
* Returns the filename extension that indicates the file format this archiver handles. E.g .tar" or ".zip". In case
* of compressed archives, it will return the composite filename extensions, e.g. ".tar.gz"
- *
+ *
* @return a filename extension with a preceding dot
*/
String getFilenameExtension();
+
+ /**
+ * Returns the archiver's format
+ *
+ * @return archiver format
+ */
+ ArchiveFormat getArchiveFormat();
}
diff --git a/src/main/java/org/rauschig/jarchivelib/ArchiverCompressorDecorator.java b/src/main/java/org/rauschig/jarchivelib/ArchiverCompressorDecorator.java
index 2a336f8..d79edfc 100644
--- a/src/main/java/org/rauschig/jarchivelib/ArchiverCompressorDecorator.java
+++ b/src/main/java/org/rauschig/jarchivelib/ArchiverCompressorDecorator.java
@@ -34,16 +34,16 @@
*/
class ArchiverCompressorDecorator implements Archiver {
- private CommonsArchiver archiver;
+ private Archiver archiver;
private CommonsCompressor compressor;
/**
* Decorates the given Archiver with the given Compressor.
- *
+ *
* @param archiver the archiver to decorate
* @param compressor the compressor used for compression
*/
- ArchiverCompressorDecorator(CommonsArchiver archiver, CommonsCompressor compressor) {
+ ArchiverCompressorDecorator(Archiver archiver, CommonsCompressor compressor) {
this.archiver = archiver;
this.compressor = compressor;
}
@@ -119,13 +119,18 @@ public String getFilenameExtension() {
return archiver.getFilenameExtension() + compressor.getFilenameExtension();
}
+ @Override
+ public ArchiveFormat getArchiveFormat() {
+ return archiver.getArchiveFormat();
+ }
+
/**
* Returns a file name from the given archive name. The file extension suffix will be appended according to what is
* already present.
*
* E.g. if the compressor uses the file extension "gz", the archiver "tar", and passed argument is "archive.tar",
* the returned value will be "archive.tar.gz".
- *
+ *
* @param archive the existing archive file name
* @return the normalized archive file name including the correct file name extension
*/
diff --git a/src/main/java/org/rauschig/jarchivelib/ArchiverFactory.java b/src/main/java/org/rauschig/jarchivelib/ArchiverFactory.java
index d1357c8..bec12d4 100644
--- a/src/main/java/org/rauschig/jarchivelib/ArchiverFactory.java
+++ b/src/main/java/org/rauschig/jarchivelib/ArchiverFactory.java
@@ -31,7 +31,7 @@ private ArchiverFactory() {
* Probes the given {@link File} for its file type and creates an {@link Archiver} based on this file type. If the
* File has a composite file extension such as ".tar.gz", the created {@link Archiver} will also handle ".gz"
* compression.
- *
+ *
* @param archive the archive file to check.
* @return a new Archiver instance (that may also handle compression)
* @throws IllegalArgumentException if the given file is not a known archive
@@ -49,7 +49,7 @@ public static Archiver createArchiver(File archive) throws IllegalArgumentExcept
/**
* Creates an Archiver that handles the given {@link FileType}. The Archiver may handle compression inherently, if
* the {@link FileType} uses a compression type, such as ".tgz" might.
- *
+ *
* @param fileType the file type
* @return a new Archiver instance (that may also handle compression)
*/
@@ -69,7 +69,7 @@ public static Archiver createArchiver(FileType fileType) {
/**
* Creates an Archiver for the given archive format that uses compression.
- *
+ *
* @param archiveFormat the archive format e.g. "tar" or "zip"
* @param compression the compression algorithm name e.g. "gz"
* @return a new Archiver instance that also handles compression
@@ -88,13 +88,13 @@ public static Archiver createArchiver(String archiveFormat, String compression)
/**
* Creates an Archiver for the given archive format that uses compression.
- *
+ *
* @param archiveFormat the archive format
* @param compression the compression algorithm
* @return a new Archiver instance that also handles compression
*/
public static Archiver createArchiver(ArchiveFormat archiveFormat, CompressionType compression) {
- CommonsArchiver archiver = new CommonsArchiver(archiveFormat);
+ Archiver archiver = createArchiver(archiveFormat);
CommonsCompressor compressor = new CommonsCompressor(compression);
return new ArchiverCompressorDecorator(archiver, compressor);
@@ -102,7 +102,7 @@ public static Archiver createArchiver(ArchiveFormat archiveFormat, CompressionTy
/**
* Creates an Archiver for the given archive format.
- *
+ *
* @param archiveFormat the archive format e.g. "tar" or "zip"
* @return a new Archiver instance
* @throws IllegalArgumentException if the archive format is unknown
@@ -117,7 +117,7 @@ public static Archiver createArchiver(String archiveFormat) throws IllegalArgume
/**
* Creates an Archiver for the given archive format.
- *
+ *
* @param archiveFormat the archive format
* @return a new Archiver instance
*/
@@ -126,6 +126,8 @@ public static Archiver createArchiver(ArchiveFormat archiveFormat) {
return new SevenZArchiver();
} else if (archiveFormat == ArchiveFormat.ZIP) {
return new ZipFileArchiver();
+ } else if (archiveFormat == ArchiveFormat.TAR) {
+ return new TarArchiver();
}
return new CommonsArchiver(archiveFormat);
}
diff --git a/src/main/java/org/rauschig/jarchivelib/CommonsArchiver.java b/src/main/java/org/rauschig/jarchivelib/CommonsArchiver.java
index 27f7558..0ed5dce 100644
--- a/src/main/java/org/rauschig/jarchivelib/CommonsArchiver.java
+++ b/src/main/java/org/rauschig/jarchivelib/CommonsArchiver.java
@@ -26,6 +26,7 @@
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
/**
* Implementation of an {@link Archiver} that uses {@link ArchiveStreamFactory} to generate archive streams by a given
@@ -40,6 +41,7 @@ class CommonsArchiver implements Archiver {
this.archiveFormat = archiveFormat;
}
+ @Override
public ArchiveFormat getArchiveFormat() {
return archiveFormat;
}
@@ -120,7 +122,7 @@ public String getFilenameExtension() {
/**
* Returns a new ArchiveInputStream for reading archives. Subclasses can override this to return their own custom
* implementation.
- *
+ *
* @param archive the archive file to stream from
* @return a new ArchiveInputStream for the given archive file
* @throws IOException propagated IO exceptions
@@ -152,7 +154,7 @@ protected ArchiveInputStream createArchiveInputStream(InputStream archive) throw
/**
* Returns a new ArchiveOutputStream for creating archives. Subclasses can override this to return their own custom
* implementation.
- *
+ *
* @param archiveFile the archive file to stream to
* @return a new ArchiveOutputStream for the given archive file.
* @throws IOException propagated IO exceptions
@@ -167,7 +169,7 @@ protected ArchiveOutputStream createArchiveOutputStream(File archiveFile) throws
/**
* Asserts that the given File object is a readable file that can be used to extract from.
- *
+ *
* @param archive the file to check
* @throws FileNotFoundException if the file does not exist
* @throws IllegalArgumentException if the file is a directory or not readable
@@ -185,7 +187,7 @@ protected void assertExtractSource(File archive) throws FileNotFoundException, I
/**
* Creates a new File in the given destination. The resulting name will always be "archive"."fileExtension". If the
* archive name parameter already ends with the given file name extension, it is not additionally appended.
- *
+ *
* @param archive the name of the archive
* @param extension the file extension (e.g. ".tar")
* @param destination the parent path
@@ -207,7 +209,7 @@ protected File createNewArchiveFile(String archive, String extension, File desti
* Recursion entry point for {@link #writeToArchive(File, File[], ArchiveOutputStream)}.
*
* Recursively writes all given source {@link File}s into the given {@link ArchiveOutputStream}.
- *
+ *
* @param sources the files to write in to the archive
* @param archive the archive to write into
* @throws IOException when an I/O error occurs
@@ -220,14 +222,14 @@ protected void writeToArchive(File[] sources, ArchiveOutputStream archive) throw
throw new FileNotFoundException(source.getPath() + " (Permission denied)");
}
- writeToArchive(source.getParentFile(), new File[]{ source }, archive);
+ writeToArchive(source.getParentFile(), new File[]{source}, archive);
}
}
/**
* Recursively writes all given source {@link File}s into the given {@link ArchiveOutputStream}. The paths of the
* sources in the archive will be relative to the given parent {@code File}.
- *
+ *
* @param parent the parent file node for computing a relative path (see {@link IOUtils#relativePath(File, File)})
* @param sources the files to write in to the archive
* @param archive the archive to write into
@@ -245,10 +247,18 @@ protected void writeToArchive(File parent, File[] sources, ArchiveOutputStream a
}
}
+ /**
+ * Process archive entry before it's finalized / stored
+ * @param entry archive entry
+ */
+ protected void processArchiveEntry(ArchiveEntry entry) {
+ // For specialized archivers to override. Default implementation is noop.
+ }
+
/**
* Creates a new {@link ArchiveEntry} in the given {@link ArchiveOutputStream}, and copies the given {@link File}
* into the new entry.
- *
+ *
* @param file the file to add to the archive
* @param entryName the name of the archive entry
* @param archive the archive to write to
@@ -256,7 +266,10 @@ protected void writeToArchive(File parent, File[] sources, ArchiveOutputStream a
*/
protected void createArchiveEntry(File file, String entryName, ArchiveOutputStream archive) throws IOException {
ArchiveEntry entry = archive.createArchiveEntry(file, entryName);
+
// TODO #23: read permission from file, write it to the ArchiveEntry
+
+ this.processArchiveEntry(entry);
archive.putArchiveEntry(entry);
if (!entry.isDirectory()) {
diff --git a/src/main/java/org/rauschig/jarchivelib/CommonsStreamFactory.java b/src/main/java/org/rauschig/jarchivelib/CommonsStreamFactory.java
index dfc0f63..e376c88 100644
--- a/src/main/java/org/rauschig/jarchivelib/CommonsStreamFactory.java
+++ b/src/main/java/org/rauschig/jarchivelib/CommonsStreamFactory.java
@@ -61,15 +61,15 @@ static ArchiveInputStream createArchiveInputStream(String archiverName, InputStr
* @see {@link ArchiveStreamFactory#createArchiveInputStream(String, InputStream)}
*/
static ArchiveInputStream createArchiveInputStream(ArchiveFormat archiveFormat, InputStream in)
- throws ArchiveException {
+ throws ArchiveException {
return createArchiveInputStream(archiveFormat.getName(), in);
}
/**
* @see {@link ArchiveStreamFactory#createArchiveInputStream(String, InputStream)}
*/
- static ArchiveInputStream createArchiveInputStream(CommonsArchiver archiver, InputStream in)
- throws ArchiveException {
+ static ArchiveInputStream createArchiveInputStream(Archiver archiver, InputStream in)
+ throws ArchiveException {
return createArchiveInputStream(archiver.getArchiveFormat(), in);
}
@@ -82,7 +82,7 @@ static ArchiveInputStream createArchiveInputStream(InputStream in) throws Archiv
/**
* Uses the {@link ArchiveStreamFactory} to create a new {@link ArchiveInputStream} for the given archive file.
- *
+ *
* @param archive the archive file
* @return a new {@link ArchiveInputStream} for the given archive file
* @throws IOException propagated IOException when creating the FileInputStream.
@@ -96,19 +96,19 @@ static ArchiveInputStream createArchiveInputStream(File archive) throws IOExcept
* @see {@link ArchiveStreamFactory#createArchiveOutputStream(String, OutputStream)};
*/
static ArchiveOutputStream createArchiveOutputStream(String archiverName, OutputStream out)
- throws ArchiveException {
+ throws ArchiveException {
return archiveStreamFactory.createArchiveOutputStream(archiverName, out);
}
static ArchiveOutputStream createArchiveOutputStream(ArchiveFormat format, File archive) throws IOException,
- ArchiveException {
+ ArchiveException {
return createArchiveOutputStream(format.getName(), new FileOutputStream(archive));
}
/**
* Uses the {@link ArchiveStreamFactory} and the name of the given archiver to create a new
* {@link ArchiveOutputStream} for the given archive {@link File}.
- *
+ *
* @param archiver the invoking archiver
* @param archive the archive file to create the {@link ArchiveOutputStream} for
* @return a new {@link ArchiveOutputStream}
@@ -116,14 +116,14 @@ static ArchiveOutputStream createArchiveOutputStream(ArchiveFormat format, File
* @throws ArchiveException if the archiver name is not known
*/
static ArchiveOutputStream createArchiveOutputStream(CommonsArchiver archiver, File archive) throws IOException,
- ArchiveException {
+ ArchiveException {
return createArchiveOutputStream(archiver.getArchiveFormat(), archive);
}
/**
* Uses the {@link CompressorStreamFactory} to create a new {@link CompressorInputStream} for the given source
* {@link File}.
- *
+ *
* @param source the file to create the {@link CompressorInputStream} for
* @return a new {@link CompressorInputStream}
* @throws IOException if an I/O error occurs
@@ -136,14 +136,14 @@ static CompressorInputStream createCompressorInputStream(File source) throws IOE
/**
* Uses the {@link CompressorStreamFactory} to create a new {@link CompressorInputStream} for the compression type
* and wraps the given source {@link File} with it.
- *
+ *
* @param source the file to create the {@link CompressorInputStream} for
* @return a new {@link CompressorInputStream}
* @throws IOException if an I/O error occurs
* @throws CompressorException if the compressor name is not known
*/
static CompressorInputStream createCompressorInputStream(CompressionType type, File source) throws IOException,
- CompressorException {
+ CompressorException {
return createCompressorInputStream(type, new BufferedInputStream(new FileInputStream(source)));
}
@@ -151,7 +151,7 @@ static CompressorInputStream createCompressorInputStream(CompressionType type, F
* @see {@link CompressorStreamFactory#createCompressorInputStream(String, java.io.InputStream)}
*/
static CompressorInputStream createCompressorInputStream(CompressionType compressionType, InputStream in)
- throws CompressorException {
+ throws CompressorException {
return compressorStreamFactory.createCompressorInputStream(compressionType.getName(), in);
}
@@ -163,14 +163,14 @@ static CompressorInputStream createCompressorInputStream(InputStream in) throws
}
static CompressorOutputStream createCompressorOutputStream(CompressionType compressionType, File destination)
- throws IOException, CompressorException {
+ throws IOException, CompressorException {
return createCompressorOutputStream(compressionType.getName(), new FileOutputStream(destination));
}
/**
* Uses the {@link CompressorStreamFactory} and the name of the given compressor to create a new
* {@link CompressorOutputStream} for the given destination {@link File}.
- *
+ *
* @param compressor the invoking compressor
* @param destination the file to create the {@link CompressorOutputStream} for
* @return a new {@link CompressorOutputStream}
@@ -178,7 +178,7 @@ static CompressorOutputStream createCompressorOutputStream(CompressionType compr
* @throws CompressorException if the compressor name is not known
*/
static CompressorOutputStream createCompressorOutputStream(CommonsCompressor compressor, File destination)
- throws IOException, CompressorException {
+ throws IOException, CompressorException {
return createCompressorOutputStream(compressor.getCompressionType(), destination);
}
@@ -186,7 +186,7 @@ static CompressorOutputStream createCompressorOutputStream(CommonsCompressor com
* @see {@link CompressorStreamFactory#createCompressorOutputStream(String, OutputStream)};
*/
static CompressorOutputStream createCompressorOutputStream(String compressorName, OutputStream out)
- throws CompressorException {
+ throws CompressorException {
return compressorStreamFactory.createCompressorOutputStream(compressorName, out);
}
diff --git a/src/main/java/org/rauschig/jarchivelib/TarArchiver.java b/src/main/java/org/rauschig/jarchivelib/TarArchiver.java
new file mode 100644
index 0000000..65baea7
--- /dev/null
+++ b/src/main/java/org/rauschig/jarchivelib/TarArchiver.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2013 Thomas Rausch
+ *
+ * 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.rauschig.jarchivelib;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+
+/**
+ * Archiver to handle tar archives.
+ *
+ * Created by masc on 31.10.18. + */ +public class TarArchiver extends CommonsArchiver { + private static final int DEFAULT_EXECUTABLE_FILE_MODE = 0100755; + + TarArchiver() { + super(ArchiveFormat.TAR); + } + + @Override + protected void processArchiveEntry(ArchiveEntry entry) { + if (entry instanceof TarArchiveEntry) { + + TarArchiveEntry tarEntry = (TarArchiveEntry) entry; + + // Preserve executability of files + if (tarEntry.isFile() && tarEntry.getFile().canExecute()) + tarEntry.setMode(DEFAULT_EXECUTABLE_FILE_MODE); + } + } +} \ No newline at end of file