-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Defines initial versions of JSON model/configuration entities - Creates encryption utility for key generation and key encryption tasks - Implements local file metadat parser - Adds Lombok configuration - Adds tests - Adds basic Abort-Mission configuration - Fixes some Gradle plugin configuration issues {patch} Signed-off-by: Esta Nagy <[email protected]>
- Loading branch information
Showing
34 changed files
with
1,685 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# This file is generated by the 'io.freefair.lombok' Gradle plugin | ||
config.stopBubbling = true | ||
lombok.addLombokGeneratedAnnotation = true | ||
lombok.nonNull.exceptionType = IllegalArgumentException |
This file was deleted.
Oops, something went wrong.
20 changes: 20 additions & 0 deletions
20
...-barj-core/src/main/java/com/github/nagyesta/filebarj/core/backup/FileMetadataParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.github.nagyesta.filebarj.core.backup; | ||
|
||
import com.github.nagyesta.filebarj.core.config.BackupJobConfiguration; | ||
import com.github.nagyesta.filebarj.core.model.FileMetadata; | ||
|
||
import java.io.File; | ||
|
||
/** | ||
* Parses metadata of Files. | ||
*/ | ||
public interface FileMetadataParser { | ||
|
||
/** | ||
* Reads or calculates metadata of a file we need to include in the backup. | ||
* @param file The current {@link File} we need ot evaluate | ||
* @param configuration The backup configuration | ||
* @return the parsed {@link FileMetadata} | ||
*/ | ||
FileMetadata parse(File file, BackupJobConfiguration configuration); | ||
} |
85 changes: 85 additions & 0 deletions
85
...-core/src/main/java/com/github/nagyesta/filebarj/core/backup/FileMetadataParserLocal.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package com.github.nagyesta.filebarj.core.backup; | ||
|
||
import com.github.nagyesta.filebarj.core.config.BackupJobConfiguration; | ||
import com.github.nagyesta.filebarj.core.model.FileMetadata; | ||
import com.github.nagyesta.filebarj.core.model.enums.Change; | ||
import com.github.nagyesta.filebarj.core.model.enums.FileType; | ||
import org.apache.commons.codec.digest.DigestUtils; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.LinkOption; | ||
import java.nio.file.attribute.BasicFileAttributes; | ||
import java.nio.file.attribute.PosixFileAttributes; | ||
import java.nio.file.attribute.PosixFilePermissions; | ||
import java.util.Optional; | ||
|
||
/** | ||
* Local file specific implementation of the {@link FileMetadataParser}. | ||
*/ | ||
public class FileMetadataParserLocal implements FileMetadataParser { | ||
|
||
@Override | ||
public FileMetadata parse(final File file, final BackupJobConfiguration configuration) { | ||
final var posixFileAttributes = posixPermissionsQuietly(file); | ||
final var basicAttributes = basicAttributesQuietly(file); | ||
|
||
return FileMetadata.builder() | ||
.absolutePath(file.toPath().toAbsolutePath()) | ||
.owner(posixFileAttributes.owner().getName()) | ||
.group(posixFileAttributes.group().getName()) | ||
.posixPermissions(PosixFilePermissions.toString(posixFileAttributes.permissions())) | ||
.lastModifiedUtcEpochSeconds(basicAttributes.lastModifiedTime().toInstant().getEpochSecond()) | ||
.originalSizeBytes(basicAttributes.size()) | ||
.fileType(FileType.findForAttributes(basicAttributes)) | ||
.originalChecksum(calculateChecksum(file, configuration)) | ||
.hidden(checkIsHiddenQuietly(file)) | ||
.status(Change.NEW) | ||
.build(); | ||
} | ||
|
||
private PosixFileAttributes posixPermissionsQuietly(final File file) { | ||
try { | ||
return Files.readAttributes(file.toPath(), PosixFileAttributes.class, LinkOption.NOFOLLOW_LINKS); | ||
} catch (final IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private BasicFileAttributes basicAttributesQuietly(final File file) { | ||
try { | ||
return Files.readAttributes(file.toPath(), BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS); | ||
} catch (final IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private boolean checkIsHiddenQuietly(final File file) { | ||
try { | ||
return Files.isHidden(file.toPath()); | ||
} catch (final IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
|
||
private String calculateChecksum(final File file, final BackupJobConfiguration configuration) { | ||
try { | ||
final var messageDigest = Optional.ofNullable(configuration.getChecksumAlgorithm().getAlgorithmName()) | ||
.map(DigestUtils::new); | ||
final var attributes = basicAttributesQuietly(file); | ||
if (messageDigest.isEmpty() || attributes.isOther()) { | ||
return null; | ||
} else { | ||
if (attributes.isSymbolicLink()) { | ||
return messageDigest.get().digestAsHex(Files.readSymbolicLink(file.toPath()).toAbsolutePath()); | ||
} else { | ||
return messageDigest.get().digestAsHex(file); | ||
} | ||
} | ||
} catch (final IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
} |
107 changes: 107 additions & 0 deletions
107
...j-core/src/main/java/com/github/nagyesta/filebarj/core/config/BackupJobConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package com.github.nagyesta.filebarj.core.config; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; | ||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; | ||
import com.github.nagyesta.filebarj.core.config.enums.DuplicateHandlingStrategy; | ||
import com.github.nagyesta.filebarj.core.config.enums.HashAlgorithm; | ||
import com.github.nagyesta.filebarj.core.json.PublicKeyDeserializer; | ||
import com.github.nagyesta.filebarj.core.json.PublicKeySerializer; | ||
import com.github.nagyesta.filebarj.core.model.enums.BackupType; | ||
import lombok.Builder; | ||
import lombok.Data; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.NonNull; | ||
import lombok.extern.jackson.Jacksonized; | ||
|
||
import java.nio.file.Path; | ||
import java.security.PublicKey; | ||
import java.util.Set; | ||
|
||
/** | ||
* Configuration class defining the parameters of the backup/restore job. | ||
*/ | ||
@Data | ||
@EqualsAndHashCode | ||
@Builder | ||
@Jacksonized | ||
public class BackupJobConfiguration { | ||
/** | ||
* The desired backup type which should be used when the job is executed. | ||
* <br/><br/> | ||
* NOTE: The backup will be automatically a {@link BackupType#FULL} backup | ||
* every time when there is no previous increment or there is a change in | ||
* the backup configuration since the last increment was saved. As a side | ||
* effect, this property is ignored during the first execution after each | ||
* configuration change. | ||
*/ | ||
@NonNull | ||
@JsonProperty("backup_type") | ||
private final BackupType backupType; | ||
/** | ||
* The algorithm used for checksum calculations before and after archival. | ||
* Useful for data integrity verifications. | ||
* <br/><br/> | ||
* NOTE: A change of this value requires a {@link BackupType#FULL} backup | ||
* as the previous increments cannot use a different hash algorithm. | ||
*/ | ||
@NonNull | ||
@JsonProperty("checksum_algorithm") | ||
private final HashAlgorithm checksumAlgorithm; | ||
/** | ||
* The public key of an RSA key pair used for encryption. | ||
* The files will be encrypted using automatically generated AES keys (DEK) | ||
* which will be encrypted using the RSA public key (KEK). | ||
* <br/><br/> | ||
* NOTE: A change of this value requires a {@link BackupType#FULL} backup | ||
* as the previous increments cannot use a different encryption key. | ||
*/ | ||
@JsonSerialize(using = PublicKeySerializer.class) | ||
@JsonDeserialize(using = PublicKeyDeserializer.class) | ||
@JsonProperty("encryption_key") | ||
private final PublicKey encryptionKey; | ||
/** | ||
* The strategy used for handling duplicate files. | ||
* <br/><br/> | ||
* NOTE: A change of this value requires a {@link BackupType#FULL} backup | ||
* as the previous increments cannot use a different duplicate handling | ||
* strategy. | ||
*/ | ||
@NonNull | ||
@JsonProperty("duplicate_strategy") | ||
private final DuplicateHandlingStrategy duplicateStrategy; | ||
/** | ||
* The desired maximum chunk size for the backup archive part. | ||
* <br/><br/> | ||
* NOTE: Using 0 means that the archive won't be chunked. | ||
*/ | ||
@EqualsAndHashCode.Exclude | ||
@JsonProperty("chunk_size_mebibyte") | ||
private final int chunkSizeMebibyte; | ||
/** | ||
* The prefix of the backup file names. | ||
* <br/><br/> | ||
* NOTE: A change of this value requires a {@link BackupType#FULL} backup | ||
* as the previous increments cannot use a different file name prefix. | ||
*/ | ||
@NonNull | ||
@JsonProperty("file_name_prefix") | ||
private final String fileNamePrefix; | ||
/** | ||
* The destination where the backup files will be saved. | ||
* <br/><br/> | ||
* NOTE: A change of this value requires a {@link BackupType#FULL} backup | ||
* as the metadata of the previous increments must be found in the destination | ||
* in order to calculate changes. | ||
*/ | ||
@NonNull | ||
@JsonProperty("destination_directory") | ||
private final Path destinationDirectory; | ||
/** | ||
* The source files we want to archive. | ||
*/ | ||
@NonNull | ||
@EqualsAndHashCode.Exclude | ||
@JsonProperty("sources") | ||
private final Set<BackupSource> sources; | ||
} |
Oops, something went wrong.