summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenoit Lamarche <benoitlamarche@google.com>2015-01-26 18:09:38 +0100
committerBenoit Lamarche <benoitlamarche@google.com>2015-01-27 14:37:48 +0100
commita67dc42085d6f9fa9d4dfcccd908a6a7645af70a (patch)
tree529452cb954e4810172ea9e0ea14910c8b6b2792
parent4d7a9d313dfa7251c9ca5cd3cf6d47cc0723fb53 (diff)
downloadtoolchain_jack-a67dc42085d6f9fa9d4dfcccd908a6a7645af70a.zip
toolchain_jack-a67dc42085d6f9fa9d4dfcccd908a6a7645af70a.tar.gz
toolchain_jack-a67dc42085d6f9fa9d4dfcccd908a6a7645af70a.tar.bz2
Add VFSToVFSWrapper and ReadWriteZipFS
Change-Id: I447734418fb04e2e0e3186dcbb1c37c5b769e2d4
-rw-r--r--sched/src/com/android/sched/vfs/ReadWriteZipFS.java101
-rw-r--r--sched/src/com/android/sched/vfs/VFSToVFSWrapper.java162
-rw-r--r--sched/tests/com/android/sched/vfs/VFSTest.java36
3 files changed, 299 insertions, 0 deletions
diff --git a/sched/src/com/android/sched/vfs/ReadWriteZipFS.java b/sched/src/com/android/sched/vfs/ReadWriteZipFS.java
new file mode 100644
index 0000000..1aa0ca6
--- /dev/null
+++ b/sched/src/com/android/sched/vfs/ReadWriteZipFS.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 com.android.sched.vfs;
+
+import com.google.common.io.Files;
+
+import com.android.sched.util.file.CannotCreateFileException;
+import com.android.sched.util.file.CannotSetPermissionException;
+import com.android.sched.util.file.Directory;
+import com.android.sched.util.file.FileAlreadyExistsException;
+import com.android.sched.util.file.FileOrDirectory.ChangePermission;
+import com.android.sched.util.file.FileOrDirectory.Existence;
+import com.android.sched.util.file.FileOrDirectory.Permission;
+import com.android.sched.util.file.FileUtils;
+import com.android.sched.util.file.NoSuchFileException;
+import com.android.sched.util.file.NotDirectoryException;
+import com.android.sched.util.file.OutputZipFile;
+import com.android.sched.util.file.WrongPermissionException;
+import com.android.sched.util.location.Location;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A {@link VFS} backed by a real filesystem directory, compressed into a zip archive when closed.
+ */
+public class ReadWriteZipFS implements VFS {
+
+ @Nonnull
+ private final VFSToVFSWrapper vfs;
+ @Nonnull
+ private final File dir;
+
+ public ReadWriteZipFS(@Nonnull OutputZipFile file)
+ throws NotDirectoryException,
+ WrongPermissionException,
+ CannotSetPermissionException,
+ NoSuchFileException,
+ FileAlreadyExistsException,
+ CannotCreateFileException {
+ int permissions = Permission.READ | Permission.WRITE;
+ dir = Files.createTempDir();
+ DirectFS workVFS = new DirectFS(new Directory(dir.getPath(), null, Existence.MUST_EXIST,
+ permissions, ChangePermission.NOCHANGE), permissions);
+ WriteZipFS finalVFS = new WriteZipFS(file);
+ this.vfs = new VFSToVFSWrapper(workVFS, finalVFS);
+ }
+
+ @Override
+ @Nonnull
+ public Location getLocation() {
+ return vfs.getLocation();
+ }
+
+ @Override
+ public void close() throws IOException {
+ vfs.close();
+ if (dir.exists()) {
+ FileUtils.deleteDir(dir);
+ }
+ }
+
+ @Override
+ @Nonnull
+ public String getDescription() {
+ return "zip archive writer that uses a temporary directory";
+ }
+
+ @Override
+ @Nonnull
+ public String getPath() {
+ return vfs.getPath();
+ }
+
+ @Override
+ @Nonnull
+ public VDir getRootDir() {
+ return vfs.getRootDir();
+ }
+
+ @Override
+ public boolean needsSequentialWriting() {
+ return vfs.needsSequentialWriting();
+ }
+}
diff --git a/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java b/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java
new file mode 100644
index 0000000..3e380a6
--- /dev/null
+++ b/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 com.android.sched.vfs;
+
+import com.android.sched.util.file.CannotCreateFileException;
+import com.android.sched.util.file.WrongPermissionException;
+import com.android.sched.util.location.Location;
+import com.android.sched.util.stream.ByteStreamSucker;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A double {@link VFS} wrapper that uses a work {@link VFS} during its life, and dumps it contents
+ * into a final {@link VFS} when it is closed.
+ */
+public class VFSToVFSWrapper implements VFS {
+
+ @Nonnull
+ private final BaseVFS<BaseVDir, BaseVFile> workVFS;
+ @Nonnull
+ private final BaseVFS<BaseVDir, BaseVFile> finalVFS;
+ @Nonnull
+ private final Set<Capabilities> capabilities;
+
+ private boolean closed = false;
+
+ @SuppressWarnings("unchecked")
+ public VFSToVFSWrapper(@Nonnull BaseVFS<? extends BaseVDir, ? extends BaseVFile> workVFS,
+ @Nonnull BaseVFS<? extends BaseVDir, ? extends BaseVFile> finalVFS) {
+ this.workVFS = (BaseVFS<BaseVDir, BaseVFile>) workVFS;
+ this.finalVFS = (BaseVFS<BaseVDir, BaseVFile>) finalVFS;
+
+ Set<Capabilities> capabilities = EnumSet.noneOf(Capabilities.class);
+ for (Capabilities capability : workVFS.getCapabilities()) {
+ switch (capability) {
+ case CASE_SENSITIVE:
+ if (finalVFS.getCapabilities().contains(capability)) {
+ // both VFSes need to support case sensitivity for this wrapper to support it
+ capabilities.add(capability);
+ }
+ break;
+ case DIGEST:
+ capabilities.add(capability);
+ break;
+ case PARALLEL_READ:
+ capabilities.add(capability);
+ break;
+ case PARALLEL_WRITE:
+ capabilities.add(capability);
+ break;
+ case READ:
+ capabilities.add(capability);
+ break;
+ case UNIQUE_ELEMENT:
+ capabilities.add(capability);
+ break;
+ case WRITE:
+ capabilities.add(capability);
+ break;
+ default:
+ throw new AssertionError();
+ }
+ }
+ this.capabilities = Collections.unmodifiableSet(capabilities);
+ }
+
+ @Override
+ @Nonnull
+ public Location getLocation() {
+ return finalVFS.getLocation();
+ }
+
+ @Override
+ public void close() throws CannotCreateFileException, WrongPermissionException, IOException {
+ if (!closed) {
+ dumpToDir(getRootDir(), finalVFS.getRootDir());
+ finalVFS.close();
+ workVFS.close();
+ closed = true;
+ }
+ }
+
+ private void dumpToDir(VDir srcRootDir, VDir destRootDir) throws CannotCreateFileException,
+ WrongPermissionException, IOException {
+ for (VElement element : srcRootDir.list()) {
+ String elementName = element.getName();
+ if (element.isVDir()) {
+ VDir dir = destRootDir.createVDir(elementName);
+ dumpToDir((VDir) element, dir);
+ } else {
+ VFile file = destRootDir.createVFile(elementName);
+ InputStream is = null;
+ OutputStream os = null;
+ try {
+ is = ((VFile) element).openRead();
+ os = file.openWrite();
+ ByteStreamSucker sucker = new ByteStreamSucker(is, os);
+ sucker.suck();
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ if (os != null) {
+ os.close();
+ }
+ }
+ }
+ }
+
+ }
+
+ @Override
+ @Nonnull
+ public String getDescription() {
+ return "a VFS-to-VFS wrapper";
+ }
+
+ @Override
+ @Nonnull
+ public String getPath() {
+ return finalVFS.getPath();
+ }
+
+ @Override
+ @Nonnull
+ public VDir getRootDir() {
+ return workVFS.getRootDir();
+ }
+
+ @Override
+ public boolean needsSequentialWriting() {
+ return workVFS.needsSequentialWriting();
+ }
+
+ @Override
+ @Nonnull
+ public Set<Capabilities> getCapabilities() {
+ return this.capabilities;
+ }
+
+}
diff --git a/sched/tests/com/android/sched/vfs/VFSTest.java b/sched/tests/com/android/sched/vfs/VFSTest.java
index c9b1981..401e3d1 100644
--- a/sched/tests/com/android/sched/vfs/VFSTest.java
+++ b/sched/tests/com/android/sched/vfs/VFSTest.java
@@ -504,6 +504,42 @@ public class VFSTest {
Assert.assertEquals("dirB/dirBB/fileBB1", readFromFile(fileBB1));
}
+ @Test
+ public void testReadWriteZipFS()
+ throws NotDirectoryException,
+ CannotCreateFileException,
+ WrongPermissionException,
+ CannotSetPermissionException,
+ NoSuchFileException,
+ FileAlreadyExistsException,
+ IOException {
+ File file = null;
+ InputOutputVFS zipVFS = null;
+ InputZipVFS inputZipVFS = null;
+ try {
+ file = File.createTempFile("vfs", ".zip");
+ String path = file.getAbsolutePath();
+ zipVFS = new GenericInputOutputVFS(new ReadWriteZipFS(
+ new OutputZipFile(path, null, Existence.MAY_EXIST, ChangePermission.NOCHANGE)));
+ testOutputVFS(zipVFS);
+ testInputVFS(zipVFS);
+ zipVFS.close();
+ inputZipVFS = new InputZipVFS(
+ new InputZipFile(path, null, Existence.MUST_EXIST, ChangePermission.NOCHANGE));
+ testInputVFS(inputZipVFS);
+ } finally {
+ if (zipVFS != null) {
+ zipVFS.close();
+ }
+ if (inputZipVFS != null) {
+ inputZipVFS.close();
+ }
+ if (file != null) {
+ Assert.assertTrue(file.delete());
+ }
+ }
+ }
+
private boolean containsFile(@Nonnull Collection<? extends InputVElement> elements,
@Nonnull String fileSimpleName, @Nonnull String fileContent) throws IOException {
for (VElement element : elements) {