View Javadoc
1   package auxtestlib;
2   
3   import java.io.File;
4   import java.io.IOException;
5   
6   /**
7    * Class that creates a temporary file or directory. This file or directory is
8    * removed when the JVM terminates (it may be deleted sooner if the
9    * {@link #delete()} method is called explicitly). If the created file is a
10   * directory, it will be removed recursively.
11   */
12  public class TemporaryFile {
13  	/**
14  	 * Created file. If <code>null</code> means it was already removed.
15  	 */
16  	private File m_created;
17  
18  	/**
19  	 * Creates a new temporary file (or directory). This is equivalent to call
20  	 * {@link #TemporaryFile(File, boolean, String, String)} with all other
21  	 * arguments as <code>null</code>.
22  	 * @param directory should a directory be created? If <code>false</code> a
23  	 * file is created
24  	 * @throws IOException failed to create the file
25  	 */
26  	public TemporaryFile(boolean directory) throws IOException {
27  		this(null, directory, null, null);
28  	}
29  
30  	/**
31  	 * Creates a new file (or directory).
32  	 * @param path path to the parent directory. If <code>null</code> the
33  	 * file/directory will be created on the default location.
34  	 * @param directory should a directory be created? If <code>false</code> a
35  	 * file is created
36  	 * @param prefix an optional prefix for the file (it a prefix is provided it
37  	 * must contain at least 3 characters).
38  	 * @param suffix an optional suffix for the file
39  	 * @throws IOException failed to create the file
40  	 */
41  	public TemporaryFile(File path, boolean directory, String prefix,
42  			String suffix) throws IOException {
43  		String pfx = prefix;
44  
45  		if (pfx == null) {
46  			pfx = "junit_";
47  		}
48  
49  		if (pfx.length() < 3) {
50  			throw new IllegalArgumentException("prefix must have at least "
51  					+ "3 characters");
52  		}
53  
54  		m_created = File.createTempFile(pfx, suffix, path);
55  		if (directory) {
56  			if (!m_created.delete()) {
57  				throw new IOException("Failed to delete file '"
58  						+ m_created.getAbsolutePath() + "'");
59  			}
60  
61  			if (!m_created.mkdir()) {
62  				throw new IOException("Failed to create directory '"
63  						+ m_created.getAbsolutePath() + "'");
64  			}
65  		}
66  
67  		Thread t = new Thread(new Runnable() {
68  			@Override
69  			public void run() {
70  				shutdown_delete();
71  			}
72  		});
73  
74  		Runtime.getRuntime().addShutdownHook(t);
75  	}
76  
77  	/**
78  	 * Obtains a reference to the created file.
79  	 * @return the created file (or directory).
80  	 * @deprecated use {@link #file()} instead
81  	 */
82  	@Deprecated
83  	public File getFile() {
84  		return file();
85  	}
86  
87  	/**
88  	 * Obtains a reference to the created file.
89  	 * @return the created file (or directory).
90  	 */
91  	public File file() {
92  		if (m_created == null) {
93  			throw new IllegalStateException("File/directory already deleted.");
94  		}
95  
96  		return m_created;
97  	}
98  	
99  	/**
100 	 * Deletes the file or directory. If this represents a directory, all its
101 	 * contents are recursively deleted.
102 	 */
103 	public void delete() {
104 		if (m_created == null) {
105 			throw new IllegalStateException("File already deleted.");
106 		}
107 
108 		shutdown_delete();
109 	}
110 
111 	/**
112 	 * Removes the file or directory if it hasn't been removed yet. If this
113 	 * represents a directory, all its contents are recursively deleted.
114 	 */
115 	private void shutdown_delete() {
116 		if (m_created == null) {
117 			return;
118 		}
119 
120 		do_delete(m_created);
121 
122 		m_created = null;
123 	}
124 
125 	/**
126 	 * Deletes a file. If the file is a directory, it is removed with all its
127 	 * contents.
128 	 * @param f the file or directory to remove
129 	 */
130 	private void do_delete(File f) {
131 		assert f != null;
132 
133 		if (f.exists()) {
134 			if (f.isDirectory()) {
135 				doDeleteDir(f);
136 			}
137 			boolean res = f.delete();
138 			assert res || !res; // Otherwise findbugs complains.
139 		}
140 	}
141 
142 	/**
143 	 * Removes a directory and all its contents
144 	 * @param d the directory to remove
145 	 */
146 	private void doDeleteDir(File d) {
147 		assert d != null;
148 		assert d.isDirectory();
149 
150 		File f[] = d.listFiles();
151 		for (int i = 0; i < f.length; i++) {
152 			do_delete(f[i]);
153 		}
154 	}
155 }