From 6c432898606bd9304819e1a2bf389b5a68c6200e Mon Sep 17 00:00:00 2001 From: Nathan McRae Date: Mon, 3 Mar 2025 21:10:07 -0800 Subject: [PATCH] Add removal methods to WindowsScheduler and StationSettings --- .../numbersstation/StationSettings.java | 41 +++++++++++ .../numbersstation/WindowsScheduler.java | 68 +++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/src/main/java/name/nathanmcrae/numbersstation/StationSettings.java b/src/main/java/name/nathanmcrae/numbersstation/StationSettings.java index ae431b1..bdf5f01 100644 --- a/src/main/java/name/nathanmcrae/numbersstation/StationSettings.java +++ b/src/main/java/name/nathanmcrae/numbersstation/StationSettings.java @@ -1,5 +1,6 @@ package name.nathanmcrae.numbersstation; +import com.leakyabstractions.result.api.Result; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.file.attribute.BasicFileAttributes; @@ -13,6 +14,7 @@ import java.time.LocalDate; import java.time.LocalTime; import java.util.ArrayList; import java.util.logging.Logger; +import java.util.logging.Level; import java.util.Random; public class StationSettings { @@ -65,6 +67,44 @@ public class StationSettings { scheduleStartTime = LocalTime.now(); } + public static void deleteStationData(String stationName) throws IOException { + StationSettings temp = new StationSettings(stationName); + + temp.deleteDir(); + + String osName = System.getProperty("os.name").toLowerCase(); + if (osName.contains("win")) { + WindowsScheduler.removeSchedule(temp); + } else if (osName.contains("nix") || osName.contains("nux") || osName.contains("aix")) { + // TODO: linux + logger.log(Level.SEVERE, "Unsupported OS " + osName); + } else { + logger.log(Level.SEVERE, "Unsupported OS " + osName); + } + } + + public static boolean stationDataExists(String stationName) { + StationSettings temp = new StationSettings(stationName); + if (Files.exists(temp.stationPath())) { + return true; + } + + String osName = System.getProperty("os.name").toLowerCase(); + if (osName.contains("win")) { + Result result = WindowsScheduler.scheduleExists(temp); + if (result.hasSuccess() && result.getSuccess().get()) { + return true; + } + } else if (osName.contains("nix") || osName.contains("nux") || osName.contains("aix")) { + // TODO: linux + logger.log(Level.SEVERE, "Unsupported OS " + osName); + } else { + logger.log(Level.SEVERE, "Unsupported OS " + osName); + } + + return false; + } + public void deleteDir() throws IOException { Files.walkFileTree(stationPath(), new SimpleFileVisitor() { @Override @@ -81,6 +121,7 @@ public class StationSettings { }); } + public Path nextMessagePath() { return stationPath().resolve("next-message.txt"); } diff --git a/src/main/java/name/nathanmcrae/numbersstation/WindowsScheduler.java b/src/main/java/name/nathanmcrae/numbersstation/WindowsScheduler.java index b8b80fc..1bee01b 100644 --- a/src/main/java/name/nathanmcrae/numbersstation/WindowsScheduler.java +++ b/src/main/java/name/nathanmcrae/numbersstation/WindowsScheduler.java @@ -341,6 +341,52 @@ public class WindowsScheduler { return Results.success(true); } + public static Result removeSchedule(StationSettings settings) { + Path tempFile = null; + try { + String taskName = "numbers-station-main_" + settings.getName(); + + Process queryTaskProcess = new ProcessBuilder("schtasks.exe", "/query", "/tn", taskName).start(); + if (!queryTaskProcess.waitFor(5, TimeUnit.SECONDS)) { + String message = "Failed to query " + taskName + " task: process timed out"; + logger.log(Level.SEVERE, message); + return Results.failure(message); + } + + // Remove previous instance of task if it exists + if (queryTaskProcess.exitValue() == 0) { + Process removeTaskProcess = new ProcessBuilder("schtasks.exe", "/delete", "/f", "/tn", taskName).start(); + if (!removeTaskProcess.waitFor(5, TimeUnit.SECONDS)) { + String message = "Failed to remove " + taskName + " task: process timed out"; + logger.log(Level.SEVERE, message); + return Results.failure(message); + } + + if (removeTaskProcess.exitValue() == 0) { + logger.info(taskName + " task removed successfully."); + } else { + Pair output = captureProcessOutput(removeTaskProcess); + String message = "Failed to remove " + taskName + " task. Exit code: " + removeTaskProcess.exitValue() + ". stdout: " + output.getKey() + "\n\tstderr: " + output.getValue(); + logger.log(Level.SEVERE, message); + return Results.failure(message); + } + } + } catch (IOException | InterruptedException e) { + String message = "Exception while registering schedule"; + logger.log(Level.SEVERE, message, e); + return Results.failure(message); + } finally { + if (tempFile != null) { + try { + Files.delete(tempFile); + } catch (IOException e) { + logger.log(Level.SEVERE, "Failed to delete temporary file", e); + } + } + } + return Results.success(true); + } + public static Result runSchedule(StationSettings settings) { String taskName = "numbers-station-main_" + settings.getName(); @@ -355,6 +401,28 @@ public class WindowsScheduler { return Results.success(true); } + public static Result scheduleExists(StationSettings settings) { + try { + String taskName = "numbers-station-main_" + settings.getName(); + + Process queryTaskProcess = new ProcessBuilder("schtasks.exe", "/query", "/tn", taskName).start(); + if (!queryTaskProcess.waitFor(5, TimeUnit.SECONDS)) { + String message = "Failed to query " + taskName + " task: process timed out"; + logger.log(Level.SEVERE, message); + return Results.failure(message); + } + + return Results.success(queryTaskProcess.exitValue() == 0); + } catch (InterruptedException | IOException e) { + String message = "Exception while querying schedule"; + logger.log(Level.SEVERE, message, e); + return Results.failure(message); + } + } + + /** + * @return (stdout contents, stderr contents) + */ public static Pair captureProcessOutput(Process process) throws IOException { StringBuilder output = new StringBuilder(); StringBuilder error = new StringBuilder();