slachiewicz commented on issue #13302:
URL: https://github.com/apache/maven/issues/13302#issuecomment-5919283521

   ### Wave 4 findings, part 3 of 4: maven-javadoc-plugin to maven-rar-plugin
   
   Each plugin is a local branch `agent/mvn4-api` with a "Build with Maven 4 
only" commit and a "Port to the Maven 4 API" commit; the PRs are not opened yet.
   
   <details><summary><b>maven-javadoc-plugin</b>: partial</summary>
   
   Branch `agent/mvn4-api`; PR not opened yet. Status: **partial**, 
4.0.0-beta-1-SNAPSHOT, Java 17. Every goal is ported and runs as a direct goal 
on Maven 4.0.0-rc-7; nothing runs as a site report (blocked).
   
   Verified locally: Maven 4.0.0-rc-7, JDK 21. `mvn clean verify` → 72 tests 
before (8 skipped, 0 failures), 75 after (8 skipped, 0 failures; 3 added); 
spotless, RAT and checkstyle pass. `-Prun-its` (93 ITs, run as two 
`-Dinvoker.test=` halves because the suite exceeds the 30 min time-box) → 
before 79 passed, 3 failed, 11 skipped; after 75 passed, 7 failed, 11 skipped. 
Pre-existing failures, before and after: MJAVADOC-181, MJAVADOC-444 (both 
`site`), MJAVADOC-568_jar-mixed. The 4 new failures are all `site` ITs 
(MJAVADOC-134_multiaggregate, -259, -369, site-failOnError), see Gaps. The 
other 89 outcomes are identical. Skipped: JRE-version (doclava, JDK 23 fonts) 
and toolchain-version ITs. No test deleted; 13 `MavenProjectStub` classes 
removed because the v4 harness reads the POM (see tests below). 
`testJavadocResourcesWithExcludes` fails on a second run without `clean`, 
before and after.
   
   **Per-goal status**
   | goal | status | evidence |
   |---|---|---|
   | `jar` | ported | ITs MJAVADOC-137_jar, -812, -568_export-to-testcase, 
-599, -639_requires_ignored, reproducible, -610_mrjar, toolchain probe below; 
`package` build with attach and install |
   | `test-jar` | ported | no IT in the repo; probe project `package`+`install` 
attached and installed `-test-javadoc.jar` |
   | `aggregate-jar`, `test-aggregate-jar` | ported | ITs MJAVADOC-599, 
