diff options
author | Keuin <[email protected]> | 2020-11-30 13:15:15 +0800 |
---|---|---|
committer | keuin <[email protected]> | 2020-11-30 13:15:15 +0800 |
commit | 61ade9adad4668494dfc32da7751e1b86251dc97 (patch) | |
tree | c220fe41d0691d7ad6ed08e51d351537fa220a4f /src/main/java/com/keuin/kbackupfabric/operation/backup/IncrementalBackupUtil.java | |
parent | e59bdf4ac0b66ce683be1bbc36852bfce6f70a63 (diff) |
Implementing incremental backup
Diffstat (limited to 'src/main/java/com/keuin/kbackupfabric/operation/backup/IncrementalBackupUtil.java')
-rw-r--r-- | src/main/java/com/keuin/kbackupfabric/operation/backup/IncrementalBackupUtil.java | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/main/java/com/keuin/kbackupfabric/operation/backup/IncrementalBackupUtil.java b/src/main/java/com/keuin/kbackupfabric/operation/backup/IncrementalBackupUtil.java new file mode 100644 index 0000000..f90aef1 --- /dev/null +++ b/src/main/java/com/keuin/kbackupfabric/operation/backup/IncrementalBackupUtil.java @@ -0,0 +1,90 @@ +package com.keuin.kbackupfabric.operation.backup; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.keuin.kbackupfabric.util.FilesystemUtil; +import org.apache.commons.codec.digest.DigestUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.*; +import java.util.Map; + +public class IncrementalBackupUtil { + /** + * Generate a json object representing a directory and its all sub files and directories. + * @param path path to the directory. + * @return a json object. + */ + public static JsonObject generateDirectoryJsonObject(String path) throws IOException { + JsonObject json = new JsonObject(); + File directory = new File(path); + if (!(directory.isDirectory() && directory.exists())) + throw new IOException(String.format("Path %s is not a valid directory.", path)); + + // Iterate all sub files using BFS. + try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(path))) { + for (Path sub : directoryStream) { + if (sub.toFile().isFile()) { + // A sub file + // Just hash and add it as a string + try (InputStream is = Files.newInputStream(sub)) { + String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is); + json.addProperty(sub.getFileName().toString(), md5); + } + } else { + // A sub directory + // Search into + json.addProperty(String.valueOf(sub.getFileName()), sub.toString()); + } + } + } + + return json; + } + + /** + * Save new (or modified) files to target path, based on hash json. + * @param targetSavePath where we should save new files. + * @param sourcePath where new files come from. This path must be the base directory of given hash json. + * @param hashJson the json object obtained by calling generateDirectoryJsonObject method. + * @return total size of new files. If failed, will return -1. + */ + public static long saveNewFiles(String targetSavePath, String sourcePath, JsonObject hashJson) throws IOException { + long bytesCopied = 0; + for (Map.Entry<String, JsonElement> entry : hashJson.entrySet()) { + String key = entry.getKey(); + JsonElement value = entry.getValue(); + if (value.isJsonPrimitive() && value.getAsJsonPrimitive().isString()) { + // A sub file + // key is file name + // value is file md5 + String md5 = value.getAsJsonPrimitive().getAsString(); + File saveTarget = new File(targetSavePath, md5); + if (!saveTarget.exists()) { + // Target file does not exist. We have to copy this to the target. + File sourceFile = new File(sourcePath, key); + Files.copy(sourceFile.toPath(), saveTarget.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES); + try { + bytesCopied += sourceFile.length(); + } catch (SecurityException ignored) { + // failed to get the file size. Just ignore this. + } + } + } else if (value.isJsonObject()) { + // A sub directory + // key is directory name + // value is directory json object + // Go into + if(!value.isJsonObject()) + throw new IllegalArgumentException(String.format("Hash json contains illegal argument of a directory item: %s -> %s.", key, value)); + Path pathSource = Paths.get(sourcePath, key); + bytesCopied += saveNewFiles(targetSavePath, pathSource.toString(), value.getAsJsonObject()); + } else { + throw new IllegalArgumentException(String.format("Hash json contains illegal element: %s -> %s.", key, value)); + } + } + return bytesCopied; + } +} |