finish updater

This commit is contained in:
Minecon724 2024-06-20 16:21:13 +02:00
parent 7af2a99b3f
commit 96c8777ac2
Signed by: Minecon724
GPG key ID: 3CCC4D267742C8E8
4 changed files with 98 additions and 33 deletions

View file

@ -24,15 +24,38 @@ public class UpdateCommand {
sender.sendMessage("Please wait");
CompletableFuture<VersionMetadata> latestFuture = updater.getLatestVersion();
latestFuture.thenAccept(metadata -> {
if (metadata != null) {
sender.sendMessage("An update is available!");
sender.sendMessage("RealWeather %s released %s".formatted(metadata.label, metadata.getFormattedDate()));
sender.sendMessage("To download: /rwadmin update download");
} else {
sender.sendMessage("No new updates"); // TODO color
}
});
if (args.length == 0) {
latestFuture.thenAccept(metadata -> {
if (metadata != null) {
sender.sendMessage("An update is available!");
sender.sendMessage("RealWeather %s released %s".formatted(metadata.label, metadata.getFormattedDate()));
sender.sendMessage("To download: /rwadmin update download");
} else {
sender.sendMessage("No new updates"); // TODO color
}
});
} else {
String action = args[1]; // remember this function is proxied
if (action.equals("download")) {
sender.sendMessage("Started download");
updater.downloadUpdate().handle((file, ex) -> {
sender.sendMessage("Download failed. See console for details.");
ex.printStackTrace();
return null;
}).thenAccept(file -> {
if (file != null)
sender.sendMessage("Download finished, install with /rwadmin update install");
});
} else if (action.equals("install")) {
if (updater.installUpdate())
sender.sendMessage("Update installed, restart server to apply.");
else sender.sendMessage("Update not installed, see console.");
} else return false;
}
return true;
}

View file

@ -7,37 +7,48 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.ProxySelector;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpClient.Redirect;
import java.net.http.HttpResponse.BodyHandlers;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.Arrays;
import java.util.HexFormat;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import org.bukkit.plugin.Plugin;
public class UpdateDownloader {
private Plugin plugin;
private File getRunningPluginFile() {
try {
return new File(plugin.getClass().getProtectionDomain().getCodeSource().getLocation().toURI());
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
/**
*
* @param url
* @param sha256hex
* @return
* @throws SignatureException if signature doesnt match
*/
public CompletableFuture<File> downloadAndVerify(String url, String sha256hex) {
return download(url).thenApply(file -> {
try {
byte[] hash = computeFileSha256Hash(file);
boolean matches = compareBytesHex(hash, sha256hex);
if (!matches) {
// TODO clean?
throw new SignatureException();
}
return file;
} catch (IOException | SignatureException e) {
throw new CompletionException(e);
}
});
}
private CompletableFuture<File> download(String url) {
private CompletableFuture<File> download(String url) { // TODO progress?
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
@ -73,11 +84,6 @@ public class UpdateDownloader {
return fileFuture;
}
private void install(File file) throws IOException {
// TODO what if we changed File to Path and every ref in this file
Files.move(file.toPath(), getRunningPluginFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
}
private byte[] computeFileSha256Hash(File file) throws IOException {
MessageDigest digest = null;
try {

View file

@ -1,5 +1,10 @@
package eu.m724.realweather.updater;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@ -23,9 +28,13 @@ import net.md_5.bungee.api.chat.ComponentBuilder;
public class Updater extends BukkitRunnable implements Listener {
private UpdaterConfig updaterConfig;
private MetadataRetriever metadataRetriever;
private UpdateDownloader updateDownloader;
private Plugin plugin = GlobalConstants.getPlugin();
private File jarFile;
private CompletableFuture<File> downloadFuture;
private VersionMetadata currentMetadata;
private VersionMetadata latestMetadata;
private long checkCacheExpires;
@ -71,6 +80,11 @@ public class Updater extends BukkitRunnable implements Listener {
}
}
try {
jarFile = new File(plugin.getClass().getProtectionDomain().getCodeSource().getLocation().toURI());
} catch (URISyntaxException e) { }
updateDownloader = new UpdateDownloader();
if (updaterConfig.notify) {
this.runTaskTimerAsynchronously(plugin, 0, 216000); // 3h
plugin.getServer().getPluginManager().registerEvents(this, plugin);
@ -80,11 +94,33 @@ public class Updater extends BukkitRunnable implements Listener {
DebugLogger.info("updater loaded", 1);
}
public boolean installUpdate() {
/**
* download latest update
* @return null if no update else a future with the file (it can error with ioexcepton or signatureexception if signanture invalid)
*/
public CompletableFuture<File> downloadUpdate() {
if (latestMetadata == null)
return false;
return null;
String url = metadataRetriever.getFileUrl(latestMetadata.label, latestMetadata.fileUrl);
downloadFuture = updateDownloader.downloadAndVerify(url, latestMetadata.sha256);
return downloadFuture;
}
public boolean installUpdate() {
File downloadedFile = null;
try {
downloadedFile = downloadFuture.join();
// TODO what if we changed File to Path and every ref in this file
Files.move(downloadedFile.toPath(), jarFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (CompletionException | IOException e) {
e.printStackTrace();
return false;
} finally {
downloadFuture = null;
}
// TODO dont forget about verifictaion
return true;
}

View file

@ -26,9 +26,9 @@ public class VersionMetadata {
public String label;
/**
* filename of the jar file in the version directory
* url of the downloadable jar file
*/
public String file;
public String fileUrl;
public String sha256;