mirror of
https://github.com/openeggbert/bit-backup.git
synced 2025-03-25 15:37:53 +01:00
Big refactoring
This commit is contained in:
parent
edba08f896
commit
46eaeb824e
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@
|
|||||||
#*.class
|
#*.class
|
||||||
/target/
|
/target/
|
||||||
|
|
||||||
|
/nbproject/
|
||||||
|
28
pom.xml
28
pom.xml
@ -25,7 +25,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.nanoboot.essential</groupId>
|
<groupId>org.nanoboot.essential</groupId>
|
||||||
<artifactId>nanoboot-parent</artifactId>
|
<artifactId>nanoboot-parent</artifactId>
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
<version>0.1.1-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>org.nanoboot.tools</groupId>
|
<groupId>org.nanoboot.tools</groupId>
|
||||||
@ -42,7 +42,7 @@
|
|||||||
<power.version>2.0.1-SNAPSHOT</power.version>
|
<power.version>2.0.1-SNAPSHOT</power.version>
|
||||||
<maven.compiler.source>19</maven.compiler.source>
|
<maven.compiler.source>19</maven.compiler.source>
|
||||||
<maven.compiler.target>19</maven.compiler.target>
|
<maven.compiler.target>19</maven.compiler.target>
|
||||||
<db-migration-core.version>0.1.0</db-migration-core.version>
|
<db-migration-core.version>0.1.1-SNAPSHOT</db-migration-core.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@ -158,11 +158,24 @@
|
|||||||
|
|
||||||
<!-- Other dependencies -->
|
<!-- Other dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
<version>${junit4.version}</version>
|
<version>${junit-jupiter.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>${junit-jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
|
<version>${junit-jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.nanoboot.tools.dbmigration</groupId>
|
<groupId>org.nanoboot.tools.dbmigration</groupId>
|
||||||
<artifactId>db-migration-core</artifactId>
|
<artifactId>db-migration-core</artifactId>
|
||||||
@ -202,6 +215,11 @@
|
|||||||
<artifactId>log4j-slf4j-impl</artifactId>
|
<artifactId>log4j-slf4j-impl</artifactId>
|
||||||
<version>${log4j.version}</version>
|
<version>${log4j.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>dev.mccue</groupId>
|
||||||
|
<artifactId>guava-io</artifactId>
|
||||||
|
<version>0.0.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -25,4 +25,5 @@ module bitinspector {
|
|||||||
requires java.sql;
|
requires java.sql;
|
||||||
requires powerframework.time;
|
requires powerframework.time;
|
||||||
requires powerframework.collections;
|
requires powerframework.collections;
|
||||||
|
requires dev.mccue.guava.io;
|
||||||
}
|
}
|
||||||
|
@ -27,30 +27,41 @@ import org.nanoboot.bitinspector.core.Utils;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class BirIgnoreRegex implements Predicate<String> {
|
public class BirIgnoreRegex implements Predicate<String> {
|
||||||
|
|
||||||
private final List<String> patterns = new ArrayList<>();
|
private final List<String> patterns = new ArrayList<>();
|
||||||
|
|
||||||
public BirIgnoreRegex(File birIgnoreFile) {
|
public BirIgnoreRegex(File birIgnoreFile) {
|
||||||
|
|
||||||
|
patterns.add(convertUnixRegexToJavaRegex("*.birreport.csv"));
|
||||||
|
addBirIgnoreFile(birIgnoreFile);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void addBirIgnoreFile(File birIgnoreFile) {
|
||||||
|
addBirIgnoreFile(birIgnoreFile, null);
|
||||||
|
}
|
||||||
|
public final void addBirIgnoreFile(File birIgnoreFile, File workingDir) {
|
||||||
String[] lines = birIgnoreFile.exists() ? Utils.readTextFromFile(birIgnoreFile).split("\\R") : new String[]{};
|
String[] lines = birIgnoreFile.exists() ? Utils.readTextFromFile(birIgnoreFile).split("\\R") : new String[]{};
|
||||||
if (lines.length == 0) {
|
String addPrefix = workingDir == null ? "" : birIgnoreFile.getParentFile().getAbsolutePath().replace(workingDir.getAbsolutePath() + "/", "");
|
||||||
//nothing to do
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (String l : lines) {
|
for (String l : lines) {
|
||||||
if (l.isBlank() || l.trim().startsWith("#")) {
|
if (l.isBlank() || l.trim().startsWith("#")) {
|
||||||
//nothing to do
|
//nothing to do
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
patterns.add(convertUnixRegexToJavaRegex(l));
|
if(addPrefix == null) {
|
||||||
|
patterns.add(convertUnixRegexToJavaRegex(l));
|
||||||
|
} else {
|
||||||
|
patterns.add(convertUnixRegexToJavaRegex(addPrefix + l));
|
||||||
|
patterns.forEach(e->System.out.println("$$$" + e));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
patterns.add(convertUnixRegexToJavaRegex("*.birreport.csv"));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(String text) {
|
public boolean test(String text) {
|
||||||
if (patterns.isEmpty()) {
|
if (patterns.isEmpty()) {
|
||||||
@ -63,7 +74,7 @@ public class BirIgnoreRegex implements Predicate<String> {
|
|||||||
if (b) {
|
if (b) {
|
||||||
ignore = true;
|
ignore = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (ignore) {
|
// if (ignore) {
|
||||||
@ -73,7 +84,7 @@ public class BirIgnoreRegex implements Predicate<String> {
|
|||||||
// }
|
// }
|
||||||
return ignore;
|
return ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String convertUnixRegexToJavaRegex(String wildcard) {
|
public static String convertUnixRegexToJavaRegex(String wildcard) {
|
||||||
StringBuffer s = new StringBuffer(wildcard.length());
|
StringBuffer s = new StringBuffer(wildcard.length());
|
||||||
s.append('^');
|
s.append('^');
|
||||||
@ -109,5 +120,5 @@ public class BirIgnoreRegex implements Predicate<String> {
|
|||||||
s.append('$');
|
s.append('$');
|
||||||
return (s.toString());
|
return (s.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,225 +22,195 @@ import java.io.File;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.nanoboot.bitinspector.core.BirContext;
|
||||||
import org.nanoboot.bitinspector.core.Command;
|
import org.nanoboot.bitinspector.core.Command;
|
||||||
import org.nanoboot.bitinspector.core.BitInspectorArgs;
|
import org.nanoboot.bitinspector.core.BirArgs;
|
||||||
import org.nanoboot.bitinspector.core.BitInspectorException;
|
import org.nanoboot.bitinspector.core.BitInspectorException;
|
||||||
|
import org.nanoboot.bitinspector.core.BirFiles;
|
||||||
|
import org.nanoboot.bitinspector.core.ListSet;
|
||||||
import org.nanoboot.bitinspector.core.Utils;
|
import org.nanoboot.bitinspector.core.Utils;
|
||||||
import org.nanoboot.bitinspector.entity.FsFile;
|
import org.nanoboot.bitinspector.entity.FsFile;
|
||||||
import org.nanoboot.bitinspector.entity.SystemItem;
|
import org.nanoboot.bitinspector.entity.SystemItem;
|
||||||
import org.nanoboot.bitinspector.persistence.api.FileRepository;
|
import org.nanoboot.bitinspector.persistence.api.FileRepository;
|
||||||
import org.nanoboot.bitinspector.persistence.api.SystemItemRepository;
|
|
||||||
import org.nanoboot.bitinspector.persistence.impl.sqlite.FileRepositoryImplSqlite;
|
|
||||||
import org.nanoboot.bitinspector.persistence.impl.sqlite.SqliteDatabaseMigration;
|
import org.nanoboot.bitinspector.persistence.impl.sqlite.SqliteDatabaseMigration;
|
||||||
import org.nanoboot.bitinspector.persistence.impl.sqlite.SystemItemRepositoryImplSqlite;
|
import org.nanoboot.dbmigration.core.main.MigrationResult;
|
||||||
|
import org.nanoboot.powerframework.time.duration.Duration;
|
||||||
|
import org.nanoboot.powerframework.time.moment.LocalDateTime;
|
||||||
|
import org.nanoboot.powerframework.time.utils.RemainingTimeCalculator;
|
||||||
|
import org.nanoboot.powerframework.time.utils.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author pc00289
|
* @author r
|
||||||
*/
|
*/
|
||||||
public class CheckCommand implements Command {
|
public class CheckCommand implements Command {
|
||||||
|
|
||||||
private final File currentDirRoot = new File(".");
|
private static final Logger LOG = LogManager.getLogger(CheckCommand.class);
|
||||||
private final File birSQLite3File = new File("./.bir.sqlite3");
|
public static final String NAME = "check";
|
||||||
private final File birSQLite3FileSha512 = new File("./.bir.sqlite3.sha512");
|
|
||||||
private final File birIgnore = new File("./.birignore");
|
|
||||||
BirIgnoreRegex birIgnoreRegex = new BirIgnoreRegex(birIgnore);
|
|
||||||
|
|
||||||
public CheckCommand() {
|
public CheckCommand() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "check";
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i = 0;
|
enum CheckCommandPart {
|
||||||
|
|
||||||
|
CHECK_OLD_DB_CHECKSUM(1),
|
||||||
|
MIGRATE_DB_SCHEMA_IF_NEEDED(2),
|
||||||
|
UPDATE_VERSION(3),
|
||||||
|
FOUND_FILES_IN_FILESYSTEM(4),
|
||||||
|
FOUND_FILES_IN_DB(5),
|
||||||
|
ADD_NEW_FILES_TO_DB(6),
|
||||||
|
REMOVE_DELETED_FILES_FROM_DB(7),
|
||||||
|
COMPARE_CONTENT_AND_LAST_MODTIME(8),
|
||||||
|
CREATE_REPORT_CSV_IF_NEEDED(9),
|
||||||
|
CHECK_NEW_DB_CHECKSUM(10);
|
||||||
|
|
||||||
|
private int number;
|
||||||
|
|
||||||
|
CheckCommandPart(int number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toText() {
|
||||||
|
return "Part " + number + ": ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iStatic = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(BitInspectorArgs bitInspectorArgs) {
|
public String run(BirArgs birArgs) {
|
||||||
SqliteDatabaseMigration sqliteDatabaseMigration = new SqliteDatabaseMigration();
|
BirFiles birFiles = new BirFiles(birArgs);
|
||||||
sqliteDatabaseMigration.migrate();
|
BirContext birContext = new BirContext(birFiles.getWorkingDirAbsolutePath());
|
||||||
|
//
|
||||||
SystemItemRepository systemItemRepository = new SystemItemRepositoryImplSqlite();
|
//part 1:
|
||||||
FileRepository fileRepository = new FileRepositoryImplSqlite();
|
part1CheckDbHasExpectedHashSum(birFiles);
|
||||||
////
|
//part 2:
|
||||||
String version = systemItemRepository.read("bir.version").getValue();
|
boolean part2Result = part2MigrateDbSchemaIfNeeded(birFiles);
|
||||||
System.out.println("bir.version=" + version);
|
if(!part2Result) {
|
||||||
if (version == null) {
|
return "part 2 failed";
|
||||||
systemItemRepository.create(new SystemItem("bir.version", "0.0.0-SNAPSHOT"));
|
|
||||||
}
|
}
|
||||||
System.out.println("Updating version in DB.");
|
//part 3:
|
||||||
version = systemItemRepository.read("bir.version").getValue();
|
part3UpdateVersionInDbIfNeeded(birContext);
|
||||||
System.out.println("bir.version=" + version);
|
|
||||||
////
|
|
||||||
|
|
||||||
//// Check ,SQLite DB file has the expected SHA-512 hash sum
|
ListSet<File> filesInFileSystem = part4FoundFilesInFileSystem(birFiles, birArgs);
|
||||||
if (birSQLite3File.exists() && birSQLite3FileSha512.exists()) {
|
ListSet<FsFile> filesInDb = part5FoundFilesInDb(birContext.getFileRepository(), birArgs);
|
||||||
String expectedHash = Utils.readTextFromFile(birSQLite3FileSha512);
|
|
||||||
String returnedHash = Utils.calculateSHA512Hash(birSQLite3File);
|
|
||||||
if (!returnedHash.equals(expectedHash)) {
|
|
||||||
throw new BitInspectorException("Unexpected hash " + returnedHash + ". Expected SHA-512 hash sum was: " + expectedHash + " for file " + birSQLite3File.getAbsolutePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//// Found files in directory
|
|
||||||
|
|
||||||
List<File> filesInDir = foundFilesInCurrentDir(currentDirRoot, new ArrayList<>());
|
LocalDateTime now = part6AddNewFilesToDb(filesInFileSystem, birFiles, filesInDb, birContext);
|
||||||
Set<String> filesInDirSet = filesInDir.stream().map(f -> loadPathButOnlyTheNeededPart(currentDirRoot, f)).collect(Collectors.toSet());
|
|
||||||
System.out.println("Found files:");
|
|
||||||
filesInDir.stream().forEach((f -> System.out.println("#" + (++i) + " " + f.getAbsolutePath().substring(currentDirRoot.getAbsolutePath().length() + 1))));
|
|
||||||
|
|
||||||
//// Found files in DB
|
List<FsFile> filesToBeRemovedFromDb = part7RemoveDeletedFilesFromDb(filesInDb, filesInFileSystem, birContext);
|
||||||
List<FsFile> filesInDb = fileRepository.list();
|
|
||||||
Set<String> filesInDbSet = filesInDb.stream().map(f -> f.getAbsolutePath()).collect(Collectors.toSet());
|
|
||||||
System.out.println("Files in DB:");
|
|
||||||
i = 0;
|
|
||||||
filesInDb.stream().forEach((f -> System.out.println("#" + (++i) + " " + f.toString())));
|
|
||||||
|
|
||||||
//// Add new files
|
List<FsFile> filesWithBitRot = part8CompareContentAndLastModificationDate(filesInDb, filesToBeRemovedFromDb, birContext, now);
|
||||||
Date lastChecked = new Date();
|
|
||||||
org.nanoboot.powerframework.time.moment.LocalDateTime now = org.nanoboot.powerframework.time.moment.LocalDateTime.convertJavaUtilDateToPowerLocalDateTime(lastChecked);
|
|
||||||
|
|
||||||
int processedCount0 = 0;
|
part9CreateReportCsvIfNeeded(birArgs, birFiles, filesWithBitRot);
|
||||||
|
part10CalculateCurrentHashSumOfDbFile(birFiles);
|
||||||
|
|
||||||
List<FsFile> filesMissingInDb = new ArrayList<>();
|
LOG.info("==========");
|
||||||
for (File fileInDir : filesInDir) {
|
LOG.info("Summary");
|
||||||
processedCount0 = processedCount0 + 1;
|
|
||||||
if (processedCount0 % 100 == 0) {
|
|
||||||
double progress = ((double) processedCount0) / filesInDir.size() * 100;
|
|
||||||
System.out.println("Add - Progress: " + processedCount0 + "/" + filesInDir.size() + " " + String.format("%,.2f", progress) + "%");
|
|
||||||
}
|
|
||||||
|
|
||||||
String absolutePathOfFileInDir = loadPathButOnlyTheNeededPart(currentDirRoot, fileInDir);
|
|
||||||
if (!filesInDbSet.contains(absolutePathOfFileInDir)) {
|
|
||||||
Date lastModified = new Date(fileInDir.lastModified());
|
|
||||||
org.nanoboot.powerframework.time.moment.LocalDateTime ldt = org.nanoboot.powerframework.time.moment.LocalDateTime.convertJavaUtilDateToPowerLocalDateTime(lastModified);
|
|
||||||
|
|
||||||
FsFile fsFile = new FsFile(
|
|
||||||
UUID.randomUUID().toString(),
|
|
||||||
fileInDir.getName(),
|
|
||||||
absolutePathOfFileInDir,
|
|
||||||
ldt.toString(),
|
|
||||||
now.toString(),
|
|
||||||
Utils.calculateSHA512Hash(fileInDir),
|
|
||||||
"SHA-512"
|
|
||||||
);
|
|
||||||
filesMissingInDb.add(fsFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
fileRepository.create(filesMissingInDb);
|
|
||||||
|
|
||||||
//// Remove deleted files
|
|
||||||
List<FsFile> filesToBeRemovedFromDb = new ArrayList<>();
|
|
||||||
int processedCount1 = 0;
|
|
||||||
|
|
||||||
for (FsFile fileInDb : filesInDb) {
|
|
||||||
processedCount1 = processedCount1 + 1;
|
|
||||||
if (processedCount1 % 100 == 0) {
|
|
||||||
double progress = ((double) processedCount1) / filesInDb.size() * 100;
|
|
||||||
System.out.println("Remove - Progress: " + processedCount1 + "/" + filesInDb.size() + " " + String.format("%,.2f", progress) + "%");
|
|
||||||
}
|
|
||||||
|
|
||||||
String absolutePathOfFileInDb = fileInDb.getAbsolutePath();
|
|
||||||
if (!filesInDirSet.contains(absolutePathOfFileInDb)) {
|
|
||||||
|
|
||||||
filesToBeRemovedFromDb.add(fileInDb);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
for (FsFile f : filesToBeRemovedFromDb) {
|
|
||||||
fileRepository.remove(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
double countOfFilesToCalculateHashSum = filesInDb.size() - filesToBeRemovedFromDb.size();
|
|
||||||
int processedCount = 0;
|
|
||||||
//// Update modified files with same last modification date
|
|
||||||
List<FsFile> filesWithBitRot = new ArrayList<>();
|
|
||||||
List<FsFile> filesToUpdateLastCheckDate = new ArrayList<>();
|
|
||||||
for (FsFile fileInDb : filesInDb) {
|
|
||||||
String absolutePathOfFileInDb = fileInDb.getAbsolutePath();
|
|
||||||
if (filesToBeRemovedFromDb.contains(fileInDb)) {
|
|
||||||
//nothing to do
|
|
||||||
continue;
|
|
||||||
|
|
||||||
}
|
|
||||||
processedCount = processedCount + 1;
|
|
||||||
if (processedCount % 100 == 0) {
|
|
||||||
double progress = ((double) processedCount) / countOfFilesToCalculateHashSum * 100;
|
|
||||||
System.out.println("Update - Progress: " + processedCount + "/" + countOfFilesToCalculateHashSum + " " + String.format("%,.2f", progress) + "%");
|
|
||||||
}
|
|
||||||
File file = new File("./" + absolutePathOfFileInDb);
|
|
||||||
|
|
||||||
Date lastModified = new Date(file.lastModified());
|
|
||||||
org.nanoboot.powerframework.time.moment.LocalDateTime ldt = org.nanoboot.powerframework.time.moment.LocalDateTime.convertJavaUtilDateToPowerLocalDateTime(lastModified);
|
|
||||||
|
|
||||||
String calculatedHash = Utils.calculateSHA512Hash(file);
|
|
||||||
if (ldt.toString().equals(fileInDb.getLastModificationDate()) && !calculatedHash.equals(fileInDb.getHashSumValue())) {
|
|
||||||
filesWithBitRot.add(fileInDb);
|
|
||||||
fileInDb.setLastCheckDate(now.toString());
|
|
||||||
fileRepository.updateFile(fileInDb);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!ldt.toString().equals(fileInDb.getLastModificationDate())) {
|
|
||||||
fileInDb.setLastCheckDate(now.toString());
|
|
||||||
fileInDb.setLastModificationDate(ldt.toString());
|
|
||||||
fileInDb.setHashSumValue(calculatedHash);
|
|
||||||
fileInDb.setHashSumAlgorithm("SHA-512");
|
|
||||||
fileRepository.updateFile(fileInDb);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (ldt.toString().equals(fileInDb.getLastModificationDate())) {
|
|
||||||
filesToUpdateLastCheckDate.add(fileInDb);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
fileRepository.updateLastCheckDate(now.toString(), filesToUpdateLastCheckDate);
|
|
||||||
|
|
||||||
//// Report files, which may have a bitrot and will have to be restored from a backup
|
|
||||||
System.out.println("\n\n");
|
|
||||||
|
|
||||||
if (filesWithBitRot.isEmpty()) {
|
if (filesWithBitRot.isEmpty()) {
|
||||||
System.out.println("No files with bit rot were found.");
|
LOG.info("Summary: OK : No files with bit rot were found.");
|
||||||
}
|
} else {
|
||||||
filesWithBitRot.stream().forEach(f
|
LOG.error("Summary: KO : Some files {} with bit rot were found.", filesWithBitRot.size());
|
||||||
-> System.out.println("Bit rot detected: \"" + f.getAbsolutePath() + "\"" + " expected_sha512=" + f.getHashSumValue() + " returned_sha512=" + Utils.calculateSHA512Hash(new File("./" + f.getAbsolutePath())))
|
|
||||||
);
|
|
||||||
if (bitInspectorArgs.hasArgument("reportid")) {
|
|
||||||
String reportId = bitInspectorArgs.getArgument("reportid");
|
|
||||||
File reportIdFile = new File("./" + reportId + ".birreport.csv");
|
|
||||||
if (reportIdFile.exists()) {
|
|
||||||
Long nowLong = org.nanoboot.powerframework.time.moment.UniversalDateTime.now().toLong();
|
|
||||||
|
|
||||||
File backup = new File(reportIdFile.getParentFile().getAbsolutePath() + "/" + nowLong + "." + reportIdFile.getName());
|
|
||||||
System.out.println("backup=" + backup);
|
|
||||||
reportIdFile.renameTo(backup);
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
if (!filesWithBitRot.isEmpty()) {
|
|
||||||
sb.append("file;expected;calculated\n");
|
|
||||||
}
|
|
||||||
filesWithBitRot.stream().forEach(f
|
filesWithBitRot.stream().forEach(f
|
||||||
-> sb.append(f.getAbsolutePath())
|
-> LOG.error("Bit rot detected: \"" + f.getAbsolutePath() + "\"" + " expected_sha512=" + f.getHashSumValue() + " returned_sha512=" + Utils.calculateSHA512Hash(new File("./" + f.getAbsolutePath())))
|
||||||
.append(";")
|
|
||||||
.append(f.getHashSumValue())
|
|
||||||
.append(";")
|
|
||||||
.append(Utils.calculateSHA512Hash(new File("./" + f.getAbsolutePath())))
|
|
||||||
.append("\n")
|
|
||||||
);
|
);
|
||||||
Utils.writeTextToFile(sb.toString(), reportIdFile);
|
|
||||||
}
|
}
|
||||||
//// Calculate current checksum of DB file.
|
|
||||||
Utils.writeTextToFile(Utils.calculateSHA512Hash(birSQLite3File), birSQLite3FileSha512);
|
|
||||||
|
|
||||||
System.out.println("foundFiles=" + foundFiles);
|
System.out.println("foundFiles=" + foundFiles);
|
||||||
System.out.println("foundDirs=" + foundDirs);
|
System.out.println("foundDirs=" + foundDirs);
|
||||||
|
return filesWithBitRot.isEmpty() ? "" : filesWithBitRot.stream().map(FsFile::getAbsolutePath).collect(Collectors.joining("\n"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, if SQLite DB file has the expected SHA-512 hash sum
|
||||||
|
*
|
||||||
|
* @param birSQLite3File
|
||||||
|
* @param birSQLite3FileSha512
|
||||||
|
* @throws BitInspectorException - if this check fails.
|
||||||
|
*/
|
||||||
|
private void part1CheckDbHasExpectedHashSum(BirFiles birInspectorFiles) throws BitInspectorException {
|
||||||
|
LOG.info("** Part {}: Checking DB, if has expected check sum.", CheckCommandPart.CHECK_OLD_DB_CHECKSUM.number);
|
||||||
|
final boolean dbExists = birInspectorFiles.getBirSQLite3File().exists();
|
||||||
|
final boolean checkSumExists = birInspectorFiles.getBirSQLite3FileSha512().exists();
|
||||||
|
if (dbExists && checkSumExists) {
|
||||||
|
String expectedHash = Utils.readTextFromFile(birInspectorFiles.getBirSQLite3FileSha512());
|
||||||
|
String returnedHash = Utils.calculateSHA512Hash(birInspectorFiles.getBirSQLite3File());
|
||||||
|
if (!returnedHash.equals(expectedHash)) {
|
||||||
|
String msg
|
||||||
|
= "Part {}: KO. "
|
||||||
|
+ "Unexpected hash "
|
||||||
|
+ returnedHash
|
||||||
|
+ ". Expected SHA-512 hash sum was: "
|
||||||
|
+ expectedHash
|
||||||
|
+ " for file "
|
||||||
|
+ birInspectorFiles.getBirSQLite3File().getAbsolutePath();
|
||||||
|
LOG.error(msg, CheckCommandPart.CHECK_OLD_DB_CHECKSUM.number);
|
||||||
|
LOG.info("Exiting because of the previous error.");
|
||||||
|
throw new BitInspectorException(msg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG.info("Part {}: OK. Nothing to do: {}",
|
||||||
|
CheckCommandPart.CHECK_OLD_DB_CHECKSUM.number,
|
||||||
|
!dbExists ? "DB does not yet exist." : "Check sum file does not exist.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean part2MigrateDbSchemaIfNeeded(BirFiles birFiles) {
|
||||||
|
LOG.info("** Part {}: Migrating schema, if needed.", CheckCommandPart.MIGRATE_DB_SCHEMA_IF_NEEDED.number);
|
||||||
|
try {
|
||||||
|
|
||||||
|
MigrationResult migrationResult = SqliteDatabaseMigration.getInstance().migrate(birFiles.getWorkingDirAbsolutePath());
|
||||||
|
if (migrationResult == MigrationResult.SUCCESS) {
|
||||||
|
LOG.info("Part {}: OK. Success.", CheckCommandPart.MIGRATE_DB_SCHEMA_IF_NEEDED.number);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
LOG.error("Part {}: KO. Failed.", CheckCommandPart.MIGRATE_DB_SCHEMA_IF_NEEDED.number);
|
||||||
|
throw new RuntimeException("Part " + CheckCommandPart.MIGRATE_DB_SCHEMA_IF_NEEDED.number + ": KO. Failed.");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Part {}: KO. {}", CheckCommandPart.MIGRATE_DB_SCHEMA_IF_NEEDED.number, e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void part3UpdateVersionInDbIfNeeded(BirContext birContext) {
|
||||||
|
LOG.info("** Part {}: Updating version, if needed.", CheckCommandPart.UPDATE_VERSION.number);
|
||||||
|
String version = birContext.getSystemItemRepository().read("bir.version").getValue();
|
||||||
|
System.out.println("Before: bir.version=" + version);
|
||||||
|
if (version == null) {
|
||||||
|
birContext.getSystemItemRepository().create(new SystemItem("bir.version", "0.0.0-SNAPSHOT"));
|
||||||
|
}
|
||||||
|
System.out.println("Updating version in DB.");
|
||||||
|
version = birContext.getSystemItemRepository().read("bir.version").getValue();
|
||||||
|
System.out.println("After: bir.version=" + version);
|
||||||
|
LOG.info("Part {}: OK.", CheckCommandPart.UPDATE_VERSION.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ListSet<File> part4FoundFilesInFileSystem(BirFiles birFiles, BirArgs birArgs) {
|
||||||
|
LOG.info("** Part {}: Loading files in filesystem", CheckCommandPart.FOUND_FILES_IN_FILESYSTEM.number);
|
||||||
|
String workingDir = birFiles.getWorkingDirAbsolutePath();
|
||||||
|
List<File> filesAlreadyFound = new ArrayList<>();
|
||||||
|
List<File> filesInDirList = foundFilesInCurrentDir(birFiles.getWorkingDir(), filesAlreadyFound, birFiles);
|
||||||
|
|
||||||
|
ListSet<File> listSet = new ListSet<>(filesInDirList, f -> loadPathButOnlyTheNeededPart(birFiles.getWorkingDir(), f));
|
||||||
|
|
||||||
|
LOG.info("Part {}: Found {} files.", CheckCommandPart.FOUND_FILES_IN_FILESYSTEM.number, listSet.size());
|
||||||
|
if (birArgs.isVerboseLoggingEnabled()) {
|
||||||
|
filesInDirList.stream().forEach((f -> LOG.info("#" + (++iStatic) + " " + f.getAbsolutePath().substring(workingDir.length() + 1))));
|
||||||
|
}
|
||||||
|
return listSet;
|
||||||
|
}
|
||||||
|
|
||||||
private String loadPathButOnlyTheNeededPart(File currentDir, File file) {
|
private String loadPathButOnlyTheNeededPart(File currentDir, File file) {
|
||||||
return file.getAbsolutePath().substring(currentDir.getAbsolutePath().length() + 1);
|
return file.getAbsolutePath().substring(currentDir.getAbsolutePath().length() + 1);
|
||||||
}
|
}
|
||||||
@ -249,32 +219,244 @@ public class CheckCommand implements Command {
|
|||||||
private int foundFiles;
|
private int foundFiles;
|
||||||
private int foundDirs;
|
private int foundDirs;
|
||||||
|
|
||||||
private List<File> foundFilesInCurrentDir(File currentDir, List<File> files) {
|
private List<File> foundFilesInCurrentDir(File currentDir, List<File> filesAlreadyFound, BirFiles birFiles) {
|
||||||
|
|
||||||
for (File f : currentDir.listFiles()) {
|
for (File f : currentDir.listFiles()) {
|
||||||
|
boolean isAlsoBirIgnore =f.getName().equals(birFiles.getBirIgnore().getName());
|
||||||
|
if(isAlsoBirIgnore && !f.getAbsolutePath().equals(birFiles.getBirIgnore().getAbsoluteFile())) {
|
||||||
|
birFiles.getBirIgnoreRegex().addBirIgnoreFile(f, birFiles.getWorkingDir());
|
||||||
|
}
|
||||||
if (f.isDirectory()) {
|
if (f.isDirectory()) {
|
||||||
++foundDirs;
|
++foundDirs;
|
||||||
foundFilesInCurrentDir(f, files);
|
foundFilesInCurrentDir(f, filesAlreadyFound, birFiles);
|
||||||
} else {
|
} else {
|
||||||
++foundFiles;
|
++foundFiles;
|
||||||
if (f.getAbsolutePath().equals(birSQLite3File.getAbsolutePath())) {
|
if (f.getAbsolutePath().equals(birFiles.getBirSQLite3File().getAbsolutePath())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (f.getAbsolutePath().equals(birSQLite3FileSha512.getAbsolutePath())) {
|
if (f.getAbsolutePath().equals(birFiles.getBirSQLite3FileSha512().getAbsolutePath())) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (f.getAbsolutePath().equals(birIgnore.getAbsolutePath())) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
++iii;
|
++iii;
|
||||||
//System.out.println("Testing file: " + iii + "#" + " " + loadPathButOnlyTheNeededPart(currentDirRoot, f));
|
//System.out.println("Testing file: " + iii + "#" + " " + loadPathButOnlyTheNeededPart(currentDirRoot, f));
|
||||||
if (birIgnoreRegex.test(loadPathButOnlyTheNeededPart(currentDirRoot, f))) {
|
if (birFiles.getBirIgnoreRegex().test(loadPathButOnlyTheNeededPart(birFiles.getWorkingDir(), f))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
files.add(f);
|
filesAlreadyFound.add(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return files;
|
return filesAlreadyFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ListSet<FsFile> part5FoundFilesInDb(FileRepository fileRepository, BirArgs birArgs) {
|
||||||
|
LOG.info("** Part {}: Loading files in DB", CheckCommandPart.FOUND_FILES_IN_DB.number);
|
||||||
|
List<FsFile> filesInDb = fileRepository.list();
|
||||||
|
|
||||||
|
ListSet<FsFile> listSet = new ListSet<>(filesInDb, f -> f.getAbsolutePath());
|
||||||
|
LOG.info("Part {}: Found {} files.", CheckCommandPart.FOUND_FILES_IN_DB.number, listSet.size());
|
||||||
|
iStatic = 0;
|
||||||
|
if (birArgs.isVerboseLoggingEnabled()) {
|
||||||
|
filesInDb.stream().forEach((f -> System.out.println("#" + (++iStatic) + " " + f.toString())));
|
||||||
|
}
|
||||||
|
return listSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalDateTime part6AddNewFilesToDb(ListSet<File> filesInFileSystem, BirFiles birFiles, ListSet<FsFile> filesInDb, BirContext birContext) {
|
||||||
|
LOG.info("** Part {}: Adding new files to DB", CheckCommandPart.ADD_NEW_FILES_TO_DB.number);
|
||||||
|
Date lastChecked = new Date();
|
||||||
|
org.nanoboot.powerframework.time.moment.LocalDateTime now = org.nanoboot.powerframework.time.moment.LocalDateTime.convertJavaUtilDateToPowerLocalDateTime(lastChecked);
|
||||||
|
int processedCount0 = 0;
|
||||||
|
List<FsFile> filesMissingInDb = new ArrayList<>();
|
||||||
|
for (File fileInDir : filesInFileSystem.getList()) {
|
||||||
|
processedCount0 = processedCount0 + 1;
|
||||||
|
if (processedCount0 % 100 == 0) {
|
||||||
|
double progress = ((double) processedCount0) / filesInFileSystem.getList().size() * 100;
|
||||||
|
LOG.info("Part {}: Add - Progress: {}/{} {} %",
|
||||||
|
CheckCommandPart.ADD_NEW_FILES_TO_DB.number,
|
||||||
|
processedCount0,
|
||||||
|
filesInFileSystem.getList().size(),
|
||||||
|
String.format("%,.2f", progress));
|
||||||
|
}
|
||||||
|
|
||||||
|
String absolutePathOfFileInDir = loadPathButOnlyTheNeededPart(birFiles.getWorkingDir(), fileInDir);
|
||||||
|
if (!filesInDb.doesSetContains(absolutePathOfFileInDir)) {
|
||||||
|
Date lastModified = new Date(fileInDir.lastModified());
|
||||||
|
org.nanoboot.powerframework.time.moment.LocalDateTime ldt = org.nanoboot.powerframework.time.moment.LocalDateTime.convertJavaUtilDateToPowerLocalDateTime(lastModified);
|
||||||
|
|
||||||
|
FsFile fsFile = new FsFile(
|
||||||
|
UUID.randomUUID().toString(),
|
||||||
|
fileInDir.getName(),
|
||||||
|
absolutePathOfFileInDir,
|
||||||
|
ldt.toString(),
|
||||||
|
now.toString(),
|
||||||
|
Utils.calculateSHA512Hash(fileInDir),
|
||||||
|
"SHA-512",
|
||||||
|
fileInDir.length(),
|
||||||
|
"OK"
|
||||||
|
);
|
||||||
|
filesMissingInDb.add(fsFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
LOG.info("Adding new files: {}", filesMissingInDb.size());
|
||||||
|
birContext.getFileRepository().create(filesMissingInDb);
|
||||||
|
return now;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<FsFile> part7RemoveDeletedFilesFromDb(ListSet<FsFile> filesInDb, ListSet<File> filesInFileSystem, BirContext birContext) {
|
||||||
|
LOG.info("** Part {}: Removing deleted files from DB", CheckCommandPart.REMOVE_DELETED_FILES_FROM_DB.number);
|
||||||
|
List<FsFile> filesToBeRemovedFromDb = new ArrayList<>();
|
||||||
|
int processedCount = 0;
|
||||||
|
|
||||||
|
for (FsFile fileInDb : filesInDb.getList()) {
|
||||||
|
processedCount = processedCount + 1;
|
||||||
|
if (processedCount % 100 == 0) {
|
||||||
|
double progress = ((double) processedCount) / filesInDb.getList().size() * 100;
|
||||||
|
LOG.info(
|
||||||
|
"Part {}: Remove - Progress: {}/{} {}%",
|
||||||
|
CheckCommandPart.REMOVE_DELETED_FILES_FROM_DB.number,
|
||||||
|
processedCount,
|
||||||
|
filesInDb.getList().size(),
|
||||||
|
String.format("%,.2f", progress)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String absolutePathOfFileInDb = fileInDb.getAbsolutePath();
|
||||||
|
if (!filesInFileSystem.doesSetContains(absolutePathOfFileInDb)) {
|
||||||
|
|
||||||
|
filesToBeRemovedFromDb.add(fileInDb);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
LOG.info("Part {}: Removing files: {}",
|
||||||
|
CheckCommandPart.REMOVE_DELETED_FILES_FROM_DB.number,
|
||||||
|
filesToBeRemovedFromDb.size());
|
||||||
|
for (FsFile f : filesToBeRemovedFromDb) {
|
||||||
|
birContext.getFileRepository().remove(f);
|
||||||
|
}
|
||||||
|
return filesToBeRemovedFromDb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<FsFile> part8CompareContentAndLastModificationDate(
|
||||||
|
ListSet<FsFile> filesInDb, List<FsFile> filesToBeRemovedFromDb, BirContext birContext, LocalDateTime now) {
|
||||||
|
LOG.info("** Part {}: Comparing Content and last modification date", CheckCommandPart.COMPARE_CONTENT_AND_LAST_MODTIME.number);
|
||||||
|
double countOfFilesToCalculateHashSum = filesInDb.size() - filesToBeRemovedFromDb.size();
|
||||||
|
int processedCount = 0;
|
||||||
|
//// Update modified files with same last modification date
|
||||||
|
List<FsFile> filesWithBitRot = new ArrayList<>();
|
||||||
|
List<FsFile> filesToUpdateLastCheckDate = new ArrayList<>();
|
||||||
|
int contentAndModTimeWereChanged = 0;
|
||||||
|
|
||||||
|
RemainingTimeCalculator rtc = new RemainingTimeCalculator(filesInDb.size() - filesToBeRemovedFromDb.size());
|
||||||
|
for (FsFile fileInDb : filesInDb) {
|
||||||
|
String absolutePathOfFileInDb = fileInDb.getAbsolutePath();
|
||||||
|
if (filesToBeRemovedFromDb.contains(fileInDb)) {
|
||||||
|
//nothing to do
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
rtc.nextDone();
|
||||||
|
processedCount = processedCount + 1;
|
||||||
|
if (processedCount % 100 == 0) {
|
||||||
|
double progress = ((double) processedCount) / countOfFilesToCalculateHashSum * 100;
|
||||||
|
LOG.info("Update - Progress: " + processedCount + "/" + countOfFilesToCalculateHashSum + " " + String.format("%,.2f", progress) + "%");
|
||||||
|
LOG.info("Remains: " + Duration.of(rtc.remainingSecondsUntilEnd(), TimeUnit.SECOND).toString());
|
||||||
|
}
|
||||||
|
File file = new File("./" + absolutePathOfFileInDb);
|
||||||
|
|
||||||
|
Date lastModified = new Date(file.lastModified());
|
||||||
|
org.nanoboot.powerframework.time.moment.LocalDateTime ldt = org.nanoboot.powerframework.time.moment.LocalDateTime.convertJavaUtilDateToPowerLocalDateTime(lastModified);
|
||||||
|
|
||||||
|
|
||||||
|
String calculatedHash = Utils.calculateSHA512Hash(file);
|
||||||
|
if (ldt.toString().equals(fileInDb.getLastModificationDate()) && !calculatedHash.equals(fileInDb.getHashSumValue())) {
|
||||||
|
filesWithBitRot.add(fileInDb);
|
||||||
|
fileInDb.setLastCheckDate(now.toString());
|
||||||
|
fileInDb.setLastCheckResult("KO");
|
||||||
|
birContext.getFileRepository().updateFile(fileInDb);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!ldt.toString().equals(fileInDb.getLastModificationDate())) {
|
||||||
|
fileInDb.setLastCheckDate(now.toString());
|
||||||
|
fileInDb.setLastModificationDate(ldt.toString());
|
||||||
|
fileInDb.setHashSumValue(calculatedHash);
|
||||||
|
fileInDb.setHashSumAlgorithm("SHA-512");
|
||||||
|
fileInDb.setSize(file.length());
|
||||||
|
fileInDb.setLastCheckResult("OK");
|
||||||
|
birContext.getFileRepository().updateFile(fileInDb);
|
||||||
|
//System.out.println(fileInDb.toString());
|
||||||
|
contentAndModTimeWereChanged++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ldt.toString().equals(fileInDb.getLastModificationDate())) {
|
||||||
|
fileInDb.setLastCheckResult("OK");
|
||||||
|
|
||||||
|
if (fileInDb.getSize() == 0) {
|
||||||
|
fileInDb.setSize(file.length());
|
||||||
|
birContext.getFileRepository().updateFile(fileInDb);
|
||||||
|
} else {
|
||||||
|
filesToUpdateLastCheckDate.add(fileInDb);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
LOG.info("Part {}: Updating files - found bit rots - content was changed and last modification is the same): {}",
|
||||||
|
CheckCommandPart.COMPARE_CONTENT_AND_LAST_MODTIME.number,
|
||||||
|
filesWithBitRot.size());
|
||||||
|
LOG.info("Part {}: Updating files - content and last modification date were changed): {}",
|
||||||
|
CheckCommandPart.COMPARE_CONTENT_AND_LAST_MODTIME.number,
|
||||||
|
contentAndModTimeWereChanged);
|
||||||
|
LOG.info("Part {}: Updating files - content and last modification date were not changed): {}",
|
||||||
|
CheckCommandPart.COMPARE_CONTENT_AND_LAST_MODTIME.number,
|
||||||
|
filesToUpdateLastCheckDate.size());
|
||||||
|
birContext.getFileRepository().updateLastCheckDate(now.toString(), filesToUpdateLastCheckDate);
|
||||||
|
|
||||||
|
return filesWithBitRot;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void part9CreateReportCsvIfNeeded(BirArgs birArgs, BirFiles birFiles, List<FsFile> filesWithBitRot) {
|
||||||
|
LOG.info("** Part {}: Creating csv report, if needed", CheckCommandPart.CREATE_REPORT_CSV_IF_NEEDED.number);
|
||||||
|
if (!birArgs.hasArgument("report")) {
|
||||||
|
LOG.info(" Part {}: OK. Nothing to do. No option report was passed.", CheckCommandPart.CREATE_REPORT_CSV_IF_NEEDED.number);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!birArgs.getArgument("report").equals("true")) {
|
||||||
|
LOG.info("Part {}: Nothing to do. Option report={}",
|
||||||
|
CheckCommandPart.CREATE_REPORT_CSV_IF_NEEDED.number,
|
||||||
|
birArgs.getArgument("report"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File birReportCsv = birFiles.getBirReportCsv();
|
||||||
|
if (birReportCsv.exists()) {
|
||||||
|
Long nowLong = org.nanoboot.powerframework.time.moment.UniversalDateTime.now().toLong();
|
||||||
|
|
||||||
|
File backup = new File(birReportCsv.getParentFile().getAbsolutePath() + "/" + nowLong + "." + birReportCsv.getName());
|
||||||
|
birReportCsv.renameTo(backup);
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if (!filesWithBitRot.isEmpty()) {
|
||||||
|
sb.append("file;expected;calculated\n");
|
||||||
|
}
|
||||||
|
filesWithBitRot.stream().forEach(f
|
||||||
|
-> sb.append(f.getAbsolutePath())
|
||||||
|
.append(";")
|
||||||
|
.append(f.getHashSumValue())
|
||||||
|
.append(";")
|
||||||
|
.append(Utils.calculateSHA512Hash(new File("./" + f.getAbsolutePath())))
|
||||||
|
.append("\n")
|
||||||
|
);
|
||||||
|
Utils.writeTextToFile(sb.toString(), birReportCsv);
|
||||||
|
LOG.info("Part {}: OK.",
|
||||||
|
CheckCommandPart.CREATE_REPORT_CSV_IF_NEEDED.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void part10CalculateCurrentHashSumOfDbFile(BirFiles birFiles) {
|
||||||
|
LOG.info("** Part {}: Calculating current hash sum of DB file", CheckCommandPart.CHECK_NEW_DB_CHECKSUM.number);
|
||||||
|
Utils.writeTextToFile(Utils.calculateSHA512Hash(birFiles.getBirSQLite3File()), birFiles.getBirSQLite3FileSha512());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,304 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// dog: Tool generating documentation.
|
|
||||||
// Copyright (C) 2023-2023 the original author or authors.
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU General Public License
|
|
||||||
// as published by the Free Software Foundation; version 2
|
|
||||||
// of the License only.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
package org.nanoboot.dog.commands;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Properties;
|
|
||||||
import org.nanoboot.dog.Command;
|
|
||||||
import org.nanoboot.dog.DogArgs;
|
|
||||||
import org.nanoboot.dog.Menu;
|
|
||||||
import org.nanoboot.dog.Utils;
|
|
||||||
import org.asciidoctor.Asciidoctor;
|
|
||||||
import static org.asciidoctor.Asciidoctor.Factory.create;
|
|
||||||
import org.nanoboot.dog.DogException;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author pc00289
|
|
||||||
*/
|
|
||||||
public class GenCommand implements Command {
|
|
||||||
|
|
||||||
private static final String ADOC_EXTENSION = ".adoc";
|
|
||||||
|
|
||||||
public GenCommand() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "gen";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(DogArgs dogArgs) {
|
|
||||||
if (!dogArgs.hasArgument("in")) {
|
|
||||||
dogArgs.addArgument("in", new File(".").getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dogArgs.getArgument("in") == null) {
|
|
||||||
throw new DogException("Argument in must have a value (must not be empty).");
|
|
||||||
}
|
|
||||||
if (dogArgs.hasArgument("out") && !(new File(dogArgs.getArgument("out")).exists())) {
|
|
||||||
throw new DogException("Argument out must be an existing directory.");
|
|
||||||
}
|
|
||||||
|
|
||||||
File inDir = new File(dogArgs.getArgument("in"));
|
|
||||||
if (!inDir.exists()) {
|
|
||||||
throw new DogException("Argument in must be an existing directory, but that directory does not exist.");
|
|
||||||
}
|
|
||||||
File dogConfFile = new File(inDir, "dog.conf");
|
|
||||||
if (!dogConfFile.exists()) {
|
|
||||||
throw new DogException("File dog.conf was not found.");
|
|
||||||
}
|
|
||||||
File generatedDir = new File((dogArgs.hasArgument("out") ? new File(dogArgs.getArgument("out")) : inDir), "generated");
|
|
||||||
|
|
||||||
if (generatedDir.exists()) {
|
|
||||||
try {
|
|
||||||
FileUtils.deleteDirectory(generatedDir);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
throw new DogException("Deleting generated directory failed.", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
generatedDir.mkdir();
|
|
||||||
if (!generatedDir.exists()) {
|
|
||||||
throw new DogException("Argument out must be an existing directory, but that directory does not exist.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
Properties dogConfProperties = null;
|
|
||||||
try (InputStream input = new FileInputStream(dogConfFile.getAbsolutePath())) {
|
|
||||||
dogConfProperties = new Properties();
|
|
||||||
dogConfProperties.load(input);
|
|
||||||
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
throw new DogException("Loading file dog.conf failed.", ex);
|
|
||||||
}
|
|
||||||
Utils.writeTextToFile(Utils.readTextFromResourceFile("/dog.css"), new File(generatedDir, "dog.css"));
|
|
||||||
File contentDir = new File(inDir, "content");
|
|
||||||
Menu menuInstance = new Menu(contentDir);
|
|
||||||
File templateDir = new File(contentDir.getParentFile().getAbsolutePath() + "/templates");
|
|
||||||
String headerTemplate = Utils.readTextFromFile(new File(templateDir, "header.html"));
|
|
||||||
String footerTemplate = Utils.readTextFromFile(new File(templateDir, "footer.html"));
|
|
||||||
processContentDir(contentDir, generatedDir, contentDir, dogConfProperties, menuInstance, headerTemplate, footerTemplate);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void processContentDir(File dir, File generatedDir, File contentDir, Properties dogConfProperties, Menu menuInstance, String headerTemplate, String footerTemplate) {
|
|
||||||
for (File inFile : dir.listFiles()) {
|
|
||||||
if (inFile.isFile()) {
|
|
||||||
processFileInContentDir(inFile, dir, contentDir, dogConfProperties, headerTemplate, menuInstance, footerTemplate, generatedDir);
|
|
||||||
}
|
|
||||||
if (inFile.isDirectory()) {
|
|
||||||
processDirInContentDir(generatedDir, inFile, contentDir, dogConfProperties, menuInstance, headerTemplate, footerTemplate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void processDirInContentDir(File generatedDir, File inFile, File contentDir, Properties dogConfProperties, Menu menuInstance, String headerTemplate, String footerTemplate) {
|
|
||||||
File generatedDir2 = new File(generatedDir, inFile.getName());
|
|
||||||
generatedDir2.mkdir();
|
|
||||||
processContentDir(inFile, generatedDir2, contentDir, dogConfProperties, menuInstance, headerTemplate, footerTemplate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void processFileInContentDir(File inFile, File dir, File contentDir, Properties dogConfProperties, String headerTemplate, Menu menuInstance, String footerTemplate, File generatedDir) {
|
|
||||||
if (inFile.getName().endsWith(ADOC_EXTENSION)) {
|
|
||||||
|
|
||||||
Asciidoctor asciidoctor = create();
|
|
||||||
String asciidocText = Utils.readTextFromFile(inFile);
|
|
||||||
|
|
||||||
String asciidocCompiled = asciidoctor
|
|
||||||
.convert(asciidocText, new HashMap<String, Object>());
|
|
||||||
String pathToRoot = dir.getAbsolutePath().replace(contentDir.getAbsolutePath(), "");
|
|
||||||
|
|
||||||
if (!pathToRoot.trim().isEmpty()) {
|
|
||||||
int count = 0;
|
|
||||||
for (char ch : pathToRoot.toCharArray()) {
|
|
||||||
if (ch == '/') {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (int i = 1; i <= count; i++) {
|
|
||||||
sb.append("../");
|
|
||||||
}
|
|
||||||
pathToRoot = sb.toString();
|
|
||||||
|
|
||||||
}
|
|
||||||
String titleSeparator = dogConfProperties.containsKey("titleSeparator") ? dogConfProperties.getProperty("titleSeparator") : "::";
|
|
||||||
final String humanName = createHumanName(inFile, dogConfProperties);
|
|
||||||
|
|
||||||
String start
|
|
||||||
= """
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<meta name="generator" content="Asciidoctor 2.0.16">
|
|
||||||
<title>
|
|
||||||
"""
|
|
||||||
+ humanName
|
|
||||||
+ (dogConfProperties.containsKey("title")
|
|
||||||
? (" " + titleSeparator + " " + dogConfProperties.getProperty("title")) : "")
|
|
||||||
+ """
|
|
||||||
</title>
|
|
||||||
<link rel="stylesheet" href="
|
|
||||||
"""
|
|
||||||
+ pathToRoot
|
|
||||||
+ """
|
|
||||||
dog.css">
|
|
||||||
</head>
|
|
||||||
<body class="article">
|
|
||||||
"""
|
|
||||||
+ headerTemplate
|
|
||||||
+ """
|
|
||||||
<div id="header">
|
|
||||||
"""
|
|
||||||
+ createNavigation(inFile, contentDir, dogConfProperties)
|
|
||||||
+ "<h1>"
|
|
||||||
+ humanName
|
|
||||||
+ """
|
|
||||||
</h1>
|
|
||||||
</div>"""
|
|
||||||
+ createMenu(menuInstance, inFile)
|
|
||||||
+ """
|
|
||||||
<div id="content">
|
|
||||||
""";
|
|
||||||
String end
|
|
||||||
= """
|
|
||||||
</div>
|
|
||||||
<div id="footer">
|
|
||||||
<div id="footer-text">
|
|
||||||
Last updated """
|
|
||||||
+ " "
|
|
||||||
+ (org.nanoboot.dog.Constants.YYYYMMDDHHMMSSZ_DATE_FORMAT.format(new Date()))
|
|
||||||
+ "<br>" + footerTemplate
|
|
||||||
+ """
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
""";
|
|
||||||
|
|
||||||
List<String> dirs = new ArrayList<>();
|
|
||||||
File currentFile = inFile;
|
|
||||||
String rootContentDirPath = contentDir.getAbsolutePath();
|
|
||||||
while (!currentFile.getAbsolutePath().equals(rootContentDirPath)) {
|
|
||||||
dirs.add(currentFile.getName());
|
|
||||||
currentFile = currentFile.getParentFile();
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (int i = dirs.size() - 1; i >= 0; i--) {
|
|
||||||
String d = dirs.get(i);
|
|
||||||
sb.append(d);
|
|
||||||
if (i > 0) {
|
|
||||||
sb.append("/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String editThisPage = "<hr><a href=\"" + dogConfProperties.getProperty("editURL") + sb.toString() + "\">Edit this page</a>";
|
|
||||||
String htmlOutput = start + asciidocCompiled + editThisPage + end;
|
|
||||||
|
|
||||||
File htmlFile = new File(generatedDir, inFile.getName().replace(ADOC_EXTENSION, ".html"));
|
|
||||||
Utils.writeTextToFile(htmlOutput, htmlFile);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Utils.copyFile(inFile, generatedDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static String createMenu(Menu menu, File currentFile) {
|
|
||||||
|
|
||||||
return //"<pre>" + menu.toAsciidoc(currentFile.getAbsolutePath().split("content")[1]) + "</pre>" +
|
|
||||||
menu.toHtml(currentFile.getAbsolutePath().split("content")[1]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String createNavigation(File adocFile, File rootContentDir, Properties dogConfProperties) {
|
|
||||||
List<File> files = new ArrayList<>();
|
|
||||||
File currentFile = adocFile;
|
|
||||||
while (!currentFile.getAbsolutePath().equals(rootContentDir.getAbsolutePath())) {
|
|
||||||
|
|
||||||
if (currentFile.getName().equals("content")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
files.add(currentFile);
|
|
||||||
currentFile = currentFile.getParentFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder("<div class=\"navigation\" style=\"margin-top:20px;\"><a href=\"" + /*path +*/ Utils.createDoubleDotSlash(files.size() - 1) + "index.html\">Home</a>");
|
|
||||||
if (files.size() > 1 || !currentFile.getName().equals("index.adoc")) {
|
|
||||||
sb.append(" > ");
|
|
||||||
}
|
|
||||||
for (int i = (files.size() - 1); i >= 0; i--) {
|
|
||||||
File file = files.get(i);
|
|
||||||
if (file.getName().equals("index.adoc")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sb
|
|
||||||
.append("<a href=\"")
|
|
||||||
.append(Utils.createDoubleDotSlash(i - 1))
|
|
||||||
.append(i == 0 ? (file.getName().replace(ADOC_EXTENSION, "")) : "index")
|
|
||||||
.append(".html\">")
|
|
||||||
.append(createHumanName(file, dogConfProperties))
|
|
||||||
.append("</a>\n");
|
|
||||||
|
|
||||||
sb.append(" > ");
|
|
||||||
|
|
||||||
}
|
|
||||||
sb.append("</div>");
|
|
||||||
String result = sb.toString();
|
|
||||||
if (result.endsWith(" > </div>")) {
|
|
||||||
result = result.substring(0, result.length() - 9);
|
|
||||||
result = result + "</div>";
|
|
||||||
}
|
|
||||||
return result + "<hr>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String createHumanName(File inFile, Properties dogConfProperties) {
|
|
||||||
|
|
||||||
String result = inFile.getName();
|
|
||||||
if (result.endsWith(ADOC_EXTENSION)) {
|
|
||||||
result = result.substring(0, inFile.getName().length() - ADOC_EXTENSION.length());
|
|
||||||
}
|
|
||||||
result = result.replace("_", " ");
|
|
||||||
if (Character.isLetter(result.charAt(0))) {
|
|
||||||
result = Character.toUpperCase(result.charAt(0)) + result.substring(1);
|
|
||||||
}
|
|
||||||
if (result.equals("Index")) {
|
|
||||||
File parentFile = inFile.getParentFile();
|
|
||||||
if (parentFile.getName().equals("content")) {
|
|
||||||
String frontPageName = dogConfProperties.getProperty("frontPageName", "");
|
|
||||||
return frontPageName.isBlank() ? "Home" : frontPageName;
|
|
||||||
}
|
|
||||||
return createHumanName(parentFile, dogConfProperties);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,24 +19,26 @@
|
|||||||
package org.nanoboot.bitinspector.commands;
|
package org.nanoboot.bitinspector.commands;
|
||||||
|
|
||||||
import org.nanoboot.bitinspector.core.Command;
|
import org.nanoboot.bitinspector.core.Command;
|
||||||
import org.nanoboot.bitinspector.core.BitInspectorArgs;
|
import org.nanoboot.bitinspector.core.BirArgs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author pc00289
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class HelpCommand implements Command {
|
public class HelpCommand implements Command {
|
||||||
|
|
||||||
|
public static final String NAME = "help";
|
||||||
|
|
||||||
public HelpCommand() {
|
public HelpCommand() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "help";
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(BitInspectorArgs bitInspectorArgs) {
|
public String run(BirArgs bitInspectorArgs) {
|
||||||
String str = """
|
String str = """
|
||||||
NAME
|
NAME
|
||||||
bir - " Bit Inspector"
|
bir - " Bit Inspector"
|
||||||
@ -51,13 +53,15 @@ public class HelpCommand implements Command {
|
|||||||
COMMAND
|
COMMAND
|
||||||
check Generates the static website
|
check Generates the static website
|
||||||
OPTIONS
|
OPTIONS
|
||||||
reportid={unique name for this report, usually `date +'%Y%m%d_%H%M%S'`}
|
dir={working directory to be checked for bit rot}
|
||||||
Optional. Default= (nothing will be reported to file report.{reportid}.bitreport.txt).
|
Optional. Default=. (current working directory)
|
||||||
|
report=true or false
|
||||||
|
Optional. Default= false (nothing will be reported to file .birreport.csv).
|
||||||
help Display help information
|
help Display help information
|
||||||
version Display version information
|
version Display version information
|
||||||
""";
|
""";
|
||||||
System.out.println(str);
|
System.out.println(str);
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,26 +19,32 @@
|
|||||||
|
|
||||||
package org.nanoboot.bitinspector.commands;
|
package org.nanoboot.bitinspector.commands;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.nanoboot.bitinspector.core.Command;
|
import org.nanoboot.bitinspector.core.Command;
|
||||||
import org.nanoboot.bitinspector.core.BitInspectorArgs;
|
import org.nanoboot.bitinspector.core.BirArgs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author pc00289
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class VersionCommand implements Command {
|
public class VersionCommand implements Command {
|
||||||
|
|
||||||
|
public static final String NAME = "version";
|
||||||
|
private static final Logger LOG = LogManager.getLogger(VersionCommand.class);
|
||||||
public VersionCommand() {
|
public VersionCommand() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "version";
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(BitInspectorArgs bitInspectorArgs) {
|
public String run(BirArgs bitInspectorArgs) {
|
||||||
System.out.println("Bit Inspector 0.0.0-SNAPSHOT");
|
String result = "Bit Inspector 0.0.0-SNAPSHOT";
|
||||||
|
LOG.info(result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
package org.nanoboot.bitinspector.core;
|
package org.nanoboot.bitinspector.core;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -25,15 +24,33 @@ import lombok.Getter;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author pc00289
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class BitInspectorArgs {
|
public class BirArgs {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final String command;
|
private final String command;
|
||||||
private final Map<String, String> internalMap = new HashMap<>();
|
private final Map<String, String> internalMap = new HashMap<>();
|
||||||
|
|
||||||
public BitInspectorArgs(String[] args) {
|
private static String[] convertToStringArray(String command, Map<String, String> map) {
|
||||||
|
String[] array = new String[1 + map.size()];
|
||||||
|
array[0] = command;
|
||||||
|
int i = 0;
|
||||||
|
for (String key : map.keySet()) {
|
||||||
|
array[++i] = key + "=" + map.get(key);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BirArgs(BitInspectorCommand command, Map<String, String> map) {
|
||||||
|
this(convertToStringArray(command.name().toLowerCase(), map));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BirArgs(String command, Map<String, String> map) {
|
||||||
|
this(convertToStringArray(command, map));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BirArgs(String[] args) {
|
||||||
command = args.length == 0 ? "check" : args[0];
|
command = args.length == 0 ? "check" : args[0];
|
||||||
|
|
||||||
if (args.length > 1) {
|
if (args.length > 1) {
|
||||||
@ -54,15 +71,20 @@ public class BitInspectorArgs {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasArgument(String arg) {
|
public boolean hasArgument(String arg) {
|
||||||
return internalMap.containsKey(arg);
|
return internalMap.containsKey(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addArgument(String arg, String value) {
|
public void addArgument(String arg, String value) {
|
||||||
this.internalMap.put(arg,value);
|
this.internalMap.put(arg, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getArgument(String arg) {
|
public String getArgument(String arg) {
|
||||||
return internalMap.get(arg);
|
return internalMap.get(arg);
|
||||||
}
|
}
|
||||||
|
public boolean isVerboseLoggingEnabled() {
|
||||||
|
return hasArgument("verbose")&&getArgument("verbose").equals("true");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
49
src/main/java/org/nanoboot/bitinspector/core/BirContext.java
Normal file
49
src/main/java/org/nanoboot/bitinspector/core/BirContext.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// bit-inspector: Tool detecting bit rots in files.
|
||||||
|
// Copyright (C) 2023-2023 the original author or authors.
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; version 2
|
||||||
|
// of the License only.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
package org.nanoboot.bitinspector.core;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.nanoboot.bitinspector.persistence.api.ConnectionFactory;
|
||||||
|
import org.nanoboot.bitinspector.persistence.api.FileRepository;
|
||||||
|
import org.nanoboot.bitinspector.persistence.api.SystemItemRepository;
|
||||||
|
import org.nanoboot.bitinspector.persistence.impl.sqlite.FileRepositoryImplSqlite;
|
||||||
|
import org.nanoboot.bitinspector.persistence.impl.sqlite.SqliteConnectionFactory;
|
||||||
|
import org.nanoboot.bitinspector.persistence.impl.sqlite.SystemItemRepositoryImplSqlite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
|
*/
|
||||||
|
public class BirContext {
|
||||||
|
private final String directoryWhereSqliteFileIs;
|
||||||
|
private ConnectionFactory connectionFactory;
|
||||||
|
@Getter
|
||||||
|
private SystemItemRepository systemItemRepository;
|
||||||
|
@Getter
|
||||||
|
private FileRepository fileRepository;
|
||||||
|
|
||||||
|
public BirContext(String directoryWhereSqliteFileIs) {
|
||||||
|
this.directoryWhereSqliteFileIs = directoryWhereSqliteFileIs;
|
||||||
|
this.connectionFactory = new SqliteConnectionFactory(directoryWhereSqliteFileIs);
|
||||||
|
systemItemRepository = new SystemItemRepositoryImplSqlite((SqliteConnectionFactory) connectionFactory);
|
||||||
|
fileRepository = new FileRepositoryImplSqlite((SqliteConnectionFactory) connectionFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
52
src/main/java/org/nanoboot/bitinspector/core/BirFiles.java
Normal file
52
src/main/java/org/nanoboot/bitinspector/core/BirFiles.java
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// bit-inspector: Tool detecting bit rots in files.
|
||||||
|
// Copyright (C) 2023-2023 the original author or authors.
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; version 2
|
||||||
|
// of the License only.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
package org.nanoboot.bitinspector.core;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.nanoboot.bitinspector.commands.BirIgnoreRegex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Getter
|
||||||
|
public class BirFiles {
|
||||||
|
|
||||||
|
private final File workingDir;
|
||||||
|
private final String workingDirAbsolutePath;
|
||||||
|
private final File birSQLite3File;
|
||||||
|
private final File birSQLite3FileSha512;
|
||||||
|
private final File birIgnore;
|
||||||
|
private final BirIgnoreRegex birIgnoreRegex;
|
||||||
|
private final File birReportCsv;
|
||||||
|
|
||||||
|
|
||||||
|
public BirFiles(BirArgs bitInspectorArgs) {
|
||||||
|
workingDir = new File(bitInspectorArgs.hasArgument("dir") ? bitInspectorArgs.getArgument("dir") : ".");
|
||||||
|
workingDirAbsolutePath = workingDir.getAbsolutePath();
|
||||||
|
birSQLite3File = new File(workingDirAbsolutePath + "/.bir.sqlite3");
|
||||||
|
birSQLite3FileSha512 = new File(workingDirAbsolutePath + "/.bir.sqlite3.sha512");
|
||||||
|
birIgnore = new File(workingDirAbsolutePath + "/.birignore");
|
||||||
|
birIgnoreRegex = new BirIgnoreRegex(birIgnore);
|
||||||
|
birReportCsv = new File(workingDirAbsolutePath + "/.birreport.csv");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// bit-inspector: Tool detecting bit rots in files.
|
||||||
|
// Copyright (C) 2023-2023 the original author or authors.
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; version 2
|
||||||
|
// of the License only.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
package org.nanoboot.bitinspector.core;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.nanoboot.bitinspector.commands.CheckCommand;
|
||||||
|
import org.nanoboot.bitinspector.commands.HelpCommand;
|
||||||
|
import org.nanoboot.bitinspector.commands.VersionCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
|
*/
|
||||||
|
public class BitInspector {
|
||||||
|
|
||||||
|
private static final Logger LOG = LogManager.getLogger(BitInspector.class);
|
||||||
|
|
||||||
|
private final Set<Command> commandImplementations;
|
||||||
|
public BitInspector() {
|
||||||
|
commandImplementations = new HashSet<>();
|
||||||
|
commandImplementations.add(new CheckCommand());
|
||||||
|
commandImplementations.add(new HelpCommand());
|
||||||
|
commandImplementations.add(new VersionCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(String[] args) {
|
||||||
|
run(new BirArgs(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(BirArgs bitInspectorArgs) {
|
||||||
|
String command = bitInspectorArgs.getCommand();
|
||||||
|
Command foundCommand = null;
|
||||||
|
for(Command e:commandImplementations) {
|
||||||
|
if(e.getName().equals(command)) {
|
||||||
|
foundCommand = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(foundCommand == null) {
|
||||||
|
String msg = "Command \"" + command + "\" is not supported.";
|
||||||
|
LOG.error(msg);
|
||||||
|
|
||||||
|
new HelpCommand().run(bitInspectorArgs);
|
||||||
|
throw new BitInspectorException(msg);
|
||||||
|
}
|
||||||
|
foundCommand.run(bitInspectorArgs);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// bit-inspector: Tool detecting bit rots in files.
|
||||||
|
// Copyright (C) 2023-2023 the original author or authors.
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; version 2
|
||||||
|
// of the License only.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
package org.nanoboot.bitinspector.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
|
*/
|
||||||
|
public enum BitInspectorCommand {
|
||||||
|
CHECK, HELP, VERSION;
|
||||||
|
}
|
@ -21,11 +21,11 @@ package org.nanoboot.bitinspector.core;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author pc00289
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public interface Command {
|
public interface Command {
|
||||||
public String getName();
|
public String getName();
|
||||||
default void run(BitInspectorArgs bitInspectorArgs) {
|
default String run(BirArgs bitInspectorArgs) {
|
||||||
throw new BitInspectorException("Not yet implemented.");
|
throw new BitInspectorException("Not yet implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import java.text.SimpleDateFormat;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author pc00289
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class Constants {
|
public class Constants {
|
||||||
|
|
||||||
|
57
src/main/java/org/nanoboot/bitinspector/core/ListSet.java
Normal file
57
src/main/java/org/nanoboot/bitinspector/core/ListSet.java
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// bit-inspector: Tool detecting bit rots in files.
|
||||||
|
// Copyright (C) 2023-2023 the original author or authors.
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; version 2
|
||||||
|
// of the License only.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
package org.nanoboot.bitinspector.core;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author robertvokac
|
||||||
|
*/
|
||||||
|
public class ListSet<T> implements Iterable<T> {
|
||||||
|
@Getter
|
||||||
|
private final List<T> list;
|
||||||
|
@Getter
|
||||||
|
private final Set<String> set;
|
||||||
|
|
||||||
|
public ListSet(List<T> list, Function<? super T, String> mapper) {
|
||||||
|
this.list = Collections.unmodifiableList(list);
|
||||||
|
this.set = Collections.unmodifiableSet(list.stream().map(mapper).collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
public boolean doesSetContains(String s) {
|
||||||
|
return set.contains(s);
|
||||||
|
}
|
||||||
|
public int size() {
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return list.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -18,12 +18,6 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
package org.nanoboot.bitinspector.core;
|
package org.nanoboot.bitinspector.core;
|
||||||
|
|
||||||
import org.nanoboot.bitinspector.commands.HelpCommand;
|
|
||||||
import org.nanoboot.bitinspector.commands.CheckCommand;
|
|
||||||
import org.nanoboot.bitinspector.commands.VersionCommand;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
* @since 0.0.0
|
* @since 0.0.0
|
||||||
@ -32,28 +26,9 @@ public class Main {
|
|||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
System.out.println("Bir - Detects bit rotten files in the given directory to keep your files forever.\n");
|
System.out.println("Bir - Detects bit rotten files in the given directory to keep your files forever.\n");
|
||||||
|
|
||||||
BitInspectorArgs BitInspectorArgs = new BitInspectorArgs(args);
|
BitInspector bitInspector = new BitInspector();
|
||||||
String command = BitInspectorArgs.getCommand();
|
bitInspector.run(args);
|
||||||
|
|
||||||
Set<Command> commandImplementations = new HashSet<>();
|
|
||||||
commandImplementations.add(new CheckCommand());
|
|
||||||
commandImplementations.add(new HelpCommand());
|
|
||||||
commandImplementations.add(new VersionCommand());
|
|
||||||
Command foundCommand = null;
|
|
||||||
for(Command e:commandImplementations) {
|
|
||||||
if(e.getName().equals(command)) {
|
|
||||||
foundCommand = e;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(foundCommand == null) {
|
|
||||||
System.err.println("Error: Command \"" + command + "\" is not supported.\n");
|
|
||||||
|
|
||||||
new HelpCommand().run(BitInspectorArgs);
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
foundCommand.run(BitInspectorArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,8 +16,11 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
package org.nanoboot.bitinspector.core;
|
package org.nanoboot.bitinspector.core;
|
||||||
|
|
||||||
|
import dev.mccue.guava.hash.Hashing;
|
||||||
|
import dev.mccue.guava.io.Files;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
@ -25,12 +28,10 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -38,7 +39,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author pc00289
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
@ -65,31 +66,6 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getCountOfSlashOccurences(String string) {
|
|
||||||
int i = 0;
|
|
||||||
for (char ch : string.toCharArray()) {
|
|
||||||
if (ch == '/') {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<File> listAdocFilesInDir(File dir) {
|
|
||||||
return listAdocFilesInDir(dir, new ArrayList<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<File> listAdocFilesInDir(File dir, List<File> files) {
|
|
||||||
List<File> allFiles = listAllFilesInDir(dir, files);
|
|
||||||
List<File> adocFiles = new ArrayList<>();
|
|
||||||
for (File f : allFiles) {
|
|
||||||
if (f.getName().endsWith(".adoc") && !f.isDirectory()) {
|
|
||||||
adocFiles.add(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return adocFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<File> listAllFilesInDir(File dir) {
|
public static List<File> listAllFilesInDir(File dir) {
|
||||||
return listAllFilesInDir(dir, new ArrayList<>());
|
return listAllFilesInDir(dir, new ArrayList<>());
|
||||||
}
|
}
|
||||||
@ -106,21 +82,12 @@ public class Utils {
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String createDoubleDotSlash(int times) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (int i = 1; i <= times; i++) {
|
|
||||||
sb.append("../");
|
|
||||||
}
|
|
||||||
String result = sb.toString();
|
|
||||||
return result;//.substring(0, result.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void copyFile(File originalFile, File copiedFile) throws BitInspectorException {
|
public static void copyFile(File originalFile, File copiedFile) throws BitInspectorException {
|
||||||
Path originalPath = originalFile.toPath();
|
Path originalPath = originalFile.toPath();
|
||||||
Path copied = new File(copiedFile, originalFile.getName()).toPath();
|
Path copied = new File(copiedFile, originalFile.getName()).toPath();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.copy(originalPath, copied, StandardCopyOption.REPLACE_EXISTING);
|
java.nio.file.Files.copy(originalPath, copied, StandardCopyOption.REPLACE_EXISTING);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
throw new BitInspectorException("Copying file failed: " + originalFile.getAbsolutePath());
|
throw new BitInspectorException("Copying file failed: " + originalFile.getAbsolutePath());
|
||||||
@ -145,7 +112,7 @@ public class Utils {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return new String(Files.readAllBytes(Paths.get(file.getAbsolutePath())));
|
return new String(java.nio.file.Files.readAllBytes(Paths.get(file.getAbsolutePath())));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new BitInspectorException("Reading file failed: " + file.getName(), ex);
|
throw new BitInspectorException("Reading file failed: " + file.getName(), ex);
|
||||||
}
|
}
|
||||||
@ -176,24 +143,36 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String calculateSHA512Hash(File file) {
|
public static String calculateSHA512Hash(File file) {
|
||||||
final Path path = Paths.get(file.getAbsolutePath());
|
|
||||||
byte[] bytes;
|
|
||||||
try {
|
try {
|
||||||
bytes = Files.readAllBytes(path);
|
return Files.hash(file, Hashing.sha512()).toString();
|
||||||
|
// final Path path = Paths.get(file.getAbsolutePath());
|
||||||
|
// byte[] bytes;
|
||||||
|
// try {
|
||||||
|
// bytes = Files.readAllBytes(path);
|
||||||
|
// } catch (IOException ex) {
|
||||||
|
// throw new BitInspectorException(ex);
|
||||||
|
// }
|
||||||
|
// byte[] sha512sumByteArray;
|
||||||
|
// if(file.length() >= Integer.MAX_VALUE) {
|
||||||
|
// throw new RuntimeException("File is too large: " + file.getAbsolutePath());
|
||||||
|
// }
|
||||||
|
// try {
|
||||||
|
// sha512sumByteArray = MessageDigest.getInstance("SHA-512").digest(bytes);
|
||||||
|
// } catch (NoSuchAlgorithmException ex) {
|
||||||
|
// throw new BitInspectorException(ex);
|
||||||
|
// }
|
||||||
|
// StringBuilder sb = new StringBuilder(sha512sumByteArray.length * 2);
|
||||||
|
// for (byte b : sha512sumByteArray) {
|
||||||
|
// sb.append(String.format("%02x", b));
|
||||||
|
// }
|
||||||
|
// String hexString = sb.toString();
|
||||||
|
// return hexString;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(Utils.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
throw new BitInspectorException(ex);
|
throw new BitInspectorException(ex);
|
||||||
}
|
}
|
||||||
byte[] sha512sumByteArray;
|
}
|
||||||
try {
|
public static String createJdbcUrl(String directoryWhereSqliteFileIs) {
|
||||||
sha512sumByteArray = MessageDigest.getInstance("SHA-512").digest(bytes);
|
return "jdbc:sqlite:" + directoryWhereSqliteFileIs + "/" + ".bir.sqlite3?foreign_keys=on;";
|
||||||
} catch (NoSuchAlgorithmException ex) {
|
|
||||||
throw new BitInspectorException(ex);
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder(sha512sumByteArray.length * 2);
|
|
||||||
for (byte b : sha512sumByteArray) {
|
|
||||||
sb.append(String.format("%02x", b));
|
|
||||||
}
|
|
||||||
String hexString = sb.toString();
|
|
||||||
return hexString;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ import lombok.ToString;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@ -40,5 +40,7 @@ public class FsFile {
|
|||||||
private String lastCheckDate;
|
private String lastCheckDate;
|
||||||
private String hashSumValue;
|
private String hashSumValue;
|
||||||
private String hashSumAlgorithm;
|
private String hashSumAlgorithm;
|
||||||
|
private long size;
|
||||||
|
private String lastCheckResult;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import lombok.Setter;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
@ -1,38 +1,30 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// dog: Tool generating documentation.
|
// bit-inspector: Tool detecting bit rots in files.
|
||||||
// Copyright (C) 2023-2023 the original author or authors.
|
// Copyright (C) 2023-2023 the original author or authors.
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or
|
// This program is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU General Public License
|
// modify it under the terms of the GNU General Public License
|
||||||
// as published by the Free Software Foundation; version 2
|
// as published by the Free Software Foundation; version 2
|
||||||
// of the License only.
|
// of the License only.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
package org.nanoboot.bitinspector.persistence.api;
|
||||||
package org.nanoboot.dog.commands;
|
|
||||||
|
import java.sql.Connection;
|
||||||
import org.nanoboot.dog.Command;
|
|
||||||
|
/**
|
||||||
/**
|
*
|
||||||
*
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
* @author pc00289
|
*/
|
||||||
*/
|
public interface ConnectionFactory {
|
||||||
public class HelpCommand implements Command {
|
|
||||||
|
Connection createConnection() throws ClassNotFoundException;
|
||||||
public HelpCommand() {
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "help";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -24,7 +24,7 @@ import org.nanoboot.bitinspector.entity.FsFile;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public interface FileRepository {
|
public interface FileRepository {
|
||||||
void create(List<FsFile> files);
|
void create(List<FsFile> files);
|
||||||
|
@ -24,7 +24,7 @@ import org.nanoboot.bitinspector.entity.SystemItem;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public interface SystemItemRepository {
|
public interface SystemItemRepository {
|
||||||
String create(SystemItem systemItem);
|
String create(SystemItem systemItem);
|
||||||
|
@ -20,10 +20,10 @@ package org.nanoboot.bitinspector.persistence.impl.sqlite;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class Constants {
|
public class Constants {
|
||||||
static final String JDBC_URL = "jdbc:sqlite:" + "." + "/" + ".bir.sqlite3?foreign_keys=on;";
|
|
||||||
private Constants() {
|
private Constants() {
|
||||||
//Not meant to be instantiated.
|
//Not meant to be instantiated.
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,16 @@ import org.nanoboot.bitinspector.persistence.api.FileRepository;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class FileRepositoryImplSqlite implements FileRepository {
|
public class FileRepositoryImplSqlite implements FileRepository {
|
||||||
|
|
||||||
|
private SqliteConnectionFactory sqliteConnectionFactory;
|
||||||
|
|
||||||
|
public FileRepositoryImplSqlite(SqliteConnectionFactory sqliteConnectionFactory) {
|
||||||
|
this.sqliteConnectionFactory = sqliteConnectionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(List<FsFile> files) {
|
public void create(List<FsFile> files) {
|
||||||
if (files.isEmpty()) {
|
if (files.isEmpty()) {
|
||||||
@ -69,13 +75,15 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
.append(FileTable.LAST_CHECK_DATE).append(",")
|
.append(FileTable.LAST_CHECK_DATE).append(",")
|
||||||
//
|
//
|
||||||
.append(FileTable.HASH_SUM_VALUE).append(",")
|
.append(FileTable.HASH_SUM_VALUE).append(",")
|
||||||
.append(FileTable.HASH_SUM_ALGORITHM);
|
.append(FileTable.HASH_SUM_ALGORITHM).append(",")
|
||||||
|
.append(FileTable.SIZE).append(",")
|
||||||
|
.append(FileTable.LAST_CHECK_RESULT).append("");
|
||||||
|
|
||||||
sb.append(") VALUES ");
|
sb.append(") VALUES ");
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (FsFile f : files) {
|
for (FsFile f : files) {
|
||||||
sb.append(" (?,?,?,?,?, ?,?)");
|
sb.append(" (?,?,?,?,?, ?,?,?,?)");
|
||||||
boolean lastFile = index == (files.size() - 1);
|
boolean lastFile = index == (files.size() - 1);
|
||||||
if (!lastFile) {
|
if (!lastFile) {
|
||||||
sb.append(",");
|
sb.append(",");
|
||||||
@ -84,7 +92,7 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String sql = sb.toString();
|
String sql = sb.toString();
|
||||||
System.err.println(sql);
|
//System.err.println(sql);
|
||||||
try (
|
try (
|
||||||
Connection connection = createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
Connection connection = createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -99,11 +107,13 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
//
|
//
|
||||||
stmt.setString(++i, f.getHashSumValue());
|
stmt.setString(++i, f.getHashSumValue());
|
||||||
stmt.setString(++i, f.getHashSumAlgorithm());
|
stmt.setString(++i, f.getHashSumAlgorithm());
|
||||||
|
stmt.setLong(++i, f.getSize());
|
||||||
|
stmt.setString(++i, f.getLastCheckResult());
|
||||||
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
stmt.execute();
|
stmt.execute();
|
||||||
System.out.println(stmt.toString());
|
//System.out.println(stmt.toString());
|
||||||
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
System.out.println(e.getMessage());
|
System.out.println(e.getMessage());
|
||||||
@ -124,7 +134,7 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
.append(FileTable.TABLE_NAME);
|
.append(FileTable.TABLE_NAME);
|
||||||
|
|
||||||
String sql = sb.toString();
|
String sql = sb.toString();
|
||||||
System.err.println(sql);
|
// System.err.println(sql);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try (
|
try (
|
||||||
@ -165,7 +175,7 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
sb.append(FileTable.ID);
|
sb.append(FileTable.ID);
|
||||||
sb.append("=?");
|
sb.append("=?");
|
||||||
String sql = sb.toString();
|
String sql = sb.toString();
|
||||||
System.err.println("SQL::" + sql);
|
//System.err.println("SQL::" + sql);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
try (
|
try (
|
||||||
@ -173,7 +183,7 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
|
|
||||||
stmt.setString(++i, file.getId());
|
stmt.setString(++i, file.getId());
|
||||||
|
|
||||||
System.err.println(stmt.toString());
|
//System.err.println(stmt.toString());
|
||||||
stmt.execute();
|
stmt.execute();
|
||||||
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
@ -185,7 +195,7 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Connection createConnection() throws ClassNotFoundException {
|
private Connection createConnection() throws ClassNotFoundException {
|
||||||
return new SqliteConnectionFactory().createConnection();
|
return sqliteConnectionFactory.createConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -199,7 +209,9 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
.append(FileTable.LAST_MODIFICATION_DATE).append("=?, ")
|
.append(FileTable.LAST_MODIFICATION_DATE).append("=?, ")
|
||||||
.append(FileTable.LAST_CHECK_DATE).append("=?, ")
|
.append(FileTable.LAST_CHECK_DATE).append("=?, ")
|
||||||
.append(FileTable.HASH_SUM_VALUE).append("=?, ")
|
.append(FileTable.HASH_SUM_VALUE).append("=?, ")
|
||||||
.append(FileTable.HASH_SUM_ALGORITHM).append("=? ")
|
.append(FileTable.HASH_SUM_ALGORITHM).append("=?, ")
|
||||||
|
.append(FileTable.SIZE).append("=?, ")
|
||||||
|
.append(FileTable.LAST_CHECK_RESULT).append("=? ")
|
||||||
.append(" WHERE ").append(FileTable.ID).append("=?");
|
.append(" WHERE ").append(FileTable.ID).append("=?");
|
||||||
|
|
||||||
String sql = sb.toString();
|
String sql = sb.toString();
|
||||||
@ -211,6 +223,8 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
stmt.setString(++i, file.getLastCheckDate());
|
stmt.setString(++i, file.getLastCheckDate());
|
||||||
stmt.setString(++i, file.getHashSumValue());
|
stmt.setString(++i, file.getHashSumValue());
|
||||||
stmt.setString(++i, file.getHashSumAlgorithm());
|
stmt.setString(++i, file.getHashSumAlgorithm());
|
||||||
|
stmt.setLong(++i, file.getSize());
|
||||||
|
stmt.setString(++i, file.getLastCheckResult());
|
||||||
|
|
||||||
stmt.setString(++i, file.getId());
|
stmt.setString(++i, file.getId());
|
||||||
|
|
||||||
@ -232,14 +246,16 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
rs.getString(FileTable.LAST_MODIFICATION_DATE),
|
rs.getString(FileTable.LAST_MODIFICATION_DATE),
|
||||||
rs.getString(FileTable.LAST_CHECK_DATE),
|
rs.getString(FileTable.LAST_CHECK_DATE),
|
||||||
rs.getString(FileTable.HASH_SUM_VALUE),
|
rs.getString(FileTable.HASH_SUM_VALUE),
|
||||||
rs.getString(FileTable.HASH_SUM_ALGORITHM)
|
rs.getString(FileTable.HASH_SUM_ALGORITHM),
|
||||||
|
rs.getLong(FileTable.SIZE),
|
||||||
|
rs.getString(FileTable.LAST_CHECK_RESULT)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLastCheckDate(String lastCheckDate, List<FsFile> files) {
|
public void updateLastCheckDate(String lastCheckDate, List<FsFile> files) {
|
||||||
|
|
||||||
if (files.isEmpty()) {
|
if (files.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (files.size() > 100) {
|
if (files.size() > 100) {
|
||||||
@ -258,13 +274,14 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb
|
sb
|
||||||
.append("UPDATE ")
|
.append("UPDATE ")
|
||||||
.append(FileTable.TABLE_NAME)
|
.append(FileTable.TABLE_NAME)
|
||||||
.append(" SET ")
|
.append(" SET ")
|
||||||
.append(FileTable.LAST_CHECK_DATE).append("=? ")
|
.append(FileTable.LAST_CHECK_DATE).append("=?, ")
|
||||||
|
.append(FileTable.LAST_CHECK_RESULT).append("='OK' ")
|
||||||
.append(" WHERE ").append(FileTable.ID).append(" IN (");
|
.append(" WHERE ").append(FileTable.ID).append(" IN (");
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (FsFile f : files) {
|
for (FsFile f : files) {
|
||||||
|
@ -24,7 +24,7 @@ import lombok.Setter;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@ -40,5 +40,8 @@ class FileTable {
|
|||||||
//
|
//
|
||||||
public static final String HASH_SUM_VALUE = "HASH_SUM_VALUE";
|
public static final String HASH_SUM_VALUE = "HASH_SUM_VALUE";
|
||||||
public static final String HASH_SUM_ALGORITHM = "HASH_SUM_ALGORITHM";
|
public static final String HASH_SUM_ALGORITHM = "HASH_SUM_ALGORITHM";
|
||||||
|
public static final String SIZE = "SIZE";
|
||||||
|
public static final String LAST_CHECK_RESULT = "LAST_CHECK_RESULT";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,21 +18,26 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
package org.nanoboot.bitinspector.persistence.impl.sqlite;
|
package org.nanoboot.bitinspector.persistence.impl.sqlite;
|
||||||
|
|
||||||
|
import org.nanoboot.bitinspector.persistence.api.ConnectionFactory;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import org.nanoboot.bitinspector.core.Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class SqliteConnectionFactory {
|
public class SqliteConnectionFactory implements ConnectionFactory {
|
||||||
|
private final String jdbcUrl;
|
||||||
|
public SqliteConnectionFactory(String directoryWhereSqliteFileIs) {
|
||||||
|
this.jdbcUrl = Utils.createJdbcUrl(directoryWhereSqliteFileIs);
|
||||||
|
}
|
||||||
public Connection createConnection() throws ClassNotFoundException {
|
public Connection createConnection() throws ClassNotFoundException {
|
||||||
try {
|
try {
|
||||||
Class.forName("org.sqlite.JDBC");
|
Class.forName("org.sqlite.JDBC");
|
||||||
|
|
||||||
Connection conn = DriverManager.getConnection(Constants.JDBC_URL);
|
Connection conn = DriverManager.getConnection(jdbcUrl);
|
||||||
|
|
||||||
return conn;
|
return conn;
|
||||||
|
|
||||||
|
@ -18,33 +18,48 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
package org.nanoboot.bitinspector.persistence.impl.sqlite;
|
package org.nanoboot.bitinspector.persistence.impl.sqlite;
|
||||||
|
|
||||||
|
import org.nanoboot.bitinspector.core.Utils;
|
||||||
import org.nanoboot.dbmigration.core.main.DBMigration;
|
import org.nanoboot.dbmigration.core.main.DBMigration;
|
||||||
|
import org.nanoboot.dbmigration.core.main.MigrationResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class SqliteDatabaseMigration {
|
public class SqliteDatabaseMigration {
|
||||||
|
|
||||||
public void migrate() {
|
private static SqliteDatabaseMigration INSTANCE;
|
||||||
|
|
||||||
|
private SqliteDatabaseMigration() {
|
||||||
|
//Not meant to be instantiated
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SqliteDatabaseMigration getInstance() {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
INSTANCE = new SqliteDatabaseMigration();
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MigrationResult migrate(String directoryWhereSqliteFileIs) {
|
||||||
try {
|
try {
|
||||||
Class.forName("org.sqlite.JDBC");
|
Class.forName("org.sqlite.JDBC");
|
||||||
} catch (ClassNotFoundException ex) {
|
} catch (ClassNotFoundException ex) {
|
||||||
System.err.println(ex.getMessage());
|
System.err.println(ex.getMessage());
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
System.err.println("jdbcUrl=" + Constants.JDBC_URL);
|
String jdbcUrl = Utils.createJdbcUrl(directoryWhereSqliteFileIs);
|
||||||
|
System.err.println("jdbcUrl=" + jdbcUrl);
|
||||||
String clazz = this.getClass().getName();
|
String clazz = this.getClass().getName();
|
||||||
DBMigration dbMigration = DBMigration
|
DBMigration dbMigration = DBMigration
|
||||||
.configure()
|
.configure()
|
||||||
.dataSource(Constants.JDBC_URL)
|
.dataSource(jdbcUrl)
|
||||||
.installedBy("bitinspector-persistence-impl-sqlite")
|
.installedBy("bitinspector-persistence-impl-sqlite")
|
||||||
.name("bitinspector")
|
.name("bitinspector")
|
||||||
.sqlDialect("sqlite", "org.nanoboot.dbmigration.core.persistence.impl.sqlite.DBMigrationPersistenceSqliteImpl")
|
.sqlDialect("sqlite", "org.nanoboot.dbmigration.core.persistence.impl.sqlite.DBMigrationPersistenceSqliteImpl")
|
||||||
.sqlMigrationsClass(clazz)
|
.sqlMigrationsClass(clazz)
|
||||||
.load();
|
.load();
|
||||||
dbMigration.migrate();
|
return dbMigration.migrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,16 @@ import org.nanoboot.bitinspector.persistence.api.SystemItemRepository;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
public class SystemItemRepositoryImplSqlite implements SystemItemRepository {
|
public class SystemItemRepositoryImplSqlite implements SystemItemRepository {
|
||||||
|
|
||||||
|
public SystemItemRepositoryImplSqlite(SqliteConnectionFactory sqliteConnectionFactory) {
|
||||||
|
this.sqliteConnectionFactory = sqliteConnectionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final SqliteConnectionFactory sqliteConnectionFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String create(SystemItem systemItem) {
|
public String create(SystemItem systemItem) {
|
||||||
|
|
||||||
@ -52,7 +58,7 @@ public class SystemItemRepositoryImplSqlite implements SystemItemRepository {
|
|||||||
String sql = sb.toString();
|
String sql = sb.toString();
|
||||||
System.err.println(sql);
|
System.err.println(sql);
|
||||||
try (
|
try (
|
||||||
Connection connection = new SqliteConnectionFactory().createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
Connection connection = sqliteConnectionFactory.createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
stmt.setString(++i, systemItem.getKey());
|
stmt.setString(++i, systemItem.getKey());
|
||||||
stmt.setString(++i, systemItem.getValue());
|
stmt.setString(++i, systemItem.getValue());
|
||||||
@ -95,7 +101,7 @@ public class SystemItemRepositoryImplSqlite implements SystemItemRepository {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try (
|
try (
|
||||||
Connection connection = new SqliteConnectionFactory().createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
Connection connection = sqliteConnectionFactory.createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||||
|
|
||||||
stmt.setString(++i, key);
|
stmt.setString(++i, key);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import lombok.Setter;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author robertvokac
|
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "FILE" ADD COLUMN SIZE NUMBER
|
||||||
|
|
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "FILE" ADD COLUMN LAST_CHECK_RESULT NUMBER
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user