/* * Copyright 2015 Priyesh Patel * * 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.chromium.fontinstaller.core; import com.chromium.fontinstaller.models.Font; import com.chromium.fontinstaller.models.FontPackage; import com.chromium.fontinstaller.models.Style; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import okio.BufferedSink; import okio.Okio; import rx.Observable; import timber.log.Timber; public final class FontDownloader { private static final OkHttpClient sClient = new OkHttpClient(); private static final int MAX_CONCURRENT_DOWNLOADS = 5; private FontPackage mFontPackage; public FontDownloader(FontPackage fontPackage) { mFontPackage = fontPackage; } /** * Downloads all {@link Style#values()} for {@link #mFontPackage} */ public Observable<File> downloadAllFonts() { Timber.i("downloadAllFonts: " + mFontPackage.getName()); return downloadFonts(mFontPackage.getFontSet()); } /** * Downloads the specified {@link Style}'s for {@link #mFontPackage} */ public Observable<File> downloadFontStyles(Style... styles) { Timber.i("downloadFontStyles: %s for %s", Arrays.toString(styles), mFontPackage.getName()); return Observable.from(styles) .map(mFontPackage::getFont) .filter(font -> font != null) .collect(HashSet<Font>::new, HashSet::add) .flatMap(FontDownloader::downloadFonts); } /** * Downloads a single specified {@link Style} from each of the given {@link FontPackage}'s */ public static Observable<File> downloadStyleFromPackages(List<FontPackage> packages, Style style) { Timber.i("downloadStyleFromPackages: " + style); return Observable.from(packages).flatMap(fontPackage -> downloadFonts(Collections.singleton(fontPackage.getFont(style))), MAX_CONCURRENT_DOWNLOADS); } /* package */ static Observable<File> downloadFile(final String url, final String path) { return Observable.create(subscriber -> { final Request request = new Request.Builder().url(url).build(); try { if (!subscriber.isUnsubscribed()) { final File file = new File(path); if (!file.exists()) { // noinspection ResultOfMethodCallIgnored file.getParentFile().mkdirs(); Timber.i("downloadFile: Downloading " + file.getName()); final Response response = sClient.newCall(request).execute(); final BufferedSink sink = Okio.buffer(Okio.sink(file)); sink.writeAll(response.body().source()); sink.close(); } else Timber.i("downloadFile: Retrieved from cache " + file.getName()); subscriber.onNext(file); subscriber.onCompleted(); } } catch (IOException e) { subscriber.onError(new DownloadException(e)); } }); } private static Observable<File> downloadFonts(Set<Font> fonts) { return Observable.from(fonts).flatMap(f -> downloadFile(f.getUrl(), f.getFile().getAbsolutePath())); } public static class DownloadException extends Exception { public DownloadException(Exception root) { super(root); } } }