• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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