You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/02/13 22:14:48 UTC
[commons-compress] branch master updated (71857f4 -> bbd9f34)
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git.
from 71857f4 Replace manual copy of array contents with System.arraycopy() #246.
new 5b3c8f7 Clearer local variable name.
new f2b68e9 In most IOUtil methods,the target may be null to simulate output to dev/null on Linux and NUL on Windows.
new 2949c1f ArchiveStreamFactory.createArchiveInputStream(String, InputStream, String) supports the "APK" format (it's a JAR).
new b30738c Expander example now has NIO Path versions of IO File APIs.
new bbd9f34 Test reading APK files for samples generated by Android Studio.
The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
pom.xml | 12 ++
src/changes/changes.xml | 6 +
.../compress/archivers/ArchiveStreamFactory.java | 5 +-
.../compress/archivers/examples/Expander.java | 219 +++++++++++++++++----
.../org/apache/commons/compress/utils/IOUtils.java | 14 +-
.../jar/{JarMarkerTest.java => ExpandApkTest.java} | 27 ++-
.../app/build/outputs/apk/debug/app-debug.apk | Bin 0 -> 1546505 bytes
.../build/outputs/apk/debug/compose-debug.apk | Bin 0 -> 6082169 bytes
.../views/build/outputs/apk/debug/views-debug.apk | Bin 0 -> 2439424 bytes
.../build/outputs/apk/debug/Application-debug.apk | Bin 0 -> 1648995 bytes
.../instant-run-apk/debug/Application-debug.apk | Bin 0 -> 45880 bytes
.../instant-run/debug/resources-debug.apk | Bin 0 -> 354355 bytes
.../split-apk/debug/dep/dependencies.apk | Bin 0 -> 918973 bytes
.../split-apk/debug/slices/slice_0.apk} | Bin 5120 -> 6356 bytes
.../split-apk/debug/slices/slice_1.apk | Bin 0 -> 9435 bytes
.../split-apk/debug/slices/slice_2.apk} | Bin 4140 -> 6367 bytes
.../split-apk/debug/slices/slice_3.apk | Bin 0 -> 10222 bytes
.../split-apk/debug/slices/slice_4.apk | Bin 0 -> 9422 bytes
.../split-apk/debug/slices/slice_5.apk} | Bin 4140 -> 6368 bytes
.../split-apk/debug/slices/slice_6.apk | Bin 0 -> 85660 bytes
.../split-apk/debug/slices/slice_7.apk | Bin 0 -> 13294 bytes
.../split-apk/debug/slices/slice_8.apk} | Bin 4140 -> 6354 bytes
.../split-apk/debug/slices/slice_9.apk | Bin 0 -> 30541 bytes
.../build/outputs/apk/debug/Application-debug.apk | Bin 0 -> 1489457 bytes
.../app/build/outputs/apk/debug/app-debug.apk | Bin 0 -> 3747603 bytes
.../apk/framework/debug/app-framework-debug.apk | Bin 0 -> 2222863 bytes
.../app/build/outputs/apk/debug/app-debug.apk | Bin 0 -> 2008249 bytes
.../app/build/outputs/apk/debug/app-debug.apk | Bin 0 -> 2827932 bytes
.../build/outputs/apk/debug/Application-debug.apk | Bin 0 -> 1632634 bytes
.../app/build/outputs/apk/debug/app-debug.apk | Bin 0 -> 6932352 bytes
.../build/outputs/apk/debug/Application-debug.apk | Bin 0 -> 1629154 bytes
31 files changed, 224 insertions(+), 59 deletions(-)
copy src/test/java/org/apache/commons/compress/archivers/jar/{JarMarkerTest.java => ExpandApkTest.java} (51%)
create mode 100644 src/test/resources/android/ActivitySceneTransitionBasic/app/build/outputs/apk/debug/app-debug.apk
create mode 100644 src/test/resources/android/AlwaysOnKotlin/compose/build/outputs/apk/debug/compose-debug.apk
create mode 100644 src/test/resources/android/AlwaysOnKotlin/views/build/outputs/apk/debug/views-debug.apk
create mode 100644 src/test/resources/android/BasicTransition/Application/build/outputs/apk/debug/Application-debug.apk
create mode 100644 src/test/resources/android/Camera2Basic/Application/build/intermediates/instant-run-apk/debug/Application-debug.apk
create mode 100644 src/test/resources/android/Camera2Basic/Application/build/intermediates/resources/instant-run/debug/resources-debug.apk
create mode 100644 src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/dep/dependencies.apk
copy src/test/resources/{bla.cpio => android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_0.apk} (50%)
create mode 100644 src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_1.apk
copy src/test/resources/{lbzip2_32767.bz2 => android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_2.apk} (52%)
create mode 100644 src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_3.apk
create mode 100644 src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_4.apk
copy src/test/resources/{lbzip2_32767.bz2 => android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_5.apk} (51%)
create mode 100644 src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_6.apk
create mode 100644 src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_7.apk
copy src/test/resources/{lbzip2_32767.bz2 => android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_8.apk} (50%)
create mode 100644 src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_9.apk
create mode 100644 src/test/resources/android/Camera2Basic/Application/build/outputs/apk/debug/Application-debug.apk
create mode 100644 src/test/resources/android/FragmentTransitionsRecyclerViewtoViewPager/app/build/outputs/apk/debug/app-debug.apk
create mode 100644 src/test/resources/android/InstantApps-CookieAPI/app/build/outputs/apk/framework/debug/app-framework-debug.apk
create mode 100644 src/test/resources/android/InstantApps-GoogleAnalyticsExample/app/build/outputs/apk/debug/app-debug.apk
create mode 100644 src/test/resources/android/InstantApps-InstallAPIsample/app/build/outputs/apk/debug/app-debug.apk
create mode 100644 src/test/resources/android/Interpolator/Application/build/outputs/apk/debug/Application-debug.apk
create mode 100644 src/test/resources/android/Motion/app/build/outputs/apk/debug/app-debug.apk
create mode 100644 src/test/resources/android/RevealEffectBasic/Application/build/outputs/apk/debug/Application-debug.apk
[commons-compress] 04/05: Expander example now has NIO Path versions of IO File APIs.
Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
commit b30738c974b7c960e463e60afe698c0b1f235a29
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Feb 13 17:00:15 2022 -0500
Expander example now has NIO Path versions of IO File APIs.
---
src/changes/changes.xml | 6 +
.../compress/archivers/examples/Expander.java | 219 +++++++++++++++++----
2 files changed, 183 insertions(+), 42 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 1f3385f..db11a56 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -80,6 +80,12 @@ The <action> type attribute can be add,update,fix,remove.
<action type="add" dev="ggregory" due-to="Gary Gregory">
Add APK file extension constants: ArchiveStreamFactory.APK, APKM, APKS, XAPK.
</action>
+ <action type="add" dev="ggregory" due-to="Gary Gregory">
+ ArchiveStreamFactory.createArchiveInputStream(String, InputStream, String) supports the "APK" format (it's a JAR).
+ </action>
+ <action type="add" dev="ggregory" due-to="Gary Gregory">
+ Expander example now has NIO Path versions of IO File APIs.
+ </action>
<!-- UPDATE -->
<action type="update" dev="ggregory" due-to="Dependabot">
Bump mockito-core from 3.11.1 to 4.3.1 #209, #224, #231, #235, #243.
diff --git a/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java b/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java
index e6c425e..7bdd7a1 100644
--- a/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java
+++ b/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java
@@ -27,6 +27,7 @@ import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Enumeration;
import java.util.Iterator;
@@ -62,14 +63,29 @@ public class Expander {
* <p>Tries to auto-detect the archive's format.</p>
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory
* @throws IOException if an I/O error occurs
* @throws ArchiveException if the archive cannot be read for other reasons
*/
public void expand(final File archive, final File targetDirectory) throws IOException, ArchiveException {
+ expand(archive.toPath(), toPath(targetDirectory));
+ }
+
+ /**
+ * Expands {@code archive} into {@code targetDirectory}.
+ *
+ * <p>Tries to auto-detect the archive's format.</p>
+ *
+ * @param archive the file to expand
+ * @param targetDirectory the target directory
+ * @throws IOException if an I/O error occurs
+ * @throws ArchiveException if the archive cannot be read for other reasons
+ * @since 1.22
+ */
+ public void expand(final Path archive, final Path targetDirectory) throws IOException, ArchiveException {
String format = null;
- try (InputStream i = new BufferedInputStream(Files.newInputStream(archive.toPath()))) {
- format = ArchiveStreamFactory.detect(i);
+ try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(archive))) {
+ format = ArchiveStreamFactory.detect(inputStream);
}
expand(format, archive, targetDirectory);
}
@@ -78,21 +94,40 @@ public class Expander {
* Expands {@code archive} into {@code targetDirectory}.
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory
* @param format the archive format. This uses the same format as
* accepted by {@link ArchiveStreamFactory}.
* @throws IOException if an I/O error occurs
* @throws ArchiveException if the archive cannot be read for other reasons
*/
public void expand(final String format, final File archive, final File targetDirectory) throws IOException, ArchiveException {
+ expand(format, archive.toPath(), toPath(targetDirectory));
+ }
+
+ private Path toPath(final File targetDirectory) {
+ return targetDirectory != null ? targetDirectory.toPath() : null;
+ }
+
+ /**
+ * Expands {@code archive} into {@code targetDirectory}.
+ *
+ * @param archive the file to expand
+ * @param targetDirectory the target directory
+ * @param format the archive format. This uses the same format as
+ * accepted by {@link ArchiveStreamFactory}.
+ * @throws IOException if an I/O error occurs
+ * @throws ArchiveException if the archive cannot be read for other reasons
+ * @since 1.22
+ */
+ public void expand(final String format, final Path archive, final Path targetDirectory) throws IOException, ArchiveException {
if (prefersSeekableByteChannel(format)) {
- try (SeekableByteChannel c = FileChannel.open(archive.toPath(), StandardOpenOption.READ)) {
- expand(format, c, targetDirectory, CloseableConsumer.CLOSING_CONSUMER);
+ try (SeekableByteChannel channel = FileChannel.open(archive, StandardOpenOption.READ)) {
+ expand(format, channel, targetDirectory, CloseableConsumer.CLOSING_CONSUMER);
}
return;
}
- try (InputStream i = new BufferedInputStream(Files.newInputStream(archive.toPath()))) {
- expand(format, i, targetDirectory, CloseableConsumer.CLOSING_CONSUMER);
+ try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(archive))) {
+ expand(format, inputStream, targetDirectory, CloseableConsumer.CLOSING_CONSUMER);
}
}
@@ -107,7 +142,7 @@ public class Expander {
* instead.</p>
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory
* @throws IOException if an I/O error occurs
* @throws ArchiveException if the archive cannot be read for other reasons
* @deprecated this method leaks resources
@@ -130,7 +165,7 @@ public class Expander {
* by this class.</p>
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory
* @param closeableConsumer is informed about the stream wrapped around the passed in stream
* @throws IOException if an I/O error occurs
* @throws ArchiveException if the archive cannot be read for other reasons
@@ -153,7 +188,7 @@ public class Expander {
* instead.</p>
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory
* @param format the archive format. This uses the same format as
* accepted by {@link ArchiveStreamFactory}.
* @throws IOException if an I/O error occurs
@@ -177,7 +212,7 @@ public class Expander {
* by this class.</p>
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory
* @param format the archive format. This uses the same format as
* accepted by {@link ArchiveStreamFactory}.
* @param closeableConsumer is informed about the stream wrapped around the passed in stream
@@ -187,6 +222,30 @@ public class Expander {
*/
public void expand(final String format, final InputStream archive, final File targetDirectory, final CloseableConsumer closeableConsumer)
throws IOException, ArchiveException {
+ expand(format, archive, toPath(targetDirectory), closeableConsumer);
+ }
+
+ /**
+ * Expands {@code archive} into {@code targetDirectory}.
+ *
+ * <p>This method creates a wrapper around the archive stream and
+ * the caller of this method is responsible for closing it -
+ * probably at the same time as closing the stream itself. The
+ * caller is informed about the wrapper object via the {@code
+ * closeableConsumer} callback as soon as it is no longer needed
+ * by this class.</p>
+ *
+ * @param archive the file to expand
+ * @param targetDirectory the target directory
+ * @param format the archive format. This uses the same format as
+ * accepted by {@link ArchiveStreamFactory}.
+ * @param closeableConsumer is informed about the stream wrapped around the passed in stream
+ * @throws IOException if an I/O error occurs
+ * @throws ArchiveException if the archive cannot be read for other reasons
+ * @since 1.22
+ */
+ public void expand(final String format, final InputStream archive, final Path targetDirectory, final CloseableConsumer closeableConsumer)
+ throws IOException, ArchiveException {
try (CloseableConsumerAdapter c = new CloseableConsumerAdapter(closeableConsumer)) {
expand(c.track(ArchiveStreamFactory.DEFAULT.createArchiveInputStream(format, archive)),
targetDirectory);
@@ -202,7 +261,7 @@ public class Expander {
* instead.</p>
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory
* @param format the archive format. This uses the same format as
* accepted by {@link ArchiveStreamFactory}.
* @throws IOException if an I/O error occurs
@@ -226,7 +285,7 @@ public class Expander {
* by this class.</p>
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory
* @param format the archive format. This uses the same format as
* accepted by {@link ArchiveStreamFactory}.
* @param closeableConsumer is informed about the stream wrapped around the passed in channel
@@ -234,12 +293,36 @@ public class Expander {
* @throws ArchiveException if the archive cannot be read for other reasons
* @since 1.19
*/
- public void expand(final String format, final SeekableByteChannel archive, final File targetDirectory,
+ public void expand(final String format, final SeekableByteChannel archive, final File targetDirectory, final CloseableConsumer closeableConsumer)
+ throws IOException, ArchiveException {
+ expand(format, archive, toPath(targetDirectory), closeableConsumer);
+ }
+
+ /**
+ * Expands {@code archive} into {@code targetDirectory}.
+ *
+ * <p>This method creates a wrapper around the archive channel and
+ * the caller of this method is responsible for closing it -
+ * probably at the same time as closing the channel itself. The
+ * caller is informed about the wrapper object via the {@code
+ * closeableConsumer} callback as soon as it is no longer needed
+ * by this class.</p>
+ *
+ * @param archive the file to expand
+ * @param targetDirectory the target directory
+ * @param format the archive format. This uses the same format as
+ * accepted by {@link ArchiveStreamFactory}.
+ * @param closeableConsumer is informed about the stream wrapped around the passed in channel
+ * @throws IOException if an I/O error occurs
+ * @throws ArchiveException if the archive cannot be read for other reasons
+ * @since 1.22
+ */
+ public void expand(final String format, final SeekableByteChannel archive, final Path targetDirectory,
final CloseableConsumer closeableConsumer)
throws IOException, ArchiveException {
try (CloseableConsumerAdapter c = new CloseableConsumerAdapter(closeableConsumer)) {
if (!prefersSeekableByteChannel(format)) {
- expand(format, c.track(Channels.newInputStream(archive)), targetDirectory);
+ expand(format, c.track(Channels.newInputStream(archive)), targetDirectory, CloseableConsumer.NULL_CONSUMER);
} else if (ArchiveStreamFactory.TAR.equalsIgnoreCase(format)) {
expand(c.track(new TarFile(archive)), targetDirectory);
} else if (ArchiveStreamFactory.ZIP.equalsIgnoreCase(format)) {
@@ -257,11 +340,22 @@ public class Expander {
* Expands {@code archive} into {@code targetDirectory}.
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory, may be null to simulate output to dev/null on Linux and NUL on Windows.
* @throws IOException if an I/O error occurs
*/
- public void expand(final ArchiveInputStream archive, final File targetDirectory)
- throws IOException {
+ public void expand(final ArchiveInputStream archive, final File targetDirectory) throws IOException {
+ expand(archive, toPath(targetDirectory));
+ }
+
+ /**
+ * Expands {@code archive} into {@code targetDirectory}.
+ *
+ * @param archive the file to expand
+ * @param targetDirectory the target directory, may be null to simulate output to dev/null on Linux and NUL on Windows.
+ * @throws IOException if an I/O error occurs
+ * @since 1.22
+ */
+ public void expand(final ArchiveInputStream archive, final Path targetDirectory) throws IOException {
expand(() -> {
ArchiveEntry next = archive.getNextEntry();
while (next != null && !archive.canReadEntryData(next)) {
@@ -275,11 +369,23 @@ public class Expander {
* Expands {@code archive} into {@code targetDirectory}.
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory, may be null to simulate output to dev/null on Linux and NUL on Windows.
* @throws IOException if an I/O error occurs
* @since 1.21
*/
- public void expand(final TarFile archive, final File targetDirectory)
+ public void expand(final TarFile archive, final File targetDirectory) throws IOException {
+ expand(archive, toPath(targetDirectory));
+ }
+
+ /**
+ * Expands {@code archive} into {@code targetDirectory}.
+ *
+ * @param archive the file to expand
+ * @param targetDirectory the target directory, may be null to simulate output to dev/null on Linux and NUL on Windows.
+ * @throws IOException if an I/O error occurs
+ * @since 1.22
+ */
+ public void expand(final TarFile archive, final Path targetDirectory)
throws IOException {
final Iterator<TarArchiveEntry> entryIterator = archive.getEntries().iterator();
expand(() -> entryIterator.hasNext() ? entryIterator.next() : null,
@@ -294,10 +400,22 @@ public class Expander {
* Expands {@code archive} into {@code targetDirectory}.
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory, may be null to simulate output to dev/null on Linux and NUL on Windows.
+ * @throws IOException if an I/O error occurs
+ */
+ public void expand(final ZipFile archive, final File targetDirectory) throws IOException {
+ expand(archive, toPath(targetDirectory));
+ }
+
+ /**
+ * Expands {@code archive} into {@code targetDirectory}.
+ *
+ * @param archive the file to expand
+ * @param targetDirectory the target directory, may be null to simulate output to dev/null on Linux and NUL on Windows.
* @throws IOException if an I/O error occurs
+ * @since 1.22
*/
- public void expand(final ZipFile archive, final File targetDirectory)
+ public void expand(final ZipFile archive, final Path targetDirectory)
throws IOException {
final Enumeration<ZipArchiveEntry> entries = archive.getEntries();
expand(() -> {
@@ -317,16 +435,30 @@ public class Expander {
* Expands {@code archive} into {@code targetDirectory}.
*
* @param archive the file to expand
- * @param targetDirectory the directory to write to
+ * @param targetDirectory the target directory, may be null to simulate output to dev/null on Linux and NUL on Windows.
* @throws IOException if an I/O error occurs
*/
- public void expand(final SevenZFile archive, final File targetDirectory)
+ public void expand(final SevenZFile archive, final File targetDirectory) throws IOException {
+ expand(archive, toPath(targetDirectory));
+ }
+
+ /**
+ * Expands {@code archive} into {@code targetDirectory}.
+ *
+ * @param archive the file to expand
+ * @param targetDirectory the target directory, may be null to simulate output to dev/null on Linux and NUL on Windows.
+ * @throws IOException if an I/O error occurs
+ * @since 1.22
+ */
+ public void expand(final SevenZFile archive, final Path targetDirectory)
throws IOException {
expand(archive::getNextEntry, (entry, out) -> {
final byte[] buffer = new byte[8192];
int n;
while (-1 != (n = archive.read(buffer))) {
- out.write(buffer, 0, n);
+ if (out != null) {
+ out.write(buffer, 0, n);
+ }
}
}, targetDirectory);
}
@@ -337,33 +469,36 @@ public class Expander {
|| ArchiveStreamFactory.SEVEN_Z.equalsIgnoreCase(format);
}
- private void expand(final ArchiveEntrySupplier supplier, final EntryWriter writer, final File targetDirectory)
+ /**
+ * @param targetDirectory May be null to simulate output to dev/null on Linux and NUL on Windows.
+ */
+ private void expand(final ArchiveEntrySupplier supplier, final EntryWriter writer, final Path targetDirectory)
throws IOException {
- String targetDirPath = targetDirectory.getCanonicalPath();
- if (!targetDirPath.endsWith(File.separator)) {
- targetDirPath += File.separator;
- }
+ final boolean nullTarget = targetDirectory == null;
+ final Path targetDirPath = nullTarget ? null : targetDirectory.normalize();
ArchiveEntry nextEntry = supplier.getNextReadableEntry();
while (nextEntry != null) {
- final File targetFile = new File(targetDirectory, nextEntry.getName());
+ final Path targetPath = nullTarget ? null : targetDirectory.resolve(nextEntry.getName());
// check if targetDirectory and f are the same path - this may
// happen if the nextEntry.getName() is "./"
- if (!targetFile.getCanonicalPath().startsWith(targetDirPath)
- && !Files.isSameFile(targetDirectory.toPath(), targetFile.toPath())) {
- throw new IOException("Expanding " + nextEntry.getName()
- + " would create file outside of " + targetDirectory);
+ if (!nullTarget && !targetPath.normalize().startsWith(targetDirPath) && !Files.isSameFile(targetDirectory, targetPath)) {
+ throw new IOException("Expanding " + nextEntry.getName() + " would create file outside of " + targetDirectory);
}
if (nextEntry.isDirectory()) {
- if (!targetFile.isDirectory() && !targetFile.mkdirs()) {
- throw new IOException("Failed to create directory " + targetFile);
+ if (!nullTarget && !Files.isDirectory(targetPath) && Files.createDirectories(targetPath) == null) {
+ throw new IOException("Failed to create directory " + targetPath);
}
} else {
- final File parent = targetFile.getParentFile();
- if (!parent.isDirectory() && !parent.mkdirs()) {
+ final Path parent = nullTarget ? null : targetPath.getParent();
+ if (!nullTarget && !Files.isDirectory(parent) && Files.createDirectories(parent) == null) {
throw new IOException("Failed to create directory " + parent);
}
- try (OutputStream o = Files.newOutputStream(targetFile.toPath())) {
- writer.writeEntryDataTo(nextEntry, o);
+ if (nullTarget) {
+ writer.writeEntryDataTo(nextEntry, null);
+ } else {
+ try (OutputStream outputStream = Files.newOutputStream(targetPath)) {
+ writer.writeEntryDataTo(nextEntry, outputStream);
+ }
}
}
nextEntry = supplier.getNextReadableEntry();
[commons-compress] 02/05: In most IOUtil methods, the target may be null to simulate output to dev/null on Linux and NUL on Windows.
Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
commit f2b68e96847fc6a3af50cab63f4619331633c3d9
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Feb 13 16:48:37 2022 -0500
In most IOUtil methods,the target may be null to simulate output to
dev/null on Linux and NUL on Windows.
Used a next commit.
---
.../java/org/apache/commons/compress/utils/IOUtils.java | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/main/java/org/apache/commons/compress/utils/IOUtils.java b/src/main/java/org/apache/commons/compress/utils/IOUtils.java
index a043b8e..528b858 100644
--- a/src/main/java/org/apache/commons/compress/utils/IOUtils.java
+++ b/src/main/java/org/apache/commons/compress/utils/IOUtils.java
@@ -61,7 +61,7 @@ public final class IOUtils {
* @param input
* the InputStream to copy
* @param output
- * the target Stream
+ * the target, may be null to simulate output to dev/null on Linux and NUL on Windows
* @return the number of bytes copied
* @throws IOException
* if an error occurs
@@ -76,7 +76,7 @@ public final class IOUtils {
* @param input
* the InputStream to copy
* @param output
- * the target Stream
+ * the target, may be null to simulate output to dev/null on Linux and NUL on Windows
* @param buffersize
* the buffer size to use, must be bigger than 0
* @return the number of bytes copied
@@ -93,7 +93,9 @@ public final class IOUtils {
int n = 0;
long count=0;
while (-1 != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
+ if (output != null) {
+ output.write(buffer, 0, n);
+ }
count += n;
}
return count;
@@ -309,7 +311,7 @@ public final class IOUtils {
* @param len
* maximum amount of bytes to copy
* @param output
- * the target Stream
+ * the target, may be null to simulate output to dev/null on Linux and NUL on Windows
* @param buffersize
* the buffer size to use, must be bigger than 0
* @return the number of bytes copied
@@ -328,7 +330,9 @@ public final class IOUtils {
int n = 0;
long count = 0;
while (count < len && -1 != (n = input.read(buffer, 0, (int) Math.min(len - count, buffer.length)))) {
- output.write(buffer, 0, n);
+ if (output != null) {
+ output.write(buffer, 0, n);
+ }
count += n;
}
return count;
[commons-compress] 03/05: ArchiveStreamFactory.createArchiveInputStream(String, InputStream, String) supports the "APK" format (it's a JAR).
Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
commit 2949c1f7781a10fc5289162d059d43cd77065203
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Feb 13 16:59:16 2022 -0500
ArchiveStreamFactory.createArchiveInputStream(String, InputStream,
String) supports the "APK" format (it's a JAR).
---
.../org/apache/commons/compress/archivers/ArchiveStreamFactory.java | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java b/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java
index 2d19aea..779367c 100644
--- a/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java
+++ b/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java
@@ -360,8 +360,7 @@ public class ArchiveStreamFactory implements ArchiveStreamProvider {
* read from a stream
* @throws IllegalArgumentException if the archiver name or stream is null
*/
- public ArchiveInputStream createArchiveInputStream(final String archiverName, final InputStream in)
- throws ArchiveException {
+ public ArchiveInputStream createArchiveInputStream(final String archiverName, final InputStream in) throws ArchiveException {
return createArchiveInputStream(archiverName, in, entryEncoding);
}
@@ -398,7 +397,7 @@ public class ArchiveStreamFactory implements ArchiveStreamProvider {
}
return new TarArchiveInputStream(in);
}
- if (JAR.equalsIgnoreCase(archiverName)) {
+ if (JAR.equalsIgnoreCase(archiverName) || APK.equalsIgnoreCase(archiverName)) {
if (actualEncoding != null) {
return new JarArchiveInputStream(in, actualEncoding);
}
[commons-compress] 05/05: Test reading APK files for samples generated by Android Studio.
Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
commit bbd9f349a876bc6832f049d5ae19161bb341bd90
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Feb 13 17:14:16 2022 -0500
Test reading APK files for samples generated by Android Studio.
Android Studio Bumblebee | 2021.1.1 Patch 1
Build #AI-211.7628.21.2111.8139111, built on February 1, 2022
Runtime version: 11.0.11+9-b60-7590822 amd64
VM: OpenJDK 64-Bit Server VM by Oracle Corporation
Windows 10 10.0
GC: G1 Young Generation, G1 Old Generation
Registry: external.system.auto.import.disabled=true
Non-Bundled Plugins: org.jetbrains.kotlin
(211-1.6.10-release-923-AS7442.40)
---
pom.xml | 12 ++++++
.../compress/archivers/jar/ExpandApkTest.java | 46 +++++++++++++++++++++
.../app/build/outputs/apk/debug/app-debug.apk | Bin 0 -> 1546505 bytes
.../build/outputs/apk/debug/compose-debug.apk | Bin 0 -> 6082169 bytes
.../views/build/outputs/apk/debug/views-debug.apk | Bin 0 -> 2439424 bytes
.../build/outputs/apk/debug/Application-debug.apk | Bin 0 -> 1648995 bytes
.../instant-run-apk/debug/Application-debug.apk | Bin 0 -> 45880 bytes
.../instant-run/debug/resources-debug.apk | Bin 0 -> 354355 bytes
.../split-apk/debug/dep/dependencies.apk | Bin 0 -> 918973 bytes
.../split-apk/debug/slices/slice_0.apk | Bin 0 -> 6356 bytes
.../split-apk/debug/slices/slice_1.apk | Bin 0 -> 9435 bytes
.../split-apk/debug/slices/slice_2.apk | Bin 0 -> 6367 bytes
.../split-apk/debug/slices/slice_3.apk | Bin 0 -> 10222 bytes
.../split-apk/debug/slices/slice_4.apk | Bin 0 -> 9422 bytes
.../split-apk/debug/slices/slice_5.apk | Bin 0 -> 6368 bytes
.../split-apk/debug/slices/slice_6.apk | Bin 0 -> 85660 bytes
.../split-apk/debug/slices/slice_7.apk | Bin 0 -> 13294 bytes
.../split-apk/debug/slices/slice_8.apk | Bin 0 -> 6354 bytes
.../split-apk/debug/slices/slice_9.apk | Bin 0 -> 30541 bytes
.../build/outputs/apk/debug/Application-debug.apk | Bin 0 -> 1489457 bytes
.../app/build/outputs/apk/debug/app-debug.apk | Bin 0 -> 3747603 bytes
.../apk/framework/debug/app-framework-debug.apk | Bin 0 -> 2222863 bytes
.../app/build/outputs/apk/debug/app-debug.apk | Bin 0 -> 2008249 bytes
.../app/build/outputs/apk/debug/app-debug.apk | Bin 0 -> 2827932 bytes
.../build/outputs/apk/debug/Application-debug.apk | Bin 0 -> 1632634 bytes
.../app/build/outputs/apk/debug/app-debug.apk | Bin 0 -> 6932352 bytes
.../build/outputs/apk/debug/Application-debug.apk | Bin 0 -> 1629154 bytes
27 files changed, 58 insertions(+)
diff --git a/pom.xml b/pom.xml
index 28f5bed..10bdbbc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -202,6 +202,18 @@ Brotli, Zstandard and ar, cpio, jar, tar, zip, dump, 7z, arj.
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.11.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.12.0</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.osgi</groupId>
diff --git a/src/test/java/org/apache/commons/compress/archivers/jar/ExpandApkTest.java b/src/test/java/org/apache/commons/compress/archivers/jar/ExpandApkTest.java
new file mode 100644
index 0000000..ea2ba44
--- /dev/null
+++ b/src/test/java/org/apache/commons/compress/archivers/jar/ExpandApkTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.commons.compress.archivers.jar;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+
+import org.apache.commons.compress.archivers.ArchiveStreamFactory;
+import org.apache.commons.compress.archivers.examples.Expander;
+import org.apache.commons.io.IOCase;
+import org.apache.commons.io.file.PathUtils;
+import org.apache.commons.io.filefilter.SuffixFileFilter;
+import org.apache.commons.lang3.stream.Streams;
+import org.junit.jupiter.api.Test;
+
+public class ExpandApkTest {
+
+ @Test
+ public void test() throws IOException {
+ Streams
+ .stream(
+ PathUtils.walk(Paths.get("src/test/resources/android"), new SuffixFileFilter("." + ArchiveStreamFactory.APK, IOCase.INSENSITIVE), 100, false))
+ .forEach(path -> new Expander().expand(ArchiveStreamFactory.APK, println(path), null));
+ }
+
+ private <T> T println(T object) {
+ System.out.println(object);
+ return object;
+ }
+}
diff --git a/src/test/resources/android/ActivitySceneTransitionBasic/app/build/outputs/apk/debug/app-debug.apk b/src/test/resources/android/ActivitySceneTransitionBasic/app/build/outputs/apk/debug/app-debug.apk
new file mode 100644
index 0000000..9fd736f
Binary files /dev/null and b/src/test/resources/android/ActivitySceneTransitionBasic/app/build/outputs/apk/debug/app-debug.apk differ
diff --git a/src/test/resources/android/AlwaysOnKotlin/compose/build/outputs/apk/debug/compose-debug.apk b/src/test/resources/android/AlwaysOnKotlin/compose/build/outputs/apk/debug/compose-debug.apk
new file mode 100644
index 0000000..64e6bd8
Binary files /dev/null and b/src/test/resources/android/AlwaysOnKotlin/compose/build/outputs/apk/debug/compose-debug.apk differ
diff --git a/src/test/resources/android/AlwaysOnKotlin/views/build/outputs/apk/debug/views-debug.apk b/src/test/resources/android/AlwaysOnKotlin/views/build/outputs/apk/debug/views-debug.apk
new file mode 100644
index 0000000..c523938
Binary files /dev/null and b/src/test/resources/android/AlwaysOnKotlin/views/build/outputs/apk/debug/views-debug.apk differ
diff --git a/src/test/resources/android/BasicTransition/Application/build/outputs/apk/debug/Application-debug.apk b/src/test/resources/android/BasicTransition/Application/build/outputs/apk/debug/Application-debug.apk
new file mode 100644
index 0000000..2d1f815
Binary files /dev/null and b/src/test/resources/android/BasicTransition/Application/build/outputs/apk/debug/Application-debug.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/instant-run-apk/debug/Application-debug.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/instant-run-apk/debug/Application-debug.apk
new file mode 100644
index 0000000..da3f4f3
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/instant-run-apk/debug/Application-debug.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/resources/instant-run/debug/resources-debug.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/resources/instant-run/debug/resources-debug.apk
new file mode 100644
index 0000000..77479e9
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/resources/instant-run/debug/resources-debug.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/dep/dependencies.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/dep/dependencies.apk
new file mode 100644
index 0000000..b7b5436
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/dep/dependencies.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_0.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_0.apk
new file mode 100644
index 0000000..c266255
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_0.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_1.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_1.apk
new file mode 100644
index 0000000..8095d1c
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_1.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_2.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_2.apk
new file mode 100644
index 0000000..19d4293
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_2.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_3.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_3.apk
new file mode 100644
index 0000000..438a687
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_3.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_4.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_4.apk
new file mode 100644
index 0000000..0df0b52
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_4.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_5.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_5.apk
new file mode 100644
index 0000000..b2ac1a6
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_5.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_6.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_6.apk
new file mode 100644
index 0000000..30a8669
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_6.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_7.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_7.apk
new file mode 100644
index 0000000..3bdbf54
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_7.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_8.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_8.apk
new file mode 100644
index 0000000..46cb60d
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_8.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_9.apk b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_9.apk
new file mode 100644
index 0000000..9ace4dc
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/intermediates/split-apk/debug/slices/slice_9.apk differ
diff --git a/src/test/resources/android/Camera2Basic/Application/build/outputs/apk/debug/Application-debug.apk b/src/test/resources/android/Camera2Basic/Application/build/outputs/apk/debug/Application-debug.apk
new file mode 100644
index 0000000..4e086e7
Binary files /dev/null and b/src/test/resources/android/Camera2Basic/Application/build/outputs/apk/debug/Application-debug.apk differ
diff --git a/src/test/resources/android/FragmentTransitionsRecyclerViewtoViewPager/app/build/outputs/apk/debug/app-debug.apk b/src/test/resources/android/FragmentTransitionsRecyclerViewtoViewPager/app/build/outputs/apk/debug/app-debug.apk
new file mode 100644
index 0000000..a2d7649
Binary files /dev/null and b/src/test/resources/android/FragmentTransitionsRecyclerViewtoViewPager/app/build/outputs/apk/debug/app-debug.apk differ
diff --git a/src/test/resources/android/InstantApps-CookieAPI/app/build/outputs/apk/framework/debug/app-framework-debug.apk b/src/test/resources/android/InstantApps-CookieAPI/app/build/outputs/apk/framework/debug/app-framework-debug.apk
new file mode 100644
index 0000000..e3d3a1c
Binary files /dev/null and b/src/test/resources/android/InstantApps-CookieAPI/app/build/outputs/apk/framework/debug/app-framework-debug.apk differ
diff --git a/src/test/resources/android/InstantApps-GoogleAnalyticsExample/app/build/outputs/apk/debug/app-debug.apk b/src/test/resources/android/InstantApps-GoogleAnalyticsExample/app/build/outputs/apk/debug/app-debug.apk
new file mode 100644
index 0000000..5b089b3
Binary files /dev/null and b/src/test/resources/android/InstantApps-GoogleAnalyticsExample/app/build/outputs/apk/debug/app-debug.apk differ
diff --git a/src/test/resources/android/InstantApps-InstallAPIsample/app/build/outputs/apk/debug/app-debug.apk b/src/test/resources/android/InstantApps-InstallAPIsample/app/build/outputs/apk/debug/app-debug.apk
new file mode 100644
index 0000000..3bd4b30
Binary files /dev/null and b/src/test/resources/android/InstantApps-InstallAPIsample/app/build/outputs/apk/debug/app-debug.apk differ
diff --git a/src/test/resources/android/Interpolator/Application/build/outputs/apk/debug/Application-debug.apk b/src/test/resources/android/Interpolator/Application/build/outputs/apk/debug/Application-debug.apk
new file mode 100644
index 0000000..307bee1
Binary files /dev/null and b/src/test/resources/android/Interpolator/Application/build/outputs/apk/debug/Application-debug.apk differ
diff --git a/src/test/resources/android/Motion/app/build/outputs/apk/debug/app-debug.apk b/src/test/resources/android/Motion/app/build/outputs/apk/debug/app-debug.apk
new file mode 100644
index 0000000..fe0c0d7
Binary files /dev/null and b/src/test/resources/android/Motion/app/build/outputs/apk/debug/app-debug.apk differ
diff --git a/src/test/resources/android/RevealEffectBasic/Application/build/outputs/apk/debug/Application-debug.apk b/src/test/resources/android/RevealEffectBasic/Application/build/outputs/apk/debug/Application-debug.apk
new file mode 100644
index 0000000..95bcfaf
Binary files /dev/null and b/src/test/resources/android/RevealEffectBasic/Application/build/outputs/apk/debug/Application-debug.apk differ
[commons-compress] 01/05: Clearer local variable name.
Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-compress.git
commit 5b3c8f72c20239fcc6b04592e3d06b15e94cc6d8
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Feb 13 12:33:21 2022 -0500
Clearer local variable name.
---
.../commons/compress/archivers/examples/Expander.java | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java b/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java
index 960a9dd..e6c425e 100644
--- a/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java
+++ b/src/main/java/org/apache/commons/compress/archivers/examples/Expander.java
@@ -345,24 +345,24 @@ public class Expander {
}
ArchiveEntry nextEntry = supplier.getNextReadableEntry();
while (nextEntry != null) {
- final File f = new File(targetDirectory, nextEntry.getName());
+ final File targetFile = new File(targetDirectory, nextEntry.getName());
// check if targetDirectory and f are the same path - this may
// happen if the nextEntry.getName() is "./"
- if (!f.getCanonicalPath().startsWith(targetDirPath)
- && !Files.isSameFile(targetDirectory.toPath(), f.toPath())) {
+ if (!targetFile.getCanonicalPath().startsWith(targetDirPath)
+ && !Files.isSameFile(targetDirectory.toPath(), targetFile.toPath())) {
throw new IOException("Expanding " + nextEntry.getName()
+ " would create file outside of " + targetDirectory);
}
if (nextEntry.isDirectory()) {
- if (!f.isDirectory() && !f.mkdirs()) {
- throw new IOException("Failed to create directory " + f);
+ if (!targetFile.isDirectory() && !targetFile.mkdirs()) {
+ throw new IOException("Failed to create directory " + targetFile);
}
} else {
- final File parent = f.getParentFile();
+ final File parent = targetFile.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IOException("Failed to create directory " + parent);
}
- try (OutputStream o = Files.newOutputStream(f.toPath())) {
+ try (OutputStream o = Files.newOutputStream(targetFile.toPath())) {
writer.writeEntryDataTo(nextEntry, o);
}
}