This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-clean-plugin.git


The following commit(s) were added to refs/heads/master by this push:
     new 2da1474  [MCLEAN-123] Switch to Maven 4 and the new api (#20)
2da1474 is described below

commit 2da147458800dfe9ecc24865aef0e718ac56df57
Author: Guillaume Nodet <[email protected]>
AuthorDate: Mon Jun 24 17:05:32 2024 +0200

    [MCLEAN-123] Switch to Maven 4 and the new api (#20)
---
 .github/workflows/maven-verify.yml                 |   4 +-
 pom.xml                                            |  62 ++--
 src/it/settings.xml                                |   4 +
 .../org/apache/maven/plugins/clean/CleanMojo.java  |  70 +++--
 .../org/apache/maven/plugins/clean/Cleaner.java    | 334 +++++++++++----------
 .../org/apache/maven/plugins/clean/Fileset.java    |   6 +-
 .../apt/examples/delete_additional_files.apt.vm    |   2 +-
 .../apache/maven/plugins/clean/CleanMojoTest.java  | 170 ++++++-----
 .../resources/unit/basic-clean-test/plugin-pom.xml |  35 ---
 .../plugin-pom.xml => basic-clean-test/pom.xml}    |   4 +-
 .../empty-clean-test/{plugin-pom.xml => pom.xml}   |   0
 .../fileset-clean-test/{plugin-pom.xml => pom.xml} |   5 +-
 .../pom.xml}                                       |   2 +-
 .../plugin-pom.xml => locked-file-test/pom.xml}    |   2 +-
 .../pom.xml}                                       |   2 +-
 .../unit/nested-clean-test/plugin-pom.xml          |  35 ---
 .../plugin-pom.xml => nested-clean-test/pom.xml}   |   4 +-
 17 files changed, 379 insertions(+), 362 deletions(-)

diff --git a/.github/workflows/maven-verify.yml 
b/.github/workflows/maven-verify.yml
index ce4b500..56062b5 100644
--- a/.github/workflows/maven-verify.yml
+++ b/.github/workflows/maven-verify.yml
@@ -26,4 +26,6 @@ jobs:
     name: Verify
     uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v4
     with:
-      maven4-enabled: true
+      ff-maven: "4.0.0-beta-3"                     # Maven version for 
fail-fast-build
+      maven-matrix: '[ "4.0.0-beta-3" ]'
+      jdk-matrix: '[ "17", "21" ]'
diff --git a/pom.xml b/pom.xml
index 73c3c72..a7ef0bb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@ under the License.
   </parent>
 
   <artifactId>maven-clean-plugin</artifactId>
-  <version>3.4.1-SNAPSHOT</version>
+  <version>4.0.0-SNAPSHOT</version>
   <packaging>maven-plugin</packaging>
 
   <name>Apache Maven Clean Plugin</name>
@@ -61,46 +61,44 @@ under the License.
   </distributionManagement>
 
   <properties>
-    <mavenVersion>3.6.3</mavenVersion>
+    <mavenVersion>4.0.0-beta-3</mavenVersion>
+    <javaVersion>17</javaVersion>
+    <version.maven-invoker-plugin>3.7.0</version.maven-invoker-plugin>
+    
<version.maven-plugin-testing>4.0.0-alpha-3-SNAPSHOT</version.maven-plugin-testing>
+    <version.maven-plugin-tools>4.0.0-SNAPSHOT</version.maven-plugin-tools>
     
<project.build.outputTimestamp>2024-06-16T10:25:11Z</project.build.outputTimestamp>
   </properties>
 
   <dependencies>
     <dependency>
       <groupId>org.apache.maven</groupId>
-      <artifactId>maven-plugin-api</artifactId>
+      <artifactId>maven-api-core</artifactId>
       <version>${mavenVersion}</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
-      <artifactId>maven-core</artifactId>
+      <artifactId>maven-api-di</artifactId>
       <version>${mavenVersion}</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>org.apache.maven.resolver</groupId>
-      <artifactId>maven-resolver-api</artifactId>
-      <version>1.1.1</version>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-api-meta</artifactId>
+      <version>${mavenVersion}</version>
       <scope>provided</scope>
     </dependency>
+
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
     </dependency>
 
-    <!-- dependencies to annotations -->
-    <dependency>
-      <groupId>org.apache.maven.plugin-tools</groupId>
-      <artifactId>maven-plugin-annotations</artifactId>
-      <scope>provided</scope>
-    </dependency>
-
     <!-- Test -->
     <dependency>
       <groupId>org.apache.maven.plugin-testing</groupId>
       <artifactId>maven-plugin-testing-harness</artifactId>
-      <version>4.0.0-alpha-2</version>
+      <version>${version.maven-plugin-testing}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -109,18 +107,42 @@ under the License.
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-testing</artifactId>
-      <version>1.3.0</version>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-core</artifactId>
+      <version>${mavenVersion}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-xml</artifactId>
+      <groupId>com.google.inject</groupId>
+      <artifactId>guice</artifactId>
+      <version>6.0.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <version>2.0.13</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
 
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-plugin-plugin</artifactId>
+        <version>${version.maven-plugin-tools}</version>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <redirectTestOutputToFile>true</redirectTestOutputToFile>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
   <profiles>
     <profile>
       <id>run-its</id>
diff --git a/src/it/settings.xml b/src/it/settings.xml
index c8f77f0..5617e4e 100644
--- a/src/it/settings.xml
+++ b/src/it/settings.xml
@@ -32,9 +32,11 @@ under the License.
           <url>@localRepositoryUrl@</url>
           <releases>
             <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
           </releases>
           <snapshots>
             <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
           </snapshots>
         </repository>
       </repositories>
@@ -44,9 +46,11 @@ under the License.
           <url>@localRepositoryUrl@</url>
           <releases>
             <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
           </releases>
           <snapshots>
             <enabled>true</enabled>
+            <checksumPolicy>ignore</checksumPolicy>
           </snapshots>
         </pluginRepository>
       </pluginRepositories>
diff --git a/src/main/java/org/apache/maven/plugins/clean/CleanMojo.java 
b/src/main/java/org/apache/maven/plugins/clean/CleanMojo.java
index 4f77c00..44ceb48 100644
--- a/src/main/java/org/apache/maven/plugins/clean/CleanMojo.java
+++ b/src/main/java/org/apache/maven/plugins/clean/CleanMojo.java
@@ -18,14 +18,16 @@
  */
 package org.apache.maven.plugins.clean;
 
-import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.api.Session;
+import org.apache.maven.api.di.Inject;
+import org.apache.maven.api.plugin.Log;
+import org.apache.maven.api.plugin.MojoException;
+import org.apache.maven.api.plugin.annotations.Mojo;
+import org.apache.maven.api.plugin.annotations.Parameter;
 
 /**
  * Goal which cleans the build.
@@ -43,8 +45,8 @@ import org.apache.maven.plugins.annotations.Parameter;
  * @see org.apache.maven.plugins.clean.Fileset
  * @since 2.0
  */
