Commit | Line | Data |
---|---|---|
59864f77 NR |
1 | package be.nikiroo.utils; |
2 | ||
3 | import java.io.Closeable; | |
4 | import java.io.File; | |
5 | import java.io.IOException; | |
6 | ||
7 | /** | |
8 | * A small utility class to generate auto-delete temporary files in a | |
9 | * centralised location. | |
10 | * | |
11 | * @author niki | |
12 | */ | |
13 | public class TempFiles implements Closeable { | |
82fcfcde NR |
14 | /** |
15 | * Root directory of this instance, owned by it, where all temporary files | |
16 | * must reside. | |
17 | */ | |
59864f77 NR |
18 | protected File root; |
19 | ||
20 | /** | |
21 | * Create a new {@link TempFiles} -- each instance is separate and have a | |
22 | * dedicated sub-directory in a shared temporary root. | |
23 | * <p> | |
24 | * The whole repository will be deleted on close (if you fail to call it, | |
82fcfcde | 25 | * the program will <b>try</b> to call it on JVM termination). |
59864f77 NR |
26 | * |
27 | * @param name | |
28 | * the instance name (will be <b>part</b> of the final directory | |
29 | * name) | |
30 | * | |
31 | * @throws IOException | |
32 | * in case of I/O error | |
33 | */ | |
34 | public TempFiles(String name) throws IOException { | |
82fcfcde NR |
35 | this(null, name); |
36 | } | |
37 | ||
38 | /** | |
39 | * Create a new {@link TempFiles} -- each instance is separate and have a | |
40 | * dedicated sub-directory in a given temporary root. | |
41 | * <p> | |
42 | * The whole repository will be deleted on close (if you fail to call it, | |
43 | * the program will <b>try</b> to call it on JVM termination). | |
44 | * <p> | |
45 | * Be careful, this instance will <b>own</b> the given root directory, and | |
46 | * will most probably delete all its files. | |
47 | * | |
48 | * @param base | |
49 | * the root base directory to use for all the temporary files of | |
50 | * this instance (if NULL, will be the default temporary | |
51 | * directory of the OS) | |
52 | * @param name | |
53 | * the instance name (will be <b>part</b> of the final directory | |
54 | * name) | |
55 | * | |
56 | * @throws IOException | |
57 | * in case of I/O error | |
58 | */ | |
59 | public TempFiles(File base, String name) throws IOException { | |
60 | if (base == null) { | |
61 | base = File.createTempFile(".temp", ""); | |
62 | } | |
63 | ||
64 | root = base; | |
65 | ||
59864f77 NR |
66 | IOUtils.deltree(root, true); |
67 | ||
68 | root = new File(root.getParentFile(), ".temp"); | |
69 | root.mkdir(); | |
70 | if (!root.exists()) { | |
71 | throw new IOException("Cannot create root directory: " + root); | |
72 | } | |
73 | ||
74 | root.deleteOnExit(); | |
75 | ||
76 | root = createTempFile(name); | |
77 | IOUtils.deltree(root, true); | |
78 | ||
79 | root.mkdir(); | |
80 | if (!root.exists()) { | |
81 | throw new IOException("Cannot create root subdirectory: " + root); | |
82 | } | |
83 | } | |
84 | ||
85 | /** | |
86 | * Create an auto-delete temporary file. | |
87 | * | |
88 | * @param name | |
89 | * a base for the final filename (only a <b>part</b> of said | |
90 | * filename) | |
91 | * | |
92 | * @return the newly created file | |
93 | * | |
94 | * @throws IOException | |
95 | * in case of I/O errors | |
96 | */ | |
97 | public synchronized File createTempFile(String name) throws IOException { | |
98 | name += "_"; | |
99 | while (name.length() < 3) { | |
100 | name += "_"; | |
101 | } | |
102 | ||
103 | while (true) { | |
104 | File tmp = File.createTempFile(name, ""); | |
105 | IOUtils.deltree(tmp, true); | |
106 | ||
107 | File test = new File(root, tmp.getName()); | |
108 | if (!test.exists()) { | |
109 | test.createNewFile(); | |
110 | if (!test.exists()) { | |
111 | throw new IOException("Cannot create temporary file: " | |
112 | + test); | |
113 | } | |
114 | ||
115 | test.deleteOnExit(); | |
116 | return test; | |
117 | } | |
118 | } | |
119 | } | |
120 | ||
121 | /** | |
122 | * Create an auto-delete temporary directory. | |
123 | * <p> | |
124 | * Note that creating 2 temporary directories with the same name will result | |
125 | * in two <b>different</b> directories, even if the final name is the same | |
126 | * (the absolute path will be different). | |
127 | * | |
128 | * @param name | |
129 | * the actual directory name (not path) | |
130 | * | |
131 | * @return the newly created file | |
132 | * | |
133 | * @throws IOException | |
134 | * in case of I/O errors, or if the name was a path instead of a | |
135 | * name | |
136 | */ | |
137 | public synchronized File createTempDir(String name) throws IOException { | |
138 | File localRoot = createTempFile(name); | |
139 | IOUtils.deltree(localRoot, true); | |
140 | ||
141 | localRoot.mkdir(); | |
142 | if (!localRoot.exists()) { | |
143 | throw new IOException("Cannot create subdirectory: " + localRoot); | |
144 | } | |
145 | ||
146 | File dir = new File(localRoot, name); | |
147 | if (!dir.getName().equals(name)) { | |
148 | throw new IOException( | |
149 | "Cannot create temporary directory with a path, only names are allowed: " | |
150 | + dir); | |
151 | } | |
152 | ||
153 | dir.mkdir(); | |
154 | dir.deleteOnExit(); | |
155 | ||
156 | if (!dir.exists()) { | |
157 | throw new IOException("Cannot create subdirectory: " + dir); | |
158 | } | |
159 | ||
160 | return dir; | |
161 | } | |
162 | ||
163 | @Override | |
164 | public synchronized void close() throws IOException { | |
165 | IOUtils.deltree(root); // NO exception here | |
166 | root.getParentFile().delete(); // only if empty | |
c175bf6f | 167 | root = null; |
59864f77 NR |
168 | } |
169 | ||
170 | @Override | |
171 | protected void finalize() throws Throwable { | |
172 | try { | |
173 | close(); | |
174 | } finally { | |
175 | super.finalize(); | |
176 | } | |
177 | } | |
178 | } |