• 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.testing;
17 
18 import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
19 import static com.google.common.util.concurrent.Futures.immediateVoidFuture;
20 
21 import android.net.Uri;
22 import com.google.android.libraries.mobiledatadownload.DownloadException;
23 import com.google.android.libraries.mobiledatadownload.DownloadException.DownloadResultCode;
24 import com.google.android.libraries.mobiledatadownload.downloader.DownloadRequest;
25 import com.google.android.libraries.mobiledatadownload.downloader.FileDownloader;
26 import com.google.android.libraries.mobiledatadownload.file.Opener;
27 import com.google.android.libraries.mobiledatadownload.file.SynchronousFileStorage;
28 import com.google.android.libraries.mobiledatadownload.file.openers.ReadStreamOpener;
29 import com.google.android.libraries.mobiledatadownload.file.openers.WriteStreamOpener;
30 import com.google.android.libraries.mobiledatadownload.internal.logging.LogUtil;
31 import com.google.common.io.ByteStreams;
32 import com.google.common.util.concurrent.Futures;
33 import com.google.common.util.concurrent.ListenableFuture;
34 import com.google.common.util.concurrent.ListeningExecutorService;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.OutputStream;
38 import java.util.concurrent.Executor;
39 
40 /**
41  * A {@link FileDownloader} that "downloads" by copying the file from the local folder.
42  *
43  * <p>Note that LocalFileDownloader ignores DownloadConditions.
44  */
45 public final class LocalFileDownloader implements FileDownloader {
46 
47   private static final String TAG = "LocalFileDownloader";
48 
49   private final Executor backgroudExecutor;
50   private final SynchronousFileStorage fileStorage;
51 
LocalFileDownloader( SynchronousFileStorage fileStorage, ListeningExecutorService executor)52   public LocalFileDownloader(
53       SynchronousFileStorage fileStorage, ListeningExecutorService executor) {
54     this.fileStorage = fileStorage;
55     this.backgroudExecutor = executor;
56   }
57 
58   @Override
startDownloading(DownloadRequest downloadRequest)59   public ListenableFuture<Void> startDownloading(DownloadRequest downloadRequest) {
60     return Futures.submitAsync(() -> startDownloadingInternal(downloadRequest), backgroudExecutor);
61   }
62 
startDownloadingInternal(DownloadRequest downloadRequest)63   private ListenableFuture<Void> startDownloadingInternal(DownloadRequest downloadRequest) {
64     Uri fileUri = downloadRequest.fileUri();
65     String urlToDownload = downloadRequest.urlToDownload();
66     LogUtil.d("%s: startDownloading; fileUri: %s; urlToDownload: %s", TAG, fileUri, urlToDownload);
67 
68     Uri uriToDownload = Uri.parse(urlToDownload);
69     if (uriToDownload == null) {
70       LogUtil.e("%s: Invalid urlToDownload %s", TAG, urlToDownload);
71       return immediateFailedFuture(new IllegalArgumentException("Invalid urlToDownload"));
72     }
73 
74     try {
75       Opener<InputStream> readStreamOpener = ReadStreamOpener.create();
76       Opener<OutputStream> writeStreamOpener = WriteStreamOpener.create();
77       long writtenBytes;
78       try (InputStream in = fileStorage.open(uriToDownload, readStreamOpener);
79           OutputStream out = fileStorage.open(fileUri, writeStreamOpener)) {
80         writtenBytes = ByteStreams.copy(in, out);
81       }
82       LogUtil.d("%s: File URI %s download complete, writtenBytes: %d", TAG, fileUri, writtenBytes);
83     } catch (IOException e) {
84       LogUtil.e(e, "%s: startDownloading got exception", TAG);
85       return immediateFailedFuture(
86           DownloadException.builder()
87               .setDownloadResultCode(DownloadResultCode.ANDROID_DOWNLOADER_HTTP_ERROR)
88               .build());
89     }
90 
91     return immediateVoidFuture();
92   }
93 }
94