1 /* 2 * Copyright 2022 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.libraries.mobiledatadownload.file.spi; 17 18 import android.net.Uri; 19 import android.util.Pair; 20 import com.google.android.libraries.mobiledatadownload.file.common.GcParam; 21 import com.google.android.libraries.mobiledatadownload.file.common.LockScope; 22 import com.google.android.libraries.mobiledatadownload.file.common.UnsupportedFileStorageOperation; 23 import java.io.Closeable; 24 import java.io.File; 25 import java.io.IOException; 26 import java.io.InputStream; 27 import java.io.OutputStream; 28 29 /** 30 * Backends are instantiated once per protocol during initialization. They encapsulate the methods 31 * needed to interact with a concrete storage mechanism. 32 * 33 * <p>Backend methods are expected to ignore the URI fragment, as the transform encoded in it are 34 * interpreted by the higher-level API (see {@link SynchronousFileStorage}). 35 */ 36 public interface Backend { 37 /** 38 * Name for this backend. Must be ASCII alphanumeric. Used as the scheme in the Uri. 39 * 40 * @return The name, which appears as the scheme of the uri. 41 */ name()42 String name(); 43 44 /** 45 * Open this Uri for reading. 46 * 47 * @param uri 48 * @return A InputStream for reading from. 49 * @throws IOException 50 */ openForRead(Uri uri)51 default InputStream openForRead(Uri uri) throws IOException { 52 throw new UnsupportedFileStorageOperation("openForRead not supported by " + name()); 53 } 54 55 /** 56 * Open this Uri for reading by native code in the form of a file descriptor URI. 57 * 58 * @return An fd URI. Caller is responsible for closing. 59 * @throws IOException 60 */ openForNativeRead(Uri uri)61 default Pair<Uri, Closeable> openForNativeRead(Uri uri) throws IOException { 62 throw new UnsupportedFileStorageOperation("openForNativeRead not supported by " + name()); 63 } 64 65 /** 66 * Open this Uri for writing, overwriting any existing content. 67 * 68 * <p>Any non-existent directories will be created as part of opening the file. 69 * 70 * @param uri 71 * @return A OutputStream to write to. 72 * @throws IOException 73 */ openForWrite(Uri uri)74 default OutputStream openForWrite(Uri uri) throws IOException { 75 throw new UnsupportedFileStorageOperation("openForWrite not supported by " + name()); 76 } 77 78 /** 79 * Open this Uri for append. 80 * 81 * <p>Any non-existent directories will be created as part of opening the file. 82 * 83 * @param uri 84 * @return A OutputStream to write to. 85 * @throws IOException 86 */ openForAppend(Uri uri)87 default OutputStream openForAppend(Uri uri) throws IOException { 88 throw new UnsupportedFileStorageOperation("openForAppend not supported by " + name()); 89 } 90 91 /** 92 * Delete the file identified with uri. 93 * 94 * @param uri 95 * @throws FileNotFoundException if the file does not exist, or is a directory 96 * @throws IOException if the file could not be deleted for any other reason 97 */ deleteFile(Uri uri)98 default void deleteFile(Uri uri) throws IOException { 99 throw new UnsupportedFileStorageOperation("deleteFile not supported by " + name()); 100 } 101 102 /** 103 * Deletes the directory denoted by {@code uri}. The directory must be empty in order to be 104 * deleted. 105 * 106 * @throws IOException if the directory could not be deleted for any reason 107 */ deleteDirectory(Uri uri)108 default void deleteDirectory(Uri uri) throws IOException { 109 throw new UnsupportedFileStorageOperation("deleteDirectory not supported by " + name()); 110 } 111 112 /** 113 * Rename the file or directory identified with {@code from} to {@code to}. 114 * 115 * <p>Any non-existent directories will be created as part of the rename. 116 * 117 * @throws IOException if the file could not be renamed for any reason 118 */ rename(Uri from, Uri to)119 default void rename(Uri from, Uri to) throws IOException { 120 throw new UnsupportedFileStorageOperation("rename not supported by " + name()); 121 } 122 123 /** 124 * Tells whether this file or directory exists. 125 * 126 * @param uri 127 * @return True if it exists. 128 */ exists(Uri uri)129 default boolean exists(Uri uri) throws IOException { 130 throw new UnsupportedFileStorageOperation("exists not supported by " + name()); 131 } 132 133 /** 134 * Tells whether this uri refers to a directory. 135 * 136 * @param uri 137 * @return True if it is a directory. 138 */ isDirectory(Uri uri)139 default boolean isDirectory(Uri uri) throws IOException { 140 throw new UnsupportedFileStorageOperation("isDirectory not supported by " + name()); 141 } 142 143 /** 144 * Creates a new directory. Any non-existent parent directories will also be created. 145 * 146 * @throws IOException if the directory could not be created for any reason 147 */ createDirectory(Uri uri)148 default void createDirectory(Uri uri) throws IOException { 149 throw new UnsupportedFileStorageOperation("createDirectory not supported by " + name()); 150 } 151 152 /** 153 * Gets the file size. If the uri refers to a directory or non-existent, returns 0. 154 * 155 * @param uri 156 * @return The size in bytes of the file. 157 */ fileSize(Uri uri)158 default long fileSize(Uri uri) throws IOException { 159 throw new UnsupportedFileStorageOperation("fileSize not supported by " + name()); 160 } 161 162 /** 163 * Lists the children of this parent directory. If the Uri refers to a non-directory, an exception 164 * is thrown. 165 * 166 * @param parentUri The parent directory to query for children. 167 * @return List of fully qualified URIs. 168 */ children(Uri parentUri)169 default Iterable<Uri> children(Uri parentUri) throws IOException { 170 throw new UnsupportedFileStorageOperation("children not supported by " + name()); 171 } 172 173 /** Retrieves the {@link GcParam} associated with the given URI. */ getGcParam(Uri uri)174 default GcParam getGcParam(Uri uri) throws IOException { 175 throw new UnsupportedFileStorageOperation("getGcParam not supported by " + name()); 176 } 177 178 /** Sets the {@link GcParam} associated with the given URI. */ setGcParam(Uri uri, GcParam param)179 default void setGcParam(Uri uri, GcParam param) throws IOException { 180 throw new UnsupportedFileStorageOperation("setGcParam not supported by " + name()); 181 } 182 183 /** Converts the URI to a File if possible. Like all Backend methods, ignores fragment. */ toFile(Uri uri)184 default File toFile(Uri uri) throws IOException { 185 throw new UnsupportedFileStorageOperation("Cannot convert uri to file " + name() + " " + uri); 186 } 187 188 /** Retrieves the {@link LockScope} responsible for locking files in this Backend. */ lockScope()189 default LockScope lockScope() throws IOException { 190 throw new UnsupportedFileStorageOperation("lockScope not supported by " + name()); 191 } 192 } 193