DeleteOnShutdown.java
/*
* SPDX-FileCopyrightText: none
* SPDX-License-Identifier: CC0-1.0
*/
package gov.nist.secauto.metaschema.core.util;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Used to perform cleanup on shutdown.
*/
@SuppressWarnings("PMD.DoNotUseThreads")
public final class DeleteOnShutdown {
private static Set<Path> paths = new LinkedHashSet<>();
private static final Lock LOCK = new ReentrantLock();
static {
Runtime.getRuntime().addShutdownHook(
new Thread(DeleteOnShutdown::shutdownHook));
}
@SuppressWarnings("PMD.NullAssignment")
private static void shutdownHook() {
LOCK.lock();
try {
Set<Path> localSet = new LinkedHashSet<>(paths);
paths = null;
localSet.forEach(path -> {
try {
Files.walkFileTree(path,
new SimpleFileVisitor<>() {
@Override
public FileVisitResult postVisitDirectory(
Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(
Path file, BasicFileAttributes attrs)
throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException ex) {
// this is a best effort
}
});
} finally {
LOCK.unlock();
}
}
/**
* Register a new path to be deleted on JVM termination.
* <p>
* If the path is a directory, then its contents will also be deleted.
*
* @param path
* the path to delete
*/
public static void register(Path path) {
LOCK.lock();
try {
if (paths == null) {
throw new IllegalStateException("ShutdownHook already in progress.");
}
paths.add(path);
} finally {
LOCK.unlock();
}
}
private DeleteOnShutdown() {
// disable construction
}
}