finish updater
This commit is contained in:
parent
7af2a99b3f
commit
96c8777ac2
4 changed files with 98 additions and 33 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue