/*
 * Copyright (C) 2015 Square, Inc.
 *
 * 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 okhttp3.internal.io;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import okio.Okio;
import okio.Sink;
import okio.Source;

Access to read and write files on a hierarchical data store. Most callers should use the SYSTEM implementation, which uses the host machine's local file system. Alternate implementations may be used to inject faults (for testing) or to transform stored data (to add encryption, for example).

All operations on a file system are racy. For example, guarding a call to source with exists does not guarantee that FileNotFoundException will not be thrown. The file may be moved between the two calls!

This interface is less ambitious than FileSystem introduced in Java 7. It lacks important features like file watching, metadata, permissions, and disk space information. In exchange for these limitations, this interface is easier to implement and works on all versions of Java and Android.

/** * Access to read and write files on a hierarchical data store. Most callers should use the {@link * #SYSTEM} implementation, which uses the host machine's local file system. Alternate * implementations may be used to inject faults (for testing) or to transform stored data (to add * encryption, for example). * * <p>All operations on a file system are racy. For example, guarding a call to {@link #source} with * {@link #exists} does not guarantee that {@link FileNotFoundException} will not be thrown. The * file may be moved between the two calls! * * <p>This interface is less ambitious than {@link java.nio.file.FileSystem} introduced in Java 7. * It lacks important features like file watching, metadata, permissions, and disk space * information. In exchange for these limitations, this interface is easier to implement and works * on all versions of Java and Android. */
public interface FileSystem {
The host machine's local file system.
/** The host machine's local file system. */
FileSystem SYSTEM = new FileSystem() { @Override public Source source(File file) throws FileNotFoundException { return Okio.source(file); } @Override public Sink sink(File file) throws FileNotFoundException { try { return Okio.sink(file); } catch (FileNotFoundException e) { // Maybe the parent directory doesn't exist? Try creating it first. file.getParentFile().mkdirs(); return Okio.sink(file); } } @Override public Sink appendingSink(File file) throws FileNotFoundException { try { return Okio.appendingSink(file); } catch (FileNotFoundException e) { // Maybe the parent directory doesn't exist? Try creating it first. file.getParentFile().mkdirs(); return Okio.appendingSink(file); } } @Override public void delete(File file) throws IOException { // If delete() fails, make sure it's because the file didn't exist! if (!file.delete() && file.exists()) { throw new IOException("failed to delete " + file); } } @Override public boolean exists(File file) { return file.exists(); } @Override public long size(File file) { return file.length(); } @Override public void rename(File from, File to) throws IOException { delete(to); if (!from.renameTo(to)) { throw new IOException("failed to rename " + from + " to " + to); } } @Override public void deleteContents(File directory) throws IOException { File[] files = directory.listFiles(); if (files == null) { throw new IOException("not a readable directory: " + directory); } for (File file : files) { if (file.isDirectory()) { deleteContents(file); } if (!file.delete()) { throw new IOException("failed to delete " + file); } } } };
Reads from file.
/** Reads from {@code file}. */
Source source(File file) throws FileNotFoundException;
Writes to file, discarding any data already present. Creates parent directories if necessary.
/** * Writes to {@code file}, discarding any data already present. Creates parent directories if * necessary. */
Sink sink(File file) throws FileNotFoundException;
Writes to file, appending if data is already present. Creates parent directories if necessary.
/** * Writes to {@code file}, appending if data is already present. Creates parent directories if * necessary. */
Sink appendingSink(File file) throws FileNotFoundException;
Deletes file if it exists. Throws if the file exists and cannot be deleted.
/** Deletes {@code file} if it exists. Throws if the file exists and cannot be deleted. */
void delete(File file) throws IOException;
Returns true if file exists on the file system.
/** Returns true if {@code file} exists on the file system. */
boolean exists(File file);
Returns the number of bytes stored in file, or 0 if it does not exist.
/** Returns the number of bytes stored in {@code file}, or 0 if it does not exist. */
long size(File file);
Renames from to to. Throws if the file cannot be renamed.
/** Renames {@code from} to {@code to}. Throws if the file cannot be renamed. */
void rename(File from, File to) throws IOException;
Recursively delete the contents of directory. Throws an IOException if any file could not be deleted, or if dir is not a readable directory.
/** * Recursively delete the contents of {@code directory}. Throws an IOException if any file could * not be deleted, or if {@code dir} is not a readable directory. */
void deleteContents(File directory) throws IOException; }