aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornea <romangraef@gmail.com>2022-10-14 22:23:16 +0200
committernea <romangraef@gmail.com>2022-10-14 22:23:16 +0200
commit500a04df7a3d15d858bce6732767476c5b5a69a7 (patch)
tree50593c981caf4f3e7a42231a69b12a341285f812
parentf4e8a8b343125744a80bb49a433f7796bda2fe4a (diff)
downloadlibautoupdate-500a04df7a3d15d858bce6732767476c5b5a69a7.tar.gz
libautoupdate-500a04df7a3d15d858bce6732767476c5b5a69a7.tar.bz2
libautoupdate-500a04df7a3d15d858bce6732767476c5b5a69a7.zip
Javadocs
-rw-r--r--src/main/java/moe/nea/libautoupdate/CurrentVersion.java12
-rw-r--r--src/main/java/moe/nea/libautoupdate/DeleteAndSaveInSameFolderUpdateTarget.java6
-rw-r--r--src/main/java/moe/nea/libautoupdate/ExitHookInvoker.java18
-rw-r--r--src/main/java/moe/nea/libautoupdate/PotentialUpdate.java44
-rw-r--r--src/main/java/moe/nea/libautoupdate/UpdateContext.java25
-rw-r--r--src/main/java/moe/nea/libautoupdate/UpdateSource.java9
-rw-r--r--src/main/java/moe/nea/libautoupdate/UpdateTarget.java18
-rw-r--r--updater/src/main/java/moe/nea/libautoupdate/postexit/PostExitMain.java19
8 files changed, 136 insertions, 15 deletions
diff --git a/src/main/java/moe/nea/libautoupdate/CurrentVersion.java b/src/main/java/moe/nea/libautoupdate/CurrentVersion.java
index 52b8372..8c0837e 100644
--- a/src/main/java/moe/nea/libautoupdate/CurrentVersion.java
+++ b/src/main/java/moe/nea/libautoupdate/CurrentVersion.java
@@ -1,8 +1,20 @@
package moe.nea.libautoupdate;
+/**
+ * Provider interface for getting the current version of this jar.
+ */
public interface CurrentVersion {
+ /**
+ * @return the version number
+ */
int getCurrentVersionNumber();
+ /**
+ * Create a constant {@link CurrentVersion}
+ *
+ * @param number the constant version number
+ * @return
+ */
static CurrentVersion of(int number) {
return () -> number;
}
diff --git a/src/main/java/moe/nea/libautoupdate/DeleteAndSaveInSameFolderUpdateTarget.java b/src/main/java/moe/nea/libautoupdate/DeleteAndSaveInSameFolderUpdateTarget.java
index 3e07f45..737fe79 100644
--- a/src/main/java/moe/nea/libautoupdate/DeleteAndSaveInSameFolderUpdateTarget.java
+++ b/src/main/java/moe/nea/libautoupdate/DeleteAndSaveInSameFolderUpdateTarget.java
@@ -7,8 +7,14 @@ import java.io.File;
import java.util.Arrays;
import java.util.List;
+/**
+ * Create {@link UpdateTarget} that deletes the specified Jar, and saves the new Jar in the same folder with the name specified by the download URL.
+ */
@Value
public class DeleteAndSaveInSameFolderUpdateTarget implements UpdateTarget {
+ /**
+ * The file that will be replaced.
+ */
File file;
@SneakyThrows
diff --git a/src/main/java/moe/nea/libautoupdate/ExitHookInvoker.java b/src/main/java/moe/nea/libautoupdate/ExitHookInvoker.java
index 55436a2..0b1eaee 100644
--- a/src/main/java/moe/nea/libautoupdate/ExitHookInvoker.java
+++ b/src/main/java/moe/nea/libautoupdate/ExitHookInvoker.java
@@ -4,6 +4,9 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
+/**
+ * A Utility class for setting up the exit hook, which then launches the next stage (postexit) using the same java runtime.
+ */
public class ExitHookInvoker {
private static boolean isExitHookRegistered = false;
@@ -11,7 +14,15 @@ public class ExitHookInvoker {
private static File updaterJar;
private static boolean cancelled = false;
-
+ /**
+ * Set up the exit hook to run post exit actions.
+ *
+ * <p><b>N.B.:</b> Calling this multiple times will only invoke the last set of actions.
+ * In case of multiple updates the update actions should be joined in the same list.</p>
+ *
+ * @param updaterJar the extracted updater jar
+ * @param actions the actions to execute
+ */
public static synchronized void setExitHook(File updaterJar, List<UpdateAction> actions) {
if (!isExitHookRegistered) {
Runtime.getRuntime().addShutdownHook(new Thread(ExitHookInvoker::runExitHook));
@@ -23,7 +34,10 @@ public class ExitHookInvoker {
ExitHookInvoker.updaterJar = updaterJar;
}
- public static synchronized void cancelUpdate() {
+ /**
+ * Cancel the exit hook, invalidating any previous calls to {@link #setExitHook}
+ */
+ public static synchronized void cancelExitHook() {
cancelled = true;
}
diff --git a/src/main/java/moe/nea/libautoupdate/PotentialUpdate.java b/src/main/java/moe/nea/libautoupdate/PotentialUpdate.java
index 2e6142d..febaa80 100644
--- a/src/main/java/moe/nea/libautoupdate/PotentialUpdate.java
+++ b/src/main/java/moe/nea/libautoupdate/PotentialUpdate.java
@@ -14,15 +14,29 @@ import java.util.concurrent.CompletionException;
@Value
public class PotentialUpdate {
+ /**
+ * The update data of this update.
+ */
UpdateData update;
+ /**
+ * The context of this update.
+ */
UpdateContext context;
+ /**
+ * A UUID so that each update does not conflict which each other.
+ */
UUID updateUUID = UUID.randomUUID();
+ /**
+ * @return the directory in which update data gets stored for the post exit stage.
+ */
public File getUpdateDirectory() {
return new File(".autoupdates", context.getIdentifier() + "/" + updateUUID);
}
-
+ /**
+ * @return true if an update exists and has a higher version number than our current version.
+ */
public boolean isUpdateAvailable() {
if (update == null) return false;
return update.getVersionNumber() > context.getCurrentVersion().getCurrentVersionNumber();
@@ -33,16 +47,25 @@ public class PotentialUpdate {
return new File(getUpdateDirectory(), name);
}
+ /**
+ * @return the location where the updated jar will be stored.
+ */
public File getUpdateJarStorage() {
return getFile("next.jar");
}
+ /**
+ * @return the filename of the updated jar, as specified by the {@link UpdateData#getDownload()}
+ * @throws MalformedURLException if {@link #update} contains an invalid download url.
+ */
public String getFileName() throws MalformedURLException {
val split = update.getDownloadAsURL().getPath().split("/");
return split[split.length - 1];
}
-
+ /**
+ * Extracts the updater jar (for the post exit stage) into the storage directory.
+ */
public void extractUpdater() throws IOException {
val file = getFile("updater.jar");
try (val from = getClass().getResourceAsStream("/updater.jar");
@@ -51,6 +74,9 @@ public class PotentialUpdate {
}
}
+ /**
+ * Download the updated jar into the storage directory.
+ */
public void downloadUpdate() throws IOException {
try (val from = update.getDownloadAsURL().openStream();
val to = new FileOutputStream(getUpdateJarStorage())) {
@@ -67,19 +93,29 @@ public class PotentialUpdate {
}
}
+ /**
+ * Prepare the layout of the storage directory.
+ */
public void prepareUpdate() throws IOException {
extractUpdater();
downloadUpdate();
}
-
+ /**
+ * Execute the update.
+ * This is done by first preparing the storage directory using {@link #prepareUpdate()} and then setting the {@link ExitHookInvoker}
+ */
public void executeUpdate() throws IOException {
prepareUpdate();
ExitHookInvoker.setExitHook(getFile("updater.jar"),
context.getTarget().generateUpdateActions(this));
}
-
+ /**
+ * Execute the update in another thread.
+ *
+ * @return a future which is completed when the update is downloaded and hooked on exit.
+ */
public CompletableFuture<Void> launchUpdate() {
return CompletableFuture.supplyAsync(() -> {
try {
diff --git a/src/main/java/moe/nea/libautoupdate/UpdateContext.java b/src/main/java/moe/nea/libautoupdate/UpdateContext.java
index fa8b8d5..35fd021 100644
--- a/src/main/java/moe/nea/libautoupdate/UpdateContext.java
+++ b/src/main/java/moe/nea/libautoupdate/UpdateContext.java
@@ -8,14 +8,31 @@ import java.io.File;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
+/**
+ * The update context holds information about your application, and it's update process.
+ */
@Value
public class UpdateContext {
+ /**
+ * The source from which to pull updates.
+ */
@NonNull UpdateSource source;
+ /**
+ * The update target which specifies how to install an update.
+ */
@NonNull UpdateTarget target;
+ /**
+ * The version of this application
+ */
@NonNull CurrentVersion currentVersion;
+ /**
+ * An identifier for this application, as to not collide with other applications using this update lib.
+ */
@NonNull String identifier;
-
+ /**
+ * Delete remnants of previous updates.
+ */
public void cleanup() {
File file = new File(".autoupdates", identifier).getAbsoluteFile();
try {
@@ -25,6 +42,12 @@ public class UpdateContext {
}
}
+ /**
+ * Check for an update.
+ *
+ * @param updateStream the update stream to check.
+ * @return a future that resolves to an update of this stream, or null.
+ */
public CompletableFuture<PotentialUpdate> checkUpdate(String updateStream) {
return source.checkUpdate(updateStream)
.thenApply(it -> new PotentialUpdate(it, this));
diff --git a/src/main/java/moe/nea/libautoupdate/UpdateSource.java b/src/main/java/moe/nea/libautoupdate/UpdateSource.java
index 1407063..41765a5 100644
--- a/src/main/java/moe/nea/libautoupdate/UpdateSource.java
+++ b/src/main/java/moe/nea/libautoupdate/UpdateSource.java
@@ -2,10 +2,19 @@ package moe.nea.libautoupdate;
import java.util.concurrent.CompletableFuture;
+/**
+ * UpdateSource is an interface to check for updates in an update stream.
+ */
public interface UpdateSource {
static UpdateSource gistSource(String owner, String gistId) {
return new GistSource(owner, gistId);
}
+ /**
+ * Check for updates in the given update stream.
+ *
+ * @param updateStream the update stream to check for updates.
+ * @return A future that completes with the next {@link UpdateData} or null, if there is no update.
+ */
CompletableFuture<UpdateData> checkUpdate(String updateStream);
}
diff --git a/src/main/java/moe/nea/libautoupdate/UpdateTarget.java b/src/main/java/moe/nea/libautoupdate/UpdateTarget.java
index fcaaa3e..3a60963 100644
--- a/src/main/java/moe/nea/libautoupdate/UpdateTarget.java
+++ b/src/main/java/moe/nea/libautoupdate/UpdateTarget.java
@@ -1,16 +1,32 @@
package moe.nea.libautoupdate;
-import java.io.File;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+
+import java.io.*;
import java.util.List;
+/**
+ * Interface for generating post download actions for installing the update Jar.
+ */
public interface UpdateTarget {
List<UpdateAction> generateUpdateActions(PotentialUpdate update);
+ /**
+ * Create
+ *
+ * @param containedClass
+ * @return
+ */
static UpdateTarget replaceJar(Class<?> containedClass) {
File file = UpdateUtils.getJarFileContainingClass(containedClass);
return new ReplaceJarUpdateTarget(file);
}
+
+ /**
+ * Create an update target that deletes the Jar containing the specified class, and saves the new Jar in the same
+ */
static UpdateTarget deleteAndSaveInTheSameFolder(Class<?> containedClass) {
File file = UpdateUtils.getJarFileContainingClass(containedClass);
return new DeleteAndSaveInSameFolderUpdateTarget(file);
diff --git a/updater/src/main/java/moe/nea/libautoupdate/postexit/PostExitMain.java b/updater/src/main/java/moe/nea/libautoupdate/postexit/PostExitMain.java
index d143fee..cf9a820 100644
--- a/updater/src/main/java/moe/nea/libautoupdate/postexit/PostExitMain.java
+++ b/updater/src/main/java/moe/nea/libautoupdate/postexit/PostExitMain.java
@@ -8,7 +8,7 @@ import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
public class PostExitMain {
- public static void main(String[] args) throws IOException {
+ public static void main(String[] args) throws IOException, InterruptedException {
File outputFile = new File(".autoupdates", "postexit.log");
outputFile.getParentFile().mkdirs();
PrintStream printStream = new PrintStream(new FileOutputStream(outputFile, true));
@@ -18,13 +18,15 @@ public class PostExitMain {
for (int i = 0; i < args.length; i++) {
switch (args[i].intern()) {
case "delete":
- File file = new File(args[++i]);
+ File file = unlockedFile(args[++i]);
System.out.println("Deleting " + file);
- file.delete();
+ if (!file.delete()) {
+ System.out.println("Failed to delete " + file);
+ }
break;
case "move":
- File from = new File(args[++i]);
- File to = new File(args[++i]);
+ File from = unlockedFile(args[++i]);
+ File to = unlockedFile(args[++i]);
System.out.println("Moving " + from + " to " + to);
// Use Files.move instead of File.renameTo, since renameTo is not well-defined.
Files.move(from.toPath(), to.toPath(), StandardCopyOption.REPLACE_EXISTING);
@@ -36,11 +38,14 @@ public class PostExitMain {
}
}
- public void unlockedFile(File file) throws InterruptedException {
- while (!file.exists() || !file.renameTo(file)) {
+ public static File unlockedFile(String name) throws InterruptedException {
+ File file = new File(name);
+ while (file.exists() && !file.renameTo(file)) {
+ System.out.println("Waiting on a process to relinquish access to " + file);
Thread.sleep(1000L);
}
file.getParentFile().mkdirs();
+ return file;
}
}