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 should 010 * be deleted when the test method finishes (whether it passes or 011 * fails). Whether the deletion is successful or not is not checked by this rule. 012 * No exception will be thrown in case the deletion fails. 013 * 014 * <p>Example of usage: 015 * <pre> 016 * public static class HasTempFolder { 017 * @Rule 018 * public TemporaryFolder folder= new TemporaryFolder(); 019 * 020 * @Test 021 * public void testUsingTempFolder() throws IOException { 022 * File createdFile= folder.newFile("myfile.txt"); 023 * File createdFolder= folder.newFolder("subfolder"); 024 * // ... 025 * } 026 * } 027 * </pre> 028 * 029 * @since 4.7 030 */ 031 public class TemporaryFolder extends ExternalResource { 032 private final File parentFolder; 033 private File folder; 034 035 public TemporaryFolder() { 036 this(null); 037 } 038 039 public TemporaryFolder(File parentFolder) { 040 this.parentFolder = parentFolder; 041 } 042 043 @Override 044 protected void before() throws Throwable { 045 create(); 046 } 047 048 @Override 049 protected void after() { 050 delete(); 051 } 052 053 // testing purposes only 054 055 /** 056 * for testing purposes only. Do not use. 057 */ 058 public void create() throws IOException { 059 folder = createTemporaryFolderIn(parentFolder); 060 } 061 062 /** 063 * Returns a new fresh file with the given name under the temporary folder. 064 */ 065 public File newFile(String fileName) throws IOException { 066 File file = new File(getRoot(), fileName); 067 if (!file.createNewFile()) { 068 throw new IOException( 069 "a file with the name \'" + fileName + "\' already exists in the test folder"); 070 } 071 return file; 072 } 073 074 /** 075 * Returns a new fresh file with a random name under the temporary folder. 076 */ 077 public File newFile() throws IOException { 078 return File.createTempFile("junit", null, getRoot()); 079 } 080 081 /** 082 * Returns a new fresh folder with the given name under the temporary 083 * folder. 084 */ 085 public File newFolder(String folder) throws IOException { 086 return newFolder(new String[]{folder}); 087 } 088 089 /** 090 * Returns a new fresh folder with the given name(s) under the temporary 091 * folder. 092 */ 093 public File newFolder(String... folderNames) throws IOException { 094 File file = getRoot(); 095 for (int i = 0; i < folderNames.length; i++) { 096 String folderName = folderNames[i]; 097 validateFolderName(folderName); 098 file = new File(file, folderName); 099 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 }