Implemented first working version
This commit is contained in:
parent
c6c996339c
commit
edba08f896
@ -14,11 +14,14 @@ You run the command bir:
|
||||
* All files in this directory are inspected, new files are added to the database, deleted files are removed from the database.
|
||||
* If the file last modification date in database and on the disk is the same, but the content checksum is different, then a bit rot is detected.
|
||||
|
||||
This program cannot restore files with bitrot.
|
||||
* You have to backup up your files (do snapshots).
|
||||
|
||||
## How to setup your environment on Linux
|
||||
|
||||
Example:
|
||||
|
||||
alias bir='java -jar /rv/data/desktop/code/code.nanoboot.org/nanoboot/bit-inspector/target/bir-inspector-0.0.0-SNAPSHOT-jar-with-dependencies.jar'
|
||||
alias bir='java -jar /rv/data/desktop/code/code.nanoboot.org/nanoboot/bit-inspector/target/bit-inspector-0.0.0-SNAPSHOT-jar-with-dependencies.jar'
|
||||
|
||||
## Usage
|
||||
|
||||
|
234
pom.xml
Normal file
234
pom.xml
Normal file
@ -0,0 +1,234 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
bit-inspector: Tool detecting bit rots in files.
|
||||
Copyright (C) 2016-2022 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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.nanoboot.essential</groupId>
|
||||
<artifactId>nanoboot-parent</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.nanoboot.tools</groupId>
|
||||
<artifactId>bit-inspector</artifactId>
|
||||
<version>0.0.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Bit Inspector</name>
|
||||
<description>Tool detecting bit rots in files.</description>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<checkstyle.skip>true</checkstyle.skip><!-- TODO: make false-->
|
||||
<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>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>${maven-deploy-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<!--<compilerArgs>
|
||||
-|-enable-preview
|
||||
</compilerArgs>-->
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<source>${javase.version}</source>
|
||||
<target>${javase.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>${maven-assembly-plugin.version}</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.nanoboot.bitinspector.core.Main</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id> <!-- this is used for inheritance merges -->
|
||||
<phase>package</phase> <!-- bind to the packaging phase -->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>${checkstyle.skip}</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-resource</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>add-resource</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources/db_migrations/sqlite/bitinspector</directory>
|
||||
<targetPath>db_migrations/sqlite/bitinspector</targetPath>
|
||||
<includes>
|
||||
<include>*.sql</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Power dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.nanoboot.powerframework</groupId>
|
||||
<artifactId>power-time</artifactId>
|
||||
<version>${power.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.nanoboot.powerframework</groupId>
|
||||
<artifactId>power-random</artifactId>
|
||||
<version>${power.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.nanoboot.powerframework</groupId>
|
||||
<artifactId>power-collections</artifactId>
|
||||
<version>${power.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Other dependencies -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit4.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.nanoboot.tools.dbmigration</groupId>
|
||||
<artifactId>db-migration-core</artifactId>
|
||||
<version>${db-migration-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>${sqlite-jdbc.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Lombok-->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j-impl</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>releases</id>
|
||||
<name>nanoboot-releases-repository</name>
|
||||
<url>https://maven.nanoboot.org/releases</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>snapshots</id>
|
||||
<name>nanoboot-snapshots-repository</name>
|
||||
<url>https://maven.nanoboot.org/snapshots</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>releases</id>
|
||||
<name>nanoboot-releases-repository</name>
|
||||
<url>https://maven.nanoboot.org/releases</url>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>snapshots</id>
|
||||
<name>nanoboot-snapshots-repository</name>
|
||||
<url>https://maven.nanoboot.org/snapshots</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
3
setmodtime.sh
Executable file
3
setmodtime.sh
Executable file
@ -0,0 +1,3 @@
|
||||
set_last_mod_time_the_same_as_this_file="$1"
|
||||
set_last_mod_time_for_this_file="$2"
|
||||
touch -r "$set_last_mod_time_the_same_as_this_file" "$set_last_mod_time_for_this_file"
|
28
src/main/java/module-info.java
Executable file
28
src/main/java/module-info.java
Executable file
@ -0,0 +1,28 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// bit-inspector: Tool detecting bit rots in files.
|
||||
// Copyright (C) 2016-2022 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.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module bitinspector {
|
||||
requires org.apache.commons.io;
|
||||
requires lombok;
|
||||
requires org.apache.logging.log4j;
|
||||
requires dbmigration.core;
|
||||
requires java.sql;
|
||||
requires powerframework.time;
|
||||
requires powerframework.collections;
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.commands;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import org.nanoboot.bitinspector.core.Utils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
public class BirIgnoreRegex implements Predicate<String> {
|
||||
|
||||
private final List<String> patterns = new ArrayList<>();
|
||||
|
||||
public BirIgnoreRegex(File birIgnoreFile) {
|
||||
String[] lines = birIgnoreFile.exists() ? Utils.readTextFromFile(birIgnoreFile).split("\\R") : new String[]{};
|
||||
if (lines.length == 0) {
|
||||
//nothing to do
|
||||
return;
|
||||
}
|
||||
for (String l : lines) {
|
||||
if (l.isBlank() || l.trim().startsWith("#")) {
|
||||
//nothing to do
|
||||
continue;
|
||||
}
|
||||
patterns.add(convertUnixRegexToJavaRegex(l));
|
||||
}
|
||||
patterns.add(convertUnixRegexToJavaRegex("*.birreport.csv"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(String text) {
|
||||
if (patterns.isEmpty()) {
|
||||
//nothing to do
|
||||
return false;
|
||||
}
|
||||
boolean ignore = false;
|
||||
for (String p : patterns) {
|
||||
boolean b = Pattern.matches(p, text);
|
||||
if (b) {
|
||||
ignore = true;
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
// if (ignore) {
|
||||
// System.out.println("ignoring file: " + text);
|
||||
// } else {
|
||||
// System.out.println("accepting file: " + text);
|
||||
// }
|
||||
return ignore;
|
||||
}
|
||||
|
||||
public static String convertUnixRegexToJavaRegex(String wildcard) {
|
||||
StringBuffer s = new StringBuffer(wildcard.length());
|
||||
s.append('^');
|
||||
for (int i = 0, is = wildcard.length(); i < is; i++) {
|
||||
char c = wildcard.charAt(i);
|
||||
switch (c) {
|
||||
case '*':
|
||||
s.append(".*");
|
||||
break;
|
||||
case '?':
|
||||
s.append(".");
|
||||
break;
|
||||
// escape special regexp-characters
|
||||
case '(':
|
||||
case ')':
|
||||
case '[':
|
||||
case ']':
|
||||
case '$':
|
||||
case '^':
|
||||
case '.':
|
||||
case '{':
|
||||
case '}':
|
||||
case '|':
|
||||
case '\\':
|
||||
s.append("\\");
|
||||
s.append(c);
|
||||
break;
|
||||
default:
|
||||
s.append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
s.append('$');
|
||||
return (s.toString());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,280 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.commands;
|
||||
|
||||
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.nanoboot.bitinspector.core.Command;
|
||||
import org.nanoboot.bitinspector.core.BitInspectorArgs;
|
||||
import org.nanoboot.bitinspector.core.BitInspectorException;
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author pc00289
|
||||
*/
|
||||
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);
|
||||
|
||||
public CheckCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "check";
|
||||
}
|
||||
|
||||
static int i = 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"));
|
||||
}
|
||||
System.out.println("Updating version in DB.");
|
||||
version = systemItemRepository.read("bir.version").getValue();
|
||||
System.out.println("bir.version=" + version);
|
||||
////
|
||||
|
||||
//// 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
|
||||
|
||||
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))));
|
||||
|
||||
//// 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())));
|
||||
|
||||
//// Add new files
|
||||
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 : 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");
|
||||
|
||||
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");
|
||||
}
|
||||
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(), reportIdFile);
|
||||
}
|
||||
//// Calculate current checksum of DB file.
|
||||
Utils.writeTextToFile(Utils.calculateSHA512Hash(birSQLite3File), birSQLite3FileSha512);
|
||||
|
||||
System.out.println("foundFiles=" + foundFiles);
|
||||
System.out.println("foundDirs=" + foundDirs);
|
||||
|
||||
}
|
||||
|
||||
private String loadPathButOnlyTheNeededPart(File currentDir, File file) {
|
||||
return file.getAbsolutePath().substring(currentDir.getAbsolutePath().length() + 1);
|
||||
}
|
||||
static int iii = 0;
|
||||
|
||||
private int foundFiles;
|
||||
private int foundDirs;
|
||||
|
||||
private List<File> foundFilesInCurrentDir(File currentDir, List<File> files) {
|
||||
|
||||
for (File f : currentDir.listFiles()) {
|
||||
if (f.isDirectory()) {
|
||||
++foundDirs;
|
||||
foundFilesInCurrentDir(f, files);
|
||||
} else {
|
||||
++foundFiles;
|
||||
if (f.getAbsolutePath().equals(birSQLite3File.getAbsolutePath())) {
|
||||
continue;
|
||||
}
|
||||
if (f.getAbsolutePath().equals(birSQLite3FileSha512.getAbsolutePath())) {
|
||||
continue;
|
||||
}
|
||||
if (f.getAbsolutePath().equals(birIgnore.getAbsolutePath())) {
|
||||
continue;
|
||||
}
|
||||
++iii;
|
||||
//System.out.println("Testing file: " + iii + "#" + " " + loadPathButOnlyTheNeededPart(currentDirRoot, f));
|
||||
if (birIgnoreRegex.test(loadPathButOnlyTheNeededPart(currentDirRoot, f))) {
|
||||
continue;
|
||||
}
|
||||
files.add(f);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,304 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.commands;
|
||||
|
||||
import org.nanoboot.bitinspector.core.Command;
|
||||
import org.nanoboot.bitinspector.core.BitInspectorArgs;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author pc00289
|
||||
*/
|
||||
public class HelpCommand implements Command {
|
||||
|
||||
public HelpCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "help";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(BitInspectorArgs bitInspectorArgs) {
|
||||
String str = """
|
||||
NAME
|
||||
bir - " Bit Inspector"
|
||||
|
||||
SYNOPSIS
|
||||
bir [command] [options]
|
||||
If no command is provided, then the default command check is used. This means, if you run "bit-inspector", it is the same, as to run "bir check".
|
||||
|
||||
DESCRIPTION
|
||||
Detects bit rotten files in the given directory to keep your files forever.
|
||||
|
||||
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).
|
||||
help Display help information
|
||||
version Display version information
|
||||
""";
|
||||
System.out.println(str);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.commands;
|
||||
|
||||
import org.nanoboot.bitinspector.core.Command;
|
||||
import org.nanoboot.bitinspector.core.BitInspectorArgs;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author pc00289
|
||||
*/
|
||||
public class VersionCommand implements Command {
|
||||
|
||||
public VersionCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "version";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(BitInspectorArgs bitInspectorArgs) {
|
||||
System.out.println("Bit Inspector 0.0.0-SNAPSHOT");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author pc00289
|
||||
*/
|
||||
public class BitInspectorArgs {
|
||||
|
||||
@Getter
|
||||
private final String command;
|
||||
private final Map<String, String> internalMap = new HashMap<>();
|
||||
|
||||
public BitInspectorArgs(String[] args) {
|
||||
command = args.length == 0 ? "check" : args[0];
|
||||
|
||||
if (args.length > 1) {
|
||||
|
||||
for (String arg : args) {
|
||||
if (arg == null) {
|
||||
continue;
|
||||
}
|
||||
if (args[0].equals(arg)) {
|
||||
continue;
|
||||
}
|
||||
String[] keyValue = arg.split("=", 2);
|
||||
internalMap.put(keyValue[0], keyValue.length > 1 ? keyValue[1] : null);
|
||||
}
|
||||
for (String key : internalMap.keySet()) {
|
||||
System.out.println("Found argument: " + key + "(=)" + internalMap.get(key));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public boolean hasArgument(String arg) {
|
||||
return internalMap.containsKey(arg);
|
||||
}
|
||||
public void addArgument(String arg, String value) {
|
||||
this.internalMap.put(arg,value);
|
||||
}
|
||||
|
||||
public String getArgument(String arg) {
|
||||
return internalMap.get(arg);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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>
|
||||
* @since 0.0.0
|
||||
*/
|
||||
public class BitInspectorException extends RuntimeException {
|
||||
|
||||
public BitInspectorException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public BitInspectorException(String msg, Exception e) {
|
||||
super(msg, e);
|
||||
}
|
||||
|
||||
public BitInspectorException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
}
|
32
src/main/java/org/nanoboot/bitinspector/core/Command.java
Normal file
32
src/main/java/org/nanoboot/bitinspector/core/Command.java
Normal file
@ -0,0 +1,32 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 pc00289
|
||||
*/
|
||||
public interface Command {
|
||||
public String getName();
|
||||
default void run(BitInspectorArgs bitInspectorArgs) {
|
||||
throw new BitInspectorException("Not yet implemented.");
|
||||
}
|
||||
|
||||
}
|
32
src/main/java/org/nanoboot/bitinspector/core/Constants.java
Normal file
32
src/main/java/org/nanoboot/bitinspector/core/Constants.java
Normal file
@ -0,0 +1,32 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author pc00289
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
public static final SimpleDateFormat YYYYMMDDHHMMSSZ_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");
|
||||
|
||||
}
|
60
src/main/java/org/nanoboot/bitinspector/core/Main.java
Executable file
60
src/main/java/org/nanoboot/bitinspector/core/Main.java
Executable file
@ -0,0 +1,60 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 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
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
199
src/main/java/org/nanoboot/bitinspector/core/Utils.java
Normal file
199
src/main/java/org/nanoboot/bitinspector/core/Utils.java
Normal file
@ -0,0 +1,199 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
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;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author pc00289
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
private static final String UNDERSCORE = "_";
|
||||
|
||||
private Utils() {
|
||||
//Not meant to be instantiated.
|
||||
}
|
||||
|
||||
public static String replaceUnderscoresBySpaces(String s) {
|
||||
if (!s.contains(UNDERSCORE)) {
|
||||
//nothing to do
|
||||
return s;
|
||||
}
|
||||
return s.replace(UNDERSCORE, " ");
|
||||
}
|
||||
|
||||
public static String makeFirstLetterUppercase(String s) {
|
||||
if (Character.isLetter(s.charAt(0)) && Character.isLowerCase(s.charAt(0))) {
|
||||
return Character.toUpperCase(s.charAt(0))
|
||||
+ (s.length() == 1 ? "" : s.substring(1));
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
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<>());
|
||||
}
|
||||
|
||||
private static List<File> listAllFilesInDir(File dir, List<File> files) {
|
||||
files.add(dir);
|
||||
for (File f : dir.listFiles()) {
|
||||
if (f.isDirectory()) {
|
||||
listAllFilesInDir(f, files);
|
||||
} else {
|
||||
files.add(f);
|
||||
}
|
||||
}
|
||||
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);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
throw new BitInspectorException("Copying file failed: " + originalFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeTextToFile(String text, File file) {
|
||||
FileWriter fileWriter;
|
||||
try {
|
||||
fileWriter = new FileWriter(file);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
throw new BitInspectorException("Writing to file failed: " + file.getName(), ex);
|
||||
}
|
||||
PrintWriter printWriter = new PrintWriter(fileWriter);
|
||||
printWriter.print(text);
|
||||
printWriter.close();
|
||||
}
|
||||
|
||||
public static String readTextFromFile(File file) {
|
||||
if (!file.exists()) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
return new String(Files.readAllBytes(Paths.get(file.getAbsolutePath())));
|
||||
} catch (IOException ex) {
|
||||
throw new BitInspectorException("Reading file failed: " + file.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static String readTextFromResourceFile(String fileName) {
|
||||
try {
|
||||
Class clazz = Main.class;
|
||||
InputStream inputStream = clazz.getResourceAsStream(fileName);
|
||||
return readFromInputStream(inputStream);
|
||||
} catch (IOException ex) {
|
||||
throw new BitInspectorException("Reading file failed: " + fileName, ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String readFromInputStream(InputStream inputStream)
|
||||
throws IOException {
|
||||
StringBuilder resultStringBuilder = new StringBuilder();
|
||||
try (BufferedReader br
|
||||
= new BufferedReader(new InputStreamReader(inputStream))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
resultStringBuilder.append(line).append("\n");
|
||||
}
|
||||
}
|
||||
return resultStringBuilder.toString();
|
||||
}
|
||||
|
||||
public static String calculateSHA512Hash(File file) {
|
||||
final Path path = Paths.get(file.getAbsolutePath());
|
||||
byte[] bytes;
|
||||
try {
|
||||
bytes = Files.readAllBytes(path);
|
||||
} catch (IOException 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;
|
||||
}
|
||||
}
|
44
src/main/java/org/nanoboot/bitinspector/entity/FsFile.java
Normal file
44
src/main/java/org/nanoboot/bitinspector/entity/FsFile.java
Normal file
@ -0,0 +1,44 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@ToString
|
||||
public class FsFile {
|
||||
private final String id;
|
||||
private String name;
|
||||
private String absolutePath;
|
||||
private String lastModificationDate;
|
||||
private String lastCheckDate;
|
||||
private String hashSumValue;
|
||||
private String hashSumAlgorithm;
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class SystemItem {
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
|
||||
}
|
1
src/main/java/org/nanoboot/bitinspector/lombok.config
Normal file
1
src/main/java/org/nanoboot/bitinspector/lombok.config
Normal file
@ -0,0 +1 @@
|
||||
lombok.log.fieldName=LOG
|
@ -0,0 +1,36 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.util.List;
|
||||
import org.nanoboot.bitinspector.entity.FsFile;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
public interface FileRepository {
|
||||
void create(List<FsFile> files);
|
||||
List<FsFile> list();
|
||||
void remove(FsFile file);
|
||||
void updateFile(FsFile file);
|
||||
void updateLastCheckDate(String lastCheckDate, List<FsFile> files);
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.util.List;
|
||||
import org.nanoboot.bitinspector.entity.SystemItem;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
public interface SystemItemRepository {
|
||||
String create(SystemItem systemItem);
|
||||
List<SystemItem> list();
|
||||
SystemItem read(String key);
|
||||
void remove(String key);
|
||||
void update(SystemItem systemItem);
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.impl.sqlite;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
public class Constants {
|
||||
static final String JDBC_URL = "jdbc:sqlite:" + "." + "/" + ".bir.sqlite3?foreign_keys=on;";
|
||||
private Constants() {
|
||||
//Not meant to be instantiated.
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,301 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.impl.sqlite;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.nanoboot.bitinspector.entity.FsFile;
|
||||
import org.nanoboot.bitinspector.persistence.api.FileRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
public class FileRepositoryImplSqlite implements FileRepository {
|
||||
|
||||
@Override
|
||||
public void create(List<FsFile> files) {
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (files.size() > 100) {
|
||||
List<FsFile> tmpList = new ArrayList<>();
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
FsFile e = files.get(i);
|
||||
tmpList.add(e);
|
||||
if (tmpList.size() >= 100) {
|
||||
create(tmpList);
|
||||
tmpList.clear();
|
||||
}
|
||||
}
|
||||
if (!tmpList.isEmpty()) {
|
||||
create(tmpList);
|
||||
tmpList.clear();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb
|
||||
.append("INSERT INTO ")
|
||||
.append(FileTable.TABLE_NAME)
|
||||
.append("(")
|
||||
.append(FileTable.ID).append(",")
|
||||
.append(FileTable.NAME).append(",")
|
||||
.append(FileTable.ABSOLUTE_PATH).append(",")
|
||||
.append(FileTable.LAST_MODIFICATION_DATE).append(",")
|
||||
.append(FileTable.LAST_CHECK_DATE).append(",")
|
||||
//
|
||||
.append(FileTable.HASH_SUM_VALUE).append(",")
|
||||
.append(FileTable.HASH_SUM_ALGORITHM);
|
||||
|
||||
sb.append(") VALUES ");
|
||||
|
||||
int index = 0;
|
||||
for (FsFile f : files) {
|
||||
sb.append(" (?,?,?,?,?, ?,?)");
|
||||
boolean lastFile = index == (files.size() - 1);
|
||||
if (!lastFile) {
|
||||
sb.append(",");
|
||||
}
|
||||
index = index + 1;
|
||||
}
|
||||
|
||||
String sql = sb.toString();
|
||||
System.err.println(sql);
|
||||
try (
|
||||
Connection connection = createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
int i = 0;
|
||||
|
||||
for (FsFile f : files) {
|
||||
stmt.setString(++i, f.getId());
|
||||
stmt.setString(++i, f.getName());
|
||||
stmt.setString(++i, f.getAbsolutePath());
|
||||
stmt.setString(++i, f.getLastModificationDate());
|
||||
//
|
||||
stmt.setString(++i, f.getLastCheckDate());
|
||||
//
|
||||
stmt.setString(++i, f.getHashSumValue());
|
||||
stmt.setString(++i, f.getHashSumAlgorithm());
|
||||
|
||||
}
|
||||
//
|
||||
stmt.execute();
|
||||
System.out.println(stmt.toString());
|
||||
|
||||
} catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Logger.getLogger(FileRepositoryImplSqlite.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FsFile> list() {
|
||||
|
||||
List<FsFile> result = new ArrayList<>();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb
|
||||
.append("SELECT * FROM ")
|
||||
.append(FileTable.TABLE_NAME);
|
||||
|
||||
String sql = sb.toString();
|
||||
System.err.println(sql);
|
||||
int i = 0;
|
||||
ResultSet rs = null;
|
||||
try (
|
||||
Connection connection = createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
|
||||
System.err.println(stmt.toString());
|
||||
rs = stmt.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
result.add(extractFileFromResultSet(rs));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Logger.getLogger(FileRepositoryImplSqlite.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} finally {
|
||||
try {
|
||||
if (rs != null) {
|
||||
rs.close();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(FileRepositoryImplSqlite.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(FsFile file) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb
|
||||
.append("DELETE FROM ")
|
||||
.append(FileTable.TABLE_NAME);
|
||||
sb.append(" WHERE ");
|
||||
|
||||
sb.append(FileTable.ID);
|
||||
sb.append("=?");
|
||||
String sql = sb.toString();
|
||||
System.err.println("SQL::" + sql);
|
||||
int i = 0;
|
||||
|
||||
try (
|
||||
Connection connection = createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
|
||||
stmt.setString(++i, file.getId());
|
||||
|
||||
System.err.println(stmt.toString());
|
||||
stmt.execute();
|
||||
|
||||
} catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Logger.getLogger(FileRepositoryImplSqlite.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Connection createConnection() throws ClassNotFoundException {
|
||||
return new SqliteConnectionFactory().createConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFile(FsFile file) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb
|
||||
.append("UPDATE ")
|
||||
.append(FileTable.TABLE_NAME)
|
||||
.append(" SET ")
|
||||
.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(" WHERE ").append(FileTable.ID).append("=?");
|
||||
|
||||
String sql = sb.toString();
|
||||
//System.err.println(sql);
|
||||
try (
|
||||
Connection connection = createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
int i = 0;
|
||||
stmt.setString(++i, file.getLastModificationDate());
|
||||
stmt.setString(++i, file.getLastCheckDate());
|
||||
stmt.setString(++i, file.getHashSumValue());
|
||||
stmt.setString(++i, file.getHashSumAlgorithm());
|
||||
|
||||
stmt.setString(++i, file.getId());
|
||||
|
||||
int numberOfUpdatedRows = stmt.executeUpdate();
|
||||
//System.out.println("numberOfUpdatedRows=" + numberOfUpdatedRows);
|
||||
} catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Logger.getLogger(FileRepositoryImplSqlite.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private FsFile extractFileFromResultSet(final ResultSet rs) throws SQLException {
|
||||
return new FsFile(
|
||||
rs.getString(FileTable.ID),
|
||||
rs.getString(FileTable.NAME),
|
||||
rs.getString(FileTable.ABSOLUTE_PATH),
|
||||
rs.getString(FileTable.LAST_MODIFICATION_DATE),
|
||||
rs.getString(FileTable.LAST_CHECK_DATE),
|
||||
rs.getString(FileTable.HASH_SUM_VALUE),
|
||||
rs.getString(FileTable.HASH_SUM_ALGORITHM)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLastCheckDate(String lastCheckDate, List<FsFile> files) {
|
||||
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (files.size() > 100) {
|
||||
List<FsFile> tmpList = new ArrayList<>();
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
FsFile e = files.get(i);
|
||||
tmpList.add(e);
|
||||
if (tmpList.size() >= 100) {
|
||||
updateLastCheckDate(lastCheckDate, tmpList);
|
||||
tmpList.clear();
|
||||
}
|
||||
}
|
||||
if (!tmpList.isEmpty()) {
|
||||
updateLastCheckDate(lastCheckDate, tmpList);
|
||||
tmpList.clear();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb
|
||||
.append("UPDATE ")
|
||||
.append(FileTable.TABLE_NAME)
|
||||
.append(" SET ")
|
||||
.append(FileTable.LAST_CHECK_DATE).append("=? ")
|
||||
.append(" WHERE ").append(FileTable.ID).append(" IN (");
|
||||
int index = 0;
|
||||
for (FsFile f : files) {
|
||||
index = index + 1;
|
||||
sb.append("?");
|
||||
if (index < files.size()) {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
|
||||
String sql = sb.toString();
|
||||
//System.err.println(sql);
|
||||
try (
|
||||
Connection connection = createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
int i = 0;
|
||||
|
||||
stmt.setString(++i, lastCheckDate);
|
||||
|
||||
for (FsFile f : files) {
|
||||
stmt.setString(++i, f.getId());
|
||||
}
|
||||
|
||||
int numberOfUpdatedRows = stmt.executeUpdate();
|
||||
//System.out.println("numberOfUpdatedRows=" + numberOfUpdatedRows);
|
||||
} catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Logger.getLogger(FileRepositoryImplSqlite.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.impl.sqlite;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
class FileTable {
|
||||
public static final String TABLE_NAME = "FILE";
|
||||
|
||||
public static final String ID = "ID";
|
||||
public static final String NAME = "NAME";
|
||||
public static final String ABSOLUTE_PATH = "ABSOLUTE_PATH";
|
||||
public static final String LAST_MODIFICATION_DATE = "LAST_MODIFICATION_DATE";
|
||||
public static final String LAST_CHECK_DATE = "LAST_CHECK_DATE";
|
||||
//
|
||||
public static final String HASH_SUM_VALUE = "HASH_SUM_VALUE";
|
||||
public static final String HASH_SUM_ALGORITHM = "HASH_SUM_ALGORITHM";
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.impl.sqlite;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
public class SqliteConnectionFactory {
|
||||
|
||||
public Connection createConnection() throws ClassNotFoundException {
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
|
||||
Connection conn = DriverManager.getConnection(Constants.JDBC_URL);
|
||||
|
||||
return conn;
|
||||
|
||||
} catch (SQLException ex) {
|
||||
if (true) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
System.err.println(ex.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.impl.sqlite;
|
||||
|
||||
import org.nanoboot.dbmigration.core.main.DBMigration;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
public class SqliteDatabaseMigration {
|
||||
|
||||
public void migrate() {
|
||||
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 clazz = this.getClass().getName();
|
||||
DBMigration dbMigration = DBMigration
|
||||
.configure()
|
||||
.dataSource(Constants.JDBC_URL)
|
||||
.installedBy("bitinspector-persistence-impl-sqlite")
|
||||
.name("bitinspector")
|
||||
.sqlDialect("sqlite", "org.nanoboot.dbmigration.core.persistence.impl.sqlite.DBMigrationPersistenceSqliteImpl")
|
||||
.sqlMigrationsClass(clazz)
|
||||
.load();
|
||||
dbMigration.migrate();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.impl.sqlite;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.nanoboot.bitinspector.entity.SystemItem;
|
||||
import org.nanoboot.bitinspector.persistence.api.SystemItemRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
public class SystemItemRepositoryImplSqlite implements SystemItemRepository {
|
||||
|
||||
@Override
|
||||
public String create(SystemItem systemItem) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb
|
||||
.append("INSERT INTO ")
|
||||
.append(SystemItemTable.TABLE_NAME)
|
||||
.append("(")
|
||||
.append(SystemItemTable.KEY).append(",")
|
||||
//
|
||||
.append(SystemItemTable.VALUE);
|
||||
|
||||
sb.append(")")
|
||||
.append(" VALUES (?,?)");
|
||||
|
||||
String sql = sb.toString();
|
||||
System.err.println(sql);
|
||||
try (
|
||||
Connection connection = new SqliteConnectionFactory().createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
int i = 0;
|
||||
stmt.setString(++i, systemItem.getKey());
|
||||
stmt.setString(++i, systemItem.getValue());
|
||||
|
||||
//
|
||||
stmt.execute();
|
||||
System.out.println(stmt.toString());
|
||||
|
||||
return systemItem.getKey();
|
||||
|
||||
} catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Logger.getLogger(SystemItemRepositoryImplSqlite.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
System.err.println("Error.");
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SystemItem> list() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
|
||||
}
|
||||
|
||||
@Override
|
||||
public SystemItem read(String key) {
|
||||
if (key == null) {
|
||||
throw new RuntimeException("key is null");
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb
|
||||
.append("SELECT * FROM ")
|
||||
.append(SystemItemTable.TABLE_NAME)
|
||||
.append(" WHERE ")
|
||||
.append(SystemItemTable.KEY)
|
||||
.append("=?");
|
||||
|
||||
String sql = sb.toString();
|
||||
int i = 0;
|
||||
ResultSet rs = null;
|
||||
try (
|
||||
Connection connection = new SqliteConnectionFactory().createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
|
||||
|
||||
stmt.setString(++i, key);
|
||||
|
||||
rs = stmt.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
return extractSystemItemFromResultSet(rs);
|
||||
}
|
||||
return new SystemItem(key, null);
|
||||
} catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Logger.getLogger(SystemItemRepositoryImplSqlite.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} finally {
|
||||
try {
|
||||
if (rs != null) {
|
||||
rs.close();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(SystemItemRepositoryImplSqlite.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String key) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(SystemItem systemItem) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
|
||||
}
|
||||
|
||||
private SystemItem extractSystemItemFromResultSet(final ResultSet rs) throws SQLException {
|
||||
return new SystemItem(
|
||||
rs.getString(SystemItemTable.KEY),
|
||||
rs.getString(SystemItemTable.VALUE)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.impl.sqlite;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author robertvokac
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
class SystemItemTable {
|
||||
public static final String TABLE_NAME = "SYSTEM_ITEM";
|
||||
|
||||
public static final String KEY = "KEY";
|
||||
public static final String VALUE = "VALUE";
|
||||
|
||||
}
|
0
src/main/resources/.gitkeep
Normal file
0
src/main/resources/.gitkeep
Normal file
@ -0,0 +1,14 @@
|
||||
CREATE TABLE "FILE" (
|
||||
"ID" TEXT,
|
||||
"NAME" TEXT NOT NULL,
|
||||
"ABSOLUTE_PATH" TEXT NOT NULL,
|
||||
"LAST_MODIFICATION_DATE" TEXT NOT NULL,
|
||||
"LAST_CHECK_DATE" TEXT NOT NULL,
|
||||
"HASH_SUM_VALUE" TEXT NOT NULL,
|
||||
"HASH_SUM_ALGORITHM" TEXT NOT NULL,
|
||||
UNIQUE(ABSOLUTE_PATH),
|
||||
PRIMARY KEY("ID")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IDX_FILE_ABSOLUTE_PATH
|
||||
ON FILE (ABSOLUTE_PATH);
|
@ -0,0 +1,6 @@
|
||||
CREATE TABLE "SYSTEM_ITEM" (
|
||||
"KEY" TEXT,
|
||||
"VALUE" TEXT NOT NULL,
|
||||
PRIMARY KEY("KEY")
|
||||
)
|
||||
|
5
src/main/resources/log4j2.properties
Normal file
5
src/main/resources/log4j2.properties
Normal file
@ -0,0 +1,5 @@
|
||||
appender.console.type = Console
|
||||
appender.console.name = STDOUT
|
||||
appender.console.layout.type = PatternLayout
|
||||
appender.console.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
|
||||
rootLogger=info, STDOUT
|
0
src/test/java/org/nanoboot/bitinspector/.gitkeep
Normal file
0
src/test/java/org/nanoboot/bitinspector/.gitkeep
Normal file
Loading…
x
Reference in New Issue
Block a user