/* * Copyright 2022 Google LLC * * 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.google.android.libraries.mobiledatadownload.file.openers; import android.content.Context; import android.util.Log; import androidx.annotation.VisibleForTesting; import com.google.android.libraries.mobiledatadownload.file.OpenContext; import com.google.android.libraries.mobiledatadownload.file.Opener; import com.google.android.libraries.mobiledatadownload.file.common.FileConvertible; import com.google.android.libraries.mobiledatadownload.file.common.ReleasableResource; import com.google.android.libraries.mobiledatadownload.file.common.UnsupportedFileStorageOperation; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.Nullable; /** * Opener for reading data from a {@link java.io.File} object. Depending on the backend, this may * return... * *
Usage: The caller MUST open the returned file in order to avoid a thread leak. It may only open it
* once.
*
* The caller may block on {@link #waitForPump} and handle any exceptions in order to monitor
* failures.
*
* WARNING: FIFOs require SDK level 21+ (Lollipop). If the raw file path is unavailable and the
* current SDK level is insufficient for FIFOs, the fallback will fail (throw IOException).
*
* @param executor Executor for pump threads.
* @param context Android context for the root directory where fifos are stored.
* @return This opener.
*/
@CanIgnoreReturnValue
public ReadFileOpener withFallbackToPipeUsingExecutor(ExecutorService executor, Context context) {
this.executor = executor;
this.context = context;
return this;
}
/**
* If enabled, will ONLY attempt to convert the URI to a path using string processing. Fails if
* there are any transforms enabled. This is like the {@link UriAdapter} interface, but with more
* guard rails to make it safe to expose publicly.
*/
@CanIgnoreReturnValue
public ReadFileOpener withShortCircuit() {
this.shortCircuit = true;
return this;
}
@Override
public File open(OpenContext openContext) throws IOException {
if (shortCircuit) {
if (openContext.hasTransforms()) {
throw new UnsupportedFileStorageOperation("Short circuit would skip transforms.");
}
return openContext.backend().toFile(openContext.encodedUri());
}
try (ReleasableResource
* File file = storage.open(uri,
* ReadFileOpener.create().withFallbackToPipeUsingExecutor(executor, context)));
* try (FileInputStream in = new FileInputStream(file)) {
* // Read file
* }
*
*/
public final class ReadFileOpener implements Opener