import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.file.Files;
import java.util.Iterator;
import java.util.Set;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.ThreadSafe;
+import org.checkerframework.checker.lock.qual.GuardedBy;
+import org.checkerframework.checker.lock.qual.Holding;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*
* @author Thomas Pantelis
*/
-@ThreadSafe
public class FileBackedOutputStream extends OutputStream {
private static final Logger LOG = LoggerFactory.getLogger(FileBackedOutputStream.class);
* @param fileDirectory the directory in which to create the file if needed. If null, the default temp file
* location is used.
*/
- public FileBackedOutputStream(int fileThreshold, @Nullable String fileDirectory) {
+ public FileBackedOutputStream(final int fileThreshold, @Nullable final String fileDirectory) {
this.fileThreshold = fileThreshold;
this.fileDirectory = fileDirectory;
}
* @return a ByteSource instance
* @throws IOException if close fails
*/
- @Nonnull
- public synchronized ByteSource asByteSource() throws IOException {
+ public synchronized @NonNull ByteSource asByteSource() throws IOException {
close();
if (source == null) {
public InputStream openStream() throws IOException {
synchronized (FileBackedOutputStream.this) {
if (file != null) {
- return new FileInputStream(file);
+ return Files.newInputStream(file.toPath());
} else {
return new ByteArrayInputStream(memory.getBuffer(), 0, memory.getCount());
}
@Override
@SuppressFBWarnings(value = "VO_VOLATILE_INCREMENT", justification = "Findbugs erroneously complains that the "
+ "increment of count needs to be atomic even though it is inside a synchronized block.")
- public synchronized void write(int value) throws IOException {
+ public synchronized void write(final int value) throws IOException {
possiblySwitchToFile(1);
out.write(value);
count++;
}
@Override
- public synchronized void write(byte[] bytes) throws IOException {
+ public synchronized void write(final byte[] bytes) throws IOException {
write(bytes, 0, bytes.length);
}
@Override
- public synchronized void write(byte[] bytes, int off, int len) throws IOException {
+ public synchronized void write(final byte[] bytes, final int off, final int len) throws IOException {
possiblySwitchToFile(len);
out.write(bytes, off, len);
count += len;
}
}
- @GuardedBy("this")
+ @Holding("this")
private void closeQuietly() {
try {
close();
/**
* Checks if writing {@code len} bytes would go over threshold, and switches to file buffering if so.
*/
- @GuardedBy("this")
- private void possiblySwitchToFile(int len) throws IOException {
+ @Holding("this")
+ private void possiblySwitchToFile(final int len) throws IOException {
if (out == null) {
throw new IOException("Stream already closed");
}
if (file == null && memory.getCount() + len > fileThreshold) {
- File temp = File.createTempFile("FileBackedOutputStream", null, new File(fileDirectory));
+ File temp = File.createTempFile("FileBackedOutputStream", null,
+ fileDirectory == null ? null : new File(fileDirectory));
temp.deleteOnExit();
LOG.debug("Byte count {} has exceeded threshold {} - switching to file: {}", memory.getCount() + len,
fileThreshold, temp);
- FileOutputStream transfer = null;
+ OutputStream transfer = null;
try {
- transfer = new FileOutputStream(temp);
+ transfer = Files.newOutputStream(temp.toPath());
transfer.write(memory.getBuffer(), 0, memory.getCount());
transfer.flush();
}
}
- private static void deleteFile(File file) {
+ private static void deleteFile(final File file) {
if (!file.delete()) {
LOG.warn("Could not delete temp file {}", file);
}
private static class Cleanup extends FinalizablePhantomReference<FileBackedOutputStream> {
private final File file;
- Cleanup(FileBackedOutputStream referent, File file) {
+ Cleanup(final FileBackedOutputStream referent, final File file) {
super(referent, REFERENCE_QUEUE);
this.file = file;