bug 59788: create temporary directories

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1751177 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Javen O'Neal 2016-07-03 22:58:06 +00:00
parent 15cbc2684e
commit e3f4061bc8
3 changed files with 97 additions and 15 deletions

View File

@ -19,6 +19,7 @@ package org.apache.poi.util;
import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
/**
* Interface for creating temporary files. Collects them all into one directory by default.
@ -29,6 +30,10 @@ public final class TempFile {
/** Define a constant for this property as it is sometimes mistypes as "tempdir" otherwise */
public static final String JAVA_IO_TMPDIR = "java.io.tmpdir";
private TempFile() {
// no instances of this class
}
/**
* Configures the strategy used by {@link #createTempFile(String, String)} to create the temporary files.
@ -62,6 +67,10 @@ public final class TempFile {
return strategy.createTempFile(prefix, suffix);
}
public static File createTempDirectory(String name) throws IOException {
return strategy.createTempDirectory(name);
}
/**
* Default implementation of the {@link TempFileCreationStrategy} used by {@link TempFile}:
* Files are collected into one directory and by default are deleted on exit from the VM.
@ -92,9 +101,9 @@ public final class TempFile {
this.dir = dir;
}
@Override
public File createTempFile(String prefix, String suffix) throws IOException {
private void createPOIFilesDirectory() throws IOException {
// Identify and create our temp dir, if needed
// The directory is not deleted, even if it was created by this TempFleCreationStrategy
if (dir == null) {
String tmpDir = System.getProperty(JAVA_IO_TMPDIR);
if (tmpDir == null) {
@ -102,10 +111,20 @@ public final class TempFile {
}
dir = new File(tmpDir, "poifiles");
}
if (!(dir.exists() || dir.mkdirs()) || !dir.isDirectory()) {
throw new IOException("Could not create temporary directory '" + dir + "'");
createTempDirectory(dir);
}
private void createTempDirectory(File directory) throws IOException {
if (!(directory.exists() || directory.mkdirs()) || !directory.isDirectory()) {
throw new IOException("Could not create temporary directory '" + directory + "'");
}
}
@Override
public File createTempFile(String prefix, String suffix) throws IOException {
// Identify and create our temp dir, if needed
createPOIFilesDirectory();
// Generate a unique new filename
File newFile = File.createTempFile(prefix, suffix, dir);
@ -118,5 +137,26 @@ public final class TempFile {
// All done
return newFile;
}
private static final SecureRandom random = new SecureRandom();
@Override
public File createTempDirectory(String prefix) throws IOException {
// Identify and create our temp dir, if needed
createPOIFilesDirectory();
// Generate a unique new filename
// FIXME: Java 7+: use java.nio.Files#createTempDirectory
final long n = random.nextLong();
File newDirectory = new File(dir, prefix + Long.toString(n));
createTempDirectory(newDirectory);
// Set the delete on exit flag, unless explicitly disabled
if (System.getProperty("poi.keep.tmp.files") == null) {
newDirectory.deleteOnExit();
}
// All done
return newDirectory;
}
}
}

View File

@ -35,4 +35,15 @@ public interface TempFileCreationStrategy {
* @throws IOException If no temporary file could be created.
*/
File createTempFile(String prefix, String suffix) throws IOException;
/**
* Creates a new and empty temporary directory.
*
* @param prefix The directory name to be used to generate the name of the temporary directory.
*
* @return The path to the newly created and empty temporary directory.
*
* @throws IOException If no temporary directory could be created.
*/
File createTempDirectory(String prefix) throws IOException;
}

View File

@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileOutputStream;
@ -29,12 +30,16 @@ import java.util.Arrays;
import org.apache.poi.poifs.dev.TestPOIFSDump;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class TestTempFile {
private String previousTempDir;
private File tempDir;
@Rule
public ExpectedException thrown = ExpectedException.none();
@Before
public void setUp() throws IOException {
@ -78,29 +83,54 @@ public class TestTempFile {
}
@Test
public void testCreateTempFile() throws Exception
public void testCreateTempFile() throws IOException
{
File tempFile = TempFile.createTempFile("test", ".txt");
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(1);
fos.write(1); //file can be written to
fos.close();
assertTrue(tempFile.exists());
assertEquals("poifiles", tempFile.getParentFile().getName());
assertTrue("temp file exists", tempFile.exists());
assertTrue("temp file is a file", tempFile.isFile());
assertTrue("temp file's name should start with test",
tempFile.getName().startsWith("test"));
assertTrue("temp file's name should end with .txt",
tempFile.getName().endsWith(".txt"));
assertEquals("temp file is saved in poifiles directory",
"poifiles", tempFile.getParentFile().getName());
// Can't think of a good way to check whether a file is actually deleted since it would require the VM to stop.
assertTrue(tempFile.delete());
// Solution: set TempFileCreationStrategy to something that the unit test can trigger a deletion"
assertTrue("Unable to delete temp file", tempFile.delete());
}
@Test
public void testConstructor() {
// can currently be constructed...
new TempFile();
public void createTempFileWithDefaultSuffix() throws IOException {
File tempFile = TempFile.createTempFile("test", null);
assertTrue("temp file's name should end with .tmp",
tempFile.getName().endsWith(".tmp"));
}
@Test(expected=IllegalArgumentException.class)
@Test
public void testCreateTempDirectory() throws IOException
{
File tempDir = TempFile.createTempDirectory("testDir");
assertTrue("testDir exists", tempDir.exists());
assertTrue("testDir is a directory", tempDir.isDirectory());
assertTrue("testDir's name starts with testDir",
tempDir.getName().startsWith("testDir"));
assertEquals("tempDir is saved in poifiles directory",
"poifiles", tempDir.getParentFile().getName());
// Can't think of a good way to check whether a directory is actually deleted since it would require the VM to stop.
// Solution: set TempFileCreationStrategy to something that the unit test can trigger a deletion"
assertTrue("Unable to delete tempDir", tempDir.delete());
}
@Test
public void testSetTempFileCreationStrategy() throws IOException {
TempFile.setTempFileCreationStrategy(new TempFile.DefaultTempFileCreationStrategy());
// Should be able to create two tempfiles with same prefix and suffix
File file1 = TempFile.createTempFile("TestTempFile", ".tst");
File file2 = TempFile.createTempFile("TestTempFile", ".tst");
assertFalse(file1.equals(file2));
@ -109,6 +139,7 @@ public class TestTempFile {
assertNotNull(file1);
assertTrue(file1.delete());
thrown.expect(IllegalArgumentException.class);
TempFile.setTempFileCreationStrategy(null);
}
}