aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java54
1 files changed, 48 insertions, 6 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java
index 393110d5f8..4830d8fe19 100644
--- a/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/vfs/ZipFileSystem.java
@@ -15,11 +15,15 @@ package com.google.devtools.build.lib.vfs;
import com.google.common.base.Predicate;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
+import com.google.devtools.build.lib.util.Preconditions;
+import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -31,9 +35,11 @@ import java.util.zip.ZipFile;
* Inherits the constraints imposed by ReadonlyFileSystem.
*/
@ThreadSafe
-public class ZipFileSystem extends ReadonlyFileSystem {
+public class ZipFileSystem extends ReadonlyFileSystem implements Closeable {
+ private final File tempFile; // In case this needs to be written to the file system
private final ZipFile zipFile;
+ private boolean open;
/**
* The sole purpose of this field is to hold a strong reference to all leaf
@@ -53,14 +59,25 @@ public class ZipFileSystem extends ReadonlyFileSystem {
* Constructs a ZipFileSystem from a zip file identified with a given path.
*/
public ZipFileSystem(Path zipPath) throws IOException {
- // Throw some more specific exceptions than ZipFile does.
- // We do this using File instead of Path, in case zipPath points to an
- // InMemoryFileSystem. This case is not really supported but
- // can occur in tests.
+ if (!zipPath.exists()) {
+ throw new FileNotFoundException(String.format("File '%s' does not exist", zipPath));
+ }
+
File file = zipPath.getPathFile();
if (!file.exists()) {
- throw new FileNotFoundException(String.format("File '%s' does not exist", zipPath));
+ // If the File says that it does not exist but the Path says that it does, we are probably
+ // dealing with a FileSystem that does not represent the actual file system we are running
+ // under. Then we copy the Path into a temporary File.
+ tempFile = File.createTempFile("bazel.test.", ".tmp");
+ file = tempFile;
+ byte[] contents = FileSystemUtils.readContent(zipPath);
+ try (OutputStream os = new FileOutputStream(tempFile)) {
+ os.write(contents);
+ }
+ } else {
+ tempFile = null;
}
+
if (!file.isFile()) {
throw new IOException(String.format("'%s' is not a file", zipPath));
}
@@ -70,6 +87,7 @@ public class ZipFileSystem extends ReadonlyFileSystem {
this.zipFile = new ZipFile(file);
this.paths = populatePathTree();
+ this.open = true;
}
// ZipPath extends Path with a set-once ZipEntry field.
@@ -160,12 +178,14 @@ public class ZipFileSystem extends ReadonlyFileSystem {
@Override
protected InputStream getInputStream(Path path) throws IOException {
+ Preconditions.checkState(open);
return zipFile.getInputStream(zipEntryNonNull(path));
}
@Override
protected Collection<Path> getDirectoryEntries(Path path)
throws IOException {
+ Preconditions.checkState(open);
zipEntryNonNull(path);
final Collection<Path> result = new ArrayList<>();
((ZipPath) path).applyToChildren(new Predicate<Path>() {
@@ -182,46 +202,54 @@ public class ZipFileSystem extends ReadonlyFileSystem {
@Override
protected boolean exists(Path path, boolean followSymlinks) {
+ Preconditions.checkState(open);
return zipEntry(path) != null;
}
@Override
protected boolean isDirectory(Path path, boolean followSymlinks) {
+ Preconditions.checkState(open);
ZipEntry entry = zipEntry(path);
return entry != null && entry.isDirectory();
}
@Override
protected boolean isFile(Path path, boolean followSymlinks) {
+ Preconditions.checkState(open);
ZipEntry entry = zipEntry(path);
return entry != null && !entry.isDirectory();
}
@Override
protected boolean isSpecialFile(Path path, boolean followSymlinks) {
+ Preconditions.checkState(open);
return false;
}
@Override
protected boolean isReadable(Path path) throws IOException {
+ Preconditions.checkState(open);
zipEntryNonNull(path);
return true;
}
@Override
protected boolean isWritable(Path path) throws IOException {
+ Preconditions.checkState(open);
zipEntryNonNull(path);
return false;
}
@Override
protected boolean isExecutable(Path path) throws IOException {
+ Preconditions.checkState(open);
zipEntryNonNull(path);
return false;
}
@Override
protected PathFragment readSymbolicLink(Path path) throws IOException {
+ Preconditions.checkState(open);
zipEntryNonNull(path);
throw new NotASymlinkException(path);
}
@@ -229,22 +257,26 @@ public class ZipFileSystem extends ReadonlyFileSystem {
@Override
protected long getFileSize(Path path, boolean followSymlinks)
throws IOException {
+ Preconditions.checkState(open);
return zipEntryNonNull(path).getSize();
}
@Override
protected long getLastModifiedTime(Path path, boolean followSymlinks)
throws FileNotFoundException {
+ Preconditions.checkState(open);
return zipEntryNonNull(path).getTime();
}
@Override
protected boolean isSymbolicLink(Path path) {
+ Preconditions.checkState(open);
return false;
}
@Override
protected FileStatus statIfFound(Path path, boolean followSymlinks) {
+ Preconditions.checkState(open);
try {
return stat(path, followSymlinks);
} catch (FileNotFoundException e) {
@@ -255,4 +287,14 @@ public class ZipFileSystem extends ReadonlyFileSystem {
}
}
+ @Override
+ public void close() {
+ if (open) {
+ close();
+ if (tempFile != null) {
+ tempFile.delete();
+ }
+ open = false;
+ }
+ }
}