Skip to content

Commit

Permalink
Merge pull request #14 from KastenKlicker/include-exclude
Browse files Browse the repository at this point in the history
Implement better include-exclude functionality.
  • Loading branch information
KastenKlicker authored Oct 12, 2024
2 parents 694a2a4 + 06516ce commit 12dde3b
Show file tree
Hide file tree
Showing 14 changed files with 243 additions and 51 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>de.kastenklicker</groupId>
<artifactId>secure-server-backup-library</artifactId>
<version>1.1.0</version>
<version>2.0.0</version>
<packaging>jar</packaging>

<name>${project.groupId}:${project.artifactId}</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class Backup {

private static final Logger LOGGER = LoggerFactory.getLogger("de.kastenklicker.secureserverlibrary");

private final List<String> includedFiles;
private final List<String> excludeFiles;
private final File backupDirectory;
private final File serverDirectory;
Expand All @@ -28,13 +29,15 @@ public class Backup {

/**
* Constructor for Backup class.
* @param includedFiles files which should be included in backup
* @param excludeFiles files which should be excluded from the backup
* @param backupDirectory the directory of the backups
* @param serverDirectory the directory which contains all server files
* @param uploadClient the specific class of the Upload protocol
* @param maxBackupDirectorySize the maximum size of the backup directory
*/
public Backup(List<String> excludeFiles, File backupDirectory, File serverDirectory, UploadClient uploadClient, long maxBackupDirectorySize) {
public Backup(List<String> includedFiles, List<String> excludeFiles, File backupDirectory, File serverDirectory, UploadClient uploadClient, long maxBackupDirectorySize) {
this.includedFiles = includedFiles;
this.excludeFiles = excludeFiles;
this.backupDirectory = backupDirectory;
this.serverDirectory = serverDirectory;
Expand All @@ -51,11 +54,6 @@ public File backup() {
// Append backup directory to excluded files list
excludeFiles.add(backupDirectory.getName());

// Exclude session locks, because those are locked by paper
excludeFiles.add("world/session.lock");
excludeFiles.add("world_nether/session.lock");
excludeFiles.add("world_the_end/session.lock");

// Get current time for backup file name
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm");
LocalDateTime localDateTime = LocalDateTime.now();
Expand All @@ -66,8 +64,9 @@ public File backup() {
LOGGER.debug("Zipping files into {}.", backupFile.getName());

// Compress the server files
Zip zip = new Zip(backupFile, serverDirectory, excludeFiles);
zip.zip(serverDirectory);
Zip zip = new Zip(backupFile, serverDirectory, includedFiles, excludeFiles);
for (File file : zip.getIncludedFiles())
zip.zip(file);
zip.finish();

LOGGER.debug("Finished zipping file.");
Expand Down
89 changes: 65 additions & 24 deletions src/main/java/de/kastenklicker/secureserverbackuplibrary/Zip.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.nio.file.FileSystems;
import java.nio.file.PathMatcher;
import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
Expand All @@ -18,12 +16,11 @@
* Class for zipping the server files.
*/
public class Zip {

private static final Logger LOGGER = LoggerFactory.getLogger("de.kastenklicker.secureserverlibrary");

private final ZipOutputStream zipOutputStream;
private final FileOutputStream fileOutputStream;
private final List<String> excludeFiles;
private final Set<File> includedFiles;
private final Set<File> excludeFiles;
private final File serverDirectory;

/**
Expand All @@ -33,19 +30,14 @@ public class Zip {
* @param excludeFiles List of files which should be excluded.
* @throws ZipException Thrown if file is a directory or can't be accessed/created.
*/
public Zip(File backupFile, File serverDirectory , List<String> excludeFiles) {
public Zip(File backupFile, File serverDirectory, List<String> includeFiles, List<String> excludeFiles) {
this.serverDirectory = serverDirectory;

// Get unique path for every excluded file
this.excludeFiles = excludeFiles.stream().map(path -> {
try {
return new File(serverDirectory, path).getCanonicalPath();
} catch (IOException e) {
LOGGER.debug("IOException occurred for excluded: {}", path);
return null;
}
}
).filter(Objects::nonNull).toList();

// Get all files which should be included
this.includedFiles = getFilesByRegex(includeFiles);

// Get all files which shouldn't be included
this.excludeFiles = getFilesByRegex(excludeFiles);

// Create Zip OutputStream
try {
Expand All @@ -58,6 +50,10 @@ public Zip(File backupFile, File serverDirectory , List<String> excludeFiles) {
}
}

public Set<File> getIncludedFiles() {
return includedFiles;
}

/**
* Zip files and directories recursive.
* @param file file to add
Expand All @@ -67,10 +63,8 @@ public void zip(File file) throws ZipException {

try {
// Check if file should be excluded from the backup
for (String path : excludeFiles) {
if (file.getCanonicalPath().contains(path))
return;
}
if (excludeFiles.contains(file))
return;

// If file is a directory, add all of its child files, if there are any
if (file.isDirectory()) {
Expand Down Expand Up @@ -119,4 +113,51 @@ public void finish() {
throw new ZipException(e);
}
}

/**
* Get Files by its regex path.
* @param filePaths regex paths
* @return Set of files found matching at least one regex
*/
private Set<File> getFilesByRegex(List<String> filePaths) {

Set<PathMatcher> regexMatchers = new HashSet<>();

// Create Path Matchers from regex
for (String filePath : filePaths) {
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + filePath);
regexMatchers.add(matcher);
}

return searchFile(this.serverDirectory, new HashSet<>(), regexMatchers);
}

/**
* Find file by matching regex.
* @param file the file
* @param foundFiles already found files
* @param matchers the path matchers
* @return Found files, including already found files
*/
private Set<File> searchFile(File file, Set<File> foundFiles, final Set<PathMatcher> matchers) {

for (File childFile : file.listFiles()) {

// Check if file matches one Path Matcher
for (PathMatcher matcher : matchers) {
if (matcher.matches(serverDirectory.toPath().relativize(childFile.toPath()))) {
// A Matching was found, add to foundFiles Set
foundFiles.add(childFile);
break;
}
}

// If file is directory, check if one of its children matches a Path
if (childFile.isDirectory()) {
searchFile(childFile, foundFiles, matchers);
}
}

return foundFiles;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.io.RandomAccessFile;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

Expand All @@ -31,9 +32,10 @@ public void setup() {
}

@Test
public void testBackup() throws Exception {
public void testBackup() {

assertTrue(new Backup(
List.of("."),
new ArrayList<>(),
backupsDirectory,
new File("./src/test/resources/zipTest"),
Expand Down Expand Up @@ -73,6 +75,7 @@ public void testBackupSFTP() throws Exception {
"/upload");

File backup = new Backup(
List.of("."),
new ArrayList<>(),
backupsDirectory,
new File("./src/test/resources/zipTest"),
Expand Down Expand Up @@ -110,6 +113,7 @@ public void testBackupMaxDirSizeReached() throws Exception {
assertTrue(new File("./src/test/resources/zipTest/backups/temporaryTestFile").exists());

assertTrue(new Backup(
List.of("."),
new ArrayList<>(),
backupsDirectory,
new File("./src/test/resources/zipTest"),
Expand Down
Loading

0 comments on commit 12dde3b

Please sign in to comment.