diff options
author | Benoit Lamarche <benoitlamarche@google.com> | 2014-07-25 12:09:39 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-07-23 19:33:25 +0000 |
commit | 5c8ec05f6180f26c73745fead5d14045fc84e6d4 (patch) | |
tree | 3e2cd23997c799b803e28cb800380c0893e022f0 | |
parent | 4a3eaf7d351160a937021fc07fbeb8d2173a066b (diff) | |
parent | 4a87cec7f6314b573b7b4ef0fee3af1129f900e1 (diff) | |
download | toolchain_jack-5c8ec05f6180f26c73745fead5d14045fc84e6d4.tar.gz toolchain_jack-5c8ec05f6180f26c73745fead5d14045fc84e6d4.tar.bz2 toolchain_jack-5c8ec05f6180f26c73745fead5d14045fc84e6d4.zip |
Merge "Return errors when writing VFiles w/o closing" into ub-jack
5 files changed, 134 insertions, 14 deletions
diff --git a/sched/src/com/android/sched/vfs/SequentialOutputVDir.java b/sched/src/com/android/sched/vfs/SequentialOutputVDir.java new file mode 100644 index 00000000..73320182 --- /dev/null +++ b/sched/src/com/android/sched/vfs/SequentialOutputVDir.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2014 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 java.util.concurrent.atomic.AtomicBoolean; + +import javax.annotation.Nonnull; + + +/** + * {@link OutputVDir} that contains {@link OutputVFile}s that must be written to and closed + * sequentially. + */ +public abstract class SequentialOutputVDir extends AbstractVElement implements OutputVDir { + + @Nonnull + private final AtomicBoolean lastVFileOpen = new AtomicBoolean(false); + + public void notifyVFileClosed() { + boolean previousState = lastVFileOpen.getAndSet(false); + assert previousState; + } + + public boolean notifyVFileOpenAndReturnPreviousState() { + return lastVFileOpen.getAndSet(true); + } + +} diff --git a/sched/src/com/android/sched/vfs/direct/DirectDir.java b/sched/src/com/android/sched/vfs/direct/DirectDir.java index c097cd57..789b37de 100644 --- a/sched/src/com/android/sched/vfs/direct/DirectDir.java +++ b/sched/src/com/android/sched/vfs/direct/DirectDir.java @@ -23,12 +23,12 @@ import com.android.sched.util.file.NotFileOrDirectoryException; import com.android.sched.util.location.DirectoryLocation; import com.android.sched.util.location.FileLocation; import com.android.sched.util.location.Location; -import com.android.sched.vfs.AbstractVElement; import com.android.sched.vfs.InputOutputVDir; import com.android.sched.vfs.InputRootVDir; import com.android.sched.vfs.InputVElement; import com.android.sched.vfs.InputVFile; import com.android.sched.vfs.OutputVFile; +import com.android.sched.vfs.SequentialOutputVDir; import com.android.sched.vfs.VPath; import java.io.File; @@ -42,7 +42,7 @@ import javax.annotation.Nonnull; /** * Directory in the file system. */ -public class DirectDir extends AbstractVElement implements InputRootVDir, InputOutputVDir { +public class DirectDir extends SequentialOutputVDir implements InputRootVDir, InputOutputVDir { @Nonnull private final File dir; @@ -50,10 +50,13 @@ public class DirectDir extends AbstractVElement implements InputRootVDir, InputO private ArrayList<InputVElement> list; @Nonnull private final Location location; + @Nonnull + private final InputOutputVDir vfsRoot; public DirectDir(@Nonnull Directory directory) { dir = directory.getFile(); location = directory.getLocation(); + vfsRoot = this; } public DirectDir(@Nonnull File dir) throws NotFileOrDirectoryException { @@ -62,6 +65,17 @@ public class DirectDir extends AbstractVElement implements InputRootVDir, InputO } this.dir = dir; location = new FileLocation(dir); + vfsRoot = this; + } + + DirectDir(@Nonnull File dir, @Nonnull InputOutputVDir vfsRoot) + throws NotFileOrDirectoryException { + if (!dir.isDirectory()) { + throw new NotFileOrDirectoryException(new DirectoryLocation(dir)); + } + this.dir = dir; + location = new FileLocation(dir); + this.vfsRoot = vfsRoot; } @Nonnull @@ -86,9 +100,9 @@ public class DirectDir extends AbstractVElement implements InputRootVDir, InputO for (File sub : subs) { try { if (sub.isFile()) { - list.add(new DirectFile(sub)); + list.add(new DirectFile(sub, vfsRoot)); } else { - list.add(new DirectDir(sub)); + list.add(new DirectDir(sub, vfsRoot)); } } catch (NotFileOrDirectoryException e) { throw new ConcurrentIOException(e); @@ -113,7 +127,7 @@ public class DirectDir extends AbstractVElement implements InputRootVDir, InputO if (!file.isFile()) { throw new NotFileOrDirectoryException(new FileLocation(file)); } - return new DirectFile(file); + return new DirectFile(file, vfsRoot); } @Override @@ -123,7 +137,7 @@ public class DirectDir extends AbstractVElement implements InputRootVDir, InputO if (!file.getParentFile().mkdirs() && !file.getParentFile().isDirectory()) { throw new CannotCreateFileException(new DirectoryLocation(file.getParentFile())); } - return new DirectFile(file); + return new DirectFile(file, vfsRoot); } @Override diff --git a/sched/src/com/android/sched/vfs/direct/DirectFile.java b/sched/src/com/android/sched/vfs/direct/DirectFile.java index 63abca02..3bb7fa5b 100644 --- a/sched/src/com/android/sched/vfs/direct/DirectFile.java +++ b/sched/src/com/android/sched/vfs/direct/DirectFile.java @@ -19,12 +19,17 @@ package com.android.sched.vfs.direct; import com.android.sched.util.location.FileLocation; import com.android.sched.util.location.Location; import com.android.sched.vfs.AbstractVElement; +import com.android.sched.vfs.InputOutputVDir; import com.android.sched.vfs.InputOutputVFile; +import com.android.sched.vfs.OutputVDir; +import com.android.sched.vfs.SequentialOutputVDir; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -37,9 +42,12 @@ public class DirectFile extends AbstractVElement implements InputOutputVFile { @Nonnull private final File file; + @Nonnull + private final InputOutputVDir vfsRoot; - public DirectFile(@Nonnull File file) { + public DirectFile(@Nonnull File file, @Nonnull InputOutputVDir vfsRoot) { this.file = file; + this.vfsRoot = vfsRoot; } @Nonnull @@ -51,7 +59,13 @@ public class DirectFile extends AbstractVElement implements InputOutputVFile { @Nonnull @Override public OutputStream openWrite() throws FileNotFoundException { - return new FileOutputStream(file); + if (vfsRoot instanceof SequentialOutputVDir) { + if (((SequentialOutputVDir) vfsRoot).notifyVFileOpenAndReturnPreviousState()) { + throw new AssertionError(getLocation().getDescription() + + " cannot be written to because a previous stream has not been closed."); + } + } + return new VFileOutputStream(new FileOutputStream(file), vfsRoot); } @Nonnull @@ -70,4 +84,23 @@ public class DirectFile extends AbstractVElement implements InputOutputVFile { public boolean isVDir() { return false; } + + private static class VFileOutputStream extends FilterOutputStream { + + private final OutputVDir vfsRoot; + + public VFileOutputStream(@Nonnull OutputStream out, @Nonnull OutputVDir vfsRoot) { + super(out); + this.vfsRoot = vfsRoot; + } + + @Override + public void close() throws IOException { + super.close(); + if (vfsRoot instanceof SequentialOutputVDir) { + ((SequentialOutputVDir) vfsRoot).notifyVFileClosed(); + } + } + + } } diff --git a/sched/src/com/android/sched/vfs/zip/OutputZipRootVDir.java b/sched/src/com/android/sched/vfs/zip/OutputZipRootVDir.java index 48c08b78..a1962d18 100644 --- a/sched/src/com/android/sched/vfs/zip/OutputZipRootVDir.java +++ b/sched/src/com/android/sched/vfs/zip/OutputZipRootVDir.java @@ -19,9 +19,9 @@ package com.android.sched.vfs.zip; import com.android.sched.util.file.OutputZipFile; import com.android.sched.util.location.Location; import com.android.sched.util.location.ZipLocation; -import com.android.sched.vfs.AbstractVElement; import com.android.sched.vfs.OutputVDir; import com.android.sched.vfs.OutputVFile; +import com.android.sched.vfs.SequentialOutputVDir; import com.android.sched.vfs.VElement; import com.android.sched.vfs.VPath; @@ -36,7 +36,7 @@ import javax.annotation.Nonnull; /** * A root {@link OutputVDir} backed by a zip archive. */ -public class OutputZipRootVDir extends AbstractVElement implements OutputVDir, Closeable { +public class OutputZipRootVDir extends SequentialOutputVDir implements OutputVDir, Closeable { @Nonnull protected final HashMap<String, VElement> subs = new HashMap<String, VElement>(); @@ -65,7 +65,8 @@ public class OutputZipRootVDir extends AbstractVElement implements OutputVDir, C @Override @Nonnull public OutputVFile createOutputVFile(@Nonnull VPath path) { - return new OutputZipVFile(zos, new ZipEntry(path.getPathAsString(getSeparator())), zipFile); + return new OutputZipVFile(zos, new ZipEntry(path.getPathAsString(getSeparator())), zipFile, + this); } @Override diff --git a/sched/src/com/android/sched/vfs/zip/OutputZipVFile.java b/sched/src/com/android/sched/vfs/zip/OutputZipVFile.java index 5daecc89..159c5df8 100644 --- a/sched/src/com/android/sched/vfs/zip/OutputZipVFile.java +++ b/sched/src/com/android/sched/vfs/zip/OutputZipVFile.java @@ -19,10 +19,12 @@ package com.android.sched.vfs.zip; import com.android.sched.util.file.OutputZipFile; import com.android.sched.util.location.Location; import com.android.sched.util.location.ZipLocation; -import com.android.sched.util.stream.UncloseableOutputStream; import com.android.sched.vfs.AbstractVElement; +import com.android.sched.vfs.OutputVDir; import com.android.sched.vfs.OutputVFile; +import com.android.sched.vfs.SequentialOutputVDir; +import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.zip.ZipEntry; @@ -38,19 +40,28 @@ class OutputZipVFile extends AbstractVElement implements OutputVFile { private final ZipEntry entry; @Nonnull private final Location location; + @Nonnull + private final OutputVDir vfsRoot; OutputZipVFile(@Nonnull ZipOutputStream zos, @Nonnull ZipEntry entry, - @Nonnull OutputZipFile zipFile) { + @Nonnull OutputZipFile zipFile, @Nonnull OutputVDir vfsRoot) { this.zos = zos; this.entry = entry; location = new ZipLocation(zipFile.getLocation(), entry); + this.vfsRoot = vfsRoot; } @Nonnull @Override public OutputStream openWrite() throws IOException { zos.putNextEntry(entry); - return new UncloseableOutputStream(zos); + if (vfsRoot instanceof SequentialOutputVDir) { + if (((SequentialOutputVDir) vfsRoot).notifyVFileOpenAndReturnPreviousState()) { + throw new AssertionError(getLocation().getDescription() + + " cannot be written to because a previous stream has not been closed."); + } + } + return new UnclosableVFileOutputStream(zos, vfsRoot); } @Override @@ -63,4 +74,23 @@ class OutputZipVFile extends AbstractVElement implements OutputVFile { public boolean isVDir() { return false; } + + private static class UnclosableVFileOutputStream extends FilterOutputStream { + + private final OutputVDir vfsRoot; + + public UnclosableVFileOutputStream(@Nonnull OutputStream out, @Nonnull OutputVDir vfsRoot) { + super(out); + this.vfsRoot = vfsRoot; + } + + @Override + public void close() { + // we do not actually close the stream + if (vfsRoot instanceof SequentialOutputVDir) { + ((SequentialOutputVDir) vfsRoot).notifyVFileClosed(); + } + } + + } } |