slachiewicz commented on issue #13302:
URL: https://github.com/apache/maven/issues/13302#issuecomment-5919283073
### Wave 4 findings, part 2 of 4: maven-doap-plugin to maven-jarsigner-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-doap-plugin</b>: ported</summary>
Branch `agent/mvn4-api`; PR not opened yet. Status: **ported**,
4.0.0-beta-1-SNAPSHOT, Java 17. Five approximations, all under Gaps; the
release listing and the `artifact` parameter differ from Maven 3 behaviour in
ways the unit tests cannot show.
Verified locally: `mvn verify` with Maven 4.0.0-rc-7, JDK 21 → 15 tests
before and after, 0 failures, 0 skipped; `mvn verify -Prun-its` → 4 of 4 ITs
pass before and after; `spotless:check` clean. Smoke runs on rc-7 against Maven
Central (scratch projects, not committed): a project whose releases exist on
Central (release list, `file-release` URLs and `created` date came out right)
and `<artifact>` set to `org.apache.maven:maven-artifact:3.9.9` (parent
inherited, URL and SCM effective). The pre-port plugin could not be compared on
the same projects: under rc-7 it fails with `NoClassDefFoundError:
org/codehaus/plexus/util/xml/XmlStreamReader` as soon as a repository returns
metadata, which none of the ITs do.
**Public API changes**
- `DoapMojo` implements `org.apache.maven.api.plugin.Mojo`, `@Mojo(name =
"generate")` from `org.apache.maven.api.plugin.annotations`; `execute()` throws
`MojoException`. `project` is the injected `org.apache.maven.api.Project`,
dates and model getters read from `project.getModel()`.
- Removed fields and read-only parameters: `localRepository`,
`projectBuildingRepositories`, `remoteRepositories`, `repositorySystemSession`,
`settings`, `project` (as a parameter).
- `DoapUtil.interpolate(String, Project, Settings)` takes the v4 `Project`
and `org.apache.maven.api.settings.Settings`.
`DoapUtil.getContributorsWith*Role(List<Contributor>)` lose the `I18N` argument
and use `org.apache.maven.api.model.Contributor`.
`ASFExtOptionsUtil.isASFProject(Project)` and `findChair`/`findPMCMembers` take
`org.apache.maven.api.model.Developer`.
- Modello classes (`DoapOptions`, `ASFExtOptions`, `ExtOptions`,
`DoapArtifact`) are unchanged.
**Gaps** (rc-7 `maven-api-core`, `maven-api-model`, `maven-api-settings`)
- Building a `Project` from coordinates: the v4 `ProjectBuilder` takes a
path or a `Source`, not an artifact. `<artifact>` now resolves the POM with
`Session.resolveArtifact` and builds from its path. A build from a `Source`
(`Sources.resolvedSource`) returns an empty `Optional<Project>` with no
problems listed, because `DefaultSession.getProject` drops a project without
base directory; the plugin used it first and silently fell back to the current
project. The request builder has no validation level, so Maven 3's
`VALIDATION_LEVEL_MINIMAL` is gone.
- `RemoteRepository` has no release or snapshot policy (`getId`, `getType`,
`getUrl`, `getProtocol` only). The plugin picks the first repository that
serves releases but not snapshots; it now reads the policies from the
repository of the same id in `project.getModel().getRepositories()`. A
repository that is not declared there, such as a mirror or one from
`settings.xml`, is taken as releases only, which can change which repository is
chosen.
- No repository metadata service. `Transport` (from `TransportProvider`)
fetches `g/a/maven-metadata.xml` by relative URI, and the XML is parsed with
`MetadataStaxReader`, which ships in `maven-support`, not in an API module; it
is bundled, as maven-jar-plugin does. Lost: the update and checksum policy, the
local copy of the metadata, and the distinction resolver makes between a
missing file and a failed transfer beyond `Optional.empty()`.
- `Transport` has no existence check. Whether a release file exists is now
read from its `.sha1`, so a repository that serves artifacts without checksum
files reports no `file-release`. The alternative was downloading every artifact
of every version.
- No repository layout service: `Session.getPathForRemoteArtifact` is the
path in the local cache, not in the remote repository. The default-layout
location is built by hand (`g/a/v/a-v[-c].ext`); the extension comes from
`session.requireType(type).getExtension()`, or the type itself when unknown, as
the old handler manager did.
- `ScmManager` and `I18N` are Plexus components with no v4 injection.
`ScmManager` is now a `BasicScmManager` holding only `SvnExeScmProvider`, the
same provider set the old classpath had; `I18N` is replaced by
`ResourceBundle.getBundle("doap-person")`.
- `${project.reporting.outputDirectory}` is empty in Maven 4 unless the POM
sets it (Maven 3 always gave `${project.build.directory}/site`); the plugin
applies that default itself. The `basic` IT caught it as an NPE.
- `Metadata.getVersioning().getVersions()` is immutable; the old code
reversed it in place. The unit fixture had one version, which hid the failure
until the real run.
- `ProjectManager` has no DI binding in rc-7; `ProjectBuilder` and
`TransportProvider` are bound, but their implementations cannot be built in the
test harness (`DefaultTransportProvider` needs resolver's
`TransporterProvider`). All three are looked up with `session.getService(...)`.
- Interpolation: the `project` and `pom` prefixes now resolve against the
effective `Model` (getter names match for `name`, `url`, `scm.*`,
`developers[n].*`); `basedir` is added by hand. Anything that only
`MavenProject` had (`${project.artifact...}`, `${project.file}`) no longer
resolves.
- Test harness: `maven-plugin-testing-harness` 4.0.0-beta-4 has no real
repository session (3.5.1 had `realRepositorySession = true`), so the two tests
that resolved plexus-utils 1.5.5 and xstream 1.1 from Central now use fixture
POMs (`src/test/resources/unit/artifact`, reduced by hand) and a mocked
`Session`/`ProjectBuilder`, and the release tests use a directory-backed fake
`Transport`. The real resolution path is covered only by the smoke run above,
not by a committed test.
**User-visible changes**
- Needs Maven 4.0.0-rc-7 or newer and Java 17; `<prerequisites>` follows
`mavenVersion`. The `generate` goal and its writable parameters keep their
names.
- Release listing: repository choice, existence check and metadata handling
differ as described above.
- `<artifact>` builds a model with Maven 4's default POM validation instead
of minimal validation.
- `.github/workflows/maven-verify.yml` still carries the JDK 8 / Maven 3.9.0
`matrix-include` entry, which cannot run a Maven 4 plugin; not touched.
**Improvements:** drops `maven-plugin-api`, `maven-core`, `maven-artifact`,
`maven-settings`, `maven-model`, `maven-model-builder`,
`maven-repository-metadata`, `maven-resolver-api/impl/spi`,
`maven-scm-manager-plexus`, `plexus-i18n`, `javax.inject` and the resolver test
connectors; `XmlStreamReader` is no longer needed on the release path.
**Recommendation:** port, and ask apache/maven for four things: a policy
accessor on `RemoteRepository`, an existence check on `Transport`, a `Metadata`
read service, and `ProjectBuilder` by coordinates that returns a `Project` for
a repository POM. Until then a plugin that lists releases is the kind that
loses most by moving. Release it as a 4.x line next to the 3.x one.
</details>
<details><summary><b>maven-ear-plugin</b>: partial</summary>
Branch `agent/mvn4-api`; PR not opened yet. Status: **partial**,
4.0.0-beta-1-SNAPSHOT (was 3.4.1-SNAPSHOT), Java 17.
Verified locally: Maven 4.0.0-rc-7, JDK 21. `mvn verify` -> 48 unit tests
before (8 classes) and 49 after, 0 failures/errors/skipped (one test added, see
Tests). `mvn verify -Prun-its` -> before: 18/18 invoker ITs and 103/103
`EarMojoIT` pass (45 min, run with other builds in parallel); after: 17/18
invoker ITs pass and 103/103 `EarMojoIT` pass (13 min). The one failing IT is
`skinny-wars-timestamp` (see Gaps); the before run is the 3.4.1 plugin under
Maven 4. `spotless:check` clean. Released artifacts: maven-archiver
4.0.0-beta-5, maven-filtering 4.0.0-beta-1, plugin-tools 4.0.0-beta-1. Local
snapshot consumed: maven-mapping 4.0.0-SNAPSHOT (`agent/mvn4-api` at 1f0a2fa,
worktree `wt-fbf-dep-mapping`, `mvn install -DskipTests`).
**User-visible changes**
- Runs only on Maven 4 (no `maven-plugin-api`, `maven-core`,
`maven-artifact`, `javax.inject`, `maven-shared-utils`). A 3.x line has to stay
for Maven 3 builds.
- Goals `ear` and `generate-application-xml`, their phases and every
parameter name are unchanged; `threadSafe` is no longer declared (v4 `@Mojo`
has no such attribute), nor `requiresDependencyResolution` (the plugin resolves
`PathScope.TEST_RUNTIME` itself through `DependencyResolver`).
- `earSourceDirectory` default is `${project.basedir}/src/main/application`
(`${basedir}` is not evaluated in v4, the directory was silently ignored), and
the `description` default is `${project.model.description}`.
- `@{version}@` (the default `outputFileNameMapping`) of a SNAPSHOT
dependency expands to `1.0-SNAPSHOT`, no longer to the timestamped
`1.0-20150825.210557-91`; the documented "timestamp postfix" in
customize-file-name-mapping is not reproducible (see Gaps). EAR entry names and
the Class-Path of skinny modules change accordingly for SNAPSHOT dependencies.
- maven-mapping tokens (`outputFileNameMapping`): the documented ones
(`groupId`, `artifactId`, `version`, `baseVersion`, `dashClassifier?`,
`extension`) are unaffected. The v4 port drops the `ArtifactHandler` value
source and `api.Artifact` has no `type`/`scope`; because the plugin passes the
`Dependency`, `@{type}@` now prints the `Type` object's `toString()` (not
`ejb`) and `@{scope}@` prints `COMPILE` (not `compile`), and `@{packaging}@`,
`@{language}@`, `@{file}@` stay literal in the file name. None of these is
documented or used in the repo's poms/ITs.
- Free-form parameters `artifactTypeMappings`, `jboss`, `security`,
`envEntries`, `ejbRefs`, `resourceRefs` are `XmlNode` instead of
`PlexusConfiguration`; the XML users write is unchanged.
- Modules are still typed by the dependency type:
`Dependency.getType().id()` is the declared string (`ejb`, `war`, `rar`, `sar`,
`har`, `par`, `wsr`, `app-client`, `ejb-client`, `test-jar`,
`jboss-sar`/`-har`/`-par`, custom types through `artifactTypeMappings`), so the
type to module mapping works and is covered by 103 `EarMojoIT` projects. `ejb`,
`ejb-client`, `war`, `ear`, `test-jar` are registered types in rc-7; the rest
fall back to the legacy handler (extension = type) and resolve fine. The v4
`Type` replaces the `ArtifactHandler` for `includesDependencies`/extension
only; the ear-specific mapping (`EarModuleFactory`,
`ArtifactTypeMappingService`) stays in the plugin, nothing in v4 replaces it.
- Public Java API: `EarModule.getArtifact()` returns the new
`util.ResolvedArtifact` (dependency + resolved `Path`; v4 `Dependency` carries
no file) instead of `Artifact`; module constructors, `ArtifactRepository`,
`EarExecutionContext` follow; `resolveArtifact` no longer throws the checked
`MojoFailureException`, `InvalidJavaEEVersion` extends the unchecked
`MojoException`; `ArtifactTypeMappingService.configure` takes the new
`util.XmlConfig` (a read-only view over `XmlNode`);
`EarMavenArchiver.getManifest` takes `api.Session/Project` and the deprecated
`getManifest(MavenProject, config)` overload is removed; `EarMojo` has no
constructor (archivers are created inside; `ArchiverManager` replaced by `new
ZipUnArchiver()`).
- New `Providers` (`@Provides` `ProjectManager`, `BuildContext`) for
`MavenFileFilter`; the ear artifact is attached with
`ProjectManager.attachArtifact(project, project.getMainArtifact(), ear)` or a
produced artifact of type `ear` for a classifier.
**Gaps**
- `skinny-wars-timestamp` IT fails (only after-failure): v4 gives the
resolved SNAPSHOT `Dependency` version `1.0-SNAPSHOT` and a `-SNAPSHOT`
local-repo file name; `session.resolveArtifact` returns the same. The
timestamped version is unreachable through the API, so the IT's expectations
(`eartest-jar-sample-one-1.0-20150825.210557-91.jar` in Class-Path, timestamped
jar removed from the WAR built by the 3.x war plugin) cannot hold. With a v4
war plugin both sides use `-SNAPSHOT` and the original-file-name lookup
matches; only mixed 3.x-war/4.x-ear builds leave the duplicate jar in
`WEB-INF/lib`. IT left red on purpose, not edited.
- `DependencyResolver` ignores `Type.isIncludesDependencies()` (`war`,
`ear`, `rar`) although the session has `FatArtifactTraverser`: the war's
transitives appear in the result, and an artifact reachable by several paths is
listed only below the nearest one (`skinny-wars-javaee5` and `project-089..096`
failed with it). Worked around in `AbstractEarMojo.resolveProjectArtifacts`: a
RESOLVE tree plus a verbose COLLECT tree; an artifact is kept only if reachable
without passing through an `includesDependencies` node (a reachable winner's
subtree counts). Approximation: a version conflict won by the fat path is not
re-mediated.
- `XmlNode` mojo parameters lose XML attributes
(`DefaultBeanConfigurator.XmlConverter` builds the node with `null` attributes;
same on core master): `artifactTypeMapping type= mapping=`, `security-role id`,
`loader-repository class`. Worked around by reading those elements from the
injected `MojoExecution.getConfiguration()` (model `XmlNode`, attributes
intact); values are model-interpolated only, `${session.*}`-style expressions
are not evaluated. `PlexusConfiguration` parameters cannot work at all ("Cannot
create instance of interface"): core does not export
`org.codehaus.plexus.configuration` to plugin realms, `@Mojo(configurator =
"basic")` does not help.
- `Session` has no build start time; `deleteOutdatedResources` uses the JVM
start time, so under a long-lived JVM (mvnd) stale files from an earlier build
in the same daemon are not deleted.
- Mojo failure vs error is lost (`MojoException` only), so
`MojoFailureException` paths (unknown artifact, missing candidate) now report
as errors.
- `META-INF/plexus/components.xml` (ear `ArtifactHandler` and
`LifecycleMapping`) is kept untouched and not exercised: Maven 4 core has
built-in `ear` type and `ear` lifecycle mapping
(`EarLifecycleMappingProvider`), which the ITs use; a plugin-provided packaging
needs the Plexus components in rc-7.
- System-scope dependencies: `PathScope.TEST_RUNTIME` has no `SYSTEM` scope
in rc-7, so they are not part of the module set; not covered by any IT.
**Tests:** all 48 unit tests kept. `AbstractEarTestBase` builds
`ResolvedArtifact` over a new `stub/DependencyStub` (implements
`api.Dependency`); removed `stub/ArtifactHandlerTestStub` (v3
`ArtifactHandler`, unused now). `ArtifactTypeMappingServiceTest` builds
`XmlNode` instead of `XmlPlexusConfiguration`; its
`testConfigWithSameCustomType` never populated the second mapping (it set the
attributes on the first element twice), so it only exercised the
missing-attribute path: kept as is and
`testConfigWithSameCustomTypeRegisteredTwice` added for the real duplicate (49
tests). `AbstractEarPluginIT` uses plexus-utils `FileUtils`. No IT source
changed.
**Improvements:** drops `maven-plugin-api`, `maven-core`, `maven-artifact`,
`maven-plugin-annotations`, `javax.inject`, `maven-shared-utils`; adds
`maven-api-core/di/annotations/model/xml` (provided), `plexus-build-api` and
`org.eclipse.sisu.plexus` (needed at runtime by `ThreadBuildContext`,
`AbstractLogEnabled`; `dependency:analyze` ignore entry added).
**Recommendation:** not mergeable as is. Port for Maven 4 and keep a 3.x
line, but only after the core gaps are filed: `includesDependencies` not
honoured by the API resolver, `XmlNode` parameter conversion dropping
attributes, no snapshot timestamp version and no session start time in the API.
The ear plugin itself ports with workarounds that restore behaviour for all 103
`EarMojoIT` cases and 17 of 18 invoker ITs; `skinny-wars-timestamp` is the one
documented behaviour that cannot be kept.
</details>
<details><summary><b>maven-ejb-plugin</b>: ported</summary>
Branch `agent/mvn4-api`; PR not opened yet. Status: **ported**,
4.0.0-beta-1-SNAPSHOT (was 3.3.1-SNAPSHOT), Java 17.
Verified locally: Maven 4.0.0-rc-7, JDK 21. `mvn verify` → 36 tests before
(19 EjbMojoTest, 10 EjbHelperTest, 7 IncludesExcludesTest) and 36 after, 0
failures/errors/skipped. `mvn verify -Prun-its` → 9/9 invoker ITs pass before
(4m58s) and after; `spotless:check` clean. Released artifacts only, no local
snapshots: maven-archiver 4.0.0-beta-5, maven-filtering 4.0.0-beta-1,
maven-plugin-plugin 4.0.0-beta-1, maven-testing 4.0.0-rc-7.
**User-visible changes**
- Runs only on Maven 4 (no `javax.inject`, `maven-plugin-api`, `maven-core`,
`maven-artifact`, `maven-model`, `maven-settings`, sisu annotations). A 3.x
line has to stay for Maven 3 builds.
- Goal `ejb`, phase `package` and every parameter (`classifier`,
`clientClassifier`, `ejbJar`, `ejbVersion`, `generateClient`,
`clientIncludes/Excludes`, `excludes`, `archive`, filtering options,
`outputTimestamp`) are unchanged; `threadSafe` is no longer declared (v4
`@Mojo` has no such attribute).
- Public API: `EjbMojo.getProject()` now returns
`org.apache.maven.api.Project` (was `MavenProject`); `validateEjbVersion`
throws the unchecked `MojoException` (was checked `MojoExecutionException`).
`EjbHelper` is unchanged.
- Main jar is attached via `ProjectManager.attachArtifact(project,
project.getMainArtifact(), path)`; classified jar and client jar via
`session.createProducedArtifact(..., type "ejb" / "ejb-client")`. The old
unreachable `FIXME` branch for a null client classifier did the same call as
the valid branch and is merged into it.
- Maven 4 prints the "You have to use a classifier ..." failure without the
trailing ` -> [Help 1]`, so the IT `mejb-93` now matches the message without it
(it still asserts the same behaviour: a second execution without classifier
fails).
- New `Providers` class (`@Provides`) supplies `ProjectManager` and
`BuildContext` (required by `DefaultMavenFileFilter` 4.0.0-beta-1).
**Gaps**
- `org.eclipse.sisu:org.eclipse.sisu.plexus` must be a compile dependency:
`ThreadBuildContext` (plexus-build-api 0.0.7) extends
`org.codehaus.plexus.logging.AbstractLogEnabled`, which a v4 plugin realm does
not provide. Without it all 7 ITs failed with `NoClassDefFoundError:
org/codehaus/plexus/logging/AbstractLogEnabled`. maven-resources-plugin master
carries the same dependency.
- `@Mojo(requiresDependencyResolution = RUNTIME)` has no usable v4
equivalent with maven-plugin-plugin 4.0.0-beta-1
(`dependencyResolutionPathScopes` fails descriptor generation: "Method:
'dependencyResolutionPathScopes' not found in class MojoAnnotationContent").
Dropped; `MavenArchiver.getManifest` resolves `MAIN_RUNTIME` itself through
`DependencyResolver`, and the `manifest-content` IT passes.
- The v3 harness (`AbstractMojoTestCase`, `MavenProject` stubs) has no v4
counterpart.
**Tests:** `EjbMojoTest` rewritten on JUnit 5 with `maven-testing`
(`ProjectStub`, `SessionMock`), `@TempDir` and a mocked `ProjectManager`; all
18 original scenarios kept with the same assertions, one lookup test moved to
`@MojoTest`/`@InjectMojo` (resource renamed `plugin-config.xml` to `pom.xml`),
and two attach assertions added (`verify` on `ProjectManager`/`Session` for the
default and classified+client cases). Removed and replaced:
`stub/MavenProjectBasicStub`, `MavenProjectBuildStub`,
`MavenProjectResourcesStub`, `ModelStub` (v3 `MavenProject` subclasses;
replaced by the nested `TestProject`). `vintage-engine` and
`maven-plugin-testing-harness` 3.5.1 dropped. `EjbMojo` fields are set by
reflection in these tests, as before.
**Improvements:** drops `javax.inject`, `maven-plugin-api`, `maven-core`,
`maven-artifact`, `maven-model`, `maven-settings`, `maven-shared-utils`,
`plexus-utils`, `org.eclipse.sisu.inject`, JUnit vintage, the v3 testing
harness.
**Recommendation:** port for Maven 4; keep a 3.x line for Maven 3 users.
maven-ear-plugin's pom only lists maven-ejb-plugin as an `extraArtifact` for
its ITs (`mavenEjbPluginVersion`), so it is not a compile-time consumer; its
ITs that resolve the ejb plugin would need a 4.x version together with Maven 4.
</details>
<details><summary><b>maven-gpg-plugin</b>: partial</summary>
Branch `agent/mvn4-api`; PR not opened yet. Status: **partial**,
4.0.0-beta-1-SNAPSHOT, Java 17. All three goals (`sign`,
`sign-and-deploy-file`, `sign-deployed`) ported and exercised by the ITs; one
behaviour cannot be ported with the API (encrypted settings passphrases, see
Gaps). No test or IT removed.
Verified locally: Maven 4.0.0-rc-7, JDK 21. `mvn -B -ntp verify`: 10 tests,
0 failures, 1 skipped (`BcSignerTest` 6, `GpgVersionTest` 3,
`GpgVersionConsumerTest` 1), before and after. `-Prun-its` with the Bouncy
Castle signer (`bc-integration-tests` plus failsafe `Bc*IT`): invoker 13 of 13
passed and `BcSignArtifactIT` 4 of 4, before and after. The
`gpg-integration-tests` execution and `GpgSignArtifactIT` could not be
measured: the system gpg 2.5 fails with "can't connect to the gpg-agent: File
name too long" (macOS socket path limit; the worktree path is too long), which
gave 1 of 13 before, so for the comparison that execution was switched off in a
scratch copy of the pom in both runs. The `gpg` signer path is therefore not
exercised after the port beyond compilation. Spotless clean.
**v4 routes**
- Attach: `MavenProjectHelper.attachArtifact(project, type, classifier,
file)` becomes `ProjectManager.attachArtifact(Project, ProducedArtifact, Path)`
with `session.createProducedArtifact(g, a, v, classifier, extension + ".asc",
null)` (the 6-argument factory, because the short `attachArtifact` overloads
cannot carry a classifier). `FilesCollector` reads
`ProjectManager.getPath/getAttachedArtifacts` and `ArtifactManager.getPath`.
- `sign-and-deploy-file` outside a project: yes. Same shape as
`maven-deploy-plugin` 4.0.0-beta-3 `DeployFileMojo` (`projectRequired =
false`): artifacts from `session.createProducedArtifact`, paths via
`ArtifactManager.setPath`, deploy via `ArtifactDeployer` with
`ArtifactDeployerRequest` (its `retryFailedDeploymentCount` replaces the
hand-written retry loop), repository from `session.createRemoteRepository(id,
url)`, POM read/generated with `ModelXmlFactory`. Signing itself has no API and
stays in `GpgSigner`/`BcSigner`.
- `sign-deployed`:
`session.withLocalRepository(session.createLocalRepository(tmp))` for the
private repo, `resolveArtifacts(coordinates, repos)`, `ArtifactDeployer` for
the `.asc` files.
**Public API changes**
- Mojos implement `org.apache.maven.api.plugin.Mojo`;
`MojoExecutionException`/`MojoFailureException` become the unchecked
`MojoException` in all public signatures (`AbstractGpgSigner`, `GpgSigner`,
`BcSigner`, `GpgVersionParser`, `FilesCollector`).
- `BcSigner(Session, ...)` and its `Loader` methods take
`org.apache.maven.api.Session` instead of the aether session;
`FilesCollector(Session, Project, String[], Log)` (was `MavenProject, String[],
Log`); `AbstractGpgMojo.getPassphrase(Project)`.
- `ArtifactCollectorSPI.collectArtifacts(Session, RemoteRepository)` now
uses `org.apache.maven.api.Artifact/RemoteRepository/Session`: an SPI break for
any implementor.
- The `settings` parameter (`${settings}`) and the injected
`SettingsDecrypter` are gone; `session.getSettings()` is used.
- Env variables (`env.MAVEN_GPG_*`) are read from the session user then
system properties (`BcSigner.getEnv`), replacing
`RepositorySystemSession.getConfigProperties()`.
**Gaps**
- Encrypted passphrases in `settings.xml`: rc-7 has no decrypt service in
any `maven-api-*` module (`SettingsDecrypter` exists only in compat
`maven-settings-builder`, and `maven-impl` never calls it).
`gpg.passphraseServerId` values that look encrypted (`{...}`) now fail with an
explicit `MojoException` instead of being signed with as cipher text; plain
passphrases still work (IT `sign-with-passphase-from-maven-settings` passes).
Needs a settings-decrypt service in `maven-api-core` to be closed.
- The "old way" passphrase-from-project-properties read no longer copies the
found value onto the reactor root project (`Project.getModel().getProperties()`
is immutable).
- `ModelValidator` strict validation of the coordinates in
`sign-and-deploy-file` has no API equivalent; replaced by a local check
(groupId/artifactId `[A-Za-z0-9_.-]+`, version without path or whitespace
characters, packaging non-blank), which is looser than the model validator.
- `ArtifactHandlerManager` replaced by `TypeRegistry.lookup(packaging)`;
unknown types fall back to extension = type, as before.
- Mojo constructor injection does not work with the generated `MojoFactory`
(`NoSuchMethodError: SignDeployedMojo.<init>()`): `SignDeployedMojo` uses field
injection, `@Inject @Nullable Map<String, ArtifactCollectorSPI>` (an empty map
otherwise fails to inject).
- `BcSignerTest` built an aether session with `maven-resolver-impl`; it now
uses a `java.lang.reflect.Proxy` over `Session` that answers only the two
property maps (no new test dependency, which would need a pgpverify keys-map
entry).
- `<proc>none</proc>` removed from the compiler configuration so the api.di
index is generated.
- `plexus-utils` (`FileUtils`, `SelectorUtils`, `Os`, `cli.*`,
`CachingOutputStream`) is not a Maven API and stays.
**User-visible changes**
- Requires Maven 4; Java 17; `<prerequisites>` follows `mavenVersion`.
- Failure text `MojoFailureException: Do not store passphrase...` is now
`MojoException: ...` (IT `sign-release-best-practices-fail` updated).
- Encrypted server passphrase: explicit failure, see Gaps.
`retryFailedDeploymentCount` log lines ("Retrying deployment attempt") no
longer come from the plugin.
- `maven-resolver-impl` test dependency and the `resolverVersion` property
removed.
**Improvements:** drops `maven-core`, `maven-plugin-api`, `maven-artifact`,
`maven-model`, `maven-model-builder`, `maven-settings`,
`maven-settings-builder`, `maven-resolver-api/util`,
`maven-plugin-annotations`, `javax.inject`.
**Recommendation:** port is viable; do not merge until the settings-decrypt
gap is decided (file against apache/maven), and run the `gpg` signer ITs on a
machine with a short checkout path.
</details>
<details><summary><b>maven-help-plugin</b>: ported</summary>
Branch `agent/mvn4-api`; PR not opened yet. Status: **ported**,
4.0.0-beta-1-SNAPSHOT (was 3.5.3-SNAPSHOT), Java 17. Two goals are degraded,
see Gaps.
Verified locally: Maven 4.0.0-rc-7, JDK 21. `mvn verify` before → 30 tests,
0 failed, 0 skipped; after → 61 tests, 0 failed, 0 skipped. `mvn verify
-Prun-its` before → 34 passed, 0 failed, 2 skipped (12m27s); after → 36 passed,
0 failed, 0 skipped (18m03s, run on a copy of the tree);
`describe-cmd-with-goal-report` failed on its first attempt (the report check
logged `Couldn't identify if this goal is a report goal:
org/apache/maven/plugin/AbstractMojo`, cause not isolated) and passed on the
invoker retry. `spotless:check` clean. No local snapshots consumed, released
artifacts only.
**User-visible changes**
- All 11 goals are `org.apache.maven.api.plugin.Mojo`s; `session`,
`project`, `Log` and the services are `@Inject`ed. Goal names, phases and
parameter names/properties are unchanged; `output` is now a `Path` (same XML
syntax). The plugin no longer loads under Maven 3: a 3.x line has to stay.
- `evaluate`: the expression evaluator of Maven 3 is gone. The new one
(`ExpressionEvaluator`) handles `project`, `session`, `settings`, `mojo`,
`plugin`, `localRepository`, `reactorProjects`, `basedir`, `rootDirectory`,
`env.X`, then project properties, session properties and system properties,
through the public getters of the API objects (`a.b.c`, `list[0]`, `map(key)`).
`${project.x}` falls back to the model when `Project` has no getter, so
`project.name` and `project.properties` work. Objects that are not a model,
settings or scalar are written by `XmlRenderer` (bean, list, map), not by
XStream, so the element order of such output is alphabetical instead of field
order. Interactive mode uses the `Prompter` service instead of `InputHandler`.
- `effective-pom`: properties are written sorted (the IT
`effective-pom_properties` expected the reversed hash order of Maven 4 with the
old plugin; it now expects the sorted order on every Maven version). Verbose
location comments go through `XmlWriterRequest.inputLocationFormatter`.
- `active-profiles`: the source of a POM profile is the `g:a:v` of the POM
in the parent chain that declares it (from `getDeclaredActiveProfiles`),
settings profiles are listed once as `external`. The ITs `active-profiles` and
`active-profiles_multimodule` pass.
- `list-lifecycle-phases`, `describe -Dcmd=<phase>`: phases are the Maven 4
ones (`before:compile`, `after:resources`, ...). `describe
-Dcmd=process-resources` still works through `Lifecycle.aliases()`.
- `list-packaging`, `list-dependency-types`: only the ids Maven itself
defines are listed (see Gaps).
- `describe`: plugin `groupId:artifactId[:version]` works through the plugin
jar and its `META-INF/maven/plugin.xml`; `-Dplugin=<prefix>` and
`-Dcmd=<prefix>:<goal>` work for the plugins of the project and for
`maven-<prefix>-plugin` / `<prefix>-maven-plugin` in the plugin groups of
settings, `org.apache.maven.plugins` and `org.codehaus.mojo`.
- The two ITs `evaluate-model-collections` and `evaluate-settings-servers`
were skipped on Maven 4 (`invoker.maven.version = 4-`, XStream could not
serialise immutable maps); they now run and pass, the skip line is removed.
**Gaps**
- No v4 route, goal `describe` only: plugin prefix resolution from the
repositories' group metadata (`MojoDescriptorCreator.findPluginForPrefix`,
`PluginPrefixResolver`). The prefix heuristic above cannot find a plugin with a
non-conventional artifactId that the project does not declare. No plugin
version resolver either: a missing version is the one of the project's
`build/plugins` or `pluginManagement`, else the highest non-snapshot of the
version range. Relocations of the plugin POM are not followed
(`ArtifactResolver` does not read the descriptor).
- No v4 route, goals `list-packaging` and `list-dependency-types`:
`PackagingRegistry` and `TypeRegistry` only look up by id
(`ExtensibleEnumRegistry` has no listing), and the legacy handlers come from
Sisu components. The goals probe the constants of `org.apache.maven.api.Type`
plus `ejb`, `ejb-client`, `war`, `ear`, `rar`, `par`, `sources`,
`test-sources`, and the packagings `pom, jar, maven-plugin, ejb, ejb3, war,
ear, rar`. A packaging or type that a third-party extension registers is not
listed.
- `describe` with a plugin whose POM Maven 4 rejects (the IT uses
maven-help-plugin:2.0): `ProjectBuilderRequest` has no validation level, so the
name is read from the POM file and the report-goal check falls back to the
runtime dependencies.
- v4 `MojoDescriptor`/`Parameter` drop the `<configuration>` element of a
Maven 3 `plugin.xml` (default value, expression). `describe` reads it with its
own DOM pass so that "Default" and "User property" still show for Maven 3
plugins.
- `evaluate` cannot evaluate what Maven 3 evaluated through
`PluginParameterExpressionEvaluator` and the session internals: anything that
is not reachable through a public getter or method of the API objects (for
example the plugin context). Unmeasured beyond the expressions in the ITs and
`ExpressionEvaluatorTest`.
- `active-profiles`: Maven 4 gives no per-model activation record, only
`getDeclaredActiveProfiles()` per project, so the source is the POM in the
parent chain that declares the active profile.
Tests: `AbstractHelpMojoTest` now tests `parseCoordinates` (same four
cases); in `DescribeMojoTest` the three lookup tests that mocked
`MojoDescriptorCreator`/`PluginVersionResolver`/`MavenPluginManager` are
replaced by lookups on a generated plugin jar (prefix with and without version,
GAV); the `describeCommand` tests run on mocked
`LifecycleRegistry`/`Packaging`. No test was deleted; new:
`EffectivePomMojoTest`, `EffectiveSettingsMojoTest`, `ExpressionEvaluatorTest`,
`ListMojosTest`.
**Improvements:** drops `maven-artifact`, `maven-core`, `maven-model`,
`maven-model-builder`, `maven-plugin-api`, `maven-settings`,
`maven-resolver-api`, `javax.inject`, `org.eclipse.sisu.plexus`,
`maven-plugin-annotations`, `maven-shared-utils`, `plexus-interactivity-api`
and `xstream`. `plexus-utils` (needed at runtime by `HtmlToPlainTextConverter`,
whose own dependencies are excluded), `plexus-xml`, `jdom2`,
`maven-reporting-api` 4.0.0 (only the `MavenReport` type check) and
`maven-plugin-tools-generators` stay. Adds `maven-api-core/di/annotations` and
`maven-xml` (provided).
**Recommendation:** port for Maven 4 and keep a 3.x line for Maven 3.
Upstream follow-ups worth filing: a listing method on `ExtensibleEnumRegistry`;
a plugin-prefix and plugin-version resolution service in the API;
`MojoDescriptor` keeping the v3 `<configuration>` defaults; a validation-level
option on `ProjectBuilderRequest`; a public expression evaluator for plugins.
</details>
<details><summary><b>maven-invoker-plugin</b>: partial</summary>
Branch `agent/mvn4-api`; PR not opened yet. Status: **partial**,
4.0.0-beta-1-SNAPSHOT, Java 17.
Verified locally: `mvn verify` with Maven 4.0.0-rc-7, JDK 21 → 67 unit tests
before and after, 0 failures, 0 skipped; spotless clean. `-Prun-its` (92 IT
projects): before, the 30 min time-box hit after 45 ITs (all 45 passed, none
failed); after, the same 45 ITs ran in 1770 s and all pass (44 at first,
`staging-pom` after the fix below), plus 26 more selected by the code they
touch (`-Dinvoker.test=` list of settings-*, script-*, local-repo-*, staging-*,
install-*, invoker-report, ...): 24 pass, 2 fail
(`MINVOKER-377-install-ignore-split-repo`, `invoker-report`, see Gaps). Not
run, before or after: 22 ITs (MINVOKER-196, -288-failed-setup-verify, -289,
-294, -330, exec-timeout-mojo-level, fail-build-with-verify*, fail-ignore*,
fail-noprojects_verify, invocation-cmdline-exclude, invocation-debug,
invocation-group-properties, invocation-reactor-indirect, invocation-spaces,
multiple-pre-post-build, project-cloning-reactor, rerun-build,
rerun-build-invoker-test-in-config, script-strea
mLogs-false). Not measured: running the ported plugin under Maven 3; heavy
machine load (load average >100) makes the IT timings unreliable.
Uses `maven-api-core`/`-di`/`-annotations`/`-model`/`-settings` 4.0.0-rc-7
(provided), plugin-tools 4.0.0-beta-3, and the local snapshots
`maven-reporting-api` and `maven-reporting-impl` 5.0.0-SNAPSHOT (agent/mvn4-api
branch of reporting-impl, already in the local repository, not rebuilt here).
maven-invoker 3.3.0 and maven-script-interpreter 1.9 use no Maven API and are
unchanged.
**v4 route for install into an alternate local repository**
(`invoker:install`):
`Session.withLocalRepository(session.createLocalRepository(path))` gives a
session bound to the staging repo;
`DependencyResolver.resolve(DependencyResolverRequest{project|root dependency,
PathScope})` returns `getDependencies()` (Dependency to Path) for the
transitive closure; POMs and their parent chains come from
`session.resolveArtifact(createArtifactCoordinates(g, a, v, "pom"), repos)`;
`ProjectManager.getRemoteProjectRepositories/getRemotePluginRepositories`
supply the repositories; `altSession.installArtifacts(...)` writes them. Scope
`runtime`/`compile`/`test` maps to
`PathScope.MAIN_RUNTIME`/`MAIN_COMPILE`/`TEST_RUNTIME`. Two traps, both hit by
ITs:
- `Session.setArtifactPath(ProducedArtifact, Path)` rewrites the file of
every reactor project artifact with the same id and throws
`UnsupportedOperationException: transformed artifact file cannot be set` for
the project's own (transformed) POM. Reactor artifacts must be installed as
they are (`Project.getArtifacts()` + `ProjectManager.getAttachedArtifacts()`,
the file travels inside the artifact); `setArtifactPath` only for downloaded
ones.
- `Project.getParent()` returns only reactor parents, unlike
`MavenProject.getParent()`; the parent chain has to be walked through
`project.getModel().getParent()` and resolved (IT `staging-pom` caught it).
**Script-visible bindings** (`ScriptRunner` globals,
maven-script-interpreter): none of them carries a Maven type, so no binding
changes type. `basedir` (script dir, `File`), `context`, `scriptFile`,
`logger`, `localRepositoryPath` (`File`), `mavenVersion` (`String`) and
`scriptVariables` are as before. Value changes: `localRepositoryPath` default
is now `session.getLocalRepository().getPath()` (follows `-Dmaven.repo.local`;
was `${settings.localRepository}`); `mavenVersion` with no `mavenHome` is
`session.getMavenVersion()`. What does change is the script class path: scripts
used to see the Maven 3 plugin realm, so
`org.apache.maven.plugin.MojoExecutionException` (IT
`settings-merge/postbuild.groovy`, now throws `IllegalStateException`),
`MavenProject` and friends resolved; in a v4 plugin realm they do not (`unable
to resolve class org.apache.maven.plugin.MojoExecutionException`). With
`addTestClassPath` the test class path is resolved by
`session.resolveDependencies(project, Pat
hScope.TEST_RUNTIME)` plus the project's test and main output directories,
minus the plugin's own artifact and dependencies.
**Public API changes**
- Plugin runs on Maven 4 only (v4 `Mojo`, `@Inject`, `@Mojo(defaultPhase =
"...")`); all mojos throw the unchecked `MojoException`. `MojoFailureException`
(BUILD FAILURE) and `MojoExecutionException` (error) are no longer
distinguishable.
- Goals `install`, `run`, `integration-test`, `verify`, `report` and their
parameters keep names and properties. `requiresDependencyResolution = TEST` and
`threadSafe = true` are gone (no v4 attribute); `install` and `run` resolve
what they need themselves.
- Defaults that changed: `localRepositoryPath` (install and run) has no
expression default; it falls back to the session's local repository.
`projectsDirectory` default is `${project.basedir}/src/it/` because
`${basedir}` is not evaluated in v4 (it stays literal and `run` then reports
"No projects were selected"). `invoker.install.scope` also accepts the v4 path
scope ids.
- `AbstractInvokerMojo`/`InstallMojo` constructors are gone (`Invoker`,
`SettingsBuilder`, `ToolchainManager`, `MavenProject`, `MavenSession` are no
longer injected; `DefaultInvoker` is instantiated, v4 services come from
`session.getService`). `InvokerReport` no longer takes an `I18N`; it reads the
`invoker-report` bundle directly.
- Interpolation (`CompositeMap`) now reads `project.*`/`pom.*` from the
effective `Model` (plus `basedir`, `file`): expressions that hit
`MavenProject`-only getters (`project.artifact`, `project.file` as `File`,
`project.compileSourceRoots`) no longer resolve.
- `mergeUserSettings`: the merge is hand-written (`mergeSettings` in
`AbstractInvokerMojo`), dominant entries win by id, because the v4 API has no
`SettingsUtils.merge`; the MINVOKER-133 `sourceLevelSet` reset has no
counterpart (immutable settings model).
- POM scanning also follows `<subprojects>`, which v3 could not read (not
exercised by an IT).
**Gaps**
- `invoker:install` cannot pin the resolver config of the staging
repository. The v3 code cloned the repository session with
`aether.enhancedLocalRepository.split=false` (MINVOKER-377);
`Session.withLocalRepository` inherits the outer build's config and offers no
way to override it. IT `MINVOKER-377-install-ignore-split-repo` fails
(artifacts land under `installed/`, not the flat path). Not worked around:
copying files and writing `maven-metadata-local.xml` by hand would be inventing
an installer. The forked builds still get
`-Daether.enhancedLocalRepository.split=false`, so `run` is unaffected.
- Report goal: **blocked**. It compiles against the local v4
`AbstractMavenReport` (reporting-impl 5.0.0-SNAPSHOT) but cannot run.
Standalone, `mvn
org.apache.maven.plugins:maven-invoker-plugin:4.0.0-beta-1-SNAPSHOT:report`
fails with `A required class was missing ... report:
org/apache/maven/execution/MavenSession` (`NoClassDefFoundError` at
`LegacyMavenBridge.<init>` from `AbstractMavenReport.getSiteTool`, because the
doxia-tools/site-tool side still needs maven-core classes that a v4 plugin
realm does not have). Through `mvn site`, maven-site-plugin 3.22.0 fails with
`Failed to get report for org.apache.maven.plugins:maven-invoker-plugin: Unable
to lookup Mojo: Cannot cast
org.apache.maven.plugins.invoker.InvokerReportFactory to
org.apache.maven.plugin.Mojo` (IT `invoker-report`). Needs doxia-sitetools,
site plugin and reporting-exec on v4 first.
- No v4 `Mojo`/`Plugin` API for "the plugin realm's artifacts"
(`plugin.artifacts`): approximated with
`MojoExecution.getPlugin().getArtifact()/getDependencies()` and
`Session.getArtifactPath`.
- v4 dependency resolution omits the project's own output directories, added
by hand for `addTestClassPath`.
- No removed tests; test changes: mocks of
`MavenProject`/`MavenSession`/`Settings` replaced by mocks of
`Project`/`Session`/`Settings`, constructors without arguments,
`InterpolatorUtils` takes a `Map`. IT `settings-merge` script changed as above.
**User-visible changes**
- Maven 3 users stay on 3.x; the 4.x line needs Maven 4.
- IT scripts (Groovy/BeanShell) and `invoker.properties` keep working unless
they touch Maven 3 API classes (see bindings); `${project.*}` filtering keeps
working for model properties.
- `invoker:report`/site integration does not work on the 4.x line yet;
`invoker:verify` and the `invoker-reports` XML are unchanged.
- Split local repository layouts of the invoking build are not neutralised
by `invoker:install` (MINVOKER-377 regression).
**Improvements:** drops `maven-core`, `maven-model`, `maven-plugin-api`,
`maven-artifact`, `maven-settings`, `maven-settings-builder`,
`maven-resolver-api`/`-util`, `maven-plugin-annotations`, `javax.inject`,
`plexus-i18n` and `sisu-maven-plugin`; the install logic no longer talks to
`RepositorySystem`/`RepositoryUtils`/`ProjectArtifact`.
`<prerequisites><maven>` follows `${mavenVersion}`.
**Recommendation:** port the run, install and verify goals as a 4.x line
once MINVOKER-377 has an answer (a Session-level way to set resolver config, or
a documented flat-layout install); keep the report goal on 3.x until the
reporting chain is on v4 (then only `InvokerReport` and the renderer need
touching). Scope: the 22 unrun ITs should be run before any merge.
</details>
<details><summary><b>maven-jarsigner-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 → 51 tests
before, 52 after (one added for the proxy path), 0 failures, 0 skipped; `mvn
verify -Prun-its` → 9 of 9 ITs pass before and after; `spotless:check` clean.
Smoke runs outside the ITs on rc-7 (scratch project, not committed): toolchain
selected through maven-toolchains-plugin 3.2.0, active proxy passed to
jarsigner (offline run), `storepass`/`keypass` encrypted in the legacy `{...}`
form with a `settings-security.xml` master password. Not exercised: the
new-format `settings-security4.xml`, the `gpg-agent`, `pinentry-prompt` and
`system-property` master sources, Windows.
**Public API changes**
- `AbstractJarsignerMojo` implements `org.apache.maven.api.plugin.Mojo`
instead of extending `AbstractMojo`; `execute()` and the protected hooks throw
`MojoException` instead of `MojoExecutionException`. The protected constructor
taking `JarSigner`, `ToolchainManager` and `SecDispatcher` is gone; the mojos
get a `DefaultJarSigner` and their services injected.
- `@Parameter` types `File` → `Path` for `archive`, `archiveDirectory`,
`workingDirectory` and `certchain`. `project`, `settings` and `session` are no
longer parameters.
- `getLog()` returns `org.apache.maven.api.plugin.Log`.
- New public `ToolchainAdapter` (see Gaps), package-private
`SecDispatchers`; `META-INF/plexus/components.xml` deleted.
- `maven-jarsigner` 3.1.0 is unchanged. It uses no Maven API, so it needed
no port.
**Gaps**
- No service to decrypt a configuration value. The plugin decrypts
`storepass` and `keypass` itself, and Maven's own decryptor is wired inside
`maven-impl` (`DefaultSettingsBuilder`), not reachable from a plugin.
`SecDispatchers` rebuilds it as `ApiRunner$SecDispatcherBindings` does, from
`internal` classes of plexus-sec-dispatcher 4.2.0 (`AESGCMNoPadding`,
`MasterDispatcher`, `LegacyDispatcher`, `DefaultSecDispatcher`), reading
`${user.home}/.m2/settings-security4.xml`. That is a copy of Maven's wiring and
will drift from it.
- Correction to the premise: the plugin reads no passwords from `Settings`,
only the active proxy host, port and `nonProxyHosts`. For settings passwords
the v4 route is `Session.getSettings()`: `maven-impl` wraps settings in a
`DecryptingSettingsTransformer` for server and proxy passwords (seen in
bytecode, not executed here).
- `Settings` has no `getActiveProxy()`; the plugin takes the first `Proxy`
with `isActive()`.
- `ProjectManager` has no DI binding in rc-7 (`No binding to construct an
instance for key ProjectManager`; `ArtifactManager`, `ToolchainManager`,
`Session`, `Project`, `Log` do bind). The plugin uses
`session.getService(ProjectManager.class)`.
- Toolchains silently stop working if the v4 toolchain is handed over as is:
maven-shared-utils calls `findTool(String)` reflectively on the object's class,
which is the non-public `DefaultJavaToolchainFactory$DefaultJavaToolchain`, so
it logs `unexpected IllegalAccessException` at WARN and runs the JDK that runs
Maven. `ToolchainAdapter` is a public wrapper for that call. A plugin on any
`maven-shared-utils` `JavaTool` (jmod, jlink, jdeps, jdeprscan) has the same
trap.
- `@Mojo` has no `threadSafe` attribute; `sign` keeps its own `threadCount`
executor.
- The v4 `plugin.xml` lists every parameter with `<defaultValue>` and has no
`<configuration>` block; the test helper `PluginXmlParser` reads the new
layout. An unset `String[]` parameter (`tsa`, `tsacert`, `tsapolicyid`) arrives
as an empty array, as the `basic` IT shows.
**User-visible changes**
- Needs Maven 4.0.0-rc-7 or newer and Java 17; the `<prerequisites>` follows
`mavenVersion`. The plugin no longer loads under Maven 3.
- No goal or parameter name changes. Old-format encrypted passwords keep
working through the legacy dispatcher.
- Runtime dependencies: plexus-sec-dispatcher goes from
`org.sonatype.plexus:1.4` to `org.codehaus.plexus:4.2.0`, both bundled.
**Improvements:** drops `maven-plugin-api`, `maven-core`, `maven-artifact`,
`maven-settings`, `maven-plugin-annotations`, `javax.inject` and the Plexus
component descriptor.
**Recommendation:** port once the gaps are in the open: a decrypt service in
the API, `ProjectManager` bindable, and a public toolchain type or `findTool`
hook in maven-shared-utils. Release it as a separate 4.x line; the 3.x line
keeps serving Maven 3.
</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]