001    package org.junit.rules;
002    
003    import java.io.File;
004    import java.io.IOException;
005    
006    import org.junit.Rule;
007    
008    /**
009     * The TemporaryFolder Rule allows creation of files and folders that are
010     * guaranteed to be deleted when the test method finishes (whether it passes or
011     * fails):
012     *
013     * <pre>
014     * public static class HasTempFolder {
015     *  &#064;Rule
016     *  public TemporaryFolder folder= new TemporaryFolder();
017     *
018     *  &#064;Test
019     *  public void testUsingTempFolder() throws IOException {
020     *      File createdFile= folder.newFile(&quot;myfile.txt&quot;);
021     *      File createdFolder= folder.newFolder(&quot;subfolder&quot;);
022     *      // ...
023     *     }
024     * }
025     * </pre>
026     *
027     * @since 4.7
028     */
029    public class TemporaryFolder extends ExternalResource {
030        private final File parentFolder;
031        private File folder;
032    
033        public TemporaryFolder() {
034            this(null);
035        }
036    
037        public TemporaryFolder(File parentFolder) {
038            this.parentFolder = parentFolder;
039        }
040    
041        @Override
042        protected void before() throws Throwable {
043            create();
044        }
045    
046        @Override
047        protected void after() {
048            delete();
049        }
050    
051        // testing purposes only
052    
053        /**
054         * for testing purposes only. Do not use.
055         */
056        public void create() throws IOException {
057            folder = createTemporaryFolderIn(parentFolder);
058        }
059    
060        /**
061         * Returns a new fresh file with the given name under the temporary folder.
062         */
063        public File newFile(String fileName) throws IOException {
064            File file = new File(getRoot(), fileName);
065            if (!file.createNewFile()) {
066                throw new IOException(
067                        "a file with the name \'" + fileName + "\' already exists in the test folder");
068            }
069            return file;
070        }
071    
072        /**
073         * Returns a new fresh file with a random name under the temporary folder.
074         */
075        public File newFile() throws IOException {
076            return File.createTempFile("junit", null, getRoot());
077        }
078    
079        /**
080         * Returns a new fresh folder with the given name under the temporary
081         * folder.
082         */
083        public File newFolder(String folder) throws IOException {
084            return newFolder(new String[]{folder});
085        }
086    
087        /**
088         * Returns a new fresh folder with the given name(s) under the temporary
089         * folder.
090         */
091        public File newFolder(String... folderNames) throws IOException {
092            File file = getRoot();
093            for (int i = 0; i < folderNames.length; i++) {
094                String folderName = folderNames[i];
095                file = new File(file, folderName);
096                if (!file.mkdir() && isLastElementInArray(i, folderNames)) {
097                    throw new IOException(
098                            "a folder with the name \'" + folderName + "\' already exists");
099                }
100            }
101            return file;
102        }
103    
104        private boolean isLastElementInArray(int index, String[] array) {
105            return index == array.length - 1;
106        }
107    
108        /**
109         * Returns a new fresh folder with a random name under the temporary folder.
110         */
111        public File newFolder() throws IOException {
112            return createTemporaryFolderIn(getRoot());
113        }
114    
115        private File createTemporaryFolderIn(File parentFolder) throws IOException {
116            File createdFolder = File.createTempFile("junit", "", parentFolder);
117            createdFolder.delete();
118            createdFolder.mkdir();
119            return createdFolder;
120        }
121    
122        /**
123         * @return the location of this temporary folder.
124         */
125        public File getRoot() {
126            if (folder == null) {
127                throw new IllegalStateException(
128                        "the temporary folder has not yet been created");
129            }
130            return folder;
131        }
132    
133        /**
134         * Delete all files and folders under the temporary folder. Usually not
135         * called directly, since it is automatically applied by the {@link Rule}
136         */
137        public void delete() {
138            if (folder != null) {
139                recursiveDelete(folder);
140            }
141        }
142    
143        private void recursiveDelete(File file) {
144            File[] files = file.listFiles();
145            if (files != null) {
146                for (File each : files) {
147                    recursiveDelete(each);
148                }
149            }
150            file.delete();
151        }
152    }