Skip to content

Commit e8fea70

Browse files
[MCLEAN-126] Replaced old File API with new Path equivalent where possible (#62)
1 parent a38e8bc commit e8fea70

File tree

4 files changed

+77
-60
lines changed

4 files changed

+77
-60
lines changed

src/main/java/org/apache/maven/plugins/clean/CleanMojo.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
import java.io.File;
2222
import java.io.IOException;
23+
import java.nio.file.FileSystems;
24+
import java.nio.file.Path;
2325

2426
import org.apache.maven.execution.MavenSession;
2527
import org.apache.maven.plugin.AbstractMojo;
@@ -183,7 +185,7 @@ public class CleanMojo extends AbstractMojo {
183185
* <code>${maven.multiModuleProjectDirectory}/target/.clean</code> directory will be used. If the
184186
* <code>${build.directory}</code> has been modified, you'll have to adjust this property explicitly.
185187
* In order for fast clean to work correctly, this directory and the various directories that will be deleted
186-
* should usually reside on the same volume. The exact conditions are system dependant though, but if an atomic
188+
* should usually reside on the same volume. The exact conditions are system-dependent though, but if an atomic
187189
* move is not supported, the standard deletion mechanism will be used.
188190
*
189191
* @see #fast
@@ -196,8 +198,8 @@ public class CleanMojo extends AbstractMojo {
196198
* Mode to use when using fast clean. Values are: <code>background</code> to start deletion immediately and
197199
* waiting for all files to be deleted when the session ends, <code>at-end</code> to indicate that the actual
198200
* deletion should be performed synchronously when the session ends, or <code>defer</code> to specify that
199-
* the actual file deletion should be started in the background when the session ends (this should only be used
200-
* when maven is embedded in a long running process).
201+
* the actual file deletion should be started in the background when the session ends. This should only be used
202+
* when maven is embedded in a long-running process.
201203
*
202204
* @see #fast
203205
* @since 3.2
@@ -223,11 +225,14 @@ public void execute() throws MojoExecutionException {
223225

224226
String multiModuleProjectDirectory =
225227
session != null ? session.getSystemProperties().getProperty("maven.multiModuleProjectDirectory") : null;
226-
File fastDir;
228+
Path fastDir;
227229
if (fast && this.fastDir != null) {
228-
fastDir = this.fastDir;
230+
fastDir = toNullablePath(this.fastDir);
229231
} else if (fast && multiModuleProjectDirectory != null) {
230-
fastDir = new File(multiModuleProjectDirectory, "target/.clean");
232+
fastDir = FileSystems.getDefault()
233+
.getPath(multiModuleProjectDirectory)
234+
.resolve("target")
235+
.resolve(".clean");
231236
} else {
232237
fastDir = null;
233238
if (fast) {
@@ -247,7 +252,7 @@ public void execute() throws MojoExecutionException {
247252
Cleaner cleaner = new Cleaner(session, getLog(), isVerbose(), fastDir, fastMode);
248253

249254
try {
250-
for (File directoryItem : getDirectories()) {
255+
for (Path directoryItem : getDirectories()) {
251256
if (directoryItem != null) {
252257
cleaner.delete(directoryItem, null, followSymLinks, failOnError, retryOnError);
253258
}
@@ -270,7 +275,11 @@ public void execute() throws MojoExecutionException {
270275
selector = null;
271276
}
272277
cleaner.delete(
273-
fileset.getDirectory(), selector, fileset.isFollowSymlinks(), failOnError, retryOnError);
278+
fileset.getDirectory().toPath(),
279+
selector,
280+
fileset.isFollowSymlinks(),
281+
failOnError,
282+
retryOnError);
274283
}
275284
}
276285
} catch (IOException e) {
@@ -292,13 +301,22 @@ private boolean isVerbose() {
292301
*
293302
* @return The directories to clean or an empty array if none, never <code>null</code>.
294303
*/
295-
private File[] getDirectories() {
296-
File[] directories;
304+
private Path[] getDirectories() {
305+
Path[] directories;
297306
if (excludeDefaultDirectories) {
298-
directories = new File[0];
307+
directories = new Path[0];
299308
} else {
300-
directories = new File[] {directory, outputDirectory, testOutputDirectory, reportDirectory};
309+
directories = new Path[] {
310+
toNullablePath(directory),
311+
toNullablePath(outputDirectory),
312+
toNullablePath(testOutputDirectory),
313+
toNullablePath(reportDirectory)
314+
};
301315
}
302316
return directories;
303317
}
318+
319+
private static Path toNullablePath(File file) {
320+
return file != null ? file.toPath() : null;
321+
}
304322
}

src/main/java/org/apache/maven/plugins/clean/Cleaner.java

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.lang.reflect.InvocationHandler;
2424
import java.lang.reflect.Method;
2525
import java.lang.reflect.Proxy;
26+
import java.nio.file.DirectoryStream;
2627
import java.nio.file.Files;
2728
import java.nio.file.LinkOption;
2829
import java.nio.file.Path;
@@ -37,6 +38,9 @@
3738
import org.codehaus.plexus.util.Os;
3839
import org.eclipse.aether.SessionData;
3940

41+
import static java.nio.file.Files.exists;
42+
import static java.nio.file.Files.isDirectory;
43+
import static java.nio.file.Files.newDirectoryStream;
4044
import static org.apache.maven.plugins.clean.CleanMojo.FAST_MODE_BACKGROUND;
4145
import static org.apache.maven.plugins.clean.CleanMojo.FAST_MODE_DEFER;
4246

@@ -56,7 +60,7 @@ class Cleaner {
5660
*/
5761
private final MavenSession session;
5862

59-
private final File fastDir;
63+
private final Path fastDir;
6064

6165
private final String fastMode;
6266

@@ -73,7 +77,7 @@ class Cleaner {
7377
* @param fastDir The explicit configured directory or to be deleted in fast mode.
7478
* @param fastMode The fast deletion mode.
7579
*/
76-
Cleaner(MavenSession session, final Log log, boolean verbose, File fastDir, String fastMode) {
80+
Cleaner(MavenSession session, final Log log, boolean verbose, Path fastDir, String fastMode) {
7781
this.session = session;
7882
// This can't be null as the Cleaner gets it from the CleanMojo which gets it from AbstractMojo class, where it
7983
// is never null.
@@ -96,10 +100,10 @@ class Cleaner {
96100
* @throws IOException If a file/directory could not be deleted and <code>failOnError</code> is <code>true</code>.
97101
*/
98102
public void delete(
99-
File basedir, Selector selector, boolean followSymlinks, boolean failOnError, boolean retryOnError)
103+
Path basedir, Selector selector, boolean followSymlinks, boolean failOnError, boolean retryOnError)
100104
throws IOException {
101-
if (!basedir.isDirectory()) {
102-
if (!basedir.exists()) {
105+
if (!isDirectory(basedir)) {
106+
if (!exists(basedir)) {
103107
if (log.isDebugEnabled()) {
104108
log.debug("Skipping non-existing directory " + basedir);
105109
}
@@ -112,7 +116,7 @@ public void delete(
112116
log.info("Deleting " + basedir + (selector != null ? " (" + selector + ")" : ""));
113117
}
114118

115-
File file = followSymlinks ? basedir : basedir.getCanonicalFile();
119+
Path file = followSymlinks ? basedir : basedir.toRealPath();
116120

117121
if (selector == null && !followSymlinks && fastDir != null && session != null) {
118122
// If anything wrong happens, we'll just use the usual deletion mechanism
@@ -124,9 +128,7 @@ public void delete(
124128
delete(file, "", selector, followSymlinks, failOnError, retryOnError);
125129
}
126130

127-
private boolean fastDelete(File baseDirFile) {
128-
Path baseDir = baseDirFile.toPath();
129-
Path fastDir = this.fastDir.toPath();
131+
private boolean fastDelete(Path baseDir) {
130132
// Handle the case where we use ${maven.multiModuleProjectDirectory}/target/.clean for example
131133
if (fastDir.toAbsolutePath().startsWith(baseDir.toAbsolutePath())) {
132134
try {
@@ -135,7 +137,7 @@ private boolean fastDelete(File baseDirFile) {
135137
try {
136138
Files.move(baseDir, tmpDir, StandardCopyOption.REPLACE_EXISTING);
137139
if (session != null) {
138-
session.getRepositorySession().getData().set(LAST_DIRECTORY_TO_DELETE, baseDir.toFile());
140+
session.getRepositorySession().getData().set(LAST_DIRECTORY_TO_DELETE, baseDir);
139141
}
140142
baseDir = tmpDir;
141143
} catch (IOException e) {
@@ -151,7 +153,7 @@ private boolean fastDelete(File baseDirFile) {
151153
}
152154
// Create fastDir and the needed parents if needed
153155
try {
154-
if (!Files.isDirectory(fastDir)) {
156+
if (!isDirectory(fastDir)) {
155157
Files.createDirectories(fastDir);
156158
}
157159
} catch (IOException e) {
@@ -172,7 +174,7 @@ private boolean fastDelete(File baseDirFile) {
172174
// or any other exception occurs, an exception will be thrown in which case
173175
// the method will return false and the usual deletion will be performed.
174176
Files.move(baseDir, dstDir, StandardCopyOption.ATOMIC_MOVE);
175-
BackgroundCleaner.delete(this, tmpDir.toFile(), fastMode);
177+
BackgroundCleaner.delete(this, tmpDir, fastMode);
176178
return true;
177179
} catch (IOException e) {
178180
if (log.isDebugEnabled()) {
@@ -198,7 +200,7 @@ private boolean fastDelete(File baseDirFile) {
198200
* @throws IOException If a file/directory could not be deleted and <code>failOnError</code> is <code>true</code>.
199201
*/
200202
private Result delete(
201-
File file,
203+
Path file,
202204
String pathname,
203205
Selector selector,
204206
boolean followSymlinks,
@@ -207,18 +209,16 @@ private Result delete(
207209
throws IOException {
208210
Result result = new Result();
209211

210-
boolean isDirectory = file.isDirectory();
212+
boolean isDirectory = isDirectory(file);
211213

212214
if (isDirectory) {
213215
if (selector == null || selector.couldHoldSelected(pathname)) {
214-
if (followSymlinks || !isSymbolicLink(file.toPath())) {
215-
File canonical = followSymlinks ? file : file.getCanonicalFile();
216-
String[] filenames = canonical.list();
217-
if (filenames != null) {
218-
String prefix = pathname.length() > 0 ? pathname + File.separatorChar : "";
219-
for (int i = filenames.length - 1; i >= 0; i--) {
220-
String filename = filenames[i];
221-
File child = new File(canonical, filename);
216+
if (followSymlinks || !isSymbolicLink(file)) {
217+
Path canonical = followSymlinks ? file : file.toRealPath();
218+
String prefix = pathname.length() > 0 ? pathname + File.separatorChar : "";
219+
try (DirectoryStream<Path> children = newDirectoryStream(canonical)) {
220+
for (Path child : children) {
221+
String filename = child.getFileName().toString();
222222
result.update(delete(
223223
child, prefix + filename, selector, followSymlinks, failOnError, retryOnError));
224224
}
@@ -235,7 +235,7 @@ private Result delete(
235235
String logmessage;
236236
if (isDirectory) {
237237
logmessage = "Deleting directory " + file;
238-
} else if (file.exists()) {
238+
} else if (exists(file)) {
239239
logmessage = "Deleting file " + file;
240240
} else {
241241
logmessage = "Deleting dangling symlink " + file;
@@ -272,7 +272,7 @@ private boolean isSymbolicLink(Path path) throws IOException {
272272
* @return <code>0</code> if the file was deleted, <code>1</code> otherwise.
273273
* @throws IOException If a file/directory could not be deleted and <code>failOnError</code> is <code>true</code>.
274274
*/
275-
private int delete(File file, boolean failOnError, boolean retryOnError) throws IOException {
275+
private int delete(Path file, boolean failOnError, boolean retryOnError) throws IOException {
276276
IOException failure = delete(file);
277277
if (failure != null) {
278278
boolean deleted = false;
@@ -290,10 +290,10 @@ private int delete(File file, boolean failOnError, boolean retryOnError) throws
290290
} catch (InterruptedException e) {
291291
// ignore
292292
}
293-
deleted = delete(file) == null || !file.exists();
293+
deleted = delete(file) == null || !exists(file);
294294
}
295295
} else {
296-
deleted = !file.exists();
296+
deleted = !exists(file);
297297
}
298298

299299
if (!deleted) {
@@ -311,9 +311,9 @@ private int delete(File file, boolean failOnError, boolean retryOnError) throws
311311
return 0;
312312
}
313313

314-
private static IOException delete(File file) {
314+
private static IOException delete(Path file) {
315315
try {
316-
Files.delete(file.toPath());
316+
Files.delete(file);
317317
} catch (IOException e) {
318318
return e;
319319
}
@@ -338,19 +338,19 @@ private static class BackgroundCleaner extends Thread {
338338
private static final int RUNNING = 1;
339339
private static final int STOPPED = 2;
340340
private static BackgroundCleaner instance;
341-
private final Deque<File> filesToDelete = new ArrayDeque<>();
341+
private final Deque<Path> filesToDelete = new ArrayDeque<>();
342342
private final Cleaner cleaner;
343343
private final String fastMode;
344344
private int status = NEW;
345345

346-
private BackgroundCleaner(Cleaner cleaner, File dir, String fastMode) {
346+
private BackgroundCleaner(Cleaner cleaner, Path dir, String fastMode) throws IOException {
347347
super("mvn-background-cleaner");
348348
this.cleaner = cleaner;
349349
this.fastMode = fastMode;
350350
init(cleaner.fastDir, dir);
351351
}
352352

353-
public static void delete(Cleaner cleaner, File dir, String fastMode) {
353+
public static void delete(Cleaner cleaner, Path dir, String fastMode) throws IOException {
354354
synchronized (BackgroundCleaner.class) {
355355
if (instance == null || !instance.doDelete(dir)) {
356356
instance = new BackgroundCleaner(cleaner, dir, fastMode);
@@ -368,7 +368,7 @@ static void sessionEnd() {
368368

369369
public void run() {
370370
while (true) {
371-
File basedir = pollNext();
371+
Path basedir = pollNext();
372372
if (basedir == null) {
373373
break;
374374
}
@@ -380,24 +380,23 @@ public void run() {
380380
}
381381
}
382382

383-
synchronized void init(File fastDir, File dir) {
384-
if (fastDir.isDirectory()) {
385-
File[] children = fastDir.listFiles();
386-
if (children != null && children.length > 0) {
387-
for (File child : children) {
383+
synchronized void init(Path fastDir, Path dir) throws IOException {
384+
if (isDirectory(fastDir)) {
385+
try (DirectoryStream<Path> children = newDirectoryStream(fastDir)) {
386+
for (Path child : children) {
388387
doDelete(child);
389388
}
390389
}
391390
}
392391
doDelete(dir);
393392
}
394393

395-
synchronized File pollNext() {
396-
File basedir = filesToDelete.poll();
394+
synchronized Path pollNext() {
395+
Path basedir = filesToDelete.poll();
397396
if (basedir == null) {
398397
if (cleaner.session != null) {
399398
SessionData data = cleaner.session.getRepositorySession().getData();
400-
File lastDir = (File) data.get(LAST_DIRECTORY_TO_DELETE);
399+
Path lastDir = (Path) data.get(LAST_DIRECTORY_TO_DELETE);
401400
if (lastDir != null) {
402401
data.set(LAST_DIRECTORY_TO_DELETE, null);
403402
return lastDir;
@@ -409,7 +408,7 @@ synchronized File pollNext() {
409408
return basedir;
410409
}
411410

412-
synchronized boolean doDelete(File dir) {
411+
synchronized boolean doDelete(Path dir) {
413412
if (status == STOPPED) {
414413
return false;
415414
}

src/test/java/org/apache/maven/plugins/clean/CleanMojoTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ private void testSymlink(LinkCreator linkCreator) throws Exception {
263263
Files.write(file, Collections.singleton("Hello world"));
264264
linkCreator.createLink(jctDir, orgDir);
265265
// delete
266-
cleaner.delete(dirWithLnk.toFile(), null, false, true, false);
266+
cleaner.delete(dirWithLnk, null, false, true, false);
267267
// verify
268268
assertTrue(Files.exists(file));
269269
assertFalse(Files.exists(jctDir));
@@ -276,7 +276,7 @@ private void testSymlink(LinkCreator linkCreator) throws Exception {
276276
Files.write(file, Collections.singleton("Hello world"));
277277
linkCreator.createLink(jctDir, orgDir);
278278
// delete
279-
cleaner.delete(dirWithLnk.toFile(), null, true, true, false);
279+
cleaner.delete(dirWithLnk, null, true, true, false);
280280
// verify
281281
assertFalse(Files.exists(file));
282282
assertFalse(Files.exists(jctDir));

0 commit comments

Comments
 (0)