-618_modular-war, -639_requires_ignored; probe for test-aggregate-jar (jar 
contains the module's test class page) |
   | `resource-bundle`, `test-resource-bundle` | ported | probe: both bundles 
built, attached, installed; bundles consumed by dependencySource-1..4 ITs |
   | `javadoc`, `test-javadoc`, `aggregate`, `test-aggregate`, `*-no-fork` | 
ported as direct goals (`mvn javadoc:javadoc`) | about 50 ITs use them; partial 
as reports: `mvn site` has no v4 route |
   | `fix`, `test-fix` | not in this source version | removed before this 
branch (plugin.xml lists 15 goals, `help` included) |
   | toolchains | ported | `jdkToolchain` with JDK 21 running Maven and a JDK 8 
toolchain: log `Toolchain in maven-javadoc-plugin: JDK[...zulu-8...]`, JDK 8 
output (`allclasses-frame.html`); build-context path via 
maven-toolchains-plugin 3.2.0 + `jar` in one `package` build also selects JDK 8 
|
   | module path | ported, plexus-java kept | ITs MJAVADOC-498_modulepath, 
-498_mm_modulepath, -449_aggr_modulepath, -639_aggr_static_modulepath, 
-555_link-automatic-modules, -575, -556, -568_manifest-splitpackage pass; see 
Gaps for why `JavaPathType` is not used |
   | `detectLinks`, `detectOfflineLinks`, `detectJavaApiLink` | ported | ITs 
MJAVADOC-580_detectLinks, detectLinks, -592, -495, -642_cmdline, -320, -275; 
probe: `detectLinks` resolved the dependency POM through `ArtifactResolver` + 
`ProjectBuilder` and validated the URL online → `-link 
https://commons.apache.org/proper/commons-lang/apidocs` |
   | `additionalDependencies`, `docletArtifact(s)`, `tagletArtifact(s)`, 
`resourcesArtifacts` | ported | doclet/taglet ITs need JDK ≤13, so probes: 
`-docletpath` and `-tagletpath` held the artifact plus its compile-scope 
transitive dependencies, `-classpath` held the additional dependency; unit 
tests cover taglet/stylesheet/helpfile artifacts |
   | dependency sources (`includeDependencySources`) | ported | ITs 
dependencySource-1..4, MJAVADOC-338, -494_aggregate-repositories, -526 |
   
   Differential check of the report goals: the released 3.11.2 and this port 
run on the same probe projects under Maven 4.0.0-rc-7. The `-X` parameter dump 
of all 7 non-site goals is identical except `detectOfflineLinks` (3.11.2 had an 
older default) and the injected objects. For `aggregate` on a two-module 
reactor with provided and runtime scopes the `javadoc` options file is byte 
identical after path normalisation; `javadoc` and `test-javadoc` differ only in 
class path order. This found three defects that the ITs had not (fixed): 
`${project.name}` left unevaluated, `system` scope dependencies dropped, 
runtime dependencies missing from the test class path.
   
   **Concrete build error (reporting chain):** as in the changelog finding. 
Real build, maven-site-plugin 3.22.0 on rc-7, MJAVADOC-134_multiaggregate: 
`Failed to get report for org.apache.maven.plugins:maven-javadoc-plugin: Unable 
to lookup Mojo: Cannot cast 
org.apache.maven.plugins.javadoc.AggregatorJavadocReportFactory to 
org.apache.maven.plugin.Mojo`. `reporting-api` 4.0.0 has no Maven 3 dependency, 
so `MavenMultiPageReport` is still implemented and compiles; only the site 
plugin is missing.
   
   **User-visible changes**
   - Needs Maven 4.0.0-rc-7 and Java 17 (was 3.6.3 / 8); version 
3.12.1-SNAPSHOT → 4.0.0-beta-1-SNAPSHOT.
   - Goals, parameter names, properties and defaults are unchanged (defaults 
compared by the differential run above). Exceptions: `jarOutputDirectory` and 
`finalName` no longer take `-Dproject.build.directory` / 
`-Dproject.build.finalName` (a v4 `property` is a user property, not an 
expression; now `defaultValue`); `${basedir}` defaults are `${project.basedir}`.
   - `additionalDependencies` element type `AdditionalDependency` is now a 
plain bean (groupId, artifactId, version, type, classifier, scope) instead of a 
subclass of the model `Dependency`; `<exclusions>`, `<optional>`, 
`<systemPath>` inside it are no longer accepted.
   - Class hierarchy: the `*NoFork*` mojos are now the base classes and the 
forking ones subclass them (an inherited `@Execute` cannot be cancelled). 
`TestJavadocReport` no longer extends `JavadocReport`. The plugin descriptor 
shows the same goals and `executePhase` values.
   - No `requiresDependencyResolution`: the mojos resolve in `execute()` 
(javadoc/jar: compile + provided + direct system; test goals: + test + 
runtime), so a goal no longer fails before the mojo for an unresolvable 
dependency but inside it.
   - `locale` is validated against the JVM locales only; the Doxia site tool 
also required a Maven Site translation.
   - Nested Maven runs for `detectOfflineLinks` use the default settings and 
toolchains files; `-s`, `-gs`, `-t`, `-gt` are not passed on (no v4 API).
   - Class path order of the dependencies differs from 3.x (same set).
   - `mvn site` with the plugin under `<reporting>` fails until 
maven-site-plugin has a v4 release.
   - Public/protected Java API: `AbstractJavadocMojo` implements 
`org.apache.maven.api.plugin.Mojo`; constructors with injected components are 
gone (field `@Inject` of `Session`, `Project`, `MojoExecution`, `Log`); 
`MavenProject`/`MavenSession`/`Toolchain` signatures become 
`Project`/`Session`/`org.apache.maven.api.Toolchain`; `ResourceResolver` is a 
plain class (was a Sisu component) and `SourceResolverConfig` takes a 
`Session`; `resolveDependency` takes `AdditionalDependency` and returns a 
`Path`.
   
   **Gaps**
   - Site reports: no v4 report contract accepted by maven-site-plugin 3.x 
(error above); needs the v4 site plugin and the Doxia site-tools port.
   - `@Execute(phase = "none")` fails plugin-tools 4.0.0-beta-3 (`No enum 
constant LifecyclePhase.none`) and `@Execute` is inherited, so no-fork mojos 
cannot opt out; worked around by reordering the classes.
   - No `requiresDependencyResolution` and no `threadSafe` attribute on `@Mojo`.
   - No `PathScope` includes `system`, and none combines compile, provided, 
runtime and test. The resolver therefore drops system dependencies (probe: 
`-classpath` empty where 3.11.2 had the jar) and the runtime scope for test 
goals. Workaround: direct `system` dependencies are read from the model's 
`systemPath`, test goals merge `TEST_COMPILE` and `TEST_RUNTIME`. Transitive 
system dependencies stay missing.
   - `DependencyResolverResult.getDispatchedPaths()` (what the jlink port uses) 
is not adopted for the module path: on a probe with `requires 
org.objectweb.asm` only, it still put the unrequired named module commons-lang3 
on `MODULES`, and the result is the same before and after `compile`. The 
javadoc logic needs the main descriptor parsed from `module-info.java` sources 
(the `javadoc` goal forks only `generate-sources`), `requires static`, 
patch-module and `Automatic-Module-Name` cases, which plexus-java 
`LocationManager` provides; it depends on no Maven 3 type and stays. A switch 
would change which JARs go on the module path.
   - `${project.name}` does not evaluate in parameter defaults and 
`${project.model.name}` has no artifact id fallback and stays literal when the 
project has no name; the titles are resolved in code.
   - `Project.getBuild().getSourceDirectory()`/`getResources()` are not 
reliable in v4; `ProjectManager.getEnabledSourceRoots` is used. Project 
instances are not identity stable, so projects are compared by GAV.
   - Session exposes no settings or toolchains file location from 
`-s`/`-gs`/`-t`/`-gt`, only the configured defaults 
(`Constants.MAVEN_USER_SETTINGS` etc.).
   - Doxia `SiteTool` (doxia-integration-tools) is bound to Maven 3 types and 
Sisu: dropped, locale parsing reimplemented. Plexus `ArchiverManager` cannot be 
injected: `new JarArchiver()` / `ZipUnArchiver` are used directly.
   - Test harness (maven-testing rc-7): object-array parameters that declare a 
`property` make `MojoExtension` throw an NPE unless the test POM lists the 
element; an exact `${project.basedir}` evaluates to a `Path`, so a `String` 
parameter stays null; `ProjectStub.getLanguage()` is null (the mojo treats a 
null language as Java); a test `@Provides` needs `@Singleton`.
   
   **Tests:** the 13 stubs under `src/test/java/.../stubs` are replaced by 
`TestSessions` (mock session with source roots, dependencies, artifact 
resolution from a local repo directory) and POM-based reactor projects; 37 test 
POMs list empty object arrays, use `${project.basedir}`, and three aggregate 
configs declare `<modules>`; `stale-test` declares `jar` packaging (it said 
`pom`, which the old harness ignored). Added: default titles fall back to the 
artifact id, system scope class path, test goal runtime class path, locale 
parsing.
   
   **Shared snapshots consumed:** `maven-common-artifact-filters` 
4.0.0-SNAPSHOT (from `maven-common-artifact-filters`, branch `agent/mvn4-api`, 
already in the local repository). Released: `maven-archiver` 4.0.0-beta-5, 
`maven-reporting-api` 4.0.0.
   
   **Improvements:** drops `maven-core`, `maven-model`, `maven-settings`, 
`maven-plugin-api`, `maven-artifact`, `maven-plugin-annotations`, 
`maven-resolver-api/impl/util`, `javax.inject`, `maven-reporting-impl` (javadoc 
link only), `doxia-integration-tools`, the Sisu index plugin, and the test 
dependencies `maven-plugin-testing-harness`, resolver connector/transport, 
Sisu; Mockito 4.11 → 5.24.
   
   **Recommendation:** port the non-report goals (`jar`, `test-jar`, 
`aggregate-jar`, `test-aggregate-jar`, `resource-bundle`, 
`test-resource-bundle`) and direct `javadoc:*` use; they are complete and 
verified. Do not merge as a replacement for 3.x: `mvn site` reporting breaks 
until maven-site-plugin, maven-reporting-impl and doxia-sitetools have v4 
releases in that order, and `common-artifact-filters` 4.0.0 must be released 
first. Keep a 3.x line. Open question for plugin-tools: make `@Execute` 
cancellable (or accept `none`) so the no-fork mojos need not become base 
classes.
   
   </details>
   
   <details><summary><b>maven-jdeprscan-plugin</b>: ported</summary>
   
   Branch `agent/mvn4-api`; PR not opened yet. Status: **ported**, 
4.0.0-beta-1-SNAPSHOT, Java 17.
   
   Verified locally: `mvn verify` and `mvn verify -Prun-its` with Maven 
4.0.0-rc-7, JDK 21 → unit tests 3 before, 6 after (new: 
`ToolchainSelectionTest`, 3 tests), 0 failures; ITs 6 passed, 1 skipped before 
and after (invoker), 0 failures; spotless clean; `dependency:analyze-only` runs 
and passes.
   
   **User-visible changes**
   - Plugin now requires Maven 4.0.0-rc-7 (`<prerequisites>` follows 
`mavenVersion`) and Java 17 (was Maven 3.6.3 / Java 8). It no longer runs under 
Maven 3.
   - Goals `jdeprscan`, `test-jdeprscan`, `list` and all parameters 
(`failOnWarning`, `forRemoval`, `release`, `for-removal`) keep their names, 
properties and defaults.
   - `@Mojo(threadSafe = true)` is gone: the v4 `Mojo` annotation and 
`MojoDescriptor` have no thread-safety flag.
   - `list` loses `requiresDirectInvocation = true`: the v4 annotation has no 
such attribute (the descriptor has `directInvocationOnly`, the annotation 
cannot set it), so `plugin.xml` now says `directInvocationOnly=false`. The goal 
has no default phase, so it is still not bound implicitly.
   - `requiresDependencyResolution` (COMPILE / TEST) is replaced by an explicit 
`DependencyResolver.resolve(session, project, PathScope.MAIN_COMPILE | 
TEST_COMPILE)` in the mojo. The `--class-path` order is kept: classes directory 
(plus main classes for `test-jdeprscan`), then dependencies.
   
   **Gaps**
   - None blocking. v4 `ToolchainManager` covers both lookups the old code 
needed: `getToolchainFromBuildContext(session, "jdk")` and 
`getToolchains(session, "jdk", {version=[9,)})`. The reflection fallback for 
Maven 3.3.0 is gone because the API has the method directly.
   - `Toolchain.findTool("jdeprscan")` exists on the v4 interface, so no 
toolchain internals are needed.
   
   **Improvements:** drops `maven-core`, `maven-plugin-api`, `maven-model`, 
`javax.inject` (constructor injection replaced by `@Inject` fields on 
`Session`, `ToolchainManager`, `DependencyResolver`, `Log`); adds only 
`maven-api-core`, `maven-api-di`, `maven-api-model` (provided). No new test 
dependency: the toolchain-selection test uses `java.lang.reflect.Proxy` stubs. 
`commons-lang3` and `plexus-utils` (`Commandline`, `CommandLineUtils`) stay 
because forking the tool has no v4 API.
   
   **Recommendation:** port; it is small and needs no shared component. Ship as 
4.0.0-beta-1 on master and keep a 3.x line for Maven 3 users.
   
   </details>
   
   <details><summary><b>maven-jdeps-plugin</b>: ported</summary>
   
   
   Branch `agent/mvn4-api`; PR not opened yet. Status: **ported**, 
4.0.0-beta-1-SNAPSHOT, Java 17.
   
   Verified locally: `mvn verify` with Maven 4.0.0-rc-7, JDK 21 → 11 unit tests 
before and after, 0 failures; `mvn verify -Prun-its` → 7 passed, 0 failed, 2 
skipped before (5m13s) and after (5m44s), the two skipped are 
`unsupported-api_main`/`unsupported-api_test` ("SKIPPED due to JRE version", 
same before and after); spotless clean. Toolchain fallback checked by hand (see 
Gaps). Shared snapshots consumed: none.
   
   **Public API changes** (Mojo base class, for subclasses only)
   - `AbstractJDepsMojo` implements `org.apache.maven.api.plugin.Mojo` instead 
of extending `AbstractMojo`; `@Inject` fields for `Log`, `Project`, `Session`, 
`ToolchainManager` (`org.apache.maven.api.services`), `DependencyResolver`. The 
`(ToolchainManager)` constructor is gone.
   - `getProject()` returns `org.apache.maven.api.Project`; 
`getClassesDirectory()` returns `Path`; `getClassPath()` no longer throws 
`DependencyResolutionRequiredException`; new abstract `getPathScope()`.
   - Mojos declare `@Mojo(name, defaultPhase)` with string phases; `execute()` 
throws the unchecked `MojoException`. `dotOutput` is a `Path`. Goal names, 
parameter names and `-D` properties are unchanged.
   
   **Gaps**
   - `@Resolution` field injection does not work with maven-plugin-tools 
4.0.0-beta-3: the generated `plugin.xml` has no `<resolutions>`, the field 
stays null (NPE "this.resolution is null" in all 7 ITs). Maven core supports it 
(`DefaultMavenPluginManager` reads `getResolutions()`), the descriptor 
generator does not write it (`PluginDescriptorFilesGenerator` only writes 
`dependencyResolution`). Worked around with an injected `DependencyResolver` 
and `resolve(session, project, PathScope)` inside `execute()`.
   - Constructor injection of a mojo fails: the generated 
`JDKInternalsMojoFactory` calls a no-arg constructor ("method 'void <init>()' 
not found"). Field injection only.
   - `threadSafe = true` has no v4 `@Mojo` attribute; the flag is dropped, 
nothing replaces it.
   - `requiresDependencyResolution` has no attribute either (only 
`dependencyResolutionPathScopes`, whose generation I did not test). Resolution 
therefore happens on first use inside the mojo, not before it.
   - v3 `getCompileClasspathElements()`/`getTestClasspathElements()` included 
the project's own output directories; v4 `resolveDependencies` returns 
dependencies only, so the mojos prepend 
`getOutputDirectory(ProjectScope.MAIN/TEST)` themselves. `ResolutionScope.TEST` 
maps to `PathScope.TEST_RUNTIME`, `COMPILE` to `MAIN_COMPILE`.
   - `project.getArtifacts()` (used to match `dependenciesToAnalyzeIncludes`) 
maps to `DependencyResolverResult.getDependencies()` keyed by 
`groupId:artifactId`; same filtering.
   - Toolchains: covered. `org.apache.maven.api.services.ToolchainManager` has 
`getToolchainFromBuildContext(Session, "jdk")` (Optional) and 
`getToolchains(Session, "jdk", Map)`, which replaces the 3.2.6 reflection hack; 
`Toolchain.findTool("jdeps")` is unchanged. Checked by hand with the installed 
plugin and a `toolchains.xml` holding only zulu-8: jdeps ran from 
`zulu-8.jdk/.../bin/jdeps` with the file and from the `zulu-21.jdk` JAVA_HOME 
with an empty `<toolchains/>`. Not tested: a toolchain selected by 
`maven-toolchains-plugin` (the build-context branch). No IT exercises 
toolchains, before or after.
   
   **User-visible changes**
   - Runs on Maven 4 only (v4 mojo descriptor); the plugin needs Java 17 to 
run. No 3.x support, so a 3.x line must stay for Maven 3 users.
   - Readonly parameters `project`, `session` are removed from the descriptor.
   - `src/site/markdown/index.md` still describes Maven 3.2.6 toolchain 
behaviour and the workflow still lists JDK 8 in `matrix-exclude`; neither was 
touched.
   
   **Improvements:** drops `javax.inject`, `maven-plugin-annotations`, 
`maven-plugin-api`, `maven-core`, `maven-model`, `maven-artifact`; adds 
`maven-api-core`, `maven-api-di`, `maven-api-annotations` (provided). 
`commons-lang3` and `plexus-utils` stay (`MatchPatterns`, `Commandline`). The 
reflection on `ToolchainManager.getToolchains` is gone.
   
   **Recommendation:** port for the Maven 4 line, keep 3.x for Maven 3. Nothing 
in the plugin is blocked; the two tooling gaps (`@Resolution` descriptor 
output, constructor injection) are worth a plugin-tools issue.
   
   </details>
   
   <details><summary><b>maven-jlink-plugin</b>: ported</summary>
   
   Branch `agent/mvn4-api`; PR not opened yet. Status: **ported**, 
4.0.0-beta-1-SNAPSHOT, Java 17.
   
   Verified locally: `mvn verify` and `mvn verify -Prun-its` with Maven 
4.0.0-rc-7, JDK 21 → unit tests 14 before (1 skipped, the Windows-only one), 17 
after (1 skipped); ITs 28 passed, 1 skipped before and after (invoker, 23 min 
before, 21 min after); 0 failures; spotless clean; `dependency:analyze-only` 
(failOnWarning) passes. One removed test: 
`getCompileClasspathElementsShouldSkipPomTypeArtifacts`, because the code it 
covered (`project.getArtifacts()`, skipping `pom` artifacts) is gone; the 
resolver returns paths only. Four new tests for module-path resolution (plain 
JAR, directory without descriptor, project `module-info.class`, project without 
it).
   
   **Do the v4 APIs cover toolchains and module-path resolution?** Yes for 
both, with two small workarounds.
   - Toolchains: `ToolchainManager.getToolchains(session, "jdk", 
requirements)`, `getToolchainFromBuildContext(session, "jdk")`, 
`Toolchain.findTool("jlink")` and `Toolchain.matchesRequirements(...)` replace 
the reflection on `getToolchains`, the `ToolchainPrivate` cast and 
`JavaToolchainImpl`. No gap.
   - Module path: `DependencyResolver.resolve(session, project, 
PathScope.MAIN_RUNTIME)` replaces `requiresDependencyResolution = RUNTIME`, 
`project.getArtifacts()` and plexus-java `LocationManager`. On a probe project 
(asm 6.0 with `module-info.class`, commons-lang3, `javax.inject:1` with no 
module name) `getDispatchedPaths()` gave `JavaPathType.MODULES` = asm, lang3 
and `CLASSES` = javax.inject, i.e. the same split the old code made (module, 
module, skipped as automatic). The mojo uses `getPaths()` plus 
`DependencyResolverResult.getModuleDescriptor(path)` because it needs the 
module name and the automatic flag; the resulting `--add-modules` set was 
identical to the 3.x plugin's on the probe (asm, lang3, project).
   - Workaround 1: `getModuleDescriptor` returns empty for the project's own 
`target/classes`, so the project's `module-info.class` is read with 
`java.lang.module.ModuleDescriptor.read`.
   - Workaround 2: it also returns empty for a JAR with only a file-name-based 
automatic name (plexus-java returned an automatic descriptor). An empty result 
for a regular file is treated as automatic and skipped; for a directory it is 
still the "does not have a module-info.java file" error.
   - Not expressible: the toolchain's JDK home can no longer be passed to 
module resolution (`ResolvePathsRequest.setJdkHome`). No IT or probe output 
changed; effect on system-module resolution is unmeasured.
   
   **User-visible changes**
   - Requires Maven 4.0.0-rc-7 (`<prerequisites>` follows `mavenVersion`) and 
Java 17 (was Maven 3.6.3 / Java 11).
   - `additionalResources` element type is now 
`org.apache.maven.shared.filtering.Resource` (maven-filtering 4) instead of the 
model `Resource`; `MJLINK-80_additionalResources` passes with the same 
configuration.
   - All other parameters and the `jlink` goal keep names, properties and 
defaults. `requiresDependencyResolution` is now an explicit resolve in the mojo.
   - The `jlink` packaging (artifact handler and lifecycle mapping) is still 
declared in `META-INF/plexus/components.xml`. Maven 4.0.0-rc-7 still honours 
it: every IT with `<packaging>jlink</packaging>` and 
`<extensions>true</extensions>` passes. The native SPI (`TypeProvider`, 
`LifecycleProvider`, `PackagingProvider`) was not adopted.
   - The classified artifact is attached with 
`Session.createProducedArtifact(..., classifier, "zip", "jlink")` and 
`ProjectManager.attachArtifact`; the unclassified one replaces the project's 
main artifact as before. `projectHasAlreadySetAnArtifact` now asks 
`ProjectManager.getPath`.
   
   **Gaps**
   - `ProjectManager` is not bound for `@Inject`; a `Providers` class with 
`@Provides` (as in maven-jar-plugin) supplies it. Same for plexus-build-api's 
`BuildContext`, which maven-filtering 4 needs.
   - `ThreadBuildContext` needs `org.codehaus.plexus.logging`, which the plugin 
realm does not see for a plain `jar` project 
(`MJLINK-52_classifiers_duplicate_classifier` failed loading 
`org.codehaus.plexus.logging.AbstractLogEnabled`); `org.eclipse.sisu.plexus` is 
declared for it (as maven-resources-plugin does) and whitelisted for 
`dependency:analyze`. Packaging-`jlink` ITs passed without it, so this is a 
class-loading difference between the two realms.
   - `maven-shared-utils` 3.5.0 (`Commandline`) and plexus-archiver stay: 
forking `jlink` and zipping have no v4 API.
   
   **Improvements:** drops `maven-core`, `maven-plugin-api`, `maven-model`, 
`maven-artifact`, `javax.inject`, `plexus-java`, `maven-plugin-annotations`; 
the `JavaVersion.isAtLeast("14")` check for the no-toolchain case is dead on a 
Java 17 baseline and is reduced to `Runtime.version().feature()`.
   
   **Shared snapshots consumed:** none. `maven-archiver` 4.0.0-beta-5, 
`maven-filtering` 4.0.0-beta-1 and `plexus-build-api` 0.0.7 are released 
versions.
   
   **Recommendation:** port; nothing blocks it. Keep a 3.x line for Maven 3 
users. Open question for the list: whether to move the `jlink` packaging to the 
v4 SPI or keep `components.xml` while Maven 4 honours it.
   
   </details>
   
   <details><summary><b>maven-jmod-plugin</b>: ported</summary>
   
   
   Branch `agent/mvn4-api`; PR not opened yet. Status: **ported**, 
4.0.0-beta-1-SNAPSHOT, Java 17.
   
   Verified locally: `mvn verify` with Maven 4.0.0-rc-7, JDK 21 → the module 
has no unit tests, before or after; `mvn verify -Prun-its` → 18 ITs passed, 0 
failed before (12m27s) and after (9m16s); spotless clean, RAT and 
`dependency:analyze-only` pass. Toolchain selection checked by hand (see Gaps). 
A first full IT run was cut short at the last IT (`base-it`) by a hung Maven 
process; the counts above are from a clean rerun after the final edit. Shared 
snapshots consumed: none.
   
   **User-visible changes**
   - Runs on Maven 4 only; needs Java 17 (was 8). A 3.x line must stay for 
Maven 3 users.
   - Goals, parameter names and `-D` properties are unchanged. `jmodFile`, 
`modulePath`, `config`, `libs`, `outputDirectory`, `targetClassesDirectory` are 
`Path` instead of `File`. Readonly `project` and `session` leave the 
descriptor, and so does the unused readonly `compilePath` 
(`${project.compileClasspathElements}` does not exist in v4).
   - `hash` no longer declares `requiresDependencyResolution = COMPILE`; it 
never used the result (it builds a command line and does not run it, same as 
before).
   - `create` resolves dependencies for `main-runtime` (compile and runtime, 
the same scopes as v3 `RUNTIME`) inside `execute()` through 
`DependencyResolver`, not before the mojo.
   - `MojoFailureException` and `MojoExecutionException` both become 
`MojoException`, so failures like "JMODS folder does not exists" are no longer 
separated from execution errors in the exception type.
   - The jmod file is attached with `ProjectManager.attachArtifact(project, 
project.getMainArtifact())`; the "You have to use a classifier" check is kept, 
based on `ProjectManager.getPath(project)`.
   - Subclass API: `AbstractJModMojo` implements 
`org.apache.maven.api.plugin.Mojo`; `@Inject` fields `Project`, `Session`, 
`ToolchainManager` (`org.apache.maven.api.services`), `Log`; the 
`(ToolchainManager)` constructor and `JModCreateMojo(ToolchainManager, 
LocationManager)` are gone; `getToolchain()` returns 
`org.apache.maven.api.Toolchain`, `getProject()` the v4 `Project`, 
`executeCommand(Commandline, Path)`.
   
   **Gaps**
   - ToolchainManager: covered. `getToolchains(Session, "jdk", Map)` replaces 
the reflection on `MavenSession`, `getToolchainFromBuildContext(Session, 
"jdk")` (Optional) replaces the 3.x call, and `Toolchain.findTool("jmod")` is 
unchanged. Checked by hand with the installed plugin and a `toolchains.xml` 
holding a `zulu-21` symlink marked `vendor=tc-test`: with 
`<jdkToolchain><vendor>tc-test</vendor></jdkToolchain>` the debug line shows 
`jmod` from the toolchain path; without it, from `JAVA_HOME`. Not tested: a 
toolchain selected by `maven-toolchains-plugin` (build-context branch); no IT 
touches toolchains. `JavaToolchainImpl.getJavaHome()` has no v4 accessor 
(`Toolchain` has `findTool`, `getModel`, `matchesRequirements`), so 
`ResolvePathsRequest.setJdkHome` now gets the JDK home derived from the `jmod` 
executable, which only differs from v3 if a toolchain exists but provides no 
`jmod`.
   - PathType/JavaPathType: do not cover the module-path logic. rc-7 
`DependencyResolverResult.getDispatchedPaths()` classifies each dependency 
alone from `Type.getPathTypes()` and the dependency's own module info; 
`addOutputDirectory`, which would take the project's own `module-info.class`, 
is documented "currently not called" (`DefaultDependencyResolverResult`). 
`create` needs the opposite: only modules reachable from the main module's 
`requires` go on `--module-path`, the rest on `--class-path`, `.jmod` 
dependencies move to the module path, and filename-based automodules get a 
warning. That stays in `plexus-java` `LocationManager.resolvePaths` (a plain 
library, now constructed with `new LocationManager()`), fed with the files from 
the resolver. `DependencyResolverResult.warningForFilenameBasedAutomodules()` 
exists but I did not wire it, to keep the message and the boxed warning 
unchanged.
   - `JavaPathType.option(paths)` returns two arguments (`["--class-path", 
"a:b"]`); the plugin passes `--class-path=a:b` with backslashes doubled for 
jmod, so it does not use it.
   - Packaging registration has no v4 equivalent and is untouched: 
`META-INF/plexus/components.xml` (`ArtifactHandler` and `LifecycleMapping` for 
`jmod`) still works, the ITs with `<packaging>jmod</packaging>` and 
`<type>jmod</type>` dependencies pass. rc-7 `DefaultPackagingRegistry.lookup` 
only consults a legacy `LifecycleMapping` and never the `PackagingProvider` 
beans of a project extension (read in `maven-4.0.x`, tag rc-7 plus 11 commits).
   - `@Inject ProjectManager` fails in a real build ("No binding to construct 
an instance for key ProjectManager" seen in the sibling rar port); used 
`session.getService(ProjectManager.class)`.
   - `@Resolution` is not written to `plugin.xml` by `maven-plugin-plugin` 
4.0.0-beta-1, so the field stays null and dependencies would be silently 
dropped; I avoided it by injecting `DependencyResolver`. Nothing here would 
have caught it: no unit tests, and the ITs only fail if the jmod is wrong.
   - `maven-api-annotations` has to be declared (provided) or 
`dependency:analyze` fails with "used undeclared" after the port.
   - `maven-shared-utils` 3.5.0 (`Commandline`, `CommandLineUtils`, `Os`, 
`StringUtils`, `FileUtils`, `MessageUtils`) and `plexus-java` 1.6.0 stay; 
neither is Maven API.
   - Not covered: a toolchain that lacks `jmod`; JDK 24+ without a `jmods` 
folder (the existing JEP 493 message is unchanged, I ran JDK 21 only).
   
   **Consumers that break:** none in the Apache Maven plugin and 
shared-component repositories reference `maven-jmod-plugin` or its classes; the 
`jmod` packaging is consumed by user projects and, in the estate, only by this 
plugin's own ITs.
   
   **Improvements:** drops `maven-plugin-api`, `maven-core`, `maven-model`, 
`maven-artifact`, `maven-plugin-annotations`, `javax.inject`; adds 
`maven-api-core`, `maven-api-di`, `maven-api-annotations` (provided). The 
reflection on `ToolchainManager.getToolchains` and `JavaToolchainImpl` are gone.
   
   **Recommendation:** port for the Maven 4 line, keep 3.x for Maven 3. Not 
blocked. Two API requests for apache/maven: a main-module-aware dispatch in 
`DependencyResolverResult` (wire `addOutputDirectory`) so `LocationManager` is 
no longer needed, and a Toolchain accessor for the JDK home.
   
   </details>
   
   <details><summary><b>maven-pmd-plugin</b>: partial</summary>
   
   
   Branch `agent/mvn4-api`; PR not opened yet. Status: **partial**, 
4.0.0-beta-1-SNAPSHOT, Java 17.
   
   Verified locally (Maven 4.0.0-rc-7, zulu-21, plugin-tools 4.0.0-beta-3, 
plugin-testing 4.0.0-beta-4):
   - before `mvn -B -ntp verify`: 65 tests run, 0 failures, 0 errors, 8 skipped 
(Windows-only tests on macOS); BUILD SUCCESS. `-Prun-its -DskipTests`: 46 ITs, 
Passed 41, Failed 0, Skipped 5, 14m25s.
   - after `mvn -B -ntp verify -Prun-its`: 20 tests run, 0 failures, 0 errors, 
8 skipped (same 8 Windows tests); ITs Passed 5, Failed 0 (5 new ITs, see 
below); BUILD SUCCESS, 1m36s. `spotless:check` passes; RAT and 
dependency:analyze ran in the same build.
   - 45 tests and 46 pre-existing ITs no longer run, see Gaps. Negative 
control: changing one expected count in a new IT's verify.groovy makes the IT 
FAIL.
   - Real Maven 4 runs of the installed plugin against hand-made 
`target/pmd.xml` / `cpd.xml` (no PMD run): see "Key finding".
   
   **What ported.** Non-report goals `check`, `cpd-check`, 
`aggregate-pmd-check`, `aggregate-cpd-check` are v4 mojos 
(`org.apache.maven.api.plugin.Mojo`, `@Inject Log/Project`, `MojoException`). 
Report goals `pmd`, `cpd`, `aggregate-pmd`, `aggregate-cpd`, 
`aggregate-pmd-no-fork` are **blocked**: their sources stay in the tree but are 
excluded from compilation (pom `<excludes>`/`<testExcludes>` with a comment).
   
   #### Key finding: check does not need the report goal; the only coupling is 
a fork plus a file
   
   - `check`/`cpd-check` (and the aggregate variants) read exactly one file: 
`${targetDirectory}/pmd.xml` (`cpd.xml` for CPD), default 
`${project.build.directory}`. They never touch the report object, resolution, 
rulesets or PMD analysis. Only PMD library use: `PMDVersion.VERSION` in the 
message, the modello xpp3 readers, and `RuleViolation` in 
`ExcludeViolationsFromFile`.
   - The coupling is the annotation `@Execute(goal = "pmd")` / `"cpd"` / 
`"aggregate-pmd"` / `"aggregate-cpd"`: before each check, Maven forks the 
report goal, which runs `PmdExecutor`/`CpdExecutor` and writes 
`pmd.xml`/`cpd.xml` (XML is always produced, `canGenerateReportInternal` 
returns true for xml even with no files, so check can run on an empty result). 
No other state is passed.
   - Measured in a real Maven 4 build (installed plugin, scratch projects, no 
report goal):
     - `mvn pmd:check` with a handwritten `target/pmd.xml` (1 priority-3 and 1 
priority-4 violation): BUILD FAILURE `PMD 7.28.0 has found 2 violations. For 
more details see: .../target/pmd.xml`; `-Dpmd.verbose=true 
-Dpmd.failOnViolation=false` prints the two `PMD Failure:` lines and BUILD 
SUCCESS; `-Dpmd.failurePriority=2` gives `has issued 2 warnings`, BUILD 
SUCCESS; `-Dpmd.skip=true` skips. `cpd-check`: fails on `cpd.xml` with 1 
duplication, passes with `-Dcpd.failOnViolation=false`, `-Dcpd.skip` skips.
     - Missing file: `Unable to perform check, unable to find 
.../target/pmd.xml`; `-e` shows `Caused by: 
org.apache.maven.api.plugin.MojoException`. v4 has no failure/error split: 
output reads the same as the old MojoFailureException ("Failed to execute goal 
... on project x: message", BUILD FAILURE), and the same type is used for 
unreadable XML.
     - Multi-module (root pom + a + b): `pmd:check` runs per module, 
pom-packaging root skipped; `pmd:aggregate-pmd-check` runs once on the root 
(module steps SKIPPED), reads root `target/pmd.xml`; deprecated 
`-Daggregate=true` with `check` checks only the top project 
(`isExecutionRoot()` became `Project.isTopProject()`).
     - E1, fork to a goal that does not exist (check still annotated 
`@Execute(goal="pmd")`, report sources excluded): `Could not find goal 'pmd' in 
plugin ... among available goals aggregate-cpd-check, aggregate-pmd-check, 
check, cpd-check, help`. Fails before any check logic. That is why `@Execute` 
was removed from the four check mojos in this port.
     - E3, scratch copy with a stub v4 goal `pmd` that only writes `pmd.xml`, 
`check` annotated `@Execute(goal = "pmd")` (v4 annotation): rc-7 forks the v4 
goal (`>>> pmd:...:check > :pmd @ exp >>>`, then `--- pmd:check`), check reads 
its output and fails as expected. So v4 fork v4 works; a v4 non-report producer 
goal can restore the original `check` behaviour.
   - Why the whole plugin cannot hold the report goals (one concrete error, not 
re-proven at length): with report and check mojos together, plugin-tools 
4.0.0-beta-3 writes a 2.0.0 `plugin.xml` whose report mojos carry 
`<requirements>` (role `org.codehaus.plexus.PlexusContainer`, 
`org.apache.maven.doxia.siterenderer.Renderer`, 
`org.apache.maven.doxia.tools.SiteTool`; they come from `@Component` fields of 
`AbstractMavenReport` in reporting-impl 4.0.0). Maven 4.0.0-rc-7 then fails on 
**every** goal of the plugin: `Failed to parse plugin descriptor ... ParseError 
at [row,col]:[357,7] Message: Unrecognised tag: 
'{http://maven.apache.org/PLUGIN/2.0.0}requirements'`. A v4 and a v3-report 
mojo cannot share one artifact today. The already-proven chain (site plugin 
cast error, reporting-impl needing maven-core) stays as the reason the report 
goals cannot simply be ported.
   
   #### Aux classpath and ruleset resolution without Sisu
   
   Ruleset resolution (`PmdReport.resolveRulesets`, plexus-resources 
`ResourceManager`):
   - `DefaultResourceManager` (1.4.0) has a **public constructor taking 
`Map<String, ResourceLoader>`**; the loaders have public no-arg constructors. 
No Sisu needed: `new DefaultResourceManager(Map.of(FileResourceLoader.ID, new 
FileResourceLoader(), URLResourceLoader.ID, new URLResourceLoader(), 
ThreadContextClasspathResourceLoader.ID, new 
ThreadContextClasspathResourceLoader(), JarResourceLoader.ID, new 
JarResourceLoader()))`.
   - Verified with a standalone program (plexus-resources 1.4.0 + slf4j + 
plexus-utils only, no container): after `addSearchPath(FileResourceLoader.ID, 
dir)` and `setOutputDirectory(out)`, 
`getResourceAsFile("myrules.xml","001-myrules.xml")` copies the file from the 
search path; a classpath resource (`t/cp-rules.xml`) is found through the 
thread-context classloader; a missing one throws `ResourceNotFoundException`. 
NOT exercised: http(s) rulesets (URLResourceLoader), and whether the TCCL is 
the plugin realm inside a v4 mojo (the ported plugin default rulesets live in 
plugin resources). The search paths the report adds map to 
`project.getPomPath().getParent()`, `project.getBasedir()`, and the session 
base directory (v4: `session.getRootDirectory()`/top directory, not compared 
against `getRequest().getBaseDirectory()`).
   - The copy-to-`rulesetsTargetDirectory` logic, `determineRulesetFilename`, 
`getLocationTemp` and the `001-name.xml` naming are plain Java.
   
   Aux classpath (`PmdReport.determineAuxClasspath` + `ConfigurationService`):
   - v3 uses 
`MavenProject.getCompileClasspathElements()`/`getTestClasspathElements()` 
(needs `requiresDependencyResolution=TEST`) and, for aggregation, an aether 
`CollectRequest` through `Provider<MavenSession>` + `RepositorySystem` (both 
Sisu-injected), excluding reactor siblings and then adding each module's class 
dirs.
   - v4 equivalent, prototyped in a scratch mojo (`aggregator=true`, `@Inject 
Session`, `session.getService(DependencyResolver.class)`, 
`DependencyResolverRequest.builder().session(s).project(p).requestType(RESOLVE).pathScope(...)`,
 `getPaths()`), run on root + a (commons-io compile, javax.inject provided, 
junit test, slf4j-simple runtime) + b (depends on a):
     - `PathScope.MAIN_COMPILE` = {COMPILE, PROVIDED, COMPILE_ONLY}: the same 
set as `getCompileClasspathElements` (a gets commons-io + javax.inject). 
`PathScope.TEST_COMPILE` = {COMPILE, PROVIDED, TEST, TEST_ONLY} omits runtime 
deps; `PathScope.TEST_RUNTIME` = {PROVIDED, COMPILE, RUNTIME, TEST_RUNTIME, 
TEST} (adds slf4j-simple) is the match for `getTestClasspathElements`.
     - The project's own output directories are **not** in the result: prepend 
`project.getOutputDirectory(ProjectScope.MAIN)` and, for tests, 
`ProjectScope.TEST`, and keep the existing `emptyOrNotExisting` filter.
     - Reactor siblings ARE resolved by the v4 resolver: with `mvn compile`, 
b's resolved paths contain `a/target/classes` (a DIR) plus a's transitive 
commons-io. That replaces the v3 exclusion-list and per-module class-dir loop 
of `ConfigurationService`; `aggregate-*` only needs to loop 
`session.getProjects()` (filtering to the aggregated modules by base directory, 
as `modulesForAggregatedProject` does) and call the resolver per project. NOT 
verified: behaviour without `compile` in the same build (sibling would resolve 
to a jar/repo artifact), and system-scope deps.
     - Source roots: 
`session.getService(ProjectManager.class).getEnabledSourceRoots(p, 
ProjectScope.MAIN|TEST, Language.JAVA_FAMILY)` gives `src/main/java` and the 
generated-sources dir (prototype output). There is no `getCompileSourceRoots` 
in rc-7 `ProjectManager`; `compileSourceRoots`/`testSourceRoots` parameters 
(`${project.compileSourceRoots}`) need re-checking in a v4 build.
   - Toolchains: `org.apache.maven.toolchain.Toolchain/ToolchainManager` are no 
longer in maven-core 4.0.0-rc-7 (only in maven-compat). The v4 API is 
`org.apache.maven.api.Toolchain` and 
`org.apache.maven.api.services.ToolchainManager` 
(`getToolchains(session,"jdk",map)`, 
`getToolchainFromBuildContext(session,"jdk")` returns Optional), obtained with 
`session.getService(...)`. The report-side edits below use it; they compiled 
before the sources were excluded, but were never run.
   
   #### Public API changes
   - `AbstractPmdViolationCheckMojo<D>`: `extends AbstractMojo` becomes 
`implements org.apache.maven.api.plugin.Mojo`; field `project` is 
`org.apache.maven.api.Project` (`@Inject`, no longer a `${project}` parameter); 
`log` via `@Inject Log`, `getLog()` kept; `targetDirectory` is `Path` with 
`defaultValue=${project.build.directory}` (property `project.build.directory` 
kept); `execute()` throws `MojoException` only.
   - Check mojos: `@Mojo` is `org.apache.maven.api.plugin.annotations.Mojo` 
(`defaultPhase="verify"`; `threadSafe` has no v4 attribute and is dropped); 
`@Execute` removed from all four.
   - 
`ExcludeFromFile`/`ExcludeViolationsFromFile`/`ExcludeDuplicationsFromFile.loadExcludeFromFailuresData`
 throw `MojoException` (was `MojoExecutionException`); 
`AbstractPmdReport.getPmdVersion()` no longer used by check 
(`PMDVersion.VERSION`).
   - Edited but excluded from the build (never run): `ServiceExecutor`, 
`PmdServiceExecutor`, `CpdServiceExecutor`, `PmdReport`, `AggregatorPmdReport`, 
`AggregatorPmdNoForkReport` lost the `ToolchainManager` constructor parameter 
and use the v4 toolchain API; `CpdExecutor`/`PmdExecutor` catch `MojoException`.
   - Version 3.29.0-SNAPSHOT to 4.0.0-beta-1-SNAPSHOT; `javaVersion` 17; 
`mavenVersion` 4.0.0-rc-7; `<prerequisites><maven>` is `${mavenVersion}`; 
plugin-tools 4.0.0-beta-3; plugin-testing 4.0.0-beta-4.
   
   #### Gaps
   - Report goals (`pmd`, `cpd`, `aggregate-pmd`, `aggregate-cpd`, 
`aggregate-pmd-no-fork`) blocked: plugin.xml `<requirements>` parse error 
above, plus the proven reporting chain. Not ported, not running.
   - No non-report producer goal yet, so nothing in the Maven 4 plugin runs 
PMD/CPD; `check` needs a `pmd.xml`/`cpd.xml` from elsewhere (an older plugin's 
`pmd:pmd`, the PMD CLI, or a future v4 goal).
   - PMD/CPD execution engine (`exec/*`) is not ported. Its only hard ties to 
the report API are `MavenReportException` and the classloader fork path: 
`Executor.buildClasspath()` walks `URLClassLoader.getURLs()` of the plugin 
realm and of `ConsoleLogger`'s classloader (plexus-container-default from 
core); not exercised on Maven 4.
   - No v4 `isExecutionRoot`: `Project.isTopProject()` is used; difference from 
`MavenSession.isExecutionRoot()` with `-f`/`-pl` not tested.
   - No v4 failure/error distinction (`MojoFailureException` vs 
`MojoExecutionException`): one `MojoException`.
   - Removed from the build, all exercising the excluded report code (with 
`src/test` left in the tree): `CpdReportTest` (13), `PmdReportTest` (26), 
`PmdReportNumberOfThreadsTest` (5), `exec/ExecutorTest` (1); helpers 
`CapturingPrintStream` (needs `org.slf4j.impl.MavenSlf4jSimpleFriend`, which no 
longer ships with Maven 4), `DependencyArtifactStubFactory`, `stubs/**` (v3 
`MavenProject` stubs). Also the 46 pre-existing ITs are not selected 
(`<pomIncludes>` is `check-*/pom.xml`): they run `clean site`, `pmd:pmd` or a 
forked `pmd:check`. Test dependencies only those tests used were removed: 
wiremock, commons-io, commons-lang3, maven-embedder, maven-resolver-* (the 
Maven 3 resolver 1.9.27 `provided` jar also broke the v4 harness with 
`NoClassDefFoundError: org/eclipse/aether/collection/VersionFilterBuilder`).
   - `PmdViolationCheckMojoOnWindowsTest` ported identically (8 tests) but only 
skipped here (macOS).
   - Unverified at runtime: `@Mojo(aggregator=true)` under `-T`, `Project` 
injection on projects loaded from `-f` other poms.
   
   #### User-visible changes
   - Requires Maven 4.0.0-rc-7+ and Java 17 (was Maven 3.6.3 / Java 8); not 
usable on Maven 3.
   - Goals no longer in the artifact: `pmd`, `cpd`, `aggregate-pmd`, 
`aggregate-cpd`, `aggregate-pmd-no-fork`. `<reporting>` entries for this plugin 
and `mvn site` output (HTML report, xref links) are gone.
   - `check`, `cpd-check`, `aggregate-pmd-check`, `aggregate-cpd-check` no 
longer run PMD/CPD first. A build that bound `check` to `verify` and relied on 
the fork now fails with `Unable to perform check, unable to find <dir>/pmd.xml` 
unless an earlier step produced the file.
   - Parameters of the check goals are unchanged by name/property/default 
(`failOnViolation`, `failurePriority`, `maxAllowedViolations`, 
`excludeFromFailureFile`, `verbose`, `printFailingErrors`, `skip`, deprecated 
`aggregate`, `targetDirectory`). `project` is no longer a configurable 
parameter. `${basedir}` in parameter values is not expanded by v4: use 
`${project.basedir}` (two unit-test poms changed for that).
   - `threadSafe` flag not declared on the mojos.
   - Failure output: same BUILD FAILURE message; stack trace under `-e` names 
`org.apache.maven.api.plugin.MojoException`.
   
   #### Improvements
   - Runtime dependencies dropped from the plugin: 
maven-core/artifact/model/plugin-api (now maven-api-core/di/annotations/xml, 
provided), org.eclipse.sisu.plexus and javax.inject (DI index is generated: 
`META-INF/maven/org.apache.maven.api.di.Inject`, no hand upkeep needed here, 
`<proc>` is not `none`), plexus-utils, plexus-resources, plexus-i18n, 
doxia-core/sink-api, maven-reporting-api/impl, slf4j-api; sisu-maven-plugin and 
animal-sniffer-maven-plugin removed (its `java18` signature would reject Java 
17 APIs). Kept: pmd-core (needed), pmd-java/javascript/jsp runtime (only the 
excluded report goals need them), plexus-xml (xpp3 readers).
   - 5 new ITs (maven-invoker, through the existing `run-its` profile) that run 
the goals against precomputed results in `results/` with 
`<targetDirectory>${project.basedir}/results</targetDirectory>`: fails on 2 
violations; `failurePriority=3` with `verbose` gives `1 violation and issued 1 
warning`; `cpd-check` with `failOnViolation=false` succeeds; missing results 
fail with the message; `aggregate-pmd-check` on a pom root checks only the root.
   
   #### Recommendation
   Land the check goals as a v4 plugin slice now and do not try to keep the 
reports in the same artifact until plugin-tools/Maven accept v3 report mojos in 
a 2.0.0 descriptor. Next step for a usable v4 plugin: a non-report producer 
goal (`PmdExecutor`/`CpdExecutor` with `MojoException` instead of 
`MavenReportException`, rulesets via the hand-built `DefaultResourceManager`, 
aux classpath via `DependencyResolver` with `MAIN_COMPILE`/`TEST_RUNTIME` plus 
own output dirs, toolchain via `api.services.ToolchainManager`), which the 
check goals can fork with the v4 `@Execute(goal=...)` (E3 shows that works). 
The HTML report then stays with the 3.x line or a separate artifact once the 
reporting chain moves.
   
   </details>
   
   <details><summary><b>maven-rar-plugin</b>: ported</summary>
   
   
   Branch `agent/mvn4-api`; PR not opened yet. Status: **ported** (packaging 
registration stays on the Maven 3 component model), 4.0.0-beta-1-SNAPSHOT, Java 
17.
   
   Verified locally: `mvn verify` with Maven 4.0.0-rc-7, JDK 21 → 4 unit tests 
before, 5 after, 0 failures, 0 skipped; `mvn verify -Prun-its` → 3 ITs passed, 
0 failed before (3m08s), 4 passed, 0 failed after (2m42s), the fourth 
(`dependencies`) is new; spotless clean, RAT and `dependency:analyze-only` pass 
in the verify run. The unit tests were rewritten for the v4 harness 
(`maven-testing`), so the counts are not like-for-like: the three former tests 
are kept, plus one for optional and non-library dependencies. Shared snapshots 
consumed: none (maven-archiver 4.0.0-beta-5 and maven-filtering 4.0.0-beta-1 
are released).
   
   **User-visible changes**
   - Runs on Maven 4 only; needs Java 17. A 3.x line must stay for Maven 3 
users.
   - Goal, parameter names and `-D` properties are unchanged. Readonly 
`session` and `project` leave the descriptor; `threadSafe = true` has no v4 
`@Mojo` attribute and is dropped.
   - `RarResource` (the `<rarResources>` element type) now extends 
`org.apache.maven.shared.filtering.Resource` instead of 
`org.apache.maven.model.Resource`; the XML elements are the same.
   - `rarSourceDirectory`, `raXmlFile`, `manifestFile`, `outputDirectory` are 
`Path` instead of `File`; `getBuildDir()` and `getRarFile(...)` (protected) 
change to `Path`.
   - Dependencies are resolved for `main-runtime` inside `execute()`; the v3 
mojo declared `requiresDependencyResolution = TEST`, so test-scope dependencies 
are no longer resolved and an unresolvable test dependency no longer fails the 
goal.
   - A dependency is copied when it is not optional and its `Type` has path 
types (class path or module path); that replaces 
`ArtifactHandler.isAddedToClasspath()`. A `pom` or `rar` dependency is left out 
by construction (`RarArtifactHandler` sets `addedToClasspath=false`); only 
`jar`, optional and test scope are covered by a test.
   - A blank `classifier` is now treated as no classifier and sets the main 
artifact. I did not measure what the v3 mojo did with the empty default.
   - `@Parameter` defaults use `${project.basedir}` (see Gaps).
   
   **Gaps**
   - Packaging registration has no v4 equivalent. `RarLifecycleMappingProvider` 
(`Provider<LifecycleMapping>`) and `RarArtifactHandler` still use 
`javax.inject` and `maven-core` classes 
(`org.apache.maven.lifecycle.mapping.*`, `DefaultArtifactHandler`), so 
`maven-core` and `javax.inject` stay as `provided` dependencies. 
`maven-api-spi` has `PackagingProvider`, `TypeProvider` and 
`LifecycleProvider`, but in rc-7 `DefaultPackagingRegistry.lookup` only looks 
up a legacy `LifecycleMapping` by id, and its provider list is injected at 
construction, so a provider shipped by a project extension is never consulted 
(read in `maven-4.0.x`, tag rc-7 plus 11 commits). The `default-extension` IT 
passes with the legacy classes.
   - `@Inject ProjectManager` fails in a real build: "No binding to construct 
an instance for key ProjectManager" (the `maven-testing` harness does bind it, 
so the unit tests were green). Workaround: 
`session.getService(ProjectManager.class)`.
   - `@Resolution` field injection is not usable: `maven-plugin-plugin` 
4.0.0-beta-1 writes no resolution into `plugin.xml`, the field stays null. My 
first port copied no dependencies and passed all unit tests and the 3 existing 
ITs, none of which has a dependency. Fixed with an injected 
`DependencyResolver` and `resolve(session, project, PathScope.MAIN_RUNTIME)`; 
the new `dependencies` IT guards it. I did not run a negative control against 
the `@Resolution` version.
   - `${basedir}` is not expanded in a v4 `@Parameter(defaultValue)` (the work 
directory ended up as `<basedir>/${basedir}/src/main/rar`); 
`${project.basedir}` is. The harness does not expand `${basedir}` in plugin 
configuration either, so the tests set path parameters in code.
   - `maven-filtering` 4.0.0-beta-1 needs a `BuildContext` binding, so the 
plugin adds `Providers` (`@Provides BuildContext`) and `plexus-build-api` 
0.0.7; `ThreadBuildContext` extends Plexus `AbstractLogEnabled`, so 
`org.eclipse.sisu.plexus` 1.1.0 stays on the plugin class path 
(`NoClassDefFoundError` without it).
   - `MavenArchiver.createArchive` (maven-archiver 4.0.0-beta-5) takes the v4 
`Session` and `Project` and throws unchecked `MavenArchiverException`; 
`archive.setManifestFile` takes a `Path`. `JarArchiver` is no longer 
injectable, so the mojo does `new JarArchiver()`.
   - Not covered: a multi-module reactor build in which the RAR depends on a 
sibling module; `filterRarSourceDirectory` with delimiters (only the existing 
`filtered` IT).
   
   **Consumers that break:** none in the Apache Maven plugin and 
shared-component repositories use its classes. `maven-ear-plugin` only lists 
`maven-rar-plugin:${mavenRarPluginVersion}` as an IT extra artifact and stays 
on the 3.x version until bumped.
   
   **Improvements:** drops `maven-plugin-api`, `maven-core` (only for the 
packaging registration, see Gaps), `maven-model`, `maven-artifact`, 
`maven-plugin-annotations`, `plexus-utils`, `junit` 4, `junit-vintage-engine`, 
`maven-plugin-testing-harness` 3.x and the five Maven 3 project/artifact test 
stubs; adds `maven-api-core`, `maven-api-di` (provided), `maven-testing`, 
`mockito-core` (test) and the two runtime dependencies named under Gaps.
   
   **Recommendation:** port for the Maven 4 line, keep 3.x for Maven 3. Not 
blocked; the packaging registration should move to the SPI once 
`DefaultPackagingRegistry` consults `PackagingProvider` for project extensions, 
which is an API request for apache/maven. Worth a plugin-tools issue: 
`@Resolution` is not written to `plugin.xml`.
   
   </details>
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to