Home | History | Annotate | Download | only in rules
      1 package org.junit.rules;
      2 
      3 import java.io.File;
      4 import java.io.IOException;
      5 
      6 import org.junit.Rule;
      7 
      8 /**
      9  * The TemporaryFolder Rule allows creation of files and folders that should
     10  * be deleted when the test method finishes (whether it passes or
     11  * fails). Whether the deletion is successful or not is not checked by this rule.
     12  * No exception will be thrown in case the deletion fails.
     13  *
     14  * <p>Example of usage:
     15  * <pre>
     16  * public static class HasTempFolder {
     17  *  &#064;Rule
     18  *  public TemporaryFolder folder= new TemporaryFolder();
     19  *
     20  *  &#064;Test
     21  *  public void testUsingTempFolder() throws IOException {
     22  *      File createdFile= folder.newFile(&quot;myfile.txt&quot;);
     23  *      File createdFolder= folder.newFolder(&quot;subfolder&quot;);
     24  *      // ...
     25  *     }
     26  * }
     27  * </pre>
     28  *
     29  * @since 4.7
     30  */
     31 public class TemporaryFolder extends ExternalResource {
     32     private final File parentFolder;
     33     private File folder;
     34 
     35     public TemporaryFolder() {
     36         this(null);
     37     }
     38 
     39     public TemporaryFolder(File parentFolder) {
     40         this.parentFolder = parentFolder;
     41     }
     42 
     43     @Override
     44     protected void before() throws Throwable {
     45         create();
     46     }
     47 
     48     @Override
     49     protected void after() {
     50         delete();
     51     }
     52 
     53     // testing purposes only
     54 
     55     /**
     56      * for testing purposes only. Do not use.
     57      */
     58     public void create() throws IOException {
     59         folder = createTemporaryFolderIn(parentFolder);
     60     }
     61 
     62     /**
     63      * Returns a new fresh file with the given name under the temporary folder.
     64      */
     65     public File newFile(String fileName) throws IOException {
     66         File file = new File(getRoot(), fileName);
     67         if (!file.createNewFile()) {
     68             throw new IOException(
     69                     "a file with the name \'" + fileName + "\' already exists in the test folder");
     70         }
     71         return file;
     72     }
     73 
     74     /**
     75      * Returns a new fresh file with a random name under the temporary folder.
     76      */
     77     public File newFile() throws IOException {
     78         return File.createTempFile("junit", null, getRoot());
     79     }
     80 
     81     /**
     82      * Returns a new fresh folder with the given name under the temporary
     83      * folder.
     84      */
     85     public File newFolder(String folder) throws IOException {
     86         return newFolder(new String[]{folder});
     87     }
     88 
     89     /**
     90      * Returns a new fresh folder with the given name(s) under the temporary
     91      * folder.
     92      */
     93     public File newFolder(String... folderNames) throws IOException {
     94         File file = getRoot();
     95         for (int i = 0; i < folderNames.length; i++) {
     96             String folderName = folderNames[i];
     97             validateFolderName(folderName);
     98             file = new File(file, folderName);
     99             if (!file.mkdir() && isLastElementInArray(i, folderNames)) {
    100                 throw new IOException(
    101                         "a folder with the name \'" + folderName + "\' already exists");
    102             }
    103         }
    104         return file;
    105     }
    106 
    107     /**
    108      * Validates if multiple path components were used while creating a folder.
    109      *
    110      * @param folderName
    111      *            Name of the folder being created
    112      */
    113     private void validateFolderName(String folderName) throws IOException {
    114         File tempFile = new File(folderName);
    115         if (tempFile.getParent() != null) {
    116             String errorMsg = "Folder name cannot consist of multiple path components separated by a file separator."
    117                     + " Please use newFolder('MyParentFolder','MyFolder') to create hierarchies of folders";
    118             throw new IOException(errorMsg);
    119         }
    120     }
    121 
    122     private boolean isLastElementInArray(int index, String[] array) {
    123         return index == array.length - 1;
    124     }
    125 
    126     /**
    127      * Returns a new fresh folder with a random name under the temporary folder.
    128      */
    129     public File newFolder() throws IOException {
    130         return createTemporaryFolderIn(getRoot());
    131     }
    132 
    133     private File createTemporaryFolderIn(File parentFolder) throws IOException {
    134         File createdFolder = File.createTempFile("junit", "", parentFolder);
    135         createdFolder.delete();
    136         createdFolder.mkdir();
    137         return createdFolder;
    138     }
    139 
    140     /**
    141      * @return the location of this temporary folder.
    142      */
    143     public File getRoot() {
    144         if (folder == null) {
    145             throw new IllegalStateException(
    146                     "the temporary folder has not yet been created");
    147         }
    148         return folder;
    149     }
    150 
    151     /**
    152      * Delete all files and folders under the temporary folder. Usually not
    153      * called directly, since it is automatically applied by the {@link Rule}
    154      */
    155     public void delete() {
    156         if (folder != null) {
    157             recursiveDelete(folder);
    158         }
    159     }
    160 
    161     private void recursiveDelete(File file) {
    162         File[] files = file.listFiles();
    163         if (files != null) {
    164             for (File each : files) {
    165                 recursiveDelete(each);
    166             }
    167         }
    168         file.delete();
    169     }
    170 }
    171