diff options
21 files changed, 445 insertions, 42 deletions
diff --git a/src/main/java/com/keuin/kbackupfabric/KBCommandRegister.java b/src/main/java/com/keuin/kbackupfabric/KBCommandRegister.java index b223e3f..bfbe3c1 100644 --- a/src/main/java/com/keuin/kbackupfabric/KBCommandRegister.java +++ b/src/main/java/com/keuin/kbackupfabric/KBCommandRegister.java @@ -1,6 +1,6 @@ package com.keuin.kbackupfabric; -import com.keuin.kbackupfabric.util.BackupNameSuggestionProvider; +import com.keuin.kbackupfabric.util.backup.BackupNameSuggestionProvider; import com.keuin.kbackupfabric.util.PermissionValidator; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; diff --git a/src/main/java/com/keuin/kbackupfabric/KBCommands.java b/src/main/java/com/keuin/kbackupfabric/KBCommands.java index 651a73e..9568842 100644 --- a/src/main/java/com/keuin/kbackupfabric/KBCommands.java +++ b/src/main/java/com/keuin/kbackupfabric/KBCommands.java @@ -6,9 +6,10 @@ import com.keuin.kbackupfabric.operation.BackupOperation; import com.keuin.kbackupfabric.operation.DeleteOperation; import com.keuin.kbackupfabric.operation.RestoreOperation; import com.keuin.kbackupfabric.operation.abstracts.i.Invokable; -import com.keuin.kbackupfabric.util.BackupFilesystemUtil; -import com.keuin.kbackupfabric.util.BackupNameSuggestionProvider; -import com.keuin.kbackupfabric.util.BackupNameTimeFormatter; +import com.keuin.kbackupfabric.operation.backup.BackupMethod; +import com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil; +import com.keuin.kbackupfabric.util.backup.BackupNameSuggestionProvider; +import com.keuin.kbackupfabric.util.backup.BackupNameTimeFormatter; import com.keuin.kbackupfabric.util.PrintUtil; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; @@ -16,12 +17,9 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; +import java.util.*; -import static com.keuin.kbackupfabric.util.BackupFilesystemUtil.*; +import static com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil.*; import static com.keuin.kbackupfabric.util.PrintUtil.*; public final class KBCommands { @@ -78,6 +76,7 @@ public final class KBCommands { File[] files = getBackupSaveDirectory(server).listFiles( (dir, name) -> dir.isDirectory() && name.toLowerCase().endsWith(".zip") && name.toLowerCase().startsWith(getBackupFileNamePrefix()) ); + backupNameList.clear(); if (files != null) { if (files.length != 0) { @@ -112,7 +111,7 @@ public final class KBCommands { backupName = String.format("a%s", backupName); msgWarn(context, String.format("Pure numeric name is not allowed. Renaming to %s", backupName)); } - return doBackup(context, backupName); + return doBackup(context, backupName, BackupMethod); } /** @@ -189,10 +188,10 @@ public final class KBCommands { return doBackup(context, "noname"); } - private static int doBackup(CommandContext<ServerCommandSource> context, String customName) { + private static int doBackup(CommandContext<ServerCommandSource> context, String customBackupName, BackupMethod backupMethod) { // Real backup name (compatible with legacy backup): date_name, such as 2020-04-23_21-03-00_test //KBMain.backup("name") - String backupName = BackupNameTimeFormatter.getTimeString() + "_" + customName; + String backupName = BackupNameTimeFormatter.getTimeString() + "_" + customBackupName; // Validate file name final char[] ILLEGAL_CHARACTERS = {'/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':'}; @@ -204,10 +203,9 @@ public final class KBCommands { } // Do backup - BackupMetadata metadata = new BackupMetadata(System.currentTimeMillis(), backupName); PrintUtil.info("Invoking backup worker ..."); //BackupWorker.invoke(context, backupName, metadata); - BackupOperation operation = new BackupOperation(context, backupName, metadata); + BackupOperation operation = new BackupOperation(context, backupName, backupMethod); if (operation.invoke()) { return SUCCESS; } else if (operation.isBlocked()) { diff --git a/src/main/java/com/keuin/kbackupfabric/KBPluginEvents.java b/src/main/java/com/keuin/kbackupfabric/KBPluginEvents.java index 9e90019..d67d85b 100644 --- a/src/main/java/com/keuin/kbackupfabric/KBPluginEvents.java +++ b/src/main/java/com/keuin/kbackupfabric/KBPluginEvents.java @@ -2,8 +2,8 @@ package com.keuin.kbackupfabric; import com.keuin.kbackupfabric.metadata.BackupMetadata; import com.keuin.kbackupfabric.metadata.MetadataHolder; -import com.keuin.kbackupfabric.util.BackupFilesystemUtil; -import com.keuin.kbackupfabric.util.BackupNameSuggestionProvider; +import com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil; +import com.keuin.kbackupfabric.util.backup.BackupNameSuggestionProvider; import com.keuin.kbackupfabric.util.PrintUtil; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.server.ServerStartCallback; diff --git a/src/main/java/com/keuin/kbackupfabric/Random.java b/src/main/java/com/keuin/kbackupfabric/Random.java new file mode 100644 index 0000000..e87e4c1 --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/Random.java @@ -0,0 +1,97 @@ +package com.keuin.kbackupfabric; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +public class Random { + public int random(int A, int B) { + return (int) (A + (B - A + 1) * Math.random()); + } + + public double[] randomArray(int MaxN, int lowA, int highA) { + double[] array = new double[random(1,MaxN)]; + for (int i = 0; i < array.length; i++) { + array[i] = lowA + (highA - lowA) * Math.random(); + } + return array; + } + + public double[] generate(int MaxN, int lowA, int highA) { + double[] testData = randomArray(MaxN,lowA,highA); + double x = testData[random(0,testData.length-1)]; + } + + public int R(double[] a, double x) { + List<Integer> list = new LinkedList<>(); + int k; + for (int i = 0; i < a.length; i++) { + if(Math.abs(a[i] - x) < 1e-6) + list.add(i); + } + assert !list.isEmpty(); + k = list.get(list.size() / 2); + return k; + } + + + public boolean domR(double[] a, double x) { + for (double v : a) { + if(Math.abs(v - x) < 1e-6) + return true; + } + return false; + } + + public boolean oracle(double[] a, double x, int k) { + if(!(Math.abs(a[k] - x) < 1e-6)) + return false; + int c1=0,c2=0; + for (int i = 0; i < k; i++) { + if(Math.abs(a[i] - x) < 1e-6) + ++c1; + } + for (int i = k; i < a.length; i++) { + if(Math.abs(a[i] - x) < 1e-6) + ++c2; + } + return c1 - c2 >= -1 && c1 - c2 <= 1; + } + + public boolean driver() { + int MaxN = 80, lowA = 20, highA = 50; + double[] a = randomArray(MaxN,lowA,highA); + double x = a[random(0,a.length-1)]; + return oracle(a,x,search(a,x)); + } + + + public int search(double[] a, double x) { + int counter = 0; + for (double i : a) { + if(Math.abs(i - x) < 1e-6) + ++counter; + } + counter /= 2; + for (int i = 0; i < a.length; i++) { + if(Math.abs(a[i] - x) < 1e-6) { + --counter; + if(counter == 0) + return i; + } + } + return -1; + } + + public static void Main() { + int pass = 0, fail = 0; + for (int i = 0; i < 10000; i++) { + if(driver()) + pass++; + else + fail++; + } + System.out.println(String.format("pass: %d, fail: %d.",pass,fail)); + } + +} diff --git a/src/main/java/com/keuin/kbackupfabric/operation/BackupOperation.java b/src/main/java/com/keuin/kbackupfabric/operation/BackupOperation.java index 53b05b8..4c08d14 100644 --- a/src/main/java/com/keuin/kbackupfabric/operation/BackupOperation.java +++ b/src/main/java/com/keuin/kbackupfabric/operation/BackupOperation.java @@ -3,9 +3,12 @@ package com.keuin.kbackupfabric.operation; import com.keuin.kbackupfabric.exception.ZipUtilException; import com.keuin.kbackupfabric.metadata.BackupMetadata; import com.keuin.kbackupfabric.operation.abstracts.InvokableAsyncBlockingOperation; +import com.keuin.kbackupfabric.operation.backup.BackupMethod; import com.keuin.kbackupfabric.util.PrintUtil; -import com.keuin.kbackupfabric.util.ZipUtil; +import com.keuin.kbackupfabric.util.backup.builder.BackupFileNameBuilder; +import com.keuin.kbackupfabric.util.backup.formatter.BackupFileNameFormatter; import com.mojang.brigadier.context.CommandContext; +import com.sun.istack.internal.NotNull; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.world.World; @@ -15,7 +18,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import static com.keuin.kbackupfabric.util.BackupFilesystemUtil.*; +import static com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil.*; import static com.keuin.kbackupfabric.util.PrintUtil.msgInfo; public class BackupOperation extends InvokableAsyncBlockingOperation { @@ -23,15 +26,15 @@ public class BackupOperation extends InvokableAsyncBlockingOperation { private final CommandContext<ServerCommandSource> context; private final String backupName; private final Map<World, Boolean> oldWorldsSavingDisabled = new HashMap<>(); - private final BackupMetadata backupMetadata; + private final BackupMethod backupMethod; private long startTime; - public BackupOperation(CommandContext<ServerCommandSource> context, String backupName, BackupMetadata backupMetadata) { + public BackupOperation(@NotNull CommandContext<ServerCommandSource> context, @NotNull String backupName, @NotNull BackupMethod backupMethod, @NotNull BackupFileNameBuilder backupFileNameBuilder, @NotNull BackupFileNameFormatter backupFileNameFormatter) { super("BackupWorker"); this.context = context; this.backupName = backupName; - this.backupMetadata = backupMetadata; + this.backupMethod = backupMethod; } @Override @@ -52,11 +55,8 @@ public class BackupOperation extends InvokableAsyncBlockingOperation { // Make zip String levelPath = getLevelPath(server); String backupFileName = getBackupFileName(backupName); - PrintUtil.info(String.format("zip(srcPath=%s, destPath=%s)", levelPath, backupSaveDirectoryFile.toString())); - msgInfo(context, "Compressing worlds ..."); - PrintUtil.info("Compressing level ..."); - ZipUtil.makeBackupZip(levelPath, backupSaveDirectoryFile.toString(), backupFileName, backupMetadata); - File backupZipFile = new File(backupSaveDirectoryFile, backupFileName); + + backupMethod.backup(backupName,levelPath,backupSaveDirectory); // Restore old autosave switch stat server.getWorlds().forEach(world -> world.savingDisabled = oldWorldsSavingDisabled.getOrDefault(world, true)); @@ -64,6 +64,7 @@ public class BackupOperation extends InvokableAsyncBlockingOperation { // Print finish message: time elapsed and file size long timeElapsedMillis = System.currentTimeMillis() - startTime; String msgText = String.format("Backup finished. Time elapsed: %.2fs.", timeElapsedMillis / 1000.0); + File backupZipFile = new File(backupSaveDirectory, backupFileName); try { msgText += String.format(" File size: %s.", humanFileSize(backupZipFile.length())); } catch (SecurityException ignored) { @@ -72,7 +73,7 @@ public class BackupOperation extends InvokableAsyncBlockingOperation { } catch (SecurityException e) { msgInfo(context, String.format("Failed to create backup saving directory: %s. Failed to backup.", backupSaveDirectory)); - } catch (IOException | ZipUtilException e) { + } catch (IOException e) { msgInfo(context, "Failed to make zip: " + e.getMessage()); } } diff --git a/src/main/java/com/keuin/kbackupfabric/operation/DeleteOperation.java b/src/main/java/com/keuin/kbackupfabric/operation/DeleteOperation.java index ee1a57e..30fdfc0 100644 --- a/src/main/java/com/keuin/kbackupfabric/operation/DeleteOperation.java +++ b/src/main/java/com/keuin/kbackupfabric/operation/DeleteOperation.java @@ -1,7 +1,7 @@ package com.keuin.kbackupfabric.operation; import com.keuin.kbackupfabric.operation.abstracts.InvokableAsyncBlockingOperation; -import com.keuin.kbackupfabric.util.BackupNameSuggestionProvider; +import com.keuin.kbackupfabric.util.backup.BackupNameSuggestionProvider; import com.keuin.kbackupfabric.util.PrintUtil; import com.mojang.brigadier.context.CommandContext; import net.minecraft.server.MinecraftServer; @@ -10,8 +10,8 @@ import net.minecraft.server.command.ServerCommandSource; import java.io.File; import java.io.IOException; -import static com.keuin.kbackupfabric.util.BackupFilesystemUtil.getBackupFileName; -import static com.keuin.kbackupfabric.util.BackupFilesystemUtil.getBackupSaveDirectory; +import static com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil.getBackupFileName; +import static com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil.getBackupSaveDirectory; import static com.keuin.kbackupfabric.util.PrintUtil.msgErr; import static com.keuin.kbackupfabric.util.PrintUtil.msgInfo; import static org.apache.commons.io.FileUtils.forceDelete; diff --git a/src/main/java/com/keuin/kbackupfabric/operation/RestoreOperation.java b/src/main/java/com/keuin/kbackupfabric/operation/RestoreOperation.java index 6754393..ef6ab2b 100644 --- a/src/main/java/com/keuin/kbackupfabric/operation/RestoreOperation.java +++ b/src/main/java/com/keuin/kbackupfabric/operation/RestoreOperation.java @@ -11,8 +11,8 @@ import net.minecraft.server.command.ServerCommandSource; import java.io.File; import java.io.IOException; -import static com.keuin.kbackupfabric.util.BackupFilesystemUtil.getBackupFileName; -import static com.keuin.kbackupfabric.util.BackupFilesystemUtil.getBackupSaveDirectory; +import static com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil.getBackupFileName; +import static com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil.getBackupSaveDirectory; import static org.apache.commons.io.FileUtils.forceDelete; public class RestoreOperation extends InvokableBlockingOperation { diff --git a/src/main/java/com/keuin/kbackupfabric/operation/backup/BackupMethod.java b/src/main/java/com/keuin/kbackupfabric/operation/backup/BackupMethod.java new file mode 100644 index 0000000..97c609d --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/operation/backup/BackupMethod.java @@ -0,0 +1,22 @@ +package com.keuin.kbackupfabric.operation.backup; + +import com.keuin.kbackupfabric.util.backup.builder.BackupFileNameBuilder; +import com.keuin.kbackupfabric.util.backup.formatter.BackupFileNameFormatter; +import com.sun.istack.internal.NotNull; + +import java.io.IOException; + +public interface BackupMethod { + + /** + * Perform a backup with given method. The backup will be saved as the given name. + * Note: real file name is depended by the backup type. + * @param backupName the backup name. + */ + void backup(@NotNull String backupName, @NotNull String levelPath, @NotNull String backupSaveDirectory) throws IOException; + + BackupFileNameBuilder getBackupFileNameBuilder(); + + BackupFileNameFormatter getBackupFileNameFormatter(); + +} diff --git a/src/main/java/com/keuin/kbackupfabric/operation/backup/PrimitiveBackupMehtod.java b/src/main/java/com/keuin/kbackupfabric/operation/backup/PrimitiveBackupMehtod.java new file mode 100644 index 0000000..3c2a608 --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/operation/backup/PrimitiveBackupMehtod.java @@ -0,0 +1,42 @@ +package com.keuin.kbackupfabric.operation.backup; + +import com.keuin.kbackupfabric.exception.ZipUtilException; +import com.keuin.kbackupfabric.metadata.BackupMetadata; +import com.keuin.kbackupfabric.util.PrintUtil; +import com.keuin.kbackupfabric.util.ZipUtil; +import com.keuin.kbackupfabric.util.backup.builder.BackupFileNameBuilder; +import com.keuin.kbackupfabric.util.backup.formatter.BackupFileNameFormatter; + +import java.io.File; +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class PrimitiveBackupMehtod implements BackupMethod { + @Override + public boolean backup(String backupName, String levelPath, String backupSaveDirectory) throws IOException { + try { + String backupFileName = BackupFileNameBuilder.primitiveZipBackup().build(LocalDateTime.now(),backupName); + BackupMetadata backupMetadata = new BackupMetadata(System.currentTimeMillis(), backupName); + + PrintUtil.info(String.format("zip(srcPath=%s, destPath=%s)", levelPath, backupSaveDirectory)); + PrintUtil.info("Compressing level ..."); + ZipUtil.makeBackupZip(levelPath, backupSaveDirectory, backupFileName, backupMetadata); + + } catch (ZipUtilException exception) { + PrintUtil.info("Infinite recursive of directory tree detected, backup was aborted."); + return false; + } + return true; + } + + @Override + public BackupFileNameBuilder getBackupFileNameBuilder() { + return BackupFileNameBuilder.primitiveZipBackup(); + } + + @Override + public BackupFileNameFormatter getBackupFileNameFormatter() { + return BFNF; + } +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/PrintUtil.java b/src/main/java/com/keuin/kbackupfabric/util/PrintUtil.java index 8839993..81c6a33 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/PrintUtil.java +++ b/src/main/java/com/keuin/kbackupfabric/util/PrintUtil.java @@ -80,18 +80,34 @@ public final class PrintUtil { return context; } + /** + * Print debug message on the server console. + * @param string the message. + */ public static void debug(String string) { LOGGER.debug("[KBackup] " + string); } + /** + * Print informative message on the server console. + * @param string the message. + */ public static void info(String string) { LOGGER.info("[KBackup] " + string); } + /** + * Print warning message on the server console. + * @param string the message. + */ public static void warn(String string) { LOGGER.warn("[KBackup] " + string); } + /** + * Print error message on the server console. + * @param string the message. + */ public static void error(String string) { LOGGER.error("[KBackup] " + string); } diff --git a/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java b/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java index 11b912e..0ca8da3 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java +++ b/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java @@ -68,11 +68,11 @@ public final class ZipUtil { * @param zipPath 压缩文件保存的路径。注意:zipPath不能是srcPath路径下的子文件夹 * @param zipFileName 压缩文件名 * @throws IOException IO Error - * @throws ZipUtilException General exception, such as loop recursion or invalid input. + * @throws ZipUtilException General exception, such as loop recursion. */ public static void makeBackupZip(String srcPath, String zipPath, String zipFileName, BackupMetadata backupMetadata) throws IOException, ZipUtilException { - if (srcPath.isEmpty() || zipPath.isEmpty() || zipFileName.isEmpty()) { - throw new ZipUtilException("Parameter for zip() contains null."); + if (srcPath == null || zipPath == null || zipFileName == null || backupMetadata == null || srcPath.isEmpty() || zipPath.isEmpty() || zipFileName.isEmpty()) { + throw new IllegalArgumentException("Parameter for zip() contains null."); } CheckedOutputStream checkedOutputStream; ZipOutputStream zipOutputStream = null; diff --git a/src/main/java/com/keuin/kbackupfabric/util/BackupFilesystemUtil.java b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java index ce39615..54c2f58 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/BackupFilesystemUtil.java +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupFilesystemUtil.java @@ -1,5 +1,6 @@ -package com.keuin.kbackupfabric.util; +package com.keuin.kbackupfabric.util.backup; +import com.keuin.kbackupfabric.util.ReflectionUtils; import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ThreadedAnvilChunkStorage; import net.minecraft.world.World; @@ -16,10 +17,16 @@ public final class BackupFilesystemUtil { private static final String backupSaveDirectoryName = "backups"; private static final String backupFileNamePrefix = "kbackup-"; + public static String getBackupFileNamePrefix() { + return backupFileNamePrefix; + } + + @Deprecated public static String getBackupFileName(String backupName) { return backupFileNamePrefix + backupName + ".zip"; } + @Deprecated public static String getBackupName(String backupFileName) { try { if (backupFileName.matches(backupFileNamePrefix + ".+\\.zip")) @@ -49,10 +56,7 @@ public final class BackupFilesystemUtil { return saveDir.getName(); } - public static String getBackupFileNamePrefix() { - return backupFileNamePrefix; - } - + @Deprecated public static long getBackupTimeFromBackupFileName(String backupFileName) { Matcher matcher = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}").matcher(backupFileName); if (matcher.find()) { diff --git a/src/main/java/com/keuin/kbackupfabric/util/BackupNameSuggestionProvider.java b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupNameSuggestionProvider.java index ff122b9..4639e99 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/BackupNameSuggestionProvider.java +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupNameSuggestionProvider.java @@ -1,4 +1,4 @@ -package com.keuin.kbackupfabric.util; +package com.keuin.kbackupfabric.util.backup; import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.suggestion.Suggestions; diff --git a/src/main/java/com/keuin/kbackupfabric/util/BackupNameTimeFormatter.java b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupNameTimeFormatter.java index 5d00270..3811ae8 100644 --- a/src/main/java/com/keuin/kbackupfabric/util/BackupNameTimeFormatter.java +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupNameTimeFormatter.java @@ -1,4 +1,4 @@ -package com.keuin.kbackupfabric.util; +package com.keuin.kbackupfabric.util.backup; import java.time.LocalDateTime; import java.time.ZoneId; @@ -8,10 +8,16 @@ import java.time.format.DateTimeFormatter; public class BackupNameTimeFormatter { private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"); + @Deprecated public static String getTimeString() { return LocalDateTime.now().format(formatter); } + public static String localDateTimeToString(LocalDateTime localDateTime) { + return localDateTime.format(formatter); + } + + @Deprecated public static long timeStringToEpochSeconds(String timeString) { ZoneId systemZone = ZoneId.systemDefault(); // my timezone LocalDateTime localDateTime = LocalDateTime.parse(timeString, formatter); @@ -19,4 +25,8 @@ public class BackupNameTimeFormatter { return localDateTime.toEpochSecond(currentOffsetForMyZone); } + public static LocalDateTime timeStringToLocalDateTime(String timeString) { + return LocalDateTime.parse(timeString,formatter); + } + } diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/BackupType.java b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupType.java new file mode 100644 index 0000000..95a32ae --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/BackupType.java @@ -0,0 +1,21 @@ +package com.keuin.kbackupfabric.util.backup; + +/** + * Representing the backup type. + * Should only be used in BackupFileNameBuilder and BackupFileNameFormatter + */ +public enum BackupType { + + PRIMITIVE_ZIP_BACKUP("Primitive Zip Backup"), + OBJECT_TREE_BACKUP("Object Tree Backup"); + + private final String name; + BackupType(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/builder/BackupFileNameBuilder.java b/src/main/java/com/keuin/kbackupfabric/util/backup/builder/BackupFileNameBuilder.java new file mode 100644 index 0000000..16c598b --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/builder/BackupFileNameBuilder.java @@ -0,0 +1,25 @@ +package com.keuin.kbackupfabric.util.backup.builder; + +import com.sun.istack.internal.NotNull; + +import java.time.LocalDateTime; + +public interface BackupFileNameBuilder { + + static BackupFileNameBuilder primitiveZipBackup() { + return PrimitiveZipBackupFileNameBuilder.getInstance(); + } + + static BackupFileNameBuilder objectTreeBackup() { + return ObjectTreeBackupFileNameBuilder.getInstance(); + } + + /** + * Build a backup file name based on given information. + * @param time when the backup was created. + * @param backupName the custom name of this backup. Note that this should be a valid file name in current file system. + * @return the backup file name string. + */ + String build(@NotNull LocalDateTime time, @NotNull String backupName); + +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/builder/ObjectTreeBackupFileNameBuilder.java b/src/main/java/com/keuin/kbackupfabric/util/backup/builder/ObjectTreeBackupFileNameBuilder.java new file mode 100644 index 0000000..3c15741 --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/builder/ObjectTreeBackupFileNameBuilder.java @@ -0,0 +1,20 @@ +package com.keuin.kbackupfabric.util.backup.builder; + +import com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil; +import com.keuin.kbackupfabric.util.backup.BackupNameTimeFormatter; + +import java.time.LocalDateTime; + +public class ObjectTreeBackupFileNameBuilder implements BackupFileNameBuilder { + private static final ObjectTreeBackupFileNameBuilder instance = new ObjectTreeBackupFileNameBuilder(); + + public static ObjectTreeBackupFileNameBuilder getInstance() { + return instance; + } + + @Override + public String build(LocalDateTime time, String backupName) { + String timeString = BackupNameTimeFormatter.localDateTimeToString(time); + return String.format("%s%s_%s%s", BackupFilesystemUtil.getBackupFileNamePrefix(),timeString,backupName,".json"); + } +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/builder/PrimitiveZipBackupFileNameBuilder.java b/src/main/java/com/keuin/kbackupfabric/util/backup/builder/PrimitiveZipBackupFileNameBuilder.java new file mode 100644 index 0000000..f910c37 --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/builder/PrimitiveZipBackupFileNameBuilder.java @@ -0,0 +1,22 @@ +package com.keuin.kbackupfabric.util.backup.builder; + +import com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil; +import com.keuin.kbackupfabric.util.backup.BackupNameTimeFormatter; + +import java.time.LocalDateTime; + +public class PrimitiveZipBackupFileNameBuilder implements BackupFileNameBuilder { + + private static final PrimitiveZipBackupFileNameBuilder instance = new PrimitiveZipBackupFileNameBuilder(); + + public static PrimitiveZipBackupFileNameBuilder getInstance() { + return instance; + } + + @Override + public String build(LocalDateTime time, String backupName) { + String timeString = BackupNameTimeFormatter.localDateTimeToString(time); + return String.format("%s%s_%s%s", BackupFilesystemUtil.getBackupFileNamePrefix(),timeString,backupName,".zip"); + } + +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/formatter/BackupFileNameFormatter.java b/src/main/java/com/keuin/kbackupfabric/util/backup/formatter/BackupFileNameFormatter.java new file mode 100644 index 0000000..eae3639 --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/formatter/BackupFileNameFormatter.java @@ -0,0 +1,32 @@ +package com.keuin.kbackupfabric.util.backup.formatter; + +import com.keuin.kbackupfabric.util.backup.BackupNameTimeFormatter; +import com.sun.istack.internal.NotNull; + +import java.time.LocalDateTime; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public interface BackupFileNameFormatter { + + BackupFileName format(@NotNull String fileName); + + class BackupFileName { + public final LocalDateTime time; + public final String name; + + public BackupFileName(LocalDateTime time, String name) { + this.time = time; + this.name = name; + } + } + + static BackupFileNameFormatter objectTreeBackup() { + return ObjectTreeBackupFileNameFormatter.getInstance(); + } + + static BackupFileNameFormatter primitiveZipBackup() { + return PrimitiveZipBackupFileNameFormatter.getInstance(); + } + +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/formatter/ObjectTreeBackupFileNameFormatter.java b/src/main/java/com/keuin/kbackupfabric/util/backup/formatter/ObjectTreeBackupFileNameFormatter.java new file mode 100644 index 0000000..e5503a9 --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/formatter/ObjectTreeBackupFileNameFormatter.java @@ -0,0 +1,47 @@ +package com.keuin.kbackupfabric.util.backup.formatter; + +import com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil; +import com.keuin.kbackupfabric.util.backup.BackupNameTimeFormatter; +import com.sun.istack.internal.NotNull; +import com.sun.istack.internal.Nullable; +import org.spongepowered.asm.mixin.Overwrite; + +import java.time.LocalDateTime; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ObjectTreeBackupFileNameFormatter implements BackupFileNameFormatter { + + private static final ObjectTreeBackupFileNameFormatter instance = new ObjectTreeBackupFileNameFormatter(); + + public static ObjectTreeBackupFileNameFormatter getInstance() { + return instance; + } + + @Override + public BackupFileNameFormatter.BackupFileName format(@NotNull String fileName) { + LocalDateTime time = getTime(fileName); + String name = getBackupName(fileName); + return new BackupFileNameFormatter.BackupFileName(time,name); + } + + @Nullable + private LocalDateTime getTime(String fileName) { + Matcher matcher = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}").matcher(fileName); + if (matcher.find()) { + String timeString = matcher.group(0); + return BackupNameTimeFormatter.timeStringToLocalDateTime(timeString); + } + return null; + } + + private String getBackupName(String backupFileName) { + try { + if (backupFileName.matches(BackupFilesystemUtil.getBackupFileNamePrefix() + ".+\\.json")) + return backupFileName.substring(BackupFilesystemUtil.getBackupFileNamePrefix().length(), backupFileName.length() - 4); + } catch (IndexOutOfBoundsException ignored) { + } + return backupFileName; + } + +} diff --git a/src/main/java/com/keuin/kbackupfabric/util/backup/formatter/PrimitiveZipBackupFileNameFormatter.java b/src/main/java/com/keuin/kbackupfabric/util/backup/formatter/PrimitiveZipBackupFileNameFormatter.java new file mode 100644 index 0000000..40450eb --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/util/backup/formatter/PrimitiveZipBackupFileNameFormatter.java @@ -0,0 +1,46 @@ +package com.keuin.kbackupfabric.util.backup.formatter; + +import com.keuin.kbackupfabric.util.backup.BackupFilesystemUtil; +import com.keuin.kbackupfabric.util.backup.BackupNameTimeFormatter; +import com.sun.istack.internal.NotNull; +import com.sun.istack.internal.Nullable; + +import java.time.LocalDateTime; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PrimitiveZipBackupFileNameFormatter implements BackupFileNameFormatter { + + private static final PrimitiveZipBackupFileNameFormatter instance = new PrimitiveZipBackupFileNameFormatter(); + + public static PrimitiveZipBackupFileNameFormatter getInstance() { + return instance; + } + + @Override + public BackupFileNameFormatter.BackupFileName format(@NotNull String fileName) { + LocalDateTime time = getTime(fileName); + String name = getBackupName(fileName); + return new BackupFileNameFormatter.BackupFileName(time,name); + } + + @Nullable + private LocalDateTime getTime(String fileName) { + Matcher matcher = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}").matcher(fileName); + if (matcher.find()) { + String timeString = matcher.group(0); + return BackupNameTimeFormatter.timeStringToLocalDateTime(timeString); + } + return null; + } + + private String getBackupName(String backupFileName) { + try { + if (backupFileName.matches(BackupFilesystemUtil.getBackupFileNamePrefix() + ".+\\.zip")) + return backupFileName.substring(BackupFilesystemUtil.getBackupFileNamePrefix().length(), backupFileName.length() - 4); + } catch (IndexOutOfBoundsException ignored) { + } + return backupFileName; + } + +} |