Big refactoring
This commit is contained in:
parent
edba08f896
commit
46eaeb824e
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@
|
||||
#*.class
|
||||
/target/
|
||||
|
||||
/nbproject/
|
||||
|
28
pom.xml
28
pom.xml
@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>org.nanoboot.essential</groupId>
|
||||
<artifactId>nanoboot-parent</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<version>0.1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.nanoboot.tools</groupId>
|
||||
@ -42,7 +42,7 @@
|
||||
<power.version>2.0.1-SNAPSHOT</power.version>
|
||||
<maven.compiler.source>19</maven.compiler.source>
|
||||
<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>
|
||||
|
||||
<build>
|
||||
@ -158,11 +158,24 @@
|
||||
|
||||
<!-- Other dependencies -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit4.version}</version>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit-jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
<groupId>org.nanoboot.tools.dbmigration</groupId>
|
||||
<artifactId>db-migration-core</artifactId>
|
||||
@ -202,6 +215,11 @@
|
||||
<artifactId>log4j-slf4j-impl</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.mccue</groupId>
|
||||
<artifactId>guava-io</artifactId>
|
||||
<version>0.0.3</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
@ -25,4 +25,5 @@ module bitinspector {
|
||||
requires java.sql;
|
||||
requires powerframework.time;
|
||||
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> {
|
||||
|
||||
|
||||
private final List<String> patterns = new ArrayList<>();
|
||||
|
||||
|
||||
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[]{};
|
||||
if (lines.length == 0) {
|
||||
//nothing to do
|
||||
return;
|
||||
}
|
||||
String addPrefix = workingDir == null ? "" : birIgnoreFile.getParentFile().getAbsolutePath().replace(workingDir.getAbsolutePath() + "/", "");
|
||||
|
||||
for (String l : lines) {
|
||||
if (l.isBlank() || l.trim().startsWith("#")) {
|
||||
//nothing to do
|
||||
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
|
||||
public boolean test(String text) {
|
||||
if (patterns.isEmpty()) {
|
||||
@ -63,7 +74,7 @@ public class BirIgnoreRegex implements Predicate<String> {
|
||||
if (b) {
|
||||
ignore = true;
|
||||
} else {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
// if (ignore) {
|
||||
@ -73,7 +84,7 @@ public class BirIgnoreRegex implements Predicate<String> {
|
||||
// }
|
||||
return ignore;
|
||||
}
|
||||
|
||||
|
||||
public static String convertUnixRegexToJavaRegex(String wildcard) {
|
||||
StringBuffer s = new StringBuffer(wildcard.length());
|
||||
s.append('^');
|
||||
@ -109,5 +120,5 @@ public class BirIgnoreRegex implements Predicate<String> {
|
||||
s.append('$');
|
||||
return (s.toString());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -22,225 +22,195 @@ import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
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.BitInspectorArgs;
|
||||
import org.nanoboot.bitinspector.core.BirArgs;
|
||||
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.entity.FsFile;
|
||||
import org.nanoboot.bitinspector.entity.SystemItem;
|
||||
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.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 {
|
||||
|
||||
private final File currentDirRoot = new File(".");
|
||||
private final File birSQLite3File = new File("./.bir.sqlite3");
|
||||
private final File birSQLite3FileSha512 = new File("./.bir.sqlite3.sha512");
|
||||
private final File birIgnore = new File("./.birignore");
|
||||
BirIgnoreRegex birIgnoreRegex = new BirIgnoreRegex(birIgnore);
|
||||
private static final Logger LOG = LogManager.getLogger(CheckCommand.class);
|
||||
public static final String NAME = "check";
|
||||
|
||||
public CheckCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
public void run(BitInspectorArgs bitInspectorArgs) {
|
||||
SqliteDatabaseMigration sqliteDatabaseMigration = new SqliteDatabaseMigration();
|
||||
sqliteDatabaseMigration.migrate();
|
||||
|
||||
SystemItemRepository systemItemRepository = new SystemItemRepositoryImplSqlite();
|
||||
FileRepository fileRepository = new FileRepositoryImplSqlite();
|
||||
////
|
||||
String version = systemItemRepository.read("bir.version").getValue();
|
||||
System.out.println("bir.version=" + version);
|
||||
if (version == null) {
|
||||
systemItemRepository.create(new SystemItem("bir.version", "0.0.0-SNAPSHOT"));
|
||||
public String run(BirArgs birArgs) {
|
||||
BirFiles birFiles = new BirFiles(birArgs);
|
||||
BirContext birContext = new BirContext(birFiles.getWorkingDirAbsolutePath());
|
||||
//
|
||||
//part 1:
|
||||
part1CheckDbHasExpectedHashSum(birFiles);
|
||||
//part 2:
|
||||
boolean part2Result = part2MigrateDbSchemaIfNeeded(birFiles);
|
||||
if(!part2Result) {
|
||||
return "part 2 failed";
|
||||
}
|
||||
System.out.println("Updating version in DB.");
|
||||
version = systemItemRepository.read("bir.version").getValue();
|
||||
System.out.println("bir.version=" + version);
|
||||
////
|
||||
//part 3:
|
||||
part3UpdateVersionInDbIfNeeded(birContext);
|
||||
|
||||
//// Check ,SQLite DB file has the expected SHA-512 hash sum
|
||||
if (birSQLite3File.exists() && birSQLite3FileSha512.exists()) {
|
||||
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
|
||||
ListSet<File> filesInFileSystem = part4FoundFilesInFileSystem(birFiles, birArgs);
|
||||
ListSet<FsFile> filesInDb = part5FoundFilesInDb(birContext.getFileRepository(), birArgs);
|
||||
|
||||
List<File> filesInDir = foundFilesInCurrentDir(currentDirRoot, new ArrayList<>());
|
||||
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))));
|
||||
LocalDateTime now = part6AddNewFilesToDb(filesInFileSystem, birFiles, filesInDb, birContext);
|
||||
|
||||
//// Found files in DB
|
||||
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())));
|
||||
List<FsFile> filesToBeRemovedFromDb = part7RemoveDeletedFilesFromDb(filesInDb, filesInFileSystem, birContext);
|
||||
|
||||
//// Add new files
|
||||
Date lastChecked = new Date();
|
||||
org.nanoboot.powerframework.time.moment.LocalDateTime now = org.nanoboot.powerframework.time.moment.LocalDateTime.convertJavaUtilDateToPowerLocalDateTime(lastChecked);
|
||||
List<FsFile> filesWithBitRot = part8CompareContentAndLastModificationDate(filesInDb, filesToBeRemovedFromDb, birContext, now);
|
||||
|
||||
int processedCount0 = 0;
|
||||
part9CreateReportCsvIfNeeded(birArgs, birFiles, filesWithBitRot);
|
||||
part10CalculateCurrentHashSumOfDbFile(birFiles);
|
||||
|
||||
List<FsFile> filesMissingInDb = new ArrayList<>();
|
||||
for (File fileInDir : filesInDir) {
|
||||
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");
|
||||
LOG.info("==========");
|
||||
LOG.info("Summary");
|
||||
|
||||
if (filesWithBitRot.isEmpty()) {
|
||||
System.out.println("No files with bit rot were found.");
|
||||
}
|
||||
filesWithBitRot.stream().forEach(f
|
||||
-> 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");
|
||||
}
|
||||
LOG.info("Summary: OK : No files with bit rot were found.");
|
||||
} else {
|
||||
LOG.error("Summary: KO : Some files {} with bit rot were found.", filesWithBitRot.size());
|
||||
filesWithBitRot.stream().forEach(f
|
||||
-> sb.append(f.getAbsolutePath())
|
||||
.append(";")
|
||||
.append(f.getHashSumValue())
|
||||
.append(";")
|
||||
.append(Utils.calculateSHA512Hash(new File("./" + f.getAbsolutePath())))
|
||||
.append("\n")
|
||||
-> LOG.error("Bit rot detected: \"" + f.getAbsolutePath() + "\"" + " expected_sha512=" + f.getHashSumValue() + " returned_sha512=" + Utils.calculateSHA512Hash(new File("./" + f.getAbsolutePath())))
|
||||
);
|
||||
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("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) {
|
||||
return file.getAbsolutePath().substring(currentDir.getAbsolutePath().length() + 1);
|
||||
}
|
||||
@ -249,32 +219,244 @@ public class CheckCommand implements Command {
|
||||
private int foundFiles;
|
||||
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()) {
|
||||
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()) {
|
||||
++foundDirs;
|
||||
foundFilesInCurrentDir(f, files);
|
||||
foundFilesInCurrentDir(f, filesAlreadyFound, birFiles);
|
||||
} else {
|
||||
++foundFiles;
|
||||
if (f.getAbsolutePath().equals(birSQLite3File.getAbsolutePath())) {
|
||||
if (f.getAbsolutePath().equals(birFiles.getBirSQLite3File().getAbsolutePath())) {
|
||||
continue;
|
||||
}
|
||||
if (f.getAbsolutePath().equals(birSQLite3FileSha512.getAbsolutePath())) {
|
||||
continue;
|
||||
}
|
||||
if (f.getAbsolutePath().equals(birIgnore.getAbsolutePath())) {
|
||||
if (f.getAbsolutePath().equals(birFiles.getBirSQLite3FileSha512().getAbsolutePath())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++iii;
|
||||
//System.out.println("Testing file: " + iii + "#" + " " + loadPathButOnlyTheNeededPart(currentDirRoot, f));
|
||||
if (birIgnoreRegex.test(loadPathButOnlyTheNeededPart(currentDirRoot, f))) {
|
||||
if (birFiles.getBirIgnoreRegex().test(loadPathButOnlyTheNeededPart(birFiles.getWorkingDir(), f))) {
|
||||
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;
|
||||
|
||||
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 static final String NAME = "help";
|
||||
|
||||
public HelpCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "help";
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(BitInspectorArgs bitInspectorArgs) {
|
||||
public String run(BirArgs bitInspectorArgs) {
|
||||
String str = """
|
||||
NAME
|
||||
bir - " Bit Inspector"
|
||||
@ -51,13 +53,15 @@ public class HelpCommand implements Command {
|
||||
COMMAND
|
||||
check Generates the static website
|
||||
OPTIONS
|
||||
reportid={unique name for this report, usually `date +'%Y%m%d_%H%M%S'`}
|
||||
Optional. Default= (nothing will be reported to file report.{reportid}.bitreport.txt).
|
||||
dir={working directory to be checked for bit rot}
|
||||
Optional. Default=. (current working directory)
|
||||
report=true or false
|
||||
Optional. Default= false (nothing will be reported to file .birreport.csv).
|
||||
help Display help information
|
||||
version Display version information
|
||||
""";
|
||||
System.out.println(str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,26 +19,32 @@
|
||||
|
||||
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.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 static final String NAME = "version";
|
||||
private static final Logger LOG = LogManager.getLogger(VersionCommand.class);
|
||||
public VersionCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "version";
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(BitInspectorArgs bitInspectorArgs) {
|
||||
System.out.println("Bit Inspector 0.0.0-SNAPSHOT");
|
||||
public String run(BirArgs bitInspectorArgs) {
|
||||
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
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
package org.nanoboot.bitinspector.core;
|
||||
|
||||
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
|
||||
private final String command;
|
||||
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];
|
||||
|
||||
if (args.length > 1) {
|
||||
@ -54,15 +71,20 @@ public class BitInspectorArgs {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasArgument(String arg) {
|
||||
return internalMap.containsKey(arg);
|
||||
}
|
||||
|
||||
public void addArgument(String arg, String value) {
|
||||
this.internalMap.put(arg,value);
|
||||
this.internalMap.put(arg, value);
|
||||
}
|
||||
|
||||
public String getArgument(String 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 String getName();
|
||||
default void run(BitInspectorArgs bitInspectorArgs) {
|
||||
default String run(BirArgs bitInspectorArgs) {
|
||||
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 {
|
||||
|
||||
|
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;
|
||||
|
||||
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>
|
||||
* @since 0.0.0
|
||||
@ -32,28 +26,9 @@ public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Bir - Detects bit rotten files in the given directory to keep your files forever.\n");
|
||||
|
||||
BitInspectorArgs BitInspectorArgs = new BitInspectorArgs(args);
|
||||
String command = BitInspectorArgs.getCommand();
|
||||
|
||||
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);
|
||||
|
||||
BitInspector bitInspector = new BitInspector();
|
||||
bitInspector.run(args);
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,8 +16,11 @@
|
||||
// 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 dev.mccue.guava.hash.Hashing;
|
||||
import dev.mccue.guava.io.Files;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
@ -25,12 +28,10 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
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 {
|
||||
|
||||
@ -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) {
|
||||
return listAllFilesInDir(dir, new ArrayList<>());
|
||||
}
|
||||
@ -106,21 +82,12 @@ public class Utils {
|
||||
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 {
|
||||
Path originalPath = originalFile.toPath();
|
||||
Path copied = new File(copiedFile, originalFile.getName()).toPath();
|
||||
|
||||
try {
|
||||
Files.copy(originalPath, copied, StandardCopyOption.REPLACE_EXISTING);
|
||||
java.nio.file.Files.copy(originalPath, copied, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
throw new BitInspectorException("Copying file failed: " + originalFile.getAbsolutePath());
|
||||
@ -145,7 +112,7 @@ public class Utils {
|
||||
return "";
|
||||
}
|
||||
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) {
|
||||
throw new BitInspectorException("Reading file failed: " + file.getName(), ex);
|
||||
}
|
||||
@ -176,24 +143,36 @@ public class Utils {
|
||||
}
|
||||
|
||||
public static String calculateSHA512Hash(File file) {
|
||||
final Path path = Paths.get(file.getAbsolutePath());
|
||||
byte[] bytes;
|
||||
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) {
|
||||
Logger.getLogger(Utils.class.getName()).log(Level.SEVERE, null, ex);
|
||||
throw new BitInspectorException(ex);
|
||||
}
|
||||
byte[] sha512sumByteArray;
|
||||
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;
|
||||
}
|
||||
public static String createJdbcUrl(String directoryWhereSqliteFileIs) {
|
||||
return "jdbc:sqlite:" + directoryWhereSqliteFileIs + "/" + ".bir.sqlite3?foreign_keys=on;";
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import lombok.ToString;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ -40,5 +40,7 @@ public class FsFile {
|
||||
private String lastCheckDate;
|
||||
private String hashSumValue;
|
||||
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
|
||||
@Setter
|
||||
|
@ -1,38 +1,30 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 org.nanoboot.dog.Command;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author pc00289
|
||||
*/
|
||||
public class HelpCommand implements Command {
|
||||
|
||||
public HelpCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "help";
|
||||
}
|
||||
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.persistence.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||
*/
|
||||
public interface ConnectionFactory {
|
||||
|
||||
Connection createConnection() throws ClassNotFoundException;
|
||||
}
|
@ -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 {
|
||||
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 {
|
||||
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 {
|
||||
static final String JDBC_URL = "jdbc:sqlite:" + "." + "/" + ".bir.sqlite3?foreign_keys=on;";
|
||||
|
||||
private Constants() {
|
||||
//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 {
|
||||
|
||||
private SqliteConnectionFactory sqliteConnectionFactory;
|
||||
|
||||
public FileRepositoryImplSqlite(SqliteConnectionFactory sqliteConnectionFactory) {
|
||||
this.sqliteConnectionFactory = sqliteConnectionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(List<FsFile> files) {
|
||||
if (files.isEmpty()) {
|
||||
@ -69,13 +75,15 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
.append(FileTable.LAST_CHECK_DATE).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 ");
|
||||
|
||||
int index = 0;
|
||||
for (FsFile f : files) {
|
||||
sb.append(" (?,?,?,?,?, ?,?)");
|
||||
sb.append(" (?,?,?,?,?, ?,?,?,?)");
|
||||
boolean lastFile = index == (files.size() - 1);
|
||||
if (!lastFile) {
|
||||
sb.append(",");
|
||||
@ -84,7 +92,7 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
}
|
||||
|
||||
String sql = sb.toString();
|
||||
System.err.println(sql);
|
||||
//System.err.println(sql);
|
||||
try (
|
||||
Connection connection = createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
int i = 0;
|
||||
@ -99,11 +107,13 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
//
|
||||
stmt.setString(++i, f.getHashSumValue());
|
||||
stmt.setString(++i, f.getHashSumAlgorithm());
|
||||
stmt.setLong(++i, f.getSize());
|
||||
stmt.setString(++i, f.getLastCheckResult());
|
||||
|
||||
}
|
||||
//
|
||||
stmt.execute();
|
||||
System.out.println(stmt.toString());
|
||||
//System.out.println(stmt.toString());
|
||||
|
||||
} catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
@ -124,7 +134,7 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
.append(FileTable.TABLE_NAME);
|
||||
|
||||
String sql = sb.toString();
|
||||
System.err.println(sql);
|
||||
// System.err.println(sql);
|
||||
int i = 0;
|
||||
ResultSet rs = null;
|
||||
try (
|
||||
@ -165,7 +175,7 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
sb.append(FileTable.ID);
|
||||
sb.append("=?");
|
||||
String sql = sb.toString();
|
||||
System.err.println("SQL::" + sql);
|
||||
//System.err.println("SQL::" + sql);
|
||||
int i = 0;
|
||||
|
||||
try (
|
||||
@ -173,7 +183,7 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
|
||||
stmt.setString(++i, file.getId());
|
||||
|
||||
System.err.println(stmt.toString());
|
||||
//System.err.println(stmt.toString());
|
||||
stmt.execute();
|
||||
|
||||
} catch (SQLException e) {
|
||||
@ -185,7 +195,7 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
}
|
||||
|
||||
private Connection createConnection() throws ClassNotFoundException {
|
||||
return new SqliteConnectionFactory().createConnection();
|
||||
return sqliteConnectionFactory.createConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -199,7 +209,9 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
.append(FileTable.LAST_MODIFICATION_DATE).append("=?, ")
|
||||
.append(FileTable.LAST_CHECK_DATE).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("=?");
|
||||
|
||||
String sql = sb.toString();
|
||||
@ -211,6 +223,8 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
stmt.setString(++i, file.getLastCheckDate());
|
||||
stmt.setString(++i, file.getHashSumValue());
|
||||
stmt.setString(++i, file.getHashSumAlgorithm());
|
||||
stmt.setLong(++i, file.getSize());
|
||||
stmt.setString(++i, file.getLastCheckResult());
|
||||
|
||||
stmt.setString(++i, file.getId());
|
||||
|
||||
@ -232,14 +246,16 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
rs.getString(FileTable.LAST_MODIFICATION_DATE),
|
||||
rs.getString(FileTable.LAST_CHECK_DATE),
|
||||
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
|
||||
public void updateLastCheckDate(String lastCheckDate, List<FsFile> files) {
|
||||
|
||||
if (files.isEmpty()) {
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (files.size() > 100) {
|
||||
@ -258,13 +274,14 @@ public class FileRepositoryImplSqlite implements FileRepository {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb
|
||||
.append("UPDATE ")
|
||||
.append(FileTable.TABLE_NAME)
|
||||
.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 (");
|
||||
int index = 0;
|
||||
for (FsFile f : files) {
|
||||
|
@ -24,7 +24,7 @@ import lombok.Setter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ -40,5 +40,8 @@ class FileTable {
|
||||
//
|
||||
public static final String HASH_SUM_VALUE = "HASH_SUM_VALUE";
|
||||
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;
|
||||
|
||||
import org.nanoboot.bitinspector.persistence.api.ConnectionFactory;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
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 {
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
|
||||
Connection conn = DriverManager.getConnection(Constants.JDBC_URL);
|
||||
Connection conn = DriverManager.getConnection(jdbcUrl);
|
||||
|
||||
return conn;
|
||||
|
||||
|
@ -18,33 +18,48 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
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.MigrationResult;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||
*/
|
||||
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 {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
} catch (ClassNotFoundException ex) {
|
||||
System.err.println(ex.getMessage());
|
||||
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();
|
||||
DBMigration dbMigration = DBMigration
|
||||
.configure()
|
||||
.dataSource(Constants.JDBC_URL)
|
||||
.dataSource(jdbcUrl)
|
||||
.installedBy("bitinspector-persistence-impl-sqlite")
|
||||
.name("bitinspector")
|
||||
.sqlDialect("sqlite", "org.nanoboot.dbmigration.core.persistence.impl.sqlite.DBMigrationPersistenceSqliteImpl")
|
||||
.sqlMigrationsClass(clazz)
|
||||
.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 SystemItemRepositoryImplSqlite(SqliteConnectionFactory sqliteConnectionFactory) {
|
||||
this.sqliteConnectionFactory = sqliteConnectionFactory;
|
||||
}
|
||||
|
||||
private final SqliteConnectionFactory sqliteConnectionFactory;
|
||||
|
||||
@Override
|
||||
public String create(SystemItem systemItem) {
|
||||
|
||||
@ -52,7 +58,7 @@ public class SystemItemRepositoryImplSqlite implements SystemItemRepository {
|
||||
String sql = sb.toString();
|
||||
System.err.println(sql);
|
||||
try (
|
||||
Connection connection = new SqliteConnectionFactory().createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
Connection connection = sqliteConnectionFactory.createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
int i = 0;
|
||||
stmt.setString(++i, systemItem.getKey());
|
||||
stmt.setString(++i, systemItem.getValue());
|
||||
@ -95,7 +101,7 @@ public class SystemItemRepositoryImplSqlite implements SystemItemRepository {
|
||||
int i = 0;
|
||||
ResultSet rs = null;
|
||||
try (
|
||||
Connection connection = new SqliteConnectionFactory().createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
Connection connection = sqliteConnectionFactory.createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
|
||||
stmt.setString(++i, key);
|
||||
|
||||
|
@ -24,7 +24,7 @@ import lombok.Setter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
|
||||
*/
|
||||
@Getter
|
||||
@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