194 lines
8.8 KiB
Java
194 lines
8.8 KiB
Java
package io.gitlab.jfronny.inceptum.common;
|
|
|
|
import gsoncompile.extensions.io.gitlab.jfronny.inceptum.common.model.inceptum.UpdateMetadata.GC_UpdateMetadata;
|
|
import gsoncompile.extensions.io.gitlab.jfronny.inceptum.common.model.inceptum.WrapperConfig.GC_WrapperConfig;
|
|
import io.gitlab.jfronny.commons.OSUtils;
|
|
import io.gitlab.jfronny.inceptum.common.api.MavenApi;
|
|
import io.gitlab.jfronny.inceptum.common.model.inceptum.*;
|
|
import io.gitlab.jfronny.inceptum.common.model.maven.*;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.xml.sax.SAXException;
|
|
|
|
import javax.xml.stream.XMLStreamException;
|
|
import java.io.*;
|
|
import java.net.URISyntaxException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.*;
|
|
import java.util.function.Consumer;
|
|
import java.util.stream.Stream;
|
|
|
|
public class Updater {
|
|
public static final String PROJECT_MAVEN = "https://maven.frohnmeyer-wds.de/artifacts/";
|
|
private static final String ARTIFACTS_URL = "https://pages.frohnmeyer-wds.de/JfMods/Inceptum/artifacts/";
|
|
private static final String STABLE_URL = "https://pages.frohnmeyer-wds.de/JfMods/Inceptum/stable/";
|
|
|
|
public static UpdateMetadata getUpdate(boolean versionCompare, boolean checkEnv) throws UpdateCheckException {
|
|
return Updater.check(InceptumConfig.channel, versionCompare, checkEnv, channel -> {
|
|
Utils.LOGGER.error("No stable version was found, switching to experimental channel");
|
|
InceptumConfig.channel = channel;
|
|
InceptumConfig.saveConfig();
|
|
});
|
|
}
|
|
|
|
public static void update(UpdateMetadata source, boolean relaunch) throws IOException, URISyntaxException {
|
|
Utils.LOGGER.info("Downloading version " + source.version);
|
|
|
|
WrapperConfig config = new WrapperConfig(
|
|
new LinkedHashSet<>(),
|
|
new LinkedHashSet<>(source.repositories),
|
|
new HashMap<>()
|
|
);
|
|
source.natives.forEach((k, v) -> config.natives[k] = new LinkedHashSet<>(v));
|
|
|
|
DependencyNode node = downloadLibrary(source.repositories, "io.gitlab.jfronny.inceptum:launcher-dist:" + source.version, config.libraries);
|
|
Utils.LOGGER.info("Downloaded Dependencies:\n" + node);
|
|
|
|
List<String> currentLibraries = new LinkedList<>(config.libraries);
|
|
if (source.natives.containsKey(Utils.currentFlavor)) {
|
|
Set<String> natives = new LinkedHashSet<>();
|
|
for (String lib : source.natives[Utils.currentFlavor]) {
|
|
downloadLibrary(source.repositories, lib, natives);
|
|
}
|
|
currentLibraries.addAll(natives);
|
|
config.natives[Utils.currentFlavor] = natives;
|
|
}
|
|
|
|
GC_WrapperConfig.write(config, MetaHolder.WRAPPER_CONFIG_PATH);
|
|
|
|
if (relaunch) {
|
|
Runtime.runtime.addShutdownHook(new Thread(() -> {
|
|
try {
|
|
new ProcessBuilder(OSUtils.jvmBinary,
|
|
"-cp",
|
|
buildClasspath(currentLibraries.stream())
|
|
.map(Path::toString)
|
|
.join(File.pathSeparatorChar)
|
|
).inheritIO().start();
|
|
} catch (IOException e) {
|
|
Utils.LOGGER.error("Could not relaunch", e);
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
public static List<Path> getLaunchClasspath(WrapperConfig wrapperConfig) throws IOException, URISyntaxException {
|
|
Set<String> natives = wrapperConfig.natives[Utils.currentFlavor];
|
|
if (natives == null) natives = new LinkedHashSet<>();
|
|
Set<String> libs = wrapperConfig.libraries;
|
|
if (libs == null) libs = new LinkedHashSet<>();
|
|
|
|
boolean configChanged = false;
|
|
|
|
for (String lib : libs) {
|
|
Path p = ArtifactMeta.parse(lib).localPath;
|
|
if (!Files.exists(p)) {
|
|
configChanged = true;
|
|
downloadLibrary(wrapperConfig.repositories, lib, libs);
|
|
}
|
|
}
|
|
for (String lib : natives) {
|
|
Path p = ArtifactMeta.parse(lib).localPath;
|
|
if (!Files.exists(p)) {
|
|
configChanged = true;
|
|
downloadLibrary(wrapperConfig.repositories, lib, natives);
|
|
}
|
|
}
|
|
|
|
if (configChanged) GC_WrapperConfig.write(wrapperConfig, MetaHolder.WRAPPER_CONFIG_PATH);
|
|
|
|
return buildClasspath(libs.stream().concat(natives.stream())).toList();
|
|
}
|
|
|
|
private static Stream<Path> buildClasspath(Stream<String> libraries) {
|
|
return libraries.map(ArtifactMeta::parse).map(ArtifactMeta::getLocalPath);
|
|
}
|
|
|
|
private static DependencyNode downloadLibrary(Set<String> repositories, final String artifact, Set<String> libraries) throws IOException, URISyntaxException {
|
|
List<FileNotFoundException> suppressed = new LinkedList<>();
|
|
for (String repository : Stream.of(PROJECT_MAVEN).concat(repositories.stream())) {
|
|
ArtifactMeta meta;
|
|
try {
|
|
meta = MavenApi.getMetadata(repository, artifact);
|
|
} catch (FileNotFoundException ignored) {
|
|
meta = ArtifactMeta.parse(artifact);
|
|
} catch (IOException | URISyntaxException | SAXException e) {
|
|
throw new IOException("Could not download artifact from " + repository, e);
|
|
}
|
|
Pom pom;
|
|
try {
|
|
pom = MavenApi.getPom(repository, meta);
|
|
} catch (FileNotFoundException notFound) {
|
|
suppressed.add(notFound);
|
|
continue;
|
|
} catch (IOException | URISyntaxException | XMLStreamException | SAXException e) {
|
|
throw new IOException("Could not download artifact " + meta.mavenNotation + " from " + repository, e);
|
|
}
|
|
Set<DependencyNode> dependencies = new LinkedHashSet<>();
|
|
if (pom.dependencies != null) {
|
|
for (MavenDependency dependency : pom.dependencies) {
|
|
String mvnName = dependency.groupId + ":" + dependency.artifactId + ":" + dependency.version;
|
|
dependencies.add(downloadLibrary(repositories, mvnName, libraries));
|
|
}
|
|
}
|
|
MavenApi.downloadLibrary(repository, meta);
|
|
libraries.add(artifact);
|
|
return new DependencyNode(artifact, dependencies);
|
|
}
|
|
IOException e = new IOException("Could not find any repository containing the artifact " + artifact + " (searched: " + String.join(", ", repositories) + ")");
|
|
for (FileNotFoundException ex : suppressed) e.addSuppressed(ex);
|
|
throw e;
|
|
}
|
|
|
|
public static @Nullable UpdateMetadata check(UpdateChannel channel, boolean versionCompare, boolean checkEnv, Consumer<UpdateChannel> channelInvalid) throws UpdateCheckException {
|
|
try {
|
|
UpdateMetadata experimental = Net.downloadObject(ARTIFACTS_URL + "version.json", json -> GC_UpdateMetadata.read(json));
|
|
UpdateMetadata stable = null;
|
|
try {
|
|
stable = Net.downloadObject(STABLE_URL + "version.json", json -> GC_UpdateMetadata.read(json));
|
|
} catch (Throwable ignored) {}
|
|
if (stable == null && channel == UpdateChannel.Stable) {
|
|
channel = UpdateChannel.CI;
|
|
channelInvalid.accept(channel);
|
|
}
|
|
UpdateMetadata info = switch (channel) {
|
|
case CI -> experimental;
|
|
case Stable -> stable;
|
|
};
|
|
if (checkEnv) {
|
|
if (info.jvm > Runtime.version().feature()) throw new UpdateCheckException("A newer JVM is required to use the latest inceptum version. Please update!", "Outdated Java");
|
|
if (info.wrapperVersion != BuildMetadata.WRAPPER_VERSION) throw new UpdateCheckException("A different version of the Inceptum Wrapper is required for this update!", "Mismatched Wrapper");
|
|
}
|
|
if (versionCompare) {
|
|
Utils.LOGGER.info("Latest version is " + info.version + ", current is " + BuildMetadata.VERSION);
|
|
if (BuildMetadata.BUILD_TIME >= info.buildTime) {
|
|
Utils.LOGGER.info("Up-to-date");
|
|
return null;
|
|
}
|
|
}
|
|
return info;
|
|
} catch (IOException e) {
|
|
Utils.LOGGER.error("Could not check for updates", e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static String getShadowJarUrl(UpdateChannel channel) {
|
|
return switch (channel) {
|
|
case CI -> ARTIFACTS_URL;
|
|
case Stable -> STABLE_URL;
|
|
} + "/Inceptum-" + Utils.currentFlavor + ".jar";
|
|
}
|
|
|
|
public static class UpdateCheckException extends Exception {
|
|
public final String message;
|
|
public final String title;
|
|
|
|
public UpdateCheckException(String message, String title) {
|
|
super(message);
|
|
this.message = message;
|
|
this.title = title;
|
|
}
|
|
}
|
|
}
|