package com.milaboratory.util;
import org.apache.commons.io.FileUtils;
import org.apache.commons.math3.random.RandomDataGenerator;
import org.apache.commons.math3.random.Well44497b;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.security.SecureRandom;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
public class TempFileManager {
private static volatile String prefix = "milib_";
private static final AtomicBoolean initialized = new AtomicBoolean(false);
static final ConcurrentHashMap<String, File> createdFiles = new ConcurrentHashMap<>();
private static final RandomDataGenerator privateRandom = new RandomDataGenerator(new Well44497b());
public static void setPrefix(String prefix) {
TempFileManager.prefix = prefix;
}
public static void seed(long seed) {
synchronized ( privateRandom ){
privateRandom.getRandomGenerator().setSeed(seed);
}
}
private static void ensureInitialized() {
if (initialized.compareAndSet(false, true)) {
// Adding delete files shutdown hook on the very firs execution of getTempFile()
Runtime.getRuntime().addShutdownHook(new Thread(new RemoveAction(), "DeleteTempFiles"));
seed(System.nanoTime() + 17 * (new SecureRandom()).nextLong());
}
}
public static File getTempFile() {
try {
ensureInitialized();
File file;
String name;
do {
synchronized ( privateRandom ){
name = prefix + privateRandom.nextHexString(40);
}
file = Files.createTempFile(name, null).toFile();
} while (createdFiles.putIfAbsent(name, file) != null);
if (file.length() != 0)
throw new RuntimeException();
return file;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static File getTempDir() {
try {
ensureInitialized();
File dir;
String name;
do {
synchronized ( privateRandom ){
name = prefix + privateRandom.nextHexString(40);
}
dir = Files.createTempDirectory(name).toFile();
} while (createdFiles.putIfAbsent(name, dir) != null);
return dir;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static final class RemoveAction implements Runnable {
@Override
public void run() {
for (File file : createdFiles.values()) {
if (file.exists()) {
try {
if (Files.isDirectory(file.toPath()))
FileUtils.deleteDirectory(file);
else
file.delete();
} catch (Exception e) {
}
}
}
}
}
}