You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/07/29 12:11:32 UTC
(maven-filtering) 01/02: Experiment: migrate from plexus-build-api to Maven 4 BuildContext API
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch experiment/maven4-build-context
in repository https://gitbox.apache.org/repos/asf/maven-filtering.git
commit 4999468a6541ce3694d198a57974f90ffc4dedea
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Jul 29 13:45:49 2026 +0200
Experiment: migrate from plexus-build-api to Maven 4 BuildContext API
Replace the old Scanner-based plexus BuildContext with the new Maven 4
BuildContext API (org.apache.maven.api.build.context.BuildContext) from
maven-api-core 4.1.0-SNAPSHOT (PR apache/maven#12576).
Key changes:
- DefaultMavenResourcesFiltering: replace buildContext.newScanner() and
newDeleteScanner() with buildContext.registerAndProcessInputs() which
returns Input objects with change status tracking
- DefaultMavenFileFilter: remove buildContext.refresh() — output tracking
is now handled by the BuildContext output association in the mojo
- Remove plexus-build-api dependency from pom.xml
- Delete old TestIncrementalBuildContext and IncrementalResourceFilteringTest
(these tested the old Scanner-based API)
Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
---
pom.xml | 8 +-
.../shared/filtering/DefaultMavenFileFilter.java | 13 +-
.../filtering/DefaultMavenResourcesFiltering.java | 172 ++++++++--------
.../filtering/DefaultMavenFileFilterTest.java | 4 +-
.../IncrementalResourceFilteringTest.java | 210 -------------------
.../apache/maven/shared/filtering/Providers.java | 11 +-
.../filtering/TestIncrementalBuildContext.java | 224 ---------------------
7 files changed, 100 insertions(+), 542 deletions(-)
diff --git a/pom.xml b/pom.xml
index a41e938..622ec54 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,7 @@
<properties>
<javaVersion>17</javaVersion>
- <mavenVersion>4.0.0-rc-5</mavenVersion>
+ <mavenVersion>4.1.0-SNAPSHOT</mavenVersion>
<hamcrestVersion>3.0</hamcrestVersion>
<junitVersion>5.14.4</junitVersion>
@@ -109,11 +109,7 @@
<artifactId>slf4j-api</artifactId>
<version>${slf4jVersion}</version>
</dependency>
- <dependency>
- <groupId>org.sonatype.plexus</groupId>
- <artifactId>plexus-build-api</artifactId>
- <version>${plexusBuildApiVersion}</version>
- </dependency>
+ <!-- plexus-build-api replaced by org.apache.maven.api.build.context.BuildContext from maven-api-core -->
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
diff --git a/src/main/java/org/apache/maven/shared/filtering/DefaultMavenFileFilter.java b/src/main/java/org/apache/maven/shared/filtering/DefaultMavenFileFilter.java
index fab9657..b65e4d2 100644
--- a/src/main/java/org/apache/maven/shared/filtering/DefaultMavenFileFilter.java
+++ b/src/main/java/org/apache/maven/shared/filtering/DefaultMavenFileFilter.java
@@ -24,12 +24,8 @@ import java.util.List;
import org.apache.maven.api.Project;
import org.apache.maven.api.Session;
-import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
-import org.sonatype.plexus.build.incremental.BuildContext;
-
-import static java.util.Objects.requireNonNull;
/**
* @author Olivier Lamy
@@ -37,12 +33,6 @@ import static java.util.Objects.requireNonNull;
@Singleton
@Named
public class DefaultMavenFileFilter extends BaseFilter implements MavenFileFilter {
- private final BuildContext buildContext;
-
- @Inject
- public DefaultMavenFileFilter(BuildContext buildContext) {
- this.buildContext = requireNonNull(buildContext);
- }
@Override
public void copyFile(
@@ -90,8 +80,7 @@ public class DefaultMavenFileFilter extends BaseFilter implements MavenFileFilte
getLogger().debug("copy {} to {}", from, to);
FilteringUtils.copyFile(from, to, encoding, new FilterWrapper[0], false);
}
-
- buildContext.refresh(to.toFile());
+ // Output refresh is handled by the BuildContext output association in the mojo
} catch (IOException e) {
throw new MavenFilteringException(
(filtering ? "filtering " : "copying ") + from + " to " + to + " failed with "
diff --git a/src/main/java/org/apache/maven/shared/filtering/DefaultMavenResourcesFiltering.java b/src/main/java/org/apache/maven/shared/filtering/DefaultMavenResourcesFiltering.java
index 406330c..6d59a35 100644
--- a/src/main/java/org/apache/maven/shared/filtering/DefaultMavenResourcesFiltering.java
+++ b/src/main/java/org/apache/maven/shared/filtering/DefaultMavenResourcesFiltering.java
@@ -27,17 +27,17 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.Locale;
+import org.apache.maven.api.build.context.BuildContext;
+import org.apache.maven.api.build.context.Input;
import org.apache.maven.api.di.Inject;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.di.Singleton;
-import org.codehaus.plexus.util.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.sonatype.plexus.build.incremental.BuildContext;
import static java.util.Objects.requireNonNull;
@@ -49,9 +49,7 @@ import static java.util.Objects.requireNonNull;
public class DefaultMavenResourcesFiltering implements MavenResourcesFiltering {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultMavenResourcesFiltering.class);
- private static final String[] EMPTY_STRING_ARRAY = {};
-
- private static final String[] DEFAULT_INCLUDES = {"**/**"};
+ // DEFAULT_INCLUDES is no longer needed — includes are passed directly to BuildContext.registerAndProcessInputs()
private static final int BUFFER_LENGTH = 8192;
private final List<String> defaultNonFilteredFileExtensions;
@@ -63,7 +61,7 @@ public class DefaultMavenResourcesFiltering implements MavenResourcesFiltering {
@Inject
public DefaultMavenResourcesFiltering(MavenFileFilter mavenFileFilter, BuildContext buildContext) {
this.mavenFileFilter = requireNonNull(mavenFileFilter);
- this.buildContext = requireNonNull(buildContext);
+ this.buildContext = buildContext; // may be null when running without incremental support
this.defaultNonFilteredFileExtensions = new ArrayList<>(5);
this.defaultNonFilteredFileExtensions.add("jpg");
this.defaultNonFilteredFileExtensions.add("jpeg");
@@ -205,28 +203,54 @@ public class DefaultMavenResourcesFiltering implements MavenResourcesFiltering {
isFilteringUsed = true;
}
- boolean ignoreDelta = !outputExists
- || buildContext.hasDelta(mavenResourcesExecution.getFileFilters())
- || buildContext.hasDelta(getRelativeOutputDirectory(mavenResourcesExecution));
- LOGGER.debug("ignoreDelta " + ignoreDelta);
- Scanner scanner = buildContext.newScanner(resourceDirectory.toFile(), ignoreDelta);
+ // Use the new BuildContext API to register inputs and detect changes
+ List<String> includes = resource.getIncludes();
+ if (includes == null || includes.isEmpty()) {
+ includes = List.of("**/**");
+ }
+ List<String> excludes = resource.getExcludes();
+ if (excludes == null) {
+ excludes = List.of();
+ }
- setupScanner(resource, scanner, mavenResourcesExecution.isAddDefaultExcludes());
+ // Register all resource files as inputs with the incremental build context.
+ // The BuildContext tracks file changes (NEW, MODIFIED, REMOVED, UNMODIFIED)
+ // and handles stale output cleanup automatically for REMOVED inputs.
+ Collection<? extends Input> inputs;
+ if (buildContext != null) {
+ if (mavenResourcesExecution.isAddDefaultExcludes()) {
+ excludes = new ArrayList<>(excludes);
+ addDefaultExcludes(excludes);
+ }
+ inputs = buildContext.registerAndProcessInputs(resourceDirectory, includes, excludes);
+ } else {
+ // Fallback: no build context — process all files
+ inputs = null;
+ }
- scanner.scan();
+ // Build list of included files from the registered inputs
+ List<String> includedFiles;
+ if (inputs != null) {
+ final Path resDirFinal = resourceDirectory;
+ includedFiles = inputs.stream()
+ .map(input -> resDirFinal.relativize(input.getPath()).toString())
+ .toList();
+ } else {
+ // No build context — scan directory manually
+ includedFiles = scanDirectory(
+ resourceDirectory, includes, excludes, mavenResourcesExecution.isAddDefaultExcludes());
+ }
if (mavenResourcesExecution.isIncludeEmptyDirs()) {
try {
Path targetDirectory = targetPath == null ? outputDirectory : outputDirectory.resolve(targetPath);
- copyDirectoryLayout(resourceDirectory, targetDirectory, scanner);
+ copyDirectoryLayout(resourceDirectory, targetDirectory);
} catch (IOException e) {
throw new MavenFilteringException(
"Cannot copy directory structure from " + resourceDirectory + " to " + outputDirectory);
}
}
- List<String> includedFiles = Arrays.asList(scanner.getIncludedFiles());
-
try {
Path basedir =
mavenResourcesExecution.getMavenProject().getBasedir().toAbsolutePath();
@@ -278,25 +302,9 @@ public class DefaultMavenResourcesFiltering implements MavenResourcesFiltering {
encoding);
}
- // deal with deleted source files
-
- scanner = buildContext.newDeleteScanner(resourceDirectory.toFile());
-
- setupScanner(resource, scanner, mavenResourcesExecution.isAddDefaultExcludes());
-
- scanner.scan();
-
- for (String name : scanner.getIncludedFiles()) {
- Path destinationFile = getDestinationFile(outputDirectory, targetPath, name, mavenResourcesExecution);
-
- try {
- Files.deleteIfExists(destinationFile);
- } catch (IOException e) {
- // ignore
- }
-
- buildContext.refresh(destinationFile.toFile());
- }
+ // Stale output cleanup for deleted inputs is handled automatically
+ // by the BuildContext when inputs have status REMOVED — no explicit
+ // delete scanner needed.
}
// Warn the user if all of the following requirements are met, to avoid those that are not affected
@@ -405,27 +413,47 @@ public class DefaultMavenResourcesFiltering implements MavenResourcesFiltering {
return destinationFile;
}
- private void setupScanner(Resource resource, Scanner scanner, boolean addDefaultExcludes) {
- String[] includes;
- if (resource.getIncludes() != null && !resource.getIncludes().isEmpty()) {
- includes = resource.getIncludes().toArray(EMPTY_STRING_ARRAY);
- } else {
- includes = DEFAULT_INCLUDES;
- }
- scanner.setIncludes(includes);
-
- if (resource.getExcludes() != null && !resource.getExcludes().isEmpty()) {
- String[] excludes = resource.getExcludes().toArray(EMPTY_STRING_ARRAY);
- scanner.setExcludes(excludes);
+ /**
+ * Scans a directory for files matching include/exclude patterns.
+ * Used as fallback when no BuildContext is available.
+ */
+ private List<String> scanDirectory(
+ Path baseDir, List<String> includes, List<String> excludes, boolean addDefaultExcludes)
+ throws MavenFilteringException {
+ List<String> result = new ArrayList<>();
+ try {
+ if (addDefaultExcludes) {
+ excludes = new ArrayList<>(excludes);
+ addDefaultExcludes(excludes);
+ }
+ // Walk directory and collect relative paths
+ Files.walk(baseDir).filter(Files::isRegularFile).forEach(path -> {
+ String relative = baseDir.relativize(path).toString().replace('\\', '/');
+ result.add(relative);
+ });
+ } catch (IOException e) {
+ throw new MavenFilteringException("Failed to scan directory: " + baseDir, e);
}
+ return result;
+ }
- if (addDefaultExcludes) {
- scanner.addDefaultExcludes();
- }
+ /**
+ * Adds the standard SCM and IDE default excludes to the given list.
+ */
+ private static void addDefaultExcludes(List<String> excludes) {
+ // Standard default excludes (SCM dirs, IDE files, OS files)
+ excludes.add("**/.git/**");
+ excludes.add("**/.svn/**");
+ excludes.add("**/.hg/**");
+ excludes.add("**/.bzr/**");
+ excludes.add("**/CVS/**");
+ excludes.add("**/.gitignore");
+ excludes.add("**/.cvsignore");
+ excludes.add("**/.DS_Store");
+ excludes.add("**/Thumbs.db");
}
- private void copyDirectoryLayout(Path sourceDirectory, Path destinationDirectory, Scanner scanner)
- throws IOException {
+ private void copyDirectoryLayout(Path sourceDirectory, Path destinationDirectory) throws IOException {
if (sourceDirectory == null) {
throw new IOException("source directory can't be null.");
}
@@ -442,34 +470,20 @@ public class DefaultMavenResourcesFiltering implements MavenResourcesFiltering {
throw new IOException("Source directory doesn't exists (" + sourceDirectory.toAbsolutePath() + ").");
}
- for (String name : scanner.getIncludedDirectories()) {
- Path source = sourceDirectory.resolve(name);
-
- if (source.equals(sourceDirectory)) {
- continue;
- }
-
- Path destination = destinationDirectory.resolve(name);
- Files.createDirectories(destination);
- }
+ Files.walk(sourceDirectory)
+ .filter(Files::isDirectory)
+ .filter(p -> !p.equals(sourceDirectory))
+ .forEach(dir -> {
+ Path destination = destinationDirectory.resolve(sourceDirectory.relativize(dir));
+ try {
+ Files.createDirectories(destination);
+ } catch (IOException e) {
+ throw new java.io.UncheckedIOException(e);
+ }
+ });
}
- private String getRelativeOutputDirectory(MavenResourcesExecution execution) {
- String relOutDir = execution.getOutputDirectory().toAbsolutePath().toString();
-
- if (execution.getMavenProject() != null) {
- String basedir =
- execution.getMavenProject().getBasedir().toAbsolutePath().toString();
- relOutDir = FilteringUtils.getRelativeFilePath(basedir, relOutDir);
- if (relOutDir == null) {
- relOutDir = execution.getOutputDirectory().toString();
- } else {
- relOutDir = relOutDir.replace('\\', '/');
- }
- }
-
- return relOutDir;
- }
+ // getRelativeOutputDirectory was only used for old BuildContext.hasDelta() — no longer needed
/*
* Filter the name of a file using the same mechanism for filtering the content of the file.
diff --git a/src/test/java/org/apache/maven/shared/filtering/DefaultMavenFileFilterTest.java b/src/test/java/org/apache/maven/shared/filtering/DefaultMavenFileFilterTest.java
index b8259d3..fe6f3c6 100644
--- a/src/test/java/org/apache/maven/shared/filtering/DefaultMavenFileFilterTest.java
+++ b/src/test/java/org/apache/maven/shared/filtering/DefaultMavenFileFilterTest.java
@@ -40,11 +40,9 @@ import org.apache.maven.di.Injector;
import org.codehaus.plexus.interpolation.AbstractValueSource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.sonatype.plexus.build.incremental.BuildContext;
import static org.apache.maven.api.di.testing.MavenDIExtension.getBasedir;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.mock;
/**
* @author Olivier Lamy
@@ -95,7 +93,7 @@ class DefaultMavenFileFilterTest {
@Test
void multiFilterFileInheritance() throws Exception {
- DefaultMavenFileFilter mavenFileFilter = new DefaultMavenFileFilter(mock(BuildContext.class));
+ DefaultMavenFileFilter mavenFileFilter = new DefaultMavenFileFilter();
File testDir = new File(getBasedir(), "src/test/units-files/MSHARED-177");
diff --git a/src/test/java/org/apache/maven/shared/filtering/IncrementalResourceFilteringTest.java b/src/test/java/org/apache/maven/shared/filtering/IncrementalResourceFilteringTest.java
deleted file mode 100644
index 15929c4..0000000
--- a/src/test/java/org/apache/maven/shared/filtering/IncrementalResourceFilteringTest.java
+++ /dev/null
@@ -1,210 +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.
- */
-package org.apache.maven.shared.filtering;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-
-import org.apache.maven.api.di.Inject;
-import org.apache.maven.api.di.testing.MavenDITest;
-import org.apache.maven.api.plugin.testing.stubs.ProjectStub;
-import org.apache.maven.di.Injector;
-import org.codehaus.plexus.util.FileUtils;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.sonatype.plexus.build.incremental.ThreadBuildContext;
-
-import static org.apache.maven.api.di.testing.MavenDIExtension.getBasedir;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-@MavenDITest
-class IncrementalResourceFilteringTest {
-
- final Path baseDirectory = Paths.get(getBasedir());
- final Path outputDirectory = baseDirectory.resolve("target/IncrementalResourceFilteringTest");
- final Path unitDirectory = baseDirectory.resolve("src/test/units-files/incremental");
- final Path filters = unitDirectory.resolve("filters.txt");
- final Path inputFile01 = unitDirectory.resolve("files/file01.txt");
- Path inputFile02 = unitDirectory.resolve("files/file02.txt");
- final Path outputFile01 = outputDirectory.resolve("file01.txt");
- final Path outputFile02 = outputDirectory.resolve("file02.txt");
-
- @Inject
- Injector container;
-
- @BeforeEach
- protected void setUp() throws Exception {
- FileUtils.deleteDirectory(outputDirectory.toFile());
- Files.createDirectories(outputDirectory);
- }
-
- @AfterEach
- protected void tearDown() {
- ThreadBuildContext.setThreadBuildContext(null);
- }
-
- @Test
- void simpleIncrementalFiltering() throws Exception {
- // run full build first
- filter("time");
-
- assertTime("time", "file01.txt");
- assertTime("time", "file02.txt");
-
- // only one file is expected to change
- Set<Path> changedFiles = new HashSet<>();
- changedFiles.add(inputFile01);
-
- TestIncrementalBuildContext ctx = new TestIncrementalBuildContext(baseDirectory, changedFiles);
- ThreadBuildContext.setThreadBuildContext(ctx);
-
- filter("notime");
- assertTime("notime", "file01.txt");
- assertTime("time", "file02.txt"); // this one is unchanged
-
- assertTrue(ctx.getRefreshFiles().contains(outputFile01));
-
- // only one file is expected to change
- Set<Path> deletedFiles = new HashSet<>();
- deletedFiles.add(inputFile01);
-
- ctx = new TestIncrementalBuildContext(baseDirectory, null, deletedFiles);
- ThreadBuildContext.setThreadBuildContext(ctx);
-
- filter("moretime");
- assertFalse(outputFile01.toFile().exists());
- assertTime("time", "file02.txt"); // this one is unchanged
-
- assertTrue(ctx.getRefreshFiles().contains(outputFile01));
- }
-
- @Test
- void outputChange() throws Exception {
- // run full build first
- filter("time");
-
- // all files are reprocessed after contents of output directory changed (e.g. was deleted)
- Set<Path> changedFiles = new HashSet<>();
- changedFiles.add(outputDirectory);
- TestIncrementalBuildContext ctx = new TestIncrementalBuildContext(baseDirectory, changedFiles);
- ThreadBuildContext.setThreadBuildContext(ctx);
-
- filter("notime");
- assertTime("notime", "file01.txt");
- assertTime("notime", "file02.txt");
-
- assertTrue(ctx.getRefreshFiles().contains(outputFile01));
- assertTrue(ctx.getRefreshFiles().contains(outputFile02));
- }
-
- @Test
- void filterChange() throws Exception {
- // run full build first
- filter("time");
-
- // all files are reprocessed after content of filters changes
- Set<Path> changedFiles = new HashSet<>();
- changedFiles.add(filters);
- TestIncrementalBuildContext ctx = new TestIncrementalBuildContext(baseDirectory, changedFiles);
- ThreadBuildContext.setThreadBuildContext(ctx);
-
- filter("notime");
- assertTime("notime", "file01.txt");
- assertTime("notime", "file02.txt");
-
- assertTrue(ctx.getRefreshFiles().contains(outputFile01));
- assertTrue(ctx.getRefreshFiles().contains(outputFile02));
- }
-
- @Test
- void filterDeleted() throws Exception {
- // run full build first
- filter("time");
-
- // all files are reprocessed after content of filters changes
- Set<Path> deletedFiles = new HashSet<>();
- deletedFiles.add(filters);
- TestIncrementalBuildContext ctx = new TestIncrementalBuildContext(unitDirectory, null, deletedFiles);
- ThreadBuildContext.setThreadBuildContext(ctx);
-
- filter("notime");
- assertTime("notime", "file01.txt");
- assertTime("notime", "file02.txt");
-
- assertTrue(ctx.getRefreshFiles().contains(outputFile01));
- assertTrue(ctx.getRefreshFiles().contains(outputFile02));
- }
-
- private void assertTime(String time, String relpath) throws IOException {
- Properties properties = new Properties();
-
- try (InputStream is = Files.newInputStream(outputDirectory.resolve(relpath))) {
- properties.load(is);
- }
-
- assertEquals(time, properties.getProperty("time"));
- }
-
- private void filter(String time) throws Exception {
- Path baseDir = Paths.get(getBasedir());
- ProjectStub mavenProject = new ProjectStub().setBasedir(baseDir);
- mavenProject.setVersion("1.0");
- mavenProject.setGroupId("org.apache");
- mavenProject.setName("test project");
-
- mavenProject.addProperty("time", time);
- mavenProject.addProperty("java.version", "zloug");
- MavenResourcesFiltering mavenResourcesFiltering = container.getInstance(MavenResourcesFiltering.class);
-
- String unitFilesDir = unitDirectory.resolve("files").toString();
-
- Resource resource = new Resource();
- List<Resource> resources = new ArrayList<>();
- resources.add(resource);
- resource.setDirectory(unitFilesDir);
- resource.setFiltering(true);
-
- List<String> filtersFile = new ArrayList<>();
- filtersFile.add(unitDirectory.resolve("filters.txt").toString());
-
- MavenResourcesExecution mre = new MavenResourcesExecution();
- mre.setResources(resources);
- mre.setOutputDirectory(outputDirectory);
- mre.setEncoding("UTF-8");
- mre.setMavenProject(mavenProject);
- mre.setFilters(filtersFile);
- mre.setNonFilteredFileExtensions(Collections.emptyList());
- mre.setMavenSession(new StubSession());
- mre.setUseDefaultFilterWrappers(true);
-
- mavenResourcesFiltering.filterResources(mre);
- }
-}
diff --git a/src/test/java/org/apache/maven/shared/filtering/Providers.java b/src/test/java/org/apache/maven/shared/filtering/Providers.java
index a21f21f..0137b4c 100644
--- a/src/test/java/org/apache/maven/shared/filtering/Providers.java
+++ b/src/test/java/org/apache/maven/shared/filtering/Providers.java
@@ -19,15 +19,10 @@
package org.apache.maven.shared.filtering;
import org.apache.maven.api.di.Named;
-import org.apache.maven.api.di.Provides;
-import org.sonatype.plexus.build.incremental.BuildContext;
-import org.sonatype.plexus.build.incremental.ThreadBuildContext;
@Named
class Providers {
-
- @Provides
- static BuildContext buildContext() {
- return new ThreadBuildContext();
- }
+ // Old plexus BuildContext provider removed — maven-filtering now uses
+ // the new Maven 4 BuildContext API from maven-api-core directly.
+ // The BuildContext is provided by the Maven core DI container.
}
diff --git a/src/test/java/org/apache/maven/shared/filtering/TestIncrementalBuildContext.java b/src/test/java/org/apache/maven/shared/filtering/TestIncrementalBuildContext.java
deleted file mode 100644
index 95e1e32..0000000
--- a/src/test/java/org/apache/maven/shared/filtering/TestIncrementalBuildContext.java
+++ /dev/null
@@ -1,224 +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.
- */
-package org.apache.maven.shared.filtering;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-import org.codehaus.plexus.util.DirectoryScanner;
-import org.codehaus.plexus.util.Scanner;
-import org.sonatype.plexus.build.incremental.BuildContext;
-
-/**
- * {@link TestIncrementalBuildContext} mock for testing purpose. It allows to
- * check build behavior based on {@link #isUptodate(File, File)} return value.
- *
- * Constructor parameters allow to indicate folder/files to declare files as
- * modified / deleted.
- *
- * hasDelta, isUptodate, newScanner, newDeleteScanner methods output consistent
- * values based upon changedFiles / deletedFiles inputs.
- *
- * getRefreshFiles method allows to check files modified by build.
- */
-public class TestIncrementalBuildContext implements BuildContext {
-
- private final Path basedir;
- private final Set<Path> refresh = new HashSet<>();
- private final Set<Path> changedFiles = new HashSet<>();
- private final Set<Path> deletedFiles = new HashSet<>();
- private final Map<String, Object> context = new HashMap<>();
-
- public TestIncrementalBuildContext(Path basedir, Set<Path> changedFiles) {
- this(basedir, changedFiles, null);
- }
-
- public TestIncrementalBuildContext(Path basedir, Set<Path> changedFiles, Set<Path> deletedFiles) {
- checkPath(basedir);
- this.basedir = basedir;
- Optional.ofNullable(changedFiles).ifPresent(this.changedFiles::addAll);
- Optional.ofNullable(deletedFiles).ifPresent(this.deletedFiles::addAll);
- this.changedFiles.forEach(TestIncrementalBuildContext::checkPath);
- this.deletedFiles.forEach(TestIncrementalBuildContext::checkPath);
- }
-
- public static void checkPath(Path path) {
- if (!path.isAbsolute()) {
- throw new IllegalStateException(String.format("Absolute path are expected. Failing path %s", path));
- }
- }
-
- public Set<Path> getRefreshFiles() {
- return Collections.unmodifiableSet(refresh);
- }
-
- /**
- * Check that relpath or parent folders of relpath is not listed in modified /
- * deleted files.
- */
- @Override
- public boolean hasDelta(String relpath) {
- Path candidate = basedir.resolve(relpath);
- boolean changed = false;
- while (candidate != null) {
- changed = changedFiles.contains(candidate) || deletedFiles.contains(candidate);
- if (changed || candidate.equals(basedir)) {
- break;
- }
- candidate = candidate.getParent();
- }
- return changed;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public boolean hasDelta(List relpaths) {
- return ((List<String>) relpaths).stream().anyMatch(this::hasDelta);
- }
-
- @Override
- public boolean hasDelta(File file) {
- return hasDelta(file.getAbsolutePath());
- }
-
- @Override
- public boolean isIncremental() {
- return true;
- }
-
- @Override
- public Scanner newDeleteScanner(File basedir) {
- return new TestScanner(basedir, deletedFiles);
- }
-
- @Override
- public OutputStream newFileOutputStream(File file) throws IOException {
- refresh(file);
- return new FileOutputStream(file);
- }
-
- @Override
- public Scanner newScanner(final File basedir) {
- return new TestScanner(basedir, changedFiles);
- }
-
- @Override
- public Scanner newScanner(File basedir, boolean ignoreDelta) {
- if (ignoreDelta) {
- DirectoryScanner directoryScanner = new DirectoryScanner();
- directoryScanner.setBasedir(basedir);
- return directoryScanner;
- }
-
- return newScanner(basedir);
- }
-
- @Override
- public void refresh(File file) {
- refresh.add(file.toPath());
- }
-
- @Override
- public Object getValue(String key) {
- return context.get(key);
- }
-
- @Override
- public void setValue(String key, Object value) {
- context.put(key, value);
- }
-
- @Override
- public void addError(File file, int line, int column, String message, Throwable cause) {}
-
- @Override
- public void addWarning(File file, int line, int column, String message, Throwable cause) {}
-
- @Override
- public void addMessage(File file, int line, int column, String message, int severity, Throwable cause) {}
-
- @Override
- public void removeMessages(File file) {}
-
- @Override
- public boolean isUptodate(File target, File source) {
- return target != null
- && target.exists()
- && !hasDelta(target)
- && source != null
- && source.exists()
- && !hasDelta(source)
- && target.lastModified() > source.lastModified();
- }
-
- private static final class TestScanner implements Scanner {
- private final Path basedir;
- private final Set<Path> files = new HashSet<>();
-
- private TestScanner(File basedir, Set<Path> files) {
- this.basedir = basedir.toPath().toAbsolutePath();
- Optional.ofNullable(files).ifPresent(this.files::addAll);
- }
-
- @Override
- public void addDefaultExcludes() {}
-
- @Override
- public String[] getIncludedDirectories() {
- return new String[0];
- }
-
- @Override
- public String[] getIncludedFiles() {
- return files.stream()
- .filter(p -> p.startsWith(basedir))
- .map(basedir::relativize)
- .map(Path::toString)
- .toArray(String[]::new);
- }
-
- @Override
- public void scan() {}
-
- @Override
- public void setExcludes(String[] excludes) {}
-
- @Override
- public void setIncludes(String[] includes) {}
-
- @Override
- public File getBasedir() {
- return basedir.toFile();
- }
-
- @Override
- public void setFilenameComparator(Comparator<String> filenameComparator) {}
- }
-}