Skip to content

Commit 64aad0e

Browse files
committed
Somewhat finished state
1 parent 1fab979 commit 64aad0e

3 files changed

Lines changed: 108 additions & 141 deletions

File tree

File-Integrity-Scanner/src/main/java/org/pwss/file_integrity_scanner/component/DirectoryTraverser.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,8 @@ public class DirectoryTraverser {
2626
*
2727
* @param directoryPath the path of the directory to scan
2828
* @return a Future containing the list of files found in the directory
29-
* @throws ExecutionException if an error occurs during the asynchronous file traversal
30-
* @throws InterruptedException if the thread executing the file traversal is interrupted
3129
*/
32-
public final Future<List<File>> collectFilesInDirectory(String directoryPath)
33-
throws ExecutionException, InterruptedException {
30+
public final Future<List<File>> collectFilesInDirectory(String directoryPath) {
3431
FileTraverserImpl traverser = new FileTraverserImpl();
3532
return traverser.traverse(directoryPath);
3633
}

File-Integrity-Scanner/src/main/java/org/pwss/file_integrity_scanner/msr/service/scan/ScanService.java

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package org.pwss.file_integrity_scanner.msr.service.scan;
22

3-
import org.pwss.file_integrity_scanner.msr.domain.model.entities.scan.Scan;
3+
import org.pwss.file_integrity_scanner.msr.domain.model.entities.monitored_directory.MonitoredDirectory;
44

55
/**
66
* Service interface for managing directory scans.
@@ -17,26 +17,14 @@ public interface ScanService {
1717
void scanAllDirectories();
1818

1919
/**
20-
* Scans a monitored directory using the provided scan instance.
20+
* Initiates scanning of a single monitored directory.
2121
* <p>
22-
* This method is an overloaded variant that calls the two-parameter method with
23-
* default value set to true for
24-
* includeSubFolders.
22+
* This method starts the scanning process for the specified monitored directory.
23+
* It ensures that only the provided directory is scanned, rather than all monitored directories.
2524
*
26-
* @param scanInstance the scan instance used for scanning the directory
27-
* @return true if the monitored directory scan is successful, false otherwise
25+
* @param monitoredDirectory the monitored directory to be scanned
2826
*/
29-
Boolean scanMonitoredDirectory(Scan scanInstance);
30-
31-
/**
32-
* Scans a monitored directory using the provided scan instance.
33-
*
34-
* @param scanInstance the scan instance used for scanning the directory
35-
* @param includeSubFolders whether to include subfolders in the scan (default
36-
* is false)
37-
* @return true if the monitored directory scan is successful, false otherwise
38-
*/
39-
Boolean scanMonitoredDirectory(Scan scanInstance, boolean includeSubFolders);
27+
void scanSingleDirectory(MonitoredDirectory monitoredDirectory);
4028

4129
/**
4230
* Stops any ongoing scans.

File-Integrity-Scanner/src/main/java/org/pwss/file_integrity_scanner/msr/service/scan/ScanServiceImpl.java

Lines changed: 101 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.time.ZoneOffset;
2828
import java.time.format.DateTimeFormatter;
2929
import java.util.List;
30+
import java.util.Optional;
3031
import java.util.concurrent.ConcurrentHashMap;
3132
import java.util.concurrent.ConcurrentMap;
3233
import java.util.concurrent.ExecutionException;
@@ -114,7 +115,7 @@ public void scanAllDirectories() {
114115
Future<List<File>> futureFiles = scanDirectoryAsync(dir.getPath());
115116
activeScanTasks.put(dir.getPath(), new ScanTaskState(futureFiles, scan));
116117
} else { // If not, scan only the top-level files
117-
// TODO: Handle non subdirectory scans in a nice manner :D
118+
scanTopLevelDirectory(scan);
118119
}
119120

120121
}
@@ -123,14 +124,75 @@ public void scanAllDirectories() {
123124
}
124125
}
125126

127+
@Override
128+
public void scanSingleDirectory(MonitoredDirectory dir) {
129+
if (!dir.getIsActive()) {
130+
log.warn("Monitored directory {} is not active. Skipping scan.", dir.getPath());
131+
return;
132+
}
133+
134+
Scan scan = new Scan();
135+
scan.setMonitoredDirectory(dir);
136+
scan.setScanTime(OffsetDateTime.now());
137+
scan.setStatus(ScanStatus.IN_PROGRESS.toString());
138+
139+
repository.save(scan);
140+
141+
// If scan should include monitored directory subdirectories
142+
if (dir.getIncludeSubdirectories()) {
143+
// Add the scan to active tasks for monitoring
144+
Future<List<File>> futureFiles = scanDirectoryAsync(dir.getPath());
145+
activeScanTasks.put(dir.getPath(), new ScanTaskState(futureFiles, scan));
146+
} else { // If not, scan only the top-level files
147+
scanTopLevelDirectory(scan);
148+
}
149+
}
150+
126151
/**
127-
* Asynchronously scans a directory and its subdirectories( if specified)to retrieve a list of files.
152+
* Scans the top-level directory for files and processes them.
153+
* <p>
154+
* This method retrieves the top-level files in the monitored directory associated
155+
* with the given scan instance. If files are found, it processes them and finalizes
156+
* the scan task. If no files are found, the scan is marked as failed. Any exceptions
157+
* during the process are logged.
128158
*
129-
* @param directoryPath the path of the directory to scan
159+
* @param scanInstance the scan instance associated with the directory to be scanned
160+
*/
161+
@Async
162+
private void scanTopLevelDirectory(Scan scanInstance) {
163+
final MonitoredDirectory mDirectory = scanInstance.getMonitoredDirectory();
164+
final File file;
165+
166+
try {
167+
file = new File(mDirectory.getPath());
168+
Optional<List<File>> topLevelFiles = directoryTraverser.collectTopLevelFiles(file);
169+
if (topLevelFiles.isPresent()) {
170+
log.info("Found {} top-level files in directory: {}", topLevelFiles.get().size(), mDirectory.getPath());
171+
if (finalizeScanTask(scanInstance, topLevelFiles.get())) {
172+
log.info("Scan top-level completed successfully for directory: {}", mDirectory.getPath());
173+
} else {
174+
log.warn("Scan top-level was not completed successfully for directory: {}", mDirectory.getPath());
175+
}
176+
} else {
177+
log.warn("No top-level files found in directory: {}", mDirectory.getPath());
178+
scanInstance.setStatus(ScanStatus.FAILED.toString());
179+
repository.save(scanInstance);
180+
}
181+
} catch (ExecutionException e) {
182+
log.error("ExecutionException while scanning top-level directory {}: {}", mDirectory.getPath(), e.getMessage());
183+
} catch (InterruptedException e) {
184+
log.error("InterruptedException while scanning top-level directory {}: {}", mDirectory.getPath(), e.getMessage());
185+
}// Shouldn't reach here under normal execution
186+
}
187+
188+
/**
189+
* Asynchronously scans a directory and its subdirectories to retrieve a list of files.
190+
*
191+
* @param directoryPath the path of the directory to scan
130192
* @return a Future containing the list of files found in the directory
131193
*/
132194
@Async
133-
private Future<List<File>> scanDirectoryAsync(String directoryPath) throws ExecutionException, InterruptedException {
195+
private Future<List<File>> scanDirectoryAsync(String directoryPath) {
134196
return directoryTraverser.collectFilesInDirectory(directoryPath);
135197
}
136198

@@ -144,7 +206,7 @@ private Future<List<File>> scanDirectoryAsync(String directoryPath) throws Execu
144206
* If a scan is still in progress, it logs the status.
145207
*/
146208
@Scheduled(fixedDelay = 5000)
147-
public void monitorAsyncScans() {
209+
public void monitorOngoingScanTasks() {
148210
if (activeScanTasks.isEmpty()) {
149211
log.info("No active scan tasks to process.");
150212
return;
@@ -156,10 +218,17 @@ public void monitorAsyncScans() {
156218

157219
if (future.isDone()) {
158220
log.info("Traversing completed for directory: {}", dirPath);
159-
if (completeScanTask(task)) {
160-
log.info("Scan completed successfully for directory: {}", dirPath);
161-
} else {
162-
log.warn("Scan was not completed successfully for directory: {}", dirPath);
221+
try {
222+
List<File> files = future.get(); // Non-blocking since we check if the future is done
223+
if (finalizeScanTask(task.scan(), files)) {
224+
log.info("Scan recursive completed successfully for directory: {}", dirPath);
225+
} else {
226+
log.warn("Scan recursive was not completed successfully for directory: {}", dirPath);
227+
}
228+
} catch (InterruptedException e) {
229+
log.error("Scan interrupted for directory {}: {}", dirPath, e.getMessage());
230+
} catch (ExecutionException e) {
231+
log.error("Execution exception while completing scan for directory {}: {}", dirPath, e.getMessage());
163232
}
164233
activeScanTasks.remove(dirPath);
165234
} else {
@@ -169,44 +238,40 @@ public void monitorAsyncScans() {
169238
}
170239

171240
/**
172-
* Completes the scan process for a given scan task state.
241+
* Finalizes the scan task for a given scan instance and list of files.
173242
* <p>
174-
* This method retrieves the list of files from the completed scan task and processes each file.
175-
* If a stop request is detected, the scan is marked as cancelled. Otherwise, the scan is marked
176-
* as completed, and the baseline is established for the monitored directory if it has not been set.
177-
* <p>
178-
* Any errors during processing are logged, and the scan is marked as failed. The updated scan
179-
* status is saved to the repository at the end of the method. The task is removed from the active
180-
* scan tasks map regardless of success or failure.
243+
* This method processes each file in the provided list, updates the scan status,
244+
* and establishes a baseline for the monitored directory if necessary. If a stop
245+
* request is detected, the scan is marked as cancelled. In case of errors during
246+
* processing, the scan is marked as failed. Regardless of the outcome, the task
247+
* is removed from the active scan tasks map.
181248
*
182-
* @param scanTaskState the state of the scan task to process, containing the scan and its future result
249+
* @param scanInstance the scan instance associated with the task
250+
* @param files the list of files to process
183251
* @return true if the scan was successfully completed, false otherwise
184252
*/
185253
@Async
186-
private boolean completeScanTask(ScanTaskState scanTaskState) {
187-
String dirPath = scanTaskState.scan().getMonitoredDirectory().getPath();
188-
Scan scan = scanTaskState.scan();
254+
private boolean finalizeScanTask(Scan scanInstance, List<File> files) {
255+
String dirPath = scanInstance.getMonitoredDirectory().getPath();
189256

190257
try {
191258
// Retrieve the list of files from the completed scan
192-
List<File> files = scanTaskState.future().get(); // Non-blocking since the future is done.
193-
194259
for (File file : files) {
195260
if (stopRequested) {
196261
break;// Exit if stop is requested
197262
}
198263
// Process each file found in the directory and its subdirectories
199-
processFile(file, scanTaskState.scan());
264+
processFile(file, scanInstance);
200265
}
201266

202267
if (stopRequested) {
203268
// Mark the scan as cancelled if a stop was requested
204-
scan.setStatus(ScanStatus.CANCELLED.toString());
205-
repository.save(scan);
269+
scanInstance.setStatus(ScanStatus.CANCELLED.toString());
270+
repository.save(scanInstance);
206271
return false; // Scan Stopped / Not complete (no baseline)
207272
} else {
208-
MonitoredDirectory dir = scan.getMonitoredDirectory();
209-
scan.setStatus(ScanStatus.COMPLETED.toString());
273+
MonitoredDirectory dir = scanInstance.getMonitoredDirectory();
274+
scanInstance.setStatus(ScanStatus.COMPLETED.toString());
210275

211276
// If the Baseline has not yet been established and the Scan was Successful
212277
if (!dir.getBaselineEstablished()) {
@@ -217,23 +282,25 @@ private boolean completeScanTask(ScanTaskState scanTaskState) {
217282
log.info("Baseline already established for directory: {}", dirPath);
218283
}
219284
log.info("Completed scan for directory {}", dirPath);
220-
repository.save(scan);
285+
repository.save(scanInstance);
221286

222287
return true; // Successful Scan
223288
}
224289

225290
} catch (Exception e) {
226291
// Handle errors during scan processing
227292
log.error("Scan Failed {} - Start Time {} - End Time {}", e.getMessage(),
228-
scan.getScanTime().format(timeAndDateStringForLogFormat),
293+
scanInstance.getScanTime().format(timeAndDateStringForLogFormat),
229294
OffsetDateTime.now().format(timeAndDateStringForLogFormat));
230295

231-
scan.setStatus(ScanStatus.FAILED.toString());
232-
repository.save(scan);
296+
scanInstance.setStatus(ScanStatus.FAILED.toString());
297+
repository.save(scanInstance);
233298
} finally {
234299
// Remove the task from active tasks regardless of success or failure
235-
activeScanTasks.remove(dirPath);
236-
log.info("Removed scan task for directory: {}", dirPath);
300+
if (activeScanTasks.containsKey(dirPath)) {
301+
activeScanTasks.remove(dirPath);
302+
log.info("Removed scan task for directory: {}", dirPath);
303+
}
237304
}
238305
return false; // Shouldn't reach here under normal execution
239306
}
@@ -314,89 +381,4 @@ public void stopScan() {
314381
stopRequested = true;
315382
log.info("Scan stop requested. Will stop after current file processing.");
316383
}
317-
318-
@Override
319-
public Boolean scanMonitoredDirectory(Scan scanInstance) {
320-
return scanMonitoredDirectory(scanInstance, true);
321-
}
322-
323-
@Override
324-
public Boolean scanMonitoredDirectory(Scan scanInstance, boolean includeSubFolders) {
325-
//
326-
//final MonitoredDirectory mDirectory;
327-
//
328-
//mDirectory = scanInstance.getMonitoredDirectory();
329-
//if (includeSubFolders) {
330-
//
331-
// // Regular scan
332-
//
333-
// if (completeScan(scanInstance)) {
334-
//
335-
// log.info("Scan Successful for Monitored Directory {}", mDirectory.getPath());
336-
// scanInstance.setStatus(ScanStatus.COMPLETED.toString());
337-
//
338-
// // If the Baseline has not yet been established and the Scan was Successful
339-
// if (!mDirectory.getBaselineEstablished()) {
340-
// mDirectory.setBaselineEstablished(true);
341-
// monitoredDirectoryService.save(mDirectory);
342-
// }
343-
//
344-
// // Save scanInstance in the persistence layer
345-
// this.repository.save(scanInstance);
346-
// return true; // OK Scan :)
347-
//
348-
// } else {
349-
//
350-
// log.error("Scan failed for Monitored Directory {}", mDirectory.getPath());
351-
//
352-
// // An added Note that is saved to the persistence layer
353-
// mDirectory.setNotes(ScanStatus.FAILED.toString());
354-
// monitoredDirectoryService.save(mDirectory);
355-
// this.repository.save(scanInstance);
356-
// return false;
357-
// }
358-
//
359-
//}
360-
//
361-
//// No Subfolders
362-
//else {
363-
//
364-
// final File file;
365-
//
366-
// try {
367-
//
368-
// file = new File(mDirectory.getPath());
369-
// log.debug("Created new entity - scanMonitoredDirectory - In No Subfolders If Block - Path {}",
370-
// file.getAbsolutePath());
371-
// Optional<List<File>> topLevelFiles = directoryTraverser.collectTopLevelFiles(file);
372-
//
373-
// if (topLevelFiles.isPresent()) {
374-
//
375-
// topLevelFiles.get().stream().forEach(tp -> processFile(tp, scanInstance));
376-
//
377-
// scanInstance.setStatus(ScanStatus.COMPLETED.toString());
378-
// // Save scanInstance in the persistence layer
379-
// this.repository.save(scanInstance);
380-
// return true; // OK Scan :)
381-
// } else {
382-
// scanInstance.setStatus(ScanStatus.FAILED.toString());
383-
// // Save scanInstance in the persistence layer
384-
// this.repository.save(scanInstance);
385-
// return false; // No Top Files Present - Scan Failed
386-
// }
387-
// } catch (ExecutionException executingException) {
388-
//
389-
// log.error("ExecutionException in scanMonitoredDirectory - {}", executingException);
390-
// } catch (InterruptedException interruptedException) {
391-
//
392-
// log.error("InterruptedException in scanMonitoredDirectory", interruptedException.getMessage());
393-
// } catch (Exception exception) {
394-
//
395-
// log.error("Generic Exception in scanMonitoredDirectory", exception.getMessage());
396-
// }
397-
//
398-
//}
399-
//// Fallback return - this should not be reached under normal execution
400-
return false;
401-
}
402384
}

0 commit comments

Comments
 (0)