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 }