Skip to content

Feat: Improve matching of Toolchains versions#11786

Draft
cstamas wants to merge 3 commits intoapache:maven-3.9.xfrom
cstamas:maven-3.9.x-toolchain-req-matcher
Draft

Feat: Improve matching of Toolchains versions#11786
cstamas wants to merge 3 commits intoapache:maven-3.9.xfrom
cstamas:maven-3.9.x-toolchain-req-matcher

Conversation

@cstamas
Copy link
Member

@cstamas cstamas commented Mar 11, 2026

This feature was totally off from what it was documented. Have to note, that in this case versions (and hence, their matching) reflect exactly the version that Toolchains discovered (ie there is no "automatic" handling of 1.8 vs 8, JDK reported version is used as is).

Doco: https://maven.apache.org/plugins/maven-invoker-plugin/examples/selector-conditions.html

Expressions and changes:

  • "11" (did equality) is now "starts with 11." (as per doco, as range [1.5,) is equivalent of this)
  • "11+" (unsure what this did) is now "contained in [11,)" (as per doco)
  • "11-" (unsure what this did) is now "contained in (,11)" (as per doco)
  • otherwise parse it as range and check for contains

This feature was totally off from what it was documented.
@nielsbasjes
Copy link
Contributor

I say

  • "11" is "[11,12)"
  • "11+" is "[11,)"

@cstamas
Copy link
Member Author

cstamas commented Mar 11, 2026

I think I captured both: the latter "11+" is becoming "[11,)", and former is again same (but implemented as "starts with 11. -- DOT appended, so matches 11, 11.0, 11.999 but not 12.0) -- oohh "11" is not matched.

Edit: right, "11" is NOT matched.
Edit2: no, sorry, IS matched. Adding UT

// if requirement is not a version range itself
if (!req.contains("[") && !req.contains("(") && !req.contains(",")) {
if (!interval) {
return version.startsWith(req + "."); // "11" -> "11.xxx"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was about to propose that logic as well for #11770, i.e. when one just specifies a version requirement that the actual version should just start with the requirement to handle cases like

  • 11
  • 11.1
  • 11.1.1

Of course one has to handle the Java-8 and older versions. But maybe this can be done by removing a leading 1. to 'norm' the versions to all start with their, what's now called, feature version of the JDK.

In this case I wonder how it works if one requires 1.5.2 and has a version 1.5.2 since a trailing dot is added? But I see this case covered in tests.
Just in case that still has slipped, one could test for equals or starts with dot suffix, i.e. the current code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this call the normalized strings are tested for equality. This is what I missed in my comment above as well. So "1.5.2".equalsIgnoreCase("1.5.2") will yield true

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re 1.8 support (or older): IMHO, user must write versions as reported by JDK, especially as toolchains XML may be generated today. And if user consistently writes 1.8 there is no problem. The only problem would be 8+ that does not include Java 1.8... unsure about this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For possible 1.8 support, see this similar case: c2e4be2

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legacy code for sure wrote "1.4", "1.6" or "1.8"... and given toolchain does not have "feature version" to match against (nor could?) I'd say we are fine IF users use versions "as reported by Java".

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this call the normalized strings are tested for equality.

Oversaw that, thanks.

I'd say we are fine IF users use versions "as reported by Java".

Sounds good. I would try to keep it simple and as long as there is a way to handle it, it's fine.
Also given that the number of users at <=1.8 is hopefully declining, this should also become less of a problem.

Comment on lines +89 to +98
boolean interval = false;
boolean included = false;
if (requirement.endsWith("+")) {
interval = true;
included = true;
requirement = requirement.substring(0, requirement.length() - 1);
} else if (requirement.endsWith("-")) {
interval = true;
requirement = requirement.substring(0, requirement.length() - 1);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this code be moved into the if block that has checked that the requirement isn't a version-range? In case of the latter this seems to be ignored any-ways.

@HannesWell
Copy link

  • "11+" (unsure what this did) is now "contained in [11,)" (as per doco)

  • "11-" (unsure what this did) is now "contained in (,11)" (as per doco)

I have to admit that I wasn't aware this notation is possible and maybe for others it's the same.
And since this 'style' is not common in Maven, I want to ask the basic question if it's really worth the effort to support it, also with respect to the questions of older Java versions from #11786 (comment)?
Since one does not type version requirements all the time and the range syntax is well known in Maven (and similar to mathematical formulations), I'd argue that it is sufficient and the two characters saved are not worth it.
Instead the abbreviation could just be removed from the documentation. If it has never worked, it shouldn't be a problem.

But then then this is close to #11770, isn't it?

@nielsbasjes
Copy link
Contributor

I think I captured both: the latter "11+" is becoming "[11,)", and former is again same (but implemented as "starts with 11. -- DOT appended, so matches 11, 11.0, 11.999 but not 12.0) -- oohh "11" is not matched.

Edit: right, "11" is NOT matched. Edit2: no, sorry, IS matched. Adding UT

I was primarily reacting to this line

"11" (did equality) is now "starts with 11." (as per doco, as range [1.5,) is equivalent of this)

The 'starts with 11' is not the same as [1.5,) (or [11,) in this example).

@nielsbasjes
Copy link
Contributor

  • "11+" (unsure what this did) is now "contained in [11,)" (as per doco)
  • "11-" (unsure what this did) is now "contained in (,11)" (as per doco)

I have to admit that I wasn't aware this notation is possible and maybe for others it's the same. And since this 'style' is not common in Maven, I want to ask the basic question if it's really worth the effort to support it, also with respect to the questions of older Java versions from [#11786 (comment)]

I have only seen this notation in the invoker plugin where you can use this for the invoker.properties to specify a need for a specific java version to be active to run a specific integration test. I hit my head around this a week ago because this syntax is bot supported for the requested toolchain in the same file regarding the same kind of requirement.

From my perspective I would

  • Make the matching consistent across all places where you can do version matching like this.
  • Have a specific one for java/jdk versions where the "1.8"/"8" issue is handled.
  • Isolate the "+"/"-" syntax of the invoker plugin purely to that plugin and make it simply translate that syntax into something like '[11,)' / '(,11)' and send it to the generic code from there. Also give a deprecation warning message in the output if this is used.
  • A few versions later drop this old syntax from invoker and then the syntax is consistent across the plugins.

@cstamas
Copy link
Member Author

cstamas commented Mar 12, 2026

But then then this is close to #11770, isn't it?

Well, not quite. This PR is about Toolchains, so about key invoker.toolchain.jdk.version in Invoker properties.

But alas, invoker does behave as documented for keys like invoker.java.version.

So we will end up with two ways to control/select/match "java version"?

This was the crux and motivation for this PR, to align the two (hopefully all).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants