summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKeuin <[email protected]>2021-06-11 17:24:46 +0800
committerKeuin <[email protected]>2021-06-11 18:54:04 +0800
commit1ec5112f3487d7a2ca7aa9b1fe4825a8e3777bc3 (patch)
tree40b6cb086bb0f4f074f2c422dba491806e7f177e /src
parentfe652450ac33adc4bb15a487eff24d7b5120e1a2 (diff)
fix silent-fail IO exception in ZipUtil; Improve code quality in ZipUtil
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/keuin/kbackupfabric/operation/backup/feedback/PrimitiveBackupFeedback.java17
-rw-r--r--src/main/java/com/keuin/kbackupfabric/operation/backup/method/ConfiguredPrimitiveBackupMethod.java19
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java171
3 files changed, 106 insertions, 101 deletions
diff --git a/src/main/java/com/keuin/kbackupfabric/operation/backup/feedback/PrimitiveBackupFeedback.java b/src/main/java/com/keuin/kbackupfabric/operation/backup/feedback/PrimitiveBackupFeedback.java
index 094438c..0d99cf5 100644
--- a/src/main/java/com/keuin/kbackupfabric/operation/backup/feedback/PrimitiveBackupFeedback.java
+++ b/src/main/java/com/keuin/kbackupfabric/operation/backup/feedback/PrimitiveBackupFeedback.java
@@ -3,12 +3,23 @@ package com.keuin.kbackupfabric.operation.backup.feedback;
import static com.keuin.kbackupfabric.backup.BackupFilesystemUtil.getFriendlyFileSizeString;
public class PrimitiveBackupFeedback implements BackupFeedback {
+
private final boolean success;
- private final long backupSizeBytes;
+ private final long backupSizeBytes; // if success==false, this is invalid
+ private final String message; // if success==true, this is invalid
- public PrimitiveBackupFeedback(boolean success, long backupSizeBytes) {
+ private PrimitiveBackupFeedback(boolean success, long backupSizeBytes, String message) {
this.success = success;
this.backupSizeBytes = backupSizeBytes;
+ this.message = message;
+ }
+
+ public static PrimitiveBackupFeedback createSuccessFeedback(long backupSizeBytes) {
+ return new PrimitiveBackupFeedback(true, backupSizeBytes, "");
+ }
+
+ public static PrimitiveBackupFeedback createFailFeedback(String message) {
+ return new PrimitiveBackupFeedback(false, -1, message);
}
@Override
@@ -25,6 +36,6 @@ public class PrimitiveBackupFeedback implements BackupFeedback {
if (success && backupSizeBytes >= 0)
return String.format("Backup file size: %s.", getFriendlyFileSizeString(backupSizeBytes));
else
- return "";
+ return message;
}
}
diff --git a/src/main/java/com/keuin/kbackupfabric/operation/backup/method/ConfiguredPrimitiveBackupMethod.java b/src/main/java/com/keuin/kbackupfabric/operation/backup/method/ConfiguredPrimitiveBackupMethod.java
index 0047c44..ded514c 100644
--- a/src/main/java/com/keuin/kbackupfabric/operation/backup/method/ConfiguredPrimitiveBackupMethod.java
+++ b/src/main/java/com/keuin/kbackupfabric/operation/backup/method/ConfiguredPrimitiveBackupMethod.java
@@ -12,6 +12,7 @@ import com.keuin.kbackupfabric.util.ZipUtil;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.logging.Logger;
@@ -47,20 +48,26 @@ public class ConfiguredPrimitiveBackupMethod implements ConfiguredBackupMethod {
PrintUtil.info(String.format("zip(srcPath=%s, destPath=%s)", levelPath, backupSavePath));
PrintUtil.info("Compressing level ...");
ZipUtil.makeBackupZip(levelPath, backupSavePath, backupFileName, backupMetadata);
- feedback = new PrimitiveBackupFeedback(true, FilesystemUtil.getFileSizeBytes(backupSavePath, backupFileName));
+ feedback = PrimitiveBackupFeedback.createSuccessFeedback(
+ FilesystemUtil.getFileSizeBytes(backupSavePath, backupFileName));
} catch (ZipUtilException exception) {
- PrintUtil.info("Infinite recursive of directory tree detected, backup was aborted.");
- feedback = new PrimitiveBackupFeedback(false, 0);
+ String msg = "Infinite recursive of directory tree detected, backup was aborted.";
+ PrintUtil.info(msg);
+ feedback = PrimitiveBackupFeedback.createFailFeedback(msg);
} catch (IOException e) {
- feedback = new PrimitiveBackupFeedback(false, 0);
+ feedback = PrimitiveBackupFeedback.createFailFeedback(e.getMessage());
}
if (!feedback.isSuccess()) {
// do clean-up if failed
File backupFile = new File(backupSavePath, backupFileName);
if (backupFile.exists()) {
- if (!backupFile.delete()) {
- LOGGER.warning("Failed to clean up: cannot delete file " + backupFile.getName());
+ LOGGER.info(String.format("Deleting incomplete backup file \"%s\"...", backupFile.getPath()));
+ try {
+ Files.delete(backupFile.toPath());
+ LOGGER.info("Failed to backup, all files are cleaned up.");
+ } catch (IOException e) {
+ LOGGER.warning("Cannot delete: " + e.getMessage());
}
}
}
diff --git a/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java b/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java
index d0d0a61..c23527f 100644
--- a/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java
+++ b/src/main/java/com/keuin/kbackupfabric/util/ZipUtil.java
@@ -46,12 +46,13 @@ public final class ZipUtil {
ZipEntry entry = new ZipEntry(subPath);
zipOutputStream.putNextEntry(entry);
// BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file));
- InputStream inputStream = new FileInputStream(file);
- while ((count = inputStream.read(buffer, 0, zipBufferSize)) != -1) {
- zipOutputStream.write(buffer, 0, count);
+ try (InputStream inputStream = new FileInputStream(file)) {
+ while ((count = inputStream.read(buffer, 0, zipBufferSize)) != -1) {
+ zipOutputStream.write(buffer, 0, count);
+ }
+ } finally {
+ zipOutputStream.closeEntry();
}
- inputStream.close();
- zipOutputStream.closeEntry();
} else {
// 如果是目录,则压缩整个目录
// 压缩目录中的文件或子目录
@@ -88,49 +89,45 @@ public final class ZipUtil {
throw new IllegalArgumentException("zipFileName cannot be empty");
}
- CheckedOutputStream checkedOutputStream;
- ZipOutputStream zipOutputStream = null;
- try {
- File srcFile = new File(srcPath);
+ File srcFile = new File(srcPath);
- //判断压缩文件保存的路径是否为源文件路径的子文件夹,如果是,则抛出异常(防止无限递归压缩的发生)
- if (srcFile.isDirectory() && zipPath.contains(srcPath)) {
- throw new ZipUtilException("Detected loop recursion in directory structure, please check symlink linking to parent directories.");
- }
+ //判断压缩文件保存的路径是否为源文件路径的子文件夹,如果是,则抛出异常(防止无限递归压缩的发生)
+ if (srcFile.isDirectory() && zipPath.contains(srcPath)) {
+ throw new ZipUtilException("Detected loop recursion in directory structure, please check symlink linking to parent directories.");
+ }
- //判断压缩文件保存的路径是否存在,如果不存在,则创建目录
- File zipDir = new File(zipPath);
- if (!zipDir.exists() || !zipDir.isDirectory()) {
- if (!zipDir.mkdirs()) {
- throw new IOException(String.format("Failed to make directory tree %s", zipDir.toString()));
- }
+ //判断压缩文件保存的路径是否存在,如果不存在,则创建目录
+ File zipDir = new File(zipPath);
+ if (!zipDir.exists() || !zipDir.isDirectory()) {
+ if (!zipDir.mkdirs()) {
+ throw new IOException(String.format("Failed to make directory tree %s", zipDir.toString()));
}
+ }
- //创建压缩文件保存的文件对象
- String zipFilePath = zipPath + File.separator + zipFileName;
- File zipFile = new File(zipFilePath);
- if (zipFile.exists()) {
- //检测文件是否允许删除,如果不允许删除,将会抛出SecurityException
- SecurityManager securityManager = new SecurityManager();
- securityManager.checkDelete(zipFilePath);
- //删除已存在的目标文件
- if (!zipFile.delete()) {
- throw new IOException(String.format("Failed to delete existing file %s", zipFile.toString()));
- }
+ //创建压缩文件保存的文件对象
+ String zipFilePath = zipPath + File.separator + zipFileName;
+ File zipFile = new File(zipFilePath);
+ if (zipFile.exists()) {
+ //删除已存在的目标文件
+ if (!zipFile.delete()) {
+ throw new IOException(String.format("Failed to delete existing file %s", zipFile.toString()));
}
+ }
- checkedOutputStream = new CheckedOutputStream(new FileOutputStream(zipFile), new CRC32());
- zipOutputStream = new ZipOutputStream(checkedOutputStream);
+ try (FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
+ CheckedOutputStream checkedOutputStream = new CheckedOutputStream(fileOutputStream, new CRC32());
+ ZipOutputStream zipOutputStream = new ZipOutputStream(checkedOutputStream)) {
zipOutputStream.setLevel(zipLevel);
// If with backup metadata, we serialize it and write it into file "kbackup_metadata"
ZipEntry metadataEntry = new ZipEntry(BackupMetadata.metadataFileName);
+
zipOutputStream.putNextEntry(metadataEntry);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(backupMetadata);
- oos.close();
- zipOutputStream.write(baos.toByteArray());
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ oos.writeObject(backupMetadata);
+ zipOutputStream.write(baos.toByteArray());
+ }
zipOutputStream.closeEntry();
//如果只是压缩一个文件,则需要截取该文件的父目录
@@ -145,14 +142,6 @@ public final class ZipUtil {
//调用递归压缩方法进行目录或文件压缩
zip(srcRootDir, srcFile, zipOutputStream, Collections.singleton("session.lock"), new byte[zipBufferSize]);
zipOutputStream.flush();
- } finally {
- try {
- if (zipOutputStream != null) {
- zipOutputStream.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
}
}
@@ -193,56 +182,54 @@ public final class ZipUtil {
String entryFilePath, entryDirPath;
File entryFile, entryDir;
int index, count;
- ZipFile zip = new ZipFile(zipFile);
- Enumeration<? extends ZipEntry> entries = zip.entries();
- // 循环对压缩包里的每一个文件进行解压
- while (entries.hasMoreElements()) {
- entry = entries.nextElement();
- // 构建压缩包中一个文件解压后保存的文件全路径
- entryFilePath = unzipFilePath + File.separator + entry.getName();
-
- // 构建解压后保存的文件夹路径
- index = entryFilePath.lastIndexOf(File.separator);
- if (index != -1) {
- entryDirPath = entryFilePath.substring(0, index);
- } else {
- entryDirPath = "";
- }
- entryDir = new File(entryDirPath);
- // 如果文件夹路径不存在,则创建文件夹
- if (!entryDir.exists() || !entryDir.isDirectory()) {
- if (!entryDir.mkdirs())
- throw new IOException(String.format("Failed to make directory tree %s", entryDir.toString()));
- }
+ try (ZipFile zip = new ZipFile(zipFile)) {
+ Enumeration<? extends ZipEntry> entries = zip.entries();
+ // 循环对压缩包里的每一个文件进行解压
+ while (entries.hasMoreElements()) {
+ entry = entries.nextElement();
+ // 构建压缩包中一个文件解压后保存的文件全路径
+ entryFilePath = unzipFilePath + File.separator + entry.getName();
+
+ // 构建解压后保存的文件夹路径
+ index = entryFilePath.lastIndexOf(File.separator);
+ if (index != -1) {
+ entryDirPath = entryFilePath.substring(0, index);
+ } else {
+ entryDirPath = "";
+ }
+ entryDir = new File(entryDirPath);
+ // 如果文件夹路径不存在,则创建文件夹
+ if (!entryDir.exists() || !entryDir.isDirectory()) {
+ if (!entryDir.mkdirs())
+ throw new IOException(String.format("Failed to make directory tree %s", entryDir.toString()));
+ }
- // 创建解压文件
- entryFile = new File(entryFilePath);
- if (entryFile.exists()) {
- // 检测文件是否允许删除,如果不允许删除,将会抛出SecurityException
- SecurityManager securityManager = new SecurityManager();
- securityManager.checkDelete(entryFilePath);
- // 删除已存在的目标文件
- if (!entryFile.delete())
- throw new IOException(String.format("Failed to delete existing file %s", entryFile.toString()));
- }
- if (entry.isDirectory()) {
- // If the entry is a directory, we make its corresponding directory.
- if (!entryFile.mkdir())
- throw new IOException(String.format("Failed to create directory %s", entryFile.toString()));
- } else {
- // Is a file, we write the data
- // 写入文件
- OutputStream outputStream = new FileOutputStream(entryFile);
- InputStream inputStream = zip.getInputStream(entry);
- while ((count = inputStream.read(buffer, 0, unzipBufferSize)) != -1) {
- outputStream.write(buffer, 0, count);
+ // 创建解压文件
+ entryFile = new File(entryFilePath);
+ if (entryFile.exists()) {
+ // 检测文件是否允许删除,如果不允许删除,将会抛出SecurityException
+ SecurityManager securityManager = new SecurityManager();
+ securityManager.checkDelete(entryFilePath);
+ // 删除已存在的目标文件
+ if (!entryFile.delete())
+ throw new IOException(String.format("Failed to delete existing file %s", entryFile.toString()));
+ }
+ if (entry.isDirectory()) {
+ // If the entry is a directory, we make its corresponding directory.
+ if (!entryFile.mkdir())
+ throw new IOException(String.format("Failed to create directory %s", entryFile.toString()));
+ } else {
+ // Is a file, we write the data
+ // 写入文件
+ try (OutputStream outputStream = new FileOutputStream(entryFile);
+ InputStream inputStream = zip.getInputStream(entry)) {
+ while ((count = inputStream.read(buffer, 0, unzipBufferSize)) != -1) {
+ outputStream.write(buffer, 0, count);
+ }
+ outputStream.flush();
+ }
}
- outputStream.flush();
- outputStream.close();
}
-
-
}
- zip.close();
}
} \ No newline at end of file