-@Mojo(name = "clean", threadSafe = true)
-public class CleanMojo extends AbstractMojo {
+@Mojo(name = "clean")
+public class CleanMojo implements org.apache.maven.api.plugin.Mojo {
 
     public static final String FAST_MODE_BACKGROUND = "background";
 
@@ -52,23 +54,26 @@ public class CleanMojo extends AbstractMojo {
 
     public static final String FAST_MODE_DEFER = "defer";
 
+    @Inject
+    private Log logger;
+
     /**
      * This is where build results go.
      */
     @Parameter(defaultValue = "${project.build.directory}", readonly = true, 
required = true)
-    private File directory;
+    private Path directory;
 
     /**
      * This is where compiled classes go.
      */
     @Parameter(defaultValue = "${project.build.outputDirectory}", readonly = 
true, required = true)
-    private File outputDirectory;
+    private Path outputDirectory;
 
     /**
      * This is where compiled test classes go.
      */
     @Parameter(defaultValue = "${project.build.testOutputDirectory}", readonly 
= true, required = true)
-    private File testOutputDirectory;
+    private Path testOutputDirectory;
 
     /**
      * This is where the site plugin generates its pages.
@@ -76,7 +81,7 @@ public class CleanMojo extends AbstractMojo {
      * @since 2.1.1
      */
     @Parameter(defaultValue = "${project.build.outputDirectory}", readonly = 
true, required = true)
-    private File reportDirectory;
+    private Path reportDirectory;
 
     /**
      * Sets whether the plugin runs in verbose mode. As of plugin version 2.3, 
the default value is derived from Maven's
@@ -186,11 +191,11 @@ public class CleanMojo extends AbstractMojo {
      * should usually reside on the same volume. The exact conditions are 
system dependant though, but if an atomic
      * move is not supported, the standard deletion mechanism will be used.
      *
-     * @see #fast
      * @since 3.2
+     * @see #fast
      */
     @Parameter(property = "maven.clean.fastDir")
-    private File fastDir;
+    private Path fastDir;
 
     /**
      * Mode to use when using fast clean.  Values are: <code>background</code> 
to start deletion immediately and
@@ -199,35 +204,35 @@ public class CleanMojo extends AbstractMojo {
      * the actual file deletion should be started in the background when the 
session ends (this should only be used
      * when maven is embedded in a long running process).
      *
-     * @see #fast
      * @since 3.2
+     * @see #fast
      */
     @Parameter(property = "maven.clean.fastMode", defaultValue = 
FAST_MODE_BACKGROUND)
     private String fastMode;
 
-    @Parameter(defaultValue = "${session}", readonly = true)
-    private MavenSession session;
+    @Inject
+    private Session session;
 
     /**
      * Deletes file-sets in the following project build directory order: 
(source) directory, output directory, test
      * directory, report directory, and then the additional file-sets.
      *
-     * @throws MojoExecutionException When a directory failed to get deleted.
-     * @see org.apache.maven.plugin.Mojo#execute()
+     * @throws MojoException When a directory failed to get deleted.
+     * @see org.apache.maven.api.plugin.Mojo#execute()
      */
-    public void execute() throws MojoExecutionException {
+    public void execute() {
         if (skip) {
             getLog().info("Clean is skipped.");
             return;
         }
 
         String multiModuleProjectDirectory =
-                session != null ? 
session.getSystemProperties().getProperty("maven.multiModuleProjectDirectory") 
: null;
-        File fastDir;
+                session != null ? 
session.getSystemProperties().get("maven.multiModuleProjectDirectory") : null;
+        Path fastDir;
         if (fast && this.fastDir != null) {
             fastDir = this.fastDir;
         } else if (fast && multiModuleProjectDirectory != null) {
-            fastDir = new File(multiModuleProjectDirectory, "target/.clean");
+            fastDir = Paths.get(multiModuleProjectDirectory, "target/.clean");
         } else {
             fastDir = null;
             if (fast) {
@@ -247,7 +252,7 @@ public class CleanMojo extends AbstractMojo {
         Cleaner cleaner = new Cleaner(session, getLog(), isVerbose(), fastDir, 
fastMode);
 
         try {
-            for (File directoryItem : getDirectories()) {
+            for (Path directoryItem : getDirectories()) {
                 if (directoryItem != null) {
                     cleaner.delete(directoryItem, null, followSymLinks, 
failOnError, retryOnError);
                 }
@@ -256,7 +261,7 @@ public class CleanMojo extends AbstractMojo {
             if (filesets != null) {
                 for (Fileset fileset : filesets) {
                     if (fileset.getDirectory() == null) {
-                        throw new MojoExecutionException("Missing base 
directory for " + fileset);
+                        throw new MojoException("Missing base directory for " 
+ fileset);
                     }
                     final String[] includes = fileset.getIncludes();
                     final String[] excludes = fileset.getExcludes();
@@ -273,8 +278,9 @@ public class CleanMojo extends AbstractMojo {
                             fileset.getDirectory(), selector, 
fileset.isFollowSymlinks(), failOnError, retryOnError);
                 }
             }
+
         } catch (IOException e) {
-            throw new MojoExecutionException("Failed to clean project: " + 
e.getMessage(), e);
+            throw new MojoException("Failed to clean project: " + 
e.getMessage(), e);
         }
     }
 
@@ -292,13 +298,17 @@ public class CleanMojo extends AbstractMojo {
      *
      * @return The directories to clean or an empty array if none, never 
<code>null</code>.
      */
-    private File[] getDirectories() {
-        File[] directories;
+    private Path[] getDirectories() {
+        Path[] directories;
         if (excludeDefaultDirectories) {
-            directories = new File[0];
+            directories = new Path[0];
         } else {
-            directories = new File[] {directory, outputDirectory, 
testOutputDirectory, reportDirectory};
+            directories = new Path[] {directory, outputDirectory, 
testOutputDirectory, reportDirectory};
         }
         return directories;
     }
+
+    private Log getLog() {
+        return logger;
+    }
 }
diff --git a/src/main/java/org/apache/maven/plugins/clean/Cleaner.java 
b/src/main/java/org/apache/maven/plugins/clean/Cleaner.java
index f5c25d2..533a224 100644
--- a/src/main/java/org/apache/maven/plugins/clean/Cleaner.java
+++ b/src/main/java/org/apache/maven/plugins/clean/Cleaner.java
@@ -20,9 +20,6 @@ package org.apache.maven.plugins.clean;
 
 import java.io.File;
 import java.io.IOException;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
 import java.nio.file.Files;
 import java.nio.file.LinkOption;
 import java.nio.file.Path;
@@ -30,12 +27,17 @@ import java.nio.file.StandardCopyOption;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayDeque;
 import java.util.Deque;
-
-import org.apache.maven.execution.ExecutionListener;
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.plugin.logging.Log;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+import org.apache.maven.api.Event;
+import org.apache.maven.api.EventType;
+import org.apache.maven.api.Listener;
+import org.apache.maven.api.Session;
+import org.apache.maven.api.SessionData;
+import org.apache.maven.api.plugin.Log;
 import org.codehaus.plexus.util.Os;
-import org.eclipse.aether.SessionData;
 
 import static org.apache.maven.plugins.clean.CleanMojo.FAST_MODE_BACKGROUND;
 import static org.apache.maven.plugins.clean.CleanMojo.FAST_MODE_DEFER;
@@ -49,70 +51,93 @@ class Cleaner {
 
     private static final boolean ON_WINDOWS = Os.isFamily(Os.FAMILY_WINDOWS);
 
-    private static final String LAST_DIRECTORY_TO_DELETE = 
Cleaner.class.getName() + ".lastDirectoryToDelete";
+    private static final SessionData.Key<Path> LAST_DIRECTORY_TO_DELETE =
+            SessionData.key(Path.class, Cleaner.class.getName() + 
".lastDirectoryToDelete");
 
     /**
      * The maven session.  This is typically non-null in a real run, but it 
can be during unit tests.
      */
-    private final MavenSession session;
+    private final Session session;
 
-    private final File fastDir;
+    private final Logger logDebug;
 
-    private final String fastMode;
+    private final Logger logInfo;
+
+    private final Logger logVerbose;
 
-    private final boolean verbose;
+    private final Logger logWarn;
 
-    private Log log;
+    private final Path fastDir;
+
+    private final String fastMode;
 
     /**
      * Creates a new cleaner.
      *
      * @param session  The Maven session to be used.
-     * @param log      The logger to use.
+     * @param log      The logger to use, may be <code>null</code> to disable 
logging.
      * @param verbose  Whether to perform verbose logging.
      * @param fastDir  The explicit configured directory or to be deleted in 
fast mode.
      * @param fastMode The fast deletion mode.
      */
-    Cleaner(MavenSession session, final Log log, boolean verbose, File 
fastDir, String fastMode) {
+    Cleaner(Session session, Log log, boolean verbose, Path fastDir, String 
fastMode) {
+        logDebug = (log == null || !log.isDebugEnabled()) ? null : 
logger(log::debug, log::debug);
+
+        logInfo = (log == null || !log.isInfoEnabled()) ? null : 
logger(log::info, log::info);
+
+        logWarn = (log == null || !log.isWarnEnabled()) ? null : 
logger(log::warn, log::warn);
+
+        logVerbose = verbose ? logInfo : logDebug;
+
         this.session = session;
-        // This can't be null as the Cleaner gets it from the CleanMojo which 
gets it from AbstractMojo class, where it
-        // is never null.
-        this.log = log;
         this.fastDir = fastDir;
         this.fastMode = fastMode;
-        this.verbose = verbose;
+    }
+
+    private Logger logger(Consumer<CharSequence> l1, BiConsumer<CharSequence, 
Throwable> l2) {
+        return new Logger() {
+            @Override
+            public void log(CharSequence message) {
+                l1.accept(message);
+            }
+
+            @Override
+            public void log(CharSequence message, Throwable t) {
+                l2.accept(message, t);
+            }
+        };
     }
 
     /**
      * Deletes the specified directories and its contents.
      *
-     * @param basedir        The directory to delete, must not be 
<code>null</code>. Non-existing directories will be silently
-     *                       ignored.
-     * @param selector       The selector used to determine what contents to 
delete, may be <code>null</code> to delete
-     *                       everything.
+     * @param basedir The directory to delete, must not be <code>null</code>. 
Non-existing directories will be silently
+     *            ignored.
+     * @param selector The selector used to determine what contents to delete, 
may be <code>null</code> to delete
+     *            everything.
      * @param followSymlinks Whether to follow symlinks.
-     * @param failOnError    Whether to abort with an exception in case a 
selected file/directory could not be deleted.
-     * @param retryOnError   Whether to undertake additional delete attempts 
in case the first attempt failed.
+     * @param failOnError Whether to abort with an exception in case a 
selected file/directory could not be deleted.
+     * @param retryOnError Whether to undertake additional delete attempts in 
case the first attempt failed.
      * @throws IOException If a file/directory could not be deleted and 
<code>failOnError</code> is <code>true</code>.
      */
     public void delete(
-            File basedir, Selector selector, boolean followSymlinks, boolean 
failOnError, boolean retryOnError)
+            Path basedir, Selector selector, boolean followSymlinks, boolean 
failOnError, boolean retryOnError)
             throws IOException {
-        if (!basedir.isDirectory()) {
-            if (!basedir.exists()) {
-                if (log.isDebugEnabled()) {
-                    log.debug("Skipping non-existing directory " + basedir);
+        if (!Files.isDirectory(basedir)) {
+            if (!Files.exists(basedir)) {
+                if (logDebug != null) {
+                    logDebug.log("Skipping non-existing directory " + basedir);
                 }
                 return;
             }
             throw new IOException("Invalid base directory " + basedir);
         }
 
-        if (log.isInfoEnabled()) {
-            log.info("Deleting " + basedir + (selector != null ? " (" + 
selector + ")" : ""));
+        if (logInfo != null) {
+            logInfo.log("Deleting " + basedir + (selector != null ? " (" + 
selector + ")" : ""));
         }
 
-        File file = followSymlinks ? basedir : basedir.getCanonicalFile();
+        Path file = followSymlinks ? basedir : getCanonicalPath(basedir);
 
         if (selector == null && !followSymlinks && fastDir != null && session 
!= null) {
             // If anything wrong happens, we'll just use the usual deletion 
mechanism
@@ -124,9 +149,8 @@ class Cleaner {
         delete(file, "", selector, followSymlinks, failOnError, retryOnError);
     }
 
-    private boolean fastDelete(File baseDirFile) {
-        Path baseDir = baseDirFile.toPath();
-        Path fastDir = this.fastDir.toPath();
+    private boolean fastDelete(Path baseDir) {
+        Path fastDir = this.fastDir;
         // Handle the case where we use 
${maven.multiModuleProjectDirectory}/target/.clean for example
         if (fastDir.toAbsolutePath().startsWith(baseDir.toAbsolutePath())) {
             try {
@@ -135,7 +159,7 @@ class Cleaner {
                 try {
                     Files.move(baseDir, tmpDir, 
StandardCopyOption.REPLACE_EXISTING);
                     if (session != null) {
-                        
session.getRepositorySession().getData().set(LAST_DIRECTORY_TO_DELETE, 
baseDir.toFile());
+                        session.getData().set(LAST_DIRECTORY_TO_DELETE, 
baseDir);
                     }
                     baseDir = tmpDir;
                 } catch (IOException e) {
@@ -143,8 +167,8 @@ class Cleaner {
                     throw e;
                 }
             } catch (IOException e) {
-                if (log.isDebugEnabled()) {
-                    log.debug("Unable to fast delete directory: ", e);
+                if (logDebug != null) {
+                    logDebug.log("Unable to fast delete directory", e);
                 }
                 return false;
             }
@@ -155,10 +179,10 @@ class Cleaner {
                 Files.createDirectories(fastDir);
             }
         } catch (IOException e) {
-            if (log.isDebugEnabled()) {
-                log.debug(
+            if (logDebug != null) {
+                logDebug.log(
                         "Unable to fast delete directory as the path " + 
fastDir
-                                + " does not point to a directory or cannot be 
created: ",
+                                + " does not point to a directory or cannot be 
created",
                         e);
             }
             return false;
@@ -172,11 +196,11 @@ class Cleaner {
             // or any other exception occurs, an exception will be thrown in 
which case
             // the method will return false and the usual deletion will be 
performed.
             Files.move(baseDir, dstDir, StandardCopyOption.ATOMIC_MOVE);
-            BackgroundCleaner.delete(this, tmpDir.toFile(), fastMode);
+            BackgroundCleaner.delete(this, tmpDir, fastMode);
             return true;
         } catch (IOException e) {
-            if (log.isDebugEnabled()) {
-                log.debug("Unable to fast delete directory: ", e);
+            if (logDebug != null) {
+                logDebug.log("Unable to fast delete directory", e);
             }
             return false;
         }
@@ -185,20 +209,20 @@ class Cleaner {
     /**
      * Deletes the specified file or directory.
      *
-     * @param file           The file/directory to delete, must not be 
<code>null</code>. If <code>followSymlinks</code> is
-     *                       <code>false</code>, it is assumed that the parent 
file is canonical.
-     * @param pathname       The relative pathname of the file, using {@link 
File#separatorChar}, must not be
-     *                       <code>null</code>.
-     * @param selector       The selector used to determine what contents to 
delete, may be <code>null</code> to delete
-     *                       everything.
+     * @param file The file/directory to delete, must not be 
<code>null</code>. If <code>followSymlinks</code> is
+     *            <code>false</code>, it is assumed that the parent file is 
canonical.
+     * @param pathname The relative pathname of the file, using {@link 
File#separatorChar}, must not be
+     *            <code>null</code>.
+     * @param selector The selector used to determine what contents to delete, 
may be <code>null</code> to delete
+     *            everything.
      * @param followSymlinks Whether to follow symlinks.
-     * @param failOnError    Whether to abort with an exception in case a 
selected file/directory could not be deleted.
-     * @param retryOnError   Whether to undertake additional delete attempts 
in case the first attempt failed.
+     * @param failOnError Whether to abort with an exception in case a 
selected file/directory could not be deleted.
+     * @param retryOnError Whether to undertake additional delete attempts in 
case the first attempt failed.
      * @return The result of the cleaning, never <code>null</code>.
      * @throws IOException If a file/directory could not be deleted and 
<code>failOnError</code> is <code>true</code>.
      */
     private Result delete(
-            File file,
+            Path file,
             String pathname,
             Selector selector,
             boolean followSymlinks,
@@ -207,46 +231,43 @@ class Cleaner {
             throws IOException {
         Result result = new Result();
 
-        boolean isDirectory = file.isDirectory();
+        boolean isDirectory = Files.isDirectory(file);
 
         if (isDirectory) {
             if (selector == null || selector.couldHoldSelected(pathname)) {
-                if (followSymlinks || !isSymbolicLink(file.toPath())) {
-                    File canonical = followSymlinks ? file : 
file.getCanonicalFile();
-                    String[] filenames = canonical.list();
-                    if (filenames != null) {
-                        String prefix = pathname.length() > 0 ? pathname + 
File.separatorChar : "";
-                        for (int i = filenames.length - 1; i >= 0; i--) {
-                            String filename = filenames[i];
-                            File child = new File(canonical, filename);
+                final boolean isSymlink = isSymbolicLink(file);
+                Path canonical = followSymlinks ? file : 
getCanonicalPath(file);
+                if (followSymlinks || !isSymlink) {
+                    String prefix = !pathname.isEmpty() ? pathname + 
File.separatorChar : "";
+                    try (Stream<Path> children = Files.list(canonical)) {
+                        for (Path child : children.toList()) {
                             result.update(delete(
-                                    child, prefix + filename, selector, 
followSymlinks, failOnError, retryOnError));
+                                    child,
+                                    prefix + child.getFileName(),
+                                    selector,
+                                    followSymlinks,
+                                    failOnError,
+                                    retryOnError));
                         }
                     }
-                } else if (log.isDebugEnabled()) {
-                    log.debug("Not recursing into symlink " + file);
+                } else if (logDebug != null) {
+                    logDebug.log("Not recursing into symlink " + file);
                 }
-            } else if (log.isDebugEnabled()) {
-                log.debug("Not recursing into directory without included files 
" + file);
+            } else if (logDebug != null) {
+                logDebug.log("Not recursing into directory without included 
files " + file);
             }
         }
 
         if (!result.excluded && (selector == null || 
selector.isSelected(pathname))) {
-            String logmessage;
-            if (isDirectory) {
-                logmessage = "Deleting directory " + file;
-            } else if (file.exists()) {
-                logmessage = "Deleting file " + file;
-            } else {
-                logmessage = "Deleting dangling symlink " + file;
-            }
-
-            if (verbose && log.isInfoEnabled()) {
-                log.info(logmessage);
-            } else if (log.isDebugEnabled()) {
-                log.debug(logmessage);
+            if (logVerbose != null) {
+                if (isDirectory) {
+                    logVerbose.log("Deleting directory " + file);
+                } else if (Files.exists(file)) {
+                    logVerbose.log("Deleting file " + file);
+                } else {
+                    logVerbose.log("Deleting dangling symlink " + file);
+                }
             }
-
             result.failures += delete(file, failOnError, retryOnError);
         } else {
             result.excluded = true;
@@ -255,6 +276,14 @@ class Cleaner {
         return result;
     }
 
+    private static Path getCanonicalPath(Path path) {
+        try {
+            return path.toRealPath();
+        } catch (IOException e) {
+            return 
getCanonicalPath(path.getParent()).resolve(path.getFileName());
+        }
+    }
+
     private boolean isSymbolicLink(Path path) throws IOException {
         BasicFileAttributes attrs = Files.readAttributes(path, 
BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
         return attrs.isSymbolicLink()
@@ -262,19 +291,13 @@ class Cleaner {
                 || (attrs.isDirectory() && attrs.isOther());
     }
 
-    /**
-     * Deletes the specified file, directory. If the path denotes a symlink, 
only the link is removed, its target is
-     * left untouched.
-     *
-     * @param file         The file/directory to delete, must not be 
<code>null</code>.
-     * @param failOnError  Whether to abort with an exception in case the 
file/directory could not be deleted.
-     * @param retryOnError Whether to undertake additional delete attempts in 
case the first attempt failed.
-     * @return <code>0</code> if the file was deleted, <code>1</code> 
otherwise.
-     * @throws IOException If a file/directory could not be deleted and 
<code>failOnError</code> is <code>true</code>.
-     */
-    private int delete(File file, boolean failOnError, boolean retryOnError) 
throws IOException {
-        if (!file.delete()) {
-            boolean deleted = false;
+    private int delete(Path file, boolean failOnError, boolean retryOnError) 
throws IOException {
+        try {
+            Files.deleteIfExists(file);
+            return 0;
+        } catch (IOException e) {
+            IOException exception = new IOException("Failed to delete " + 
file);
+            exception.addSuppressed(e);
 
             if (retryOnError) {
                 if (ON_WINDOWS) {
@@ -283,24 +306,27 @@ class Cleaner {
                 }
 
                 final int[] delays = {50, 250, 750};
-                for (int i = 0; !deleted && i < delays.length; i++) {
+                for (int delay : delays) {
                     try {
-                        Thread.sleep(delays[i]);
-                    } catch (InterruptedException e) {
-                        // ignore
+                        Thread.sleep(delay);
+                    } catch (InterruptedException e2) {
+                        exception.addSuppressed(e2);
+                    }
+                    try {
+                        Files.deleteIfExists(file);
+                        return 0;
+                    } catch (IOException e2) {
+                        exception.addSuppressed(e2);
                     }
-                    deleted = file.delete() || !file.exists();
                 }
-            } else {
-                deleted = !file.exists();
             }
 
-            if (!deleted) {
+            if (Files.exists(file)) {
                 if (failOnError) {
-                    throw new IOException("Failed to delete " + file);
+                    throw new IOException("Failed to delete " + file, 
exception);
                 } else {
-                    if (log.isWarnEnabled()) {
-                        log.warn("Failed to delete " + file);
+                    if (logWarn != null) {
+                        logWarn.log("Failed to delete " + file, exception);
                     }
                     return 1;
                 }
@@ -322,25 +348,30 @@ class Cleaner {
         }
     }
 
+    private interface Logger {
+
+        void log(CharSequence message);
+
+        void log(CharSequence message, Throwable t);
+    }
+
     private static class BackgroundCleaner extends Thread {
 
-        private static final int NEW = 0;
-        private static final int RUNNING = 1;
-        private static final int STOPPED = 2;
         private static BackgroundCleaner instance;
-        private final Deque<File> filesToDelete = new ArrayDeque<>();
+
+        private final Deque<Path> filesToDelete = new ArrayDeque<>();
+
         private final Cleaner cleaner;
+
         private final String fastMode;
-        private int status = NEW;
 
-        private BackgroundCleaner(Cleaner cleaner, File dir, String fastMode) {
-            super("mvn-background-cleaner");
-            this.cleaner = cleaner;
-            this.fastMode = fastMode;
-            init(cleaner.fastDir, dir);
-        }
+        private static final int NEW = 0;
+        private static final int RUNNING = 1;
+        private static final int STOPPED = 2;
 
-        public static void delete(Cleaner cleaner, File dir, String fastMode) {
+        private int status = NEW;
+
+        public static void delete(Cleaner cleaner, Path dir, String fastMode) {
             synchronized (BackgroundCleaner.class) {
                 if (instance == null || !instance.doDelete(dir)) {
                     instance = new BackgroundCleaner(cleaner, dir, fastMode);
@@ -356,9 +387,16 @@ class Cleaner {
             }
         }
 
+        private BackgroundCleaner(Cleaner cleaner, Path dir, String fastMode) {
+            super("mvn-background-cleaner");
+            this.cleaner = cleaner;
+            this.fastMode = fastMode;
+            init(cleaner.fastDir, dir);
+        }
+
         public void run() {
             while (true) {
-                File basedir = pollNext();
+                Path basedir = pollNext();
                 if (basedir == null) {
                     break;
                 }
@@ -370,24 +408,25 @@ class Cleaner {
             }
         }
 
-        synchronized void init(File fastDir, File dir) {
-            if (fastDir.isDirectory()) {
-                File[] children = fastDir.listFiles();
-                if (children != null && children.length > 0) {
-                    for (File child : children) {
-                        doDelete(child);
+        synchronized void init(Path fastDir, Path dir) {
+            if (Files.isDirectory(fastDir)) {
+                try {
+                    try (Stream<Path> children = Files.list(fastDir)) {
+                        children.forEach(this::doDelete);
                     }
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
                 }
             }
             doDelete(dir);
         }
 
-        synchronized File pollNext() {
-            File basedir = filesToDelete.poll();
+        synchronized Path pollNext() {
+            Path basedir = filesToDelete.poll();
             if (basedir == null) {
                 if (cleaner.session != null) {
-                    SessionData data = 
cleaner.session.getRepositorySession().getData();
-                    File lastDir = (File) data.get(LAST_DIRECTORY_TO_DELETE);
+                    SessionData data = cleaner.session.getData();
+                    Path lastDir = (Path) data.get(LAST_DIRECTORY_TO_DELETE);
                     if (lastDir != null) {
                         data.set(LAST_DIRECTORY_TO_DELETE, null);
                         return lastDir;
@@ -399,7 +438,7 @@ class Cleaner {
             return basedir;
         }
 
-        synchronized boolean doDelete(File dir) {
+        synchronized boolean doDelete(Path dir) {
             if (status == STOPPED) {
                 return false;
             }
@@ -421,15 +460,10 @@ class Cleaner {
          * to outlive its main execution.
          */
         private void wrapExecutionListener() {
-            ExecutionListener executionListener = 
cleaner.session.getRequest().getExecutionListener();
-            if (executionListener == null
-                    || !Proxy.isProxyClass(executionListener.getClass())
-                    || !(Proxy.getInvocationHandler(executionListener) 
instanceof SpyInvocationHandler)) {
-                ExecutionListener listener = (ExecutionListener) 
Proxy.newProxyInstance(
-                        ExecutionListener.class.getClassLoader(),
-                        new Class[] {ExecutionListener.class},
-                        new SpyInvocationHandler(executionListener));
-                cleaner.session.getRequest().setExecutionListener(listener);
+            synchronized (CleanerListener.class) {
+                if (cleaner.session.getListeners().stream().noneMatch(l -> l 
instanceof CleanerListener)) {
+                    cleaner.session.registerListener(new CleanerListener());
+                }
             }
         }
 
@@ -440,8 +474,8 @@ class Cleaner {
                 }
                 if (!FAST_MODE_DEFER.equals(fastMode)) {
                     try {
-                        if (cleaner.log.isInfoEnabled()) {
-                            cleaner.log.info("Waiting for background file 
deletion");
+                        if (cleaner.logInfo != null) {
+                            cleaner.logInfo.log("Waiting for background file 
deletion");
                         }
                         while (status != STOPPED) {
                             wait();
@@ -454,22 +488,12 @@ class Cleaner {
         }
     }
 
-    static class SpyInvocationHandler implements InvocationHandler {
-        private final ExecutionListener delegate;
-
-        SpyInvocationHandler(ExecutionListener delegate) {
-            this.delegate = delegate;
-        }
-
+    static class CleanerListener implements Listener {
         @Override
-        public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable {
-            if ("sessionEnded".equals(method.getName())) {
+        public void onEvent(Event event) {
+            if (event.getType() == EventType.SESSION_ENDED) {
                 BackgroundCleaner.sessionEnd();
             }
-            if (delegate != null) {
-                return method.invoke(delegate, args);
-            }
-            return null;
         }
     }
 }
diff --git a/src/main/java/org/apache/maven/plugins/clean/Fileset.java 
b/src/main/java/org/apache/maven/plugins/clean/Fileset.java
index ecd88b0..7508411 100644
--- a/src/main/java/org/apache/maven/plugins/clean/Fileset.java
+++ b/src/main/java/org/apache/maven/plugins/clean/Fileset.java
@@ -18,7 +18,7 @@
  */
 package org.apache.maven.plugins.clean;
 
-import java.io.File;
+import java.nio.file.Path;
 import java.util.Arrays;
 
 /**
@@ -32,7 +32,7 @@ import java.util.Arrays;
  */
 public class Fileset {
 
-    private File directory;
+    private Path directory;
 
     private String[] includes;
 
@@ -45,7 +45,7 @@ public class Fileset {
     /**
      * @return {@link #directory}
      */
-    public File getDirectory() {
+    public Path getDirectory() {
         return directory;
     }
 
diff --git a/src/site/apt/examples/delete_additional_files.apt.vm 
b/src/site/apt/examples/delete_additional_files.apt.vm
index 0fa768c..84ed079 100644
--- a/src/site/apt/examples/delete_additional_files.apt.vm
+++ b/src/site/apt/examples/delete_additional_files.apt.vm
@@ -68,7 +68,7 @@ Delete Additional Files Not Exposed to Maven
  is equivalent to:
 
 +--------
-  <directory>${project.basedir}/some/relative/path</directory>
+  <directory>${basedir}/some/relative/path</directory>
 +--------
 
  You could also define file set rules in a parent POM. In this case, the clean 
plugin adds the subproject
diff --git a/src/test/java/org/apache/maven/plugins/clean/CleanMojoTest.java 
b/src/test/java/org/apache/maven/plugins/clean/CleanMojoTest.java
index 22287d7..5a5d0d4 100644
--- a/src/test/java/org/apache/maven/plugins/clean/CleanMojoTest.java
+++ b/src/test/java/org/apache/maven/plugins/clean/CleanMojoTest.java
@@ -29,17 +29,17 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Collections;
 
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.logging.SystemStreamLog;
-import org.apache.maven.plugin.testing.junit5.InjectMojo;
-import org.apache.maven.plugin.testing.junit5.MojoTest;
+import org.apache.maven.api.plugin.MojoException;
+import org.apache.maven.api.plugin.testing.Basedir;
+import org.apache.maven.api.plugin.testing.InjectMojo;
+import org.apache.maven.api.plugin.testing.MojoTest;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledOnOs;
 import org.junit.jupiter.api.condition.EnabledOnOs;
 import org.junit.jupiter.api.condition.OS;
 
-import static 
org.apache.maven.plugin.testing.junit5.MojoExtension.setVariableValueToObject;
-import static org.codehaus.plexus.testing.PlexusExtension.getBasedir;
+import static org.apache.maven.api.plugin.testing.MojoExtension.getBasedir;
+import static 
org.apache.maven.api.plugin.testing.MojoExtension.setVariableValueToObject;
 import static org.codehaus.plexus.util.IOUtil.copy;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -49,30 +49,25 @@ import static org.junit.jupiter.api.Assertions.fail;
 
 /**
  * Test the clean mojo.
- *
- * @author <a href="mailto:[email protected]";>Vincent Siveton</a>
  */
 @MojoTest
-class CleanMojoTest {
+public class CleanMojoTest {
+    private static final String LOCAL_REPO = "target/local-repo/";
+
     /**
      * Tests the simple removal of directories
      *
      * @throws Exception in case of an error.
      */
     @Test
-    @InjectMojo(goal = "clean", pom = 
"classpath:/unit/basic-clean-test/plugin-pom.xml")
-    void testBasicClean(CleanMojo mojo) throws Exception {
+    @Basedir("${basedir}/target/test-classes/unit/basic-clean-test")
+    @InjectMojo(goal = "clean")
+    public void testBasicClean(CleanMojo mojo) throws Exception {
         mojo.execute();
 
-        assertFalse(
-                checkExists(getBasedir() + "/target/test-classes/unit/" + 
"basic-clean-test/buildDirectory"),
-                "Directory exists");
-        assertFalse(
-                checkExists(getBasedir() + 
"/target/test-classes/unit/basic-clean-test/" + "buildOutputDirectory"),
-                "Directory exists");
-        assertFalse(
-                checkExists(getBasedir() + 
"/target/test-classes/unit/basic-clean-test/" + "buildTestDirectory"),
-                "Directory exists");
+        assertFalse(checkExists(getBasedir() + "/buildDirectory"), "Directory 
exists");
+        assertFalse(checkExists(getBasedir() + "/buildOutputDirectory"), 
"Directory exists");
+        assertFalse(checkExists(getBasedir() + "/buildTestDirectory"), 
"Directory exists");
     }
 
     /**
@@ -81,13 +76,14 @@ class CleanMojoTest {
      * @throws Exception in case of an error.
      */
     @Test
-    @InjectMojo(goal = "clean", pom = 
"classpath:/unit/nested-clean-test/plugin-pom.xml")
-    void testCleanNestedStructure(CleanMojo mojo) throws Exception {
+    @Basedir("${basedir}/target/test-classes/unit/nested-clean-test")
+    @InjectMojo(goal = "clean")
+    public void testCleanNestedStructure(CleanMojo mojo) throws Exception {
         mojo.execute();
 
-        assertFalse(checkExists(getBasedir() + 
"/target/test-classes/unit/nested-clean-test/target"));
-        assertFalse(checkExists(getBasedir() + 
"/target/test-classes/unit/nested-clean-test/target/classes"));
-        assertFalse(checkExists(getBasedir() + 
"/target/test-classes/unit/nested-clean-test/target/test-classes"));
+        assertFalse(checkExists(getBasedir() + "/target"));
+        assertFalse(checkExists(getBasedir() + "/target/classes"));
+        assertFalse(checkExists(getBasedir() + "/target/test-classes"));
     }
 
     /**
@@ -97,17 +93,15 @@ class CleanMojoTest {
      * @throws Exception in case of an error.
      */
     @Test
-    @InjectMojo(goal = "clean", pom = 
"classpath:/unit/empty-clean-test/plugin-pom.xml")
-    void testCleanEmptyDirectories(CleanMojo mojo) throws Exception {
+    @Basedir("${basedir}/target/test-classes/unit/empty-clean-test")
+    @InjectMojo(goal = "clean")
+    public void testCleanEmptyDirectories(CleanMojo mojo) throws Exception {
         mojo.execute();
 
-        assertTrue(checkExists(getBasedir() + 
"/target/test-classes/unit/empty-clean-test/testDirectoryStructure"));
-        assertTrue(checkExists(
-                getBasedir() + "/target/test-classes/unit/empty-clean-test/" + 
"testDirectoryStructure/file.txt"));
-        assertTrue(checkExists(getBasedir() + 
"/target/test-classes/unit/empty-clean-test/"
-                + "testDirectoryStructure/outputDirectory"));
-        assertTrue(checkExists(getBasedir() + 
"/target/test-classes/unit/empty-clean-test/"
-                + "testDirectoryStructure/outputDirectory/file.txt"));
+        assertTrue(checkExists(getBasedir() + "/testDirectoryStructure"));
+        assertTrue(checkExists(getBasedir() + 
"/testDirectoryStructure/file.txt"));
+        assertTrue(checkExists(getBasedir() + 
"/testDirectoryStructure/outputDirectory"));
+        assertTrue(checkExists(getBasedir() + 
"/testDirectoryStructure/outputDirectory/file.txt"));
     }
 
     /**
@@ -116,25 +110,24 @@ class CleanMojoTest {
      * @throws Exception in case of an error.
      */
     @Test
-    @InjectMojo(goal = "clean", pom = 
"classpath:/unit/fileset-clean-test/plugin-pom.xml")
-    void testFilesetsClean(CleanMojo mojo) throws Exception {
+    @Basedir("${basedir}/target/test-classes/unit/fileset-clean-test")
+    @InjectMojo(goal = "clean")
+    public void testFilesetsClean(CleanMojo mojo) throws Exception {
         mojo.execute();
 
         // fileset 1
-        assertTrue(checkExists(getBasedir() + 
"/target/test-classes/unit/fileset-clean-test/target"));
-        assertTrue(checkExists(getBasedir() + 
"/target/test-classes/unit/fileset-clean-test/target/classes"));
-        assertFalse(checkExists(getBasedir() + 
"/target/test-classes/unit/fileset-clean-test/target/test-classes"));
-        assertTrue(checkExists(getBasedir() + 
"/target/test-classes/unit/fileset-clean-test/target/subdir"));
-        assertFalse(checkExists(getBasedir() + 
"/target/test-classes/unit/fileset-clean-test/target/classes/file.txt"));
-        assertTrue(checkEmpty(getBasedir() + 
"/target/test-classes/unit/fileset-clean-test/target/classes"));
-        assertFalse(checkEmpty(getBasedir() + 
"/target/test-classes/unit/fileset-clean-test/target/subdir"));
-        assertTrue(checkExists(getBasedir() + 
"/target/test-classes/unit/fileset-clean-test/target/subdir/file.txt"));
+        assertTrue(checkExists(getBasedir() + "/target"));
+        assertTrue(checkExists(getBasedir() + "/target/classes"));
+        assertFalse(checkExists(getBasedir() + "/target/test-classes"));
+        assertTrue(checkExists(getBasedir() + "/target/subdir"));
+        assertFalse(checkExists(getBasedir() + "/target/classes/file.txt"));
+        assertTrue(checkEmpty(getBasedir() + "/target/classes"));
+        assertFalse(checkEmpty(getBasedir() + "/target/subdir"));
+        assertTrue(checkExists(getBasedir() + "/target/subdir/file.txt"));
 
         // fileset 2
-        assertTrue(
-                checkExists(getBasedir() + 
"/target/test-classes/unit/fileset-clean-test/" + "buildOutputDirectory"));
-        assertFalse(checkExists(
-                getBasedir() + "/target/test-classes/unit/fileset-clean-test/" 
+ "buildOutputDirectory/file.txt"));
+        assertTrue(checkExists(getBasedir() + "/" + "buildOutputDirectory"));
+        assertFalse(checkExists(getBasedir() + "/" + 
"buildOutputDirectory/file.txt"));
     }
 
     /**
@@ -143,9 +136,10 @@ class CleanMojoTest {
      * @throws Exception in case of an error.
      */
     @Test
-    @InjectMojo(goal = "clean", pom = 
"classpath:/unit/invalid-directory-test/plugin-pom.xml")
-    void testCleanInvalidDirectory(CleanMojo mojo) throws Exception {
-        assertThrows(MojoExecutionException.class, mojo::execute);
+    @Basedir("${basedir}/target/test-classes/unit/invalid-directory-test")
+    @InjectMojo(goal = "clean")
+    public void testCleanInvalidDirectory(CleanMojo mojo) throws Exception {
+        assertThrows(MojoException.class, mojo::execute, "Should fail to 
delete a file treated as a directory");
     }
 
     /**
@@ -154,11 +148,12 @@ class CleanMojoTest {
      * @throws Exception in case of an error.
      */
     @Test
-    @InjectMojo(goal = "clean", pom = 
"classpath:/unit/missing-directory-test/plugin-pom.xml")
-    void testMissingDirectory(CleanMojo mojo) throws Exception {
+    @Basedir("${basedir}/target/test-classes/unit/missing-directory-test")
+    @InjectMojo(goal = "clean")
+    public void testMissingDirectory(CleanMojo mojo) throws Exception {
         mojo.execute();
 
-        assertFalse(checkExists(getBasedir() + 
"/target/test-classes/unit/missing-directory-test/does-not-exist"));
+        assertFalse(checkExists(getBasedir() + "/does-not-exist"));
     }
 
     /**
@@ -171,14 +166,15 @@ class CleanMojoTest {
      */
     @Test
     @EnabledOnOs(OS.WINDOWS)
-    @InjectMojo(goal = "clean", pom = 
"classpath:/unit/locked-file-test/plugin-pom.xml")
-    void testCleanLockedFile(CleanMojo mojo) throws Exception {
-        File f = new File(getBasedir(), 
"target/test-classes/unit/locked-file-test/buildDirectory/file.txt");
+    @Basedir("${basedir}/target/test-classes/unit/locked-file-test")
+    @InjectMojo(goal = "clean")
+    public void testCleanLockedFile(CleanMojo mojo) throws Exception {
+        File f = new File(getBasedir(), "buildDirectory/file.txt");
         try (FileChannel channel = new RandomAccessFile(f, "rw").getChannel();
                 FileLock ignored = channel.lock()) {
             mojo.execute();
             fail("Should fail to delete a file that is locked");
-        } catch (MojoExecutionException expected) {
+        } catch (MojoException expected) {
             assertTrue(true);
         }
     }
@@ -193,29 +189,29 @@ class CleanMojoTest {
      */
     @Test
     @EnabledOnOs(OS.WINDOWS)
-    @InjectMojo(goal = "clean", pom = 
"classpath:/unit/locked-file-test/plugin-pom.xml")
-    void testCleanLockedFileWithNoError(CleanMojo mojo) throws Exception {
+    @Basedir("${basedir}/target/test-classes/unit/locked-file-test")
+    @InjectMojo(goal = "clean")
+    public void testCleanLockedFileWithNoError(CleanMojo mojo) throws 
Exception {
         setVariableValueToObject(mojo, "failOnError", Boolean.FALSE);
         assertNotNull(mojo);
 
-        File f = new File(getBasedir(), 
"target/test-classes/unit/locked-file-test/buildDirectory/file.txt");
+        File f = new File(getBasedir(), "buildDirectory/file.txt");
         try (FileChannel channel = new RandomAccessFile(f, "rw").getChannel();
                 FileLock ignored = channel.lock()) {
             mojo.execute();
             assertTrue(true);
-        } catch (MojoExecutionException expected) {
+        } catch (MojoException expected) {
             fail("Should display a warning when deleting a file that is 
locked");
         }
     }
 
     /**
      * Test the followLink option with windows junctions
-     *
      * @throws Exception
      */
     @Test
     @EnabledOnOs(OS.WINDOWS)
-    void testFollowLinksWithWindowsJunction() throws Exception {
+    public void testFollowLinksWithWindowsJunction() throws Exception {
         testSymlink((link, target) -> {
             Process process = new ProcessBuilder()
                     .directory(link.getParent().toFile())
@@ -233,12 +229,11 @@ class CleanMojoTest {
 
     /**
      * Test the followLink option with sym link
-     *
      * @throws Exception
      */
     @Test
     @DisabledOnOs(OS.WINDOWS)
-    void testFollowLinksWithSymLinkOnPosix() throws Exception {
+    public void testFollowLinksWithSymLinkOnPosix() throws Exception {
         testSymlink((link, target) -> {
             try {
                 Files.createSymbolicLink(link, target);
@@ -248,9 +243,13 @@ class CleanMojoTest {
         });
     }
 
+    @FunctionalInterface
+    interface LinkCreator {
+        void createLink(Path link, Path target) throws Exception;
+    }
+
     private void testSymlink(LinkCreator linkCreator) throws Exception {
-        // We use the SystemStreamLog() as the AbstractMojo class, because 
from there the Log is always provided
-        Cleaner cleaner = new Cleaner(null, new SystemStreamLog(), false, 
null, null);
+        Cleaner cleaner = new Cleaner(null, null, false, null, null);
         Path testDir = 
Paths.get("target/test-classes/unit/test-dir").toAbsolutePath();
         Path dirWithLnk = testDir.resolve("dir");
         Path orgDir = testDir.resolve("org-dir");
@@ -263,7 +262,7 @@ class CleanMojoTest {
         Files.write(file, Collections.singleton("Hello world"));
         linkCreator.createLink(jctDir, orgDir);
         // delete
-        cleaner.delete(dirWithLnk.toFile(), null, false, true, false);
+        cleaner.delete(dirWithLnk, null, false, true, false);
         // verify
         assertTrue(Files.exists(file));
         assertFalse(Files.exists(jctDir));
@@ -276,7 +275,7 @@ class CleanMojoTest {
         Files.write(file, Collections.singleton("Hello world"));
         linkCreator.createLink(jctDir, orgDir);
         // delete
-        cleaner.delete(dirWithLnk.toFile(), null, true, true, false);
+        cleaner.delete(dirWithLnk, null, true, true, false);
         // verify
         assertFalse(Files.exists(file));
         assertFalse(Files.exists(jctDir));
@@ -284,6 +283,32 @@ class CleanMojoTest {
         assertFalse(Files.exists(dirWithLnk));
     }
 
+    //    @Provides
+    //    @Singleton
+    //    private Project createProject() {
+    //        ProjectStub project = new ProjectStub();
+    //        project.setGroupId("myGroupId");
+    //        return project;
+    //    }
+
+    //    @Provides
+    //    @Singleton
+    //    @SuppressWarnings("unused")
+    //    private InternalSession createSession() {
+    //        InternalSession session = SessionStub.getMockSession(LOCAL_REPO);
+    //        Properties props = new Properties();
+    //        props.put("basedir", MojoExtension.getBasedir());
+    //        doReturn(props).when(session).getSystemProperties();
+    //        return session;
+    //    }
+
+    //    @Provides
+    //    @Singleton
+    //    @SuppressWarnings("unused")
+    //    private MojoExecution createMojoExecution() {
+    //        return new MojoExecutionStub("default-clean", "clean");
+    //    }
+
     /**
      * @param dir a dir or a file
      * @return true if a file/dir exists, false otherwise
@@ -300,9 +325,4 @@ class CleanMojoTest {
         File[] files = new File(dir).listFiles();
         return files == null || files.length == 0;
     }
-
-    @FunctionalInterface
-    interface LinkCreator {
-        void createLink(Path link, Path target) throws Exception;
-    }
 }
diff --git a/src/test/resources/unit/basic-clean-test/plugin-pom.xml 
b/src/test/resources/unit/basic-clean-test/plugin-pom.xml
deleted file mode 100644
index 38a6000..0000000
--- a/src/test/resources/unit/basic-clean-test/plugin-pom.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
--->
-
-<project>
-  <build>
-    <plugins>
-      <plugin>
-        <artifactId>maven-clean-plugin</artifactId>
-        <configuration>
-          
<directory>${basedir}/target/test-classes/unit/basic-clean-test/buildDirectory</directory>
-          
<outputDirectory>${basedir}/target/test-classes/unit/basic-clean-test/buildOutputDirectory</outputDirectory>
-          
<testOutputDirectory>${basedir}/target/test-classes/unit/basic-clean-test/buildTestDirectory</testOutputDirectory>
-          <verbose>true</verbose>
-          <failOnError>true</failOnError>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/src/test/resources/unit/locked-file-test/plugin-pom.xml 
b/src/test/resources/unit/basic-clean-test/pom.xml
similarity index 81%
copy from src/test/resources/unit/locked-file-test/plugin-pom.xml
copy to src/test/resources/unit/basic-clean-test/pom.xml
index 4101091..ba901f0 100644
--- a/src/test/resources/unit/locked-file-test/plugin-pom.xml
+++ b/src/test/resources/unit/basic-clean-test/pom.xml
@@ -23,7 +23,9 @@
       <plugin>
         <artifactId>maven-clean-plugin</artifactId>
         <configuration>
-          
<directory>${basedir}/target/test-classes/unit/locked-file-test/buildDirectory</directory>
+          <directory>${project.basedir}/buildDirectory</directory>
+          
<outputDirectory>${project.basedir}/buildOutputDirectory</outputDirectory>
+          
<testOutputDirectory>${project.basedir}/buildTestDirectory</testOutputDirectory>
           <verbose>true</verbose>
           <failOnError>true</failOnError>
         </configuration>
diff --git a/src/test/resources/unit/empty-clean-test/plugin-pom.xml 
b/src/test/resources/unit/empty-clean-test/pom.xml
similarity index 100%
rename from src/test/resources/unit/empty-clean-test/plugin-pom.xml
rename to src/test/resources/unit/empty-clean-test/pom.xml
diff --git a/src/test/resources/unit/fileset-clean-test/plugin-pom.xml 
b/src/test/resources/unit/fileset-clean-test/pom.xml
similarity index 88%
rename from src/test/resources/unit/fileset-clean-test/plugin-pom.xml
rename to src/test/resources/unit/fileset-clean-test/pom.xml
index 5cd3ab3..2457c4e 100644
--- a/src/test/resources/unit/fileset-clean-test/plugin-pom.xml
+++ b/src/test/resources/unit/fileset-clean-test/pom.xml
@@ -23,9 +23,10 @@
       <plugin>
         <artifactId>maven-clean-plugin</artifactId>
         <configuration>
+          <excludeDefaultDirectories>true</excludeDefaultDirectories>
           <filesets>
             <fileset>
-              
<directory>${basedir}/target/test-classes/unit/fileset-clean-test/target</directory>
+              <directory>${project.basedir}/target</directory>
               <includes>
                 <include>**/file.txt</include>
                 <include>**/test-classes/**</include>
@@ -35,7 +36,7 @@
               </excludes>
             </fileset>
             <fileset>
-              
<directory>${basedir}/target/test-classes/unit/fileset-clean-test/buildOutputDirectory</directory>
+              <directory>${project.basedir}/buildOutputDirectory</directory>
               <includes>
                 <include>**</include>
               </includes>
diff --git a/src/test/resources/unit/locked-file-test/plugin-pom.xml 
b/src/test/resources/unit/invalid-directory-test/pom.xml
similarity index 91%
copy from src/test/resources/unit/locked-file-test/plugin-pom.xml
copy to src/test/resources/unit/invalid-directory-test/pom.xml
index 4101091..5d35e78 100644
--- a/src/test/resources/unit/locked-file-test/plugin-pom.xml
+++ b/src/test/resources/unit/invalid-directory-test/pom.xml
@@ -23,7 +23,7 @@
       <plugin>
         <artifactId>maven-clean-plugin</artifactId>
         <configuration>
-          
<directory>${basedir}/target/test-classes/unit/locked-file-test/buildDirectory</directory>
+          <directory>${project.basedir}/this-is-a-file</directory>
           <verbose>true</verbose>
           <failOnError>true</failOnError>
         </configuration>
diff --git a/src/test/resources/unit/missing-directory-test/plugin-pom.xml 
b/src/test/resources/unit/locked-file-test/pom.xml
similarity index 91%
rename from src/test/resources/unit/missing-directory-test/plugin-pom.xml
rename to src/test/resources/unit/locked-file-test/pom.xml
index 15b3923..1f2f429 100644
--- a/src/test/resources/unit/missing-directory-test/plugin-pom.xml
+++ b/src/test/resources/unit/locked-file-test/pom.xml
@@ -23,7 +23,7 @@
       <plugin>
         <artifactId>maven-clean-plugin</artifactId>
         <configuration>
-          
<directory>${basedir}/target/test-classes/unit/missing-clean-test/does-not-exist</directory>
+          <directory>${project.basedir}/buildDirectory</directory>
           <verbose>true</verbose>
           <failOnError>true</failOnError>
         </configuration>
diff --git a/src/test/resources/unit/invalid-directory-test/plugin-pom.xml 
b/src/test/resources/unit/missing-directory-test/pom.xml
similarity index 91%
rename from src/test/resources/unit/invalid-directory-test/plugin-pom.xml
rename to src/test/resources/unit/missing-directory-test/pom.xml
index b562122..ec695d1 100644
--- a/src/test/resources/unit/invalid-directory-test/plugin-pom.xml
+++ b/src/test/resources/unit/missing-directory-test/pom.xml
@@ -23,7 +23,7 @@
       <plugin>
         <artifactId>maven-clean-plugin</artifactId>
         <configuration>
-          
<directory>${basedir}/target/test-classes/unit/invalid-directory-test/this-is-a-file</directory>
+          <directory>${project.basedir}/does-not-exist</directory>
           <verbose>true</verbose>
           <failOnError>true</failOnError>
         </configuration>
diff --git a/src/test/resources/unit/nested-clean-test/plugin-pom.xml 
b/src/test/resources/unit/nested-clean-test/plugin-pom.xml
deleted file mode 100644
index 790d14d..0000000
--- a/src/test/resources/unit/nested-clean-test/plugin-pom.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-    KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
--->
-
-<project>
-  <build>
-    <plugins>
-      <plugin>
-        <artifactId>maven-clean-plugin</artifactId>
-        <configuration>
-          
<directory>${basedir}/target/test-classes/unit/nested-clean-test/target</directory>
-          
<outputDirectory>${basedir}/target/test-classes/unit/nested-clean-test/target/classes</outputDirectory>
-          
<testOutputDirectory>${basedir}/target/test-classes/unit/nested-clean-test/target/test-classes</testOutputDirectory>
-          <verbose>true</verbose>
-          <failOnError>true</failOnError>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-</project>
diff --git a/src/test/resources/unit/locked-file-test/plugin-pom.xml 
b/src/test/resources/unit/nested-clean-test/pom.xml
similarity index 82%
rename from src/test/resources/unit/locked-file-test/plugin-pom.xml
rename to src/test/resources/unit/nested-clean-test/pom.xml
index 4101091..5f9e755 100644
--- a/src/test/resources/unit/locked-file-test/plugin-pom.xml
+++ b/src/test/resources/unit/nested-clean-test/pom.xml
@@ -23,7 +23,9 @@
       <plugin>
         <artifactId>maven-clean-plugin</artifactId>
         <configuration>
-          
<directory>${basedir}/target/test-classes/unit/locked-file-test/buildDirectory</directory>
+          <directory>${project.basedir}/target</directory>
+          <outputDirectory>${project.basedir}/target/classes</outputDirectory>
+          
<testOutputDirectory>${project.basedir}/target/test-classes</testOutputDirectory>
           <verbose>true</verbose>
           <failOnError>true</failOnError>
         </configuration>

Reply via email to