package jetbrains.buildServer.tools;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class TempFiles {
private static final File ourCurrentTempDir = new File(System.getProperty("java.io.tmpdir"));
private final File myCurrentTempDir;
private static Random ourRandom;
static {
//Enforce java.io.File to cache system property value java.io.tmpdir in order
//to workaround build agent atempt to clean agent's agentTmp dir that is
//set to java.io.tmpdir system property while build agent is runing.
try {
//noinspection ResultOfMethodCallIgnored
File.createTempFile("magic", "enforce to cache").delete();
} catch (IOException e) {
e.printStackTrace();
}
ourRandom = new Random();
ourRandom.setSeed(System.currentTimeMillis());
}
private final List<File> myFilesToDelete = new ArrayList<File>();
public TempFiles() {
myCurrentTempDir = ourCurrentTempDir;
if (!myCurrentTempDir.isDirectory()) {
throw new IllegalStateException("Temp directory is not a directory, was deleted by some process: " + myCurrentTempDir.getAbsolutePath());
}
}
private File doCreateTempDir(@Nullable String prefix, @Nullable String suffix) throws IOException {
prefix = prefix == null ? "" : prefix;
suffix = suffix == null ? ".tmp" : suffix;
do {
int count = ourRandom.nextInt();
final File f = new File(myCurrentTempDir, prefix + count + suffix);
if (!f.exists() && f.mkdirs()) {
return f.getCanonicalFile();
}
} while (true);
}
private File doCreateTempFile(String prefix, @Nullable String suffix) throws IOException {
final File file = doCreateTempDir(prefix, suffix);
file.delete();
file.createNewFile();
return file;
}
public final File createTempFile() throws IOException {
File tempFile = doCreateTempFile("test", null);
registerAsTempFile(tempFile);
return tempFile;
}
public void registerAsTempFile(final File tempFile) {
myFilesToDelete.add(tempFile);
}
public final File createTempFile(int size) throws IOException {
File tempFile = createTempFile();
int bufLen = Math.min(8 * 1024, size);
if (bufLen == 0) return tempFile;
FileOutputStream fos = new FileOutputStream(tempFile);
try {
byte[] buf = new byte[bufLen];
for (int i=0; i < buf.length; i++) {
buf[i] = (byte)Math.round(Math.random()*128);
}
int numWritten = 0;
for (int i=0; i<size / buf.length; i++) {
fos.write(buf);
numWritten += buf.length;
}
if (size > numWritten) {
fos.write(buf, 0, size - numWritten);
}
} finally {
fos.close();
}
return tempFile;
}
/**
* Returns a File object for created temp directory.
* Also stores the value into this object accessed with {@link #getCurrentTempDir()}
*
* @return a File object for created temp directory
* @throws IOException if directory creation fails.
*/
public final File createTempDir() throws IOException {
File f = doCreateTempDir("test", "");
registerAsTempFile(f);
return f;
}
/**
* Returns the current directory used by the test or null if no test is running or no directory is created yet.
*
* @return see above
*/
@Nullable
public File getCurrentTempDir() {
return myCurrentTempDir;
}
public void cleanup() {
for (File file : myFilesToDelete) {
if (file.exists()) {
delete(file);
}
}
myFilesToDelete.clear();
}
public void delete(@NotNull final File file) {
if (!file.exists()) return;
if (file.isDirectory()) {
final File[] files = file.listFiles();
if (files != null) {
for (File child : files) {
delete(child);
}
}
}
for(int i =0; i < 10; i++) {
//noinspection ResultOfMethodCallIgnored
file.delete();
if (!file.exists()) break;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
//NOP
}
}
}
}