add: retry other download source in auto installation

This commit is contained in:
huanghongxun 2020-03-22 13:19:43 +08:00
parent b3bf9d5c94
commit e68a3c7cd4
12 changed files with 43 additions and 48 deletions

View File

@ -79,6 +79,7 @@ public class BMCLAPIDownloadProvider implements DownloadProvider {
@Override @Override
public String injectURL(String baseURL) { public String injectURL(String baseURL) {
return baseURL return baseURL
.replace("https://bmclapi2.bangbang93.com", apiRoot)
.replace("https://launchermeta.mojang.com", apiRoot) .replace("https://launchermeta.mojang.com", apiRoot)
.replace("https://launcher.mojang.com", apiRoot) .replace("https://launcher.mojang.com", apiRoot)
.replace("https://libraries.minecraft.net", apiRoot + "/libraries") .replace("https://libraries.minecraft.net", apiRoot + "/libraries")

View File

@ -17,9 +17,6 @@
*/ */
package org.jackhuang.hmcl.download; package org.jackhuang.hmcl.download;
import java.util.Arrays;
import java.util.stream.Stream;
/** /**
* The service provider that provides Minecraft online file downloads. * The service provider that provides Minecraft online file downloads.
* *
@ -42,12 +39,6 @@ public interface DownloadProvider {
*/ */
String injectURL(String baseURL); String injectURL(String baseURL);
default Stream<String> injectURLs(String[] baseURLs) {
Stream<String> urls = Arrays.stream(baseURLs);
Stream<String> jsonURLs = Arrays.stream(baseURLs).map(this::injectURL);
return Stream.concat(jsonURLs, urls);
}
/** /**
* the specific version list that this download provider provides. i.e. "forge", "liteloader", "game", "optifine" * the specific version list that this download provider provides. i.e. "forge", "liteloader", "game", "optifine"
* *

View File

@ -31,6 +31,7 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jackhuang.hmcl.util.io.NetworkUtils;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
/** /**
* <b>Note</b>: Fabric should be installed first. * <b>Note</b>: Fabric should be installed first.
@ -50,7 +51,9 @@ public final class FabricInstallTask extends Task<Version> {
this.version = version; this.version = version;
this.remote = remoteVersion; this.remote = remoteVersion;
launchMetaTask = new GetTask(NetworkUtils.toURL(dependencyManager.getPrimaryDownloadProvider().injectURL(getLaunchMetaUrl(remote.getGameVersion(), remote.getSelfVersion())))) launchMetaTask = new GetTask(dependencyManager.getPreferredDownloadProviders().stream()
.map(downloadProvider -> downloadProvider.injectURL(getLaunchMetaUrl(remote.getGameVersion(), remote.getSelfVersion())))
.map(NetworkUtils::toURL).collect(Collectors.toList()))
.setCacheRepository(dependencyManager.getCacheRepository()); .setCacheRepository(dependencyManager.getCacheRepository());
} }

View File

@ -30,11 +30,7 @@ import org.jackhuang.hmcl.util.io.NetworkUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Lang.mapOf;
import static org.jackhuang.hmcl.util.Pair.pair; import static org.jackhuang.hmcl.util.Pair.pair;
@ -92,9 +88,9 @@ public final class ForgeBMCLVersionList extends VersionList<ForgeRemoteVersion>
+ (StringUtils.isNotBlank(version.getBranch()) ? "-" + version.getBranch() : ""); + (StringUtils.isNotBlank(version.getBranch()) ? "-" + version.getBranch() : "");
String fileName1 = "forge-" + classifier + "-" + file.getCategory() + "." + file.getFormat(); String fileName1 = "forge-" + classifier + "-" + file.getCategory() + "." + file.getFormat();
String fileName2 = "forge-" + classifier + "-" + gameVersion + "-" + file.getCategory() + "." + file.getFormat(); String fileName2 = "forge-" + classifier + "-" + gameVersion + "-" + file.getCategory() + "." + file.getFormat();
urls.add(apiRoot + "/maven/net/minecraftforge/forge/" + classifier + "-" + gameVersion + "/" + fileName2); urls.add("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" + classifier + "-" + gameVersion + "/" + fileName2);
urls.add(apiRoot + "/maven/net/minecraftforge/forge/" + classifier + "/" + fileName1); urls.add("https://files.minecraftforge.net/maven/net/minecraftforge/forge/" + classifier + "/" + fileName1);
urls.add(NetworkUtils.withQuery(apiRoot + "/forge/download", mapOf( urls.add(NetworkUtils.withQuery("https://bmclapi2.bangbang93.com/forge/download", mapOf(
pair("mcversion", version.getGameVersion()), pair("mcversion", version.getGameVersion()),
pair("version", version.getVersion()), pair("version", version.getVersion()),
pair("branch", version.getBranch()), pair("branch", version.getBranch()),

View File

@ -68,9 +68,9 @@ public final class ForgeInstallTask extends Task<Version> {
installer = Files.createTempFile("forge-installer", ".jar"); installer = Files.createTempFile("forge-installer", ".jar");
dependent = new FileDownloadTask( dependent = new FileDownloadTask(
Arrays.stream(remote.getUrl()) dependencyManager.getPreferredDownloadProviders().stream()
.map(NetworkUtils::toURL) .flatMap(downloadProvider -> Arrays.stream(remote.getUrl()).map(downloadProvider::injectURL))
.collect(Collectors.toList()), .map(NetworkUtils::toURL).collect(Collectors.toList()),
installer.toFile(), null) installer.toFile(), null)
.setCacheRepository(dependencyManager.getCacheRepository()) .setCacheRepository(dependencyManager.getCacheRepository())
.setCaching(true); .setCaching(true);

View File

@ -29,6 +29,7 @@ import java.io.File;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* Task to download Minecraft jar * Task to download Minecraft jar
@ -58,7 +59,9 @@ public final class GameDownloadTask extends Task<Void> {
File jar = dependencyManager.getGameRepository().getVersionJar(version); File jar = dependencyManager.getGameRepository().getVersionJar(version);
FileDownloadTask task = new FileDownloadTask( FileDownloadTask task = new FileDownloadTask(
NetworkUtils.toURL(dependencyManager.getPrimaryDownloadProvider().injectURL(version.getDownloadInfo().getUrl())), dependencyManager.getPreferredDownloadProviders().stream()
.map(downloadProvider -> downloadProvider.injectURL(version.getDownloadInfo().getUrl()))
.map(NetworkUtils::toURL).collect(Collectors.toList()),
jar, jar,
IntegrityCheck.of(CacheRepository.SHA1, version.getDownloadInfo().getSha1())) IntegrityCheck.of(CacheRepository.SHA1, version.getDownloadInfo().getSha1()))
.setCaching(true) .setCaching(true)

View File

@ -25,13 +25,12 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jackhuang.hmcl.util.io.NetworkUtils;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.nio.charset.StandardCharsets.UTF_8;
/** /**
* *
* @author huangyuhui * @author huangyuhui
@ -69,8 +68,9 @@ public final class VersionJsonDownloadTask extends Task<String> {
RemoteVersion remoteVersion = gameVersionList.getVersion(gameVersion, gameVersion) RemoteVersion remoteVersion = gameVersionList.getVersion(gameVersion, gameVersion)
.orElseThrow(() -> new IOException("Cannot find specific version " + gameVersion + " in remote repository")); .orElseThrow(() -> new IOException("Cannot find specific version " + gameVersion + " in remote repository"));
dependencies.add(new GetTask( dependencies.add(new GetTask(
dependencyManager.getPrimaryDownloadProvider().injectURLs(remoteVersion.getUrl()) dependencyManager.getPreferredDownloadProviders().stream()
.map(NetworkUtils::toURL).collect(Collectors.toList()), .flatMap(downloadProvider -> Arrays.stream(remoteVersion.getUrl()).map(downloadProvider::injectURL))
UTF_8).storeTo(this::setResult)); .map(NetworkUtils::toURL).collect(Collectors.toList())
).storeTo(this::setResult));
} }
} }

View File

@ -91,7 +91,7 @@ public final class LiteLoaderBMCLVersionList extends VersionList<LiteLoaderRemot
continue; continue;
String version = v.getVersion(); String version = v.getVersion();
String url = downloadProvider.getApiRoot() + "/liteloader/download?version=" + version; String url = "https://bmclapi2.bangbang93.com/liteloader/download?version=" + version;
if (snapshot) { if (snapshot) {
try { try {
version = version.replace("SNAPSHOT", getLatestSnapshotVersion(repository.getUrl() + "com/mumfrey/liteloader/" + v.getVersion() + "/")); version = version.replace("SNAPSHOT", getLatestSnapshotVersion(repository.getUrl() + "com/mumfrey/liteloader/" + v.getVersion() + "/"));
@ -101,7 +101,7 @@ public final class LiteLoaderBMCLVersionList extends VersionList<LiteLoaderRemot
} }
versions.put(key, new LiteLoaderRemoteVersion(gameVersion, versions.put(key, new LiteLoaderRemoteVersion(gameVersion,
version, downloadProvider.injectURL(url), version, url,
v.getTweakClass(), v.getLibraries() v.getTweakClass(), v.getLibraries()
)); ));
} }

View File

@ -26,11 +26,7 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jackhuang.hmcl.util.io.NetworkUtils;
import org.jackhuang.hmcl.util.versioning.VersionNumber; import org.jackhuang.hmcl.util.versioning.VersionNumber;
import java.util.Collection; import java.util.*;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** /**
* *
@ -71,7 +67,7 @@ public final class OptiFineBMCLVersionList extends VersionList<OptiFineRemoteVer
}.getType()); }.getType());
for (OptiFineVersion element : root) { for (OptiFineVersion element : root) {
String version = element.getType() + "_" + element.getPatch(); String version = element.getType() + "_" + element.getPatch();
String mirror = apiRoot + "/optifine/" + element.getGameVersion() + "/" + element.getType() + "/" + element.getPatch(); String mirror = "https://bmclapi2.bangbang93.com/optifine/" + element.getGameVersion() + "/" + element.getType() + "/" + element.getPatch();
if (!duplicates.add(mirror)) if (!duplicates.add(mirror))
continue; continue;

View File

@ -96,7 +96,9 @@ public final class OptiFineInstallTask extends Task<Version> {
if (installer == null) { if (installer == null) {
dependents.add(new FileDownloadTask( dependents.add(new FileDownloadTask(
Arrays.stream(remote.getUrl()).map(NetworkUtils::toURL).collect(Collectors.toList()), dependencyManager.getPreferredDownloadProviders().stream()
.flatMap(downloadProvider -> Arrays.stream(remote.getUrl()).map(downloadProvider::injectURL))
.map(NetworkUtils::toURL).collect(Collectors.toList()),
dest.toFile(), null) dest.toFile(), null)
.setCacheRepository(dependencyManager.getCacheRepository()) .setCacheRepository(dependencyManager.getCacheRepository())
.setCaching(true)); .setCaching(true));

View File

@ -207,7 +207,6 @@ public class FileDownloadTask extends Task<Void> {
checkETag = true; checkETag = true;
} }
Logging.LOG.log(Level.FINER, "Downloading " + urls.get(0) + " to " + file);
Exception exception = null; Exception exception = null;
URL failedURL = null; URL failedURL = null;
@ -217,6 +216,7 @@ public class FileDownloadTask extends Task<Void> {
break; break;
} }
Logging.LOG.log(Level.FINER, "Downloading " + url + " to " + file);
Path temp = null; Path temp = null;
try { try {

View File

@ -53,22 +53,21 @@ public final class GetTask extends Task<String> {
} }
public GetTask(URL url, Charset charset) { public GetTask(URL url, Charset charset) {
this(url, charset, 5); this(url, charset, 3);
} }
public GetTask(URL url, Charset charset, int retry) { public GetTask(URL url, Charset charset, int retry) {
this.urls = Collections.singletonList(url); this(Collections.singletonList(url), charset, retry);
this.charset = charset;
this.retry = retry;
setName(url.toString());
setExecutor(Schedulers.io());
} }
public GetTask(List<URL> urls, Charset charset) { public GetTask(List<URL> url) {
this(url, UTF_8, 3);
}
public GetTask(List<URL> urls, Charset charset, int retry) {
this.urls = new ArrayList<>(urls); this.urls = new ArrayList<>(urls);
this.charset = charset; this.charset = charset;
this.retry = urls.size(); this.retry = retry;
setName(urls.get(0).toString()); setName(urls.get(0).toString());
setExecutor(Schedulers.io()); setExecutor(Schedulers.io());
@ -84,8 +83,12 @@ public final class GetTask extends Task<String> {
Exception exception = null; Exception exception = null;
URL failedURL = null; URL failedURL = null;
boolean checkETag = true; boolean checkETag = true;
for (int time = 0; time < retry; ++time) { for (int time = 0; time < retry * urls.size(); ++time) {
URL url = urls.get(time % urls.size()); URL url = urls.get(time / retry);
if (isCancelled()) {
break;
}
try { try {
updateProgress(0); updateProgress(0);
HttpURLConnection conn = NetworkUtils.createConnection(url); HttpURLConnection conn = NetworkUtils.createConnection(url);