From 986f59683e2271ee6d4c611321f258a8892fc771 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 20 Nov 2024 21:36:48 +0100 Subject: [PATCH] [MNG-8286] Add a condition profile based on a simple expressions (#1771) --- api/maven-api-model/src/main/mdo/maven.mdo | 83 +- .../src/main/mdo/settings.mdo | 8 + .../MavenRepositorySystemSupplier.java | 1104 ----------------- .../model/ProfileActivationContext.java | 31 +- .../internal/impl/DefaultSettingsBuilder.java | 17 +- .../maven/internal/impl/SettingsUtilsV4.java | 4 + .../impl/model/DefaultModelBuilder.java | 21 +- .../impl/model/DefaultModelValidator.java | 13 + .../DefaultProfileActivationContext.java | 36 +- ...ProfileActivationFilePathInterpolator.java | 4 +- .../model/profile/ConditionFunctions.java | 296 +++++ .../impl/model/profile/ConditionParser.java | 636 ++++++++++ .../profile/ConditionProfileActivator.java | 213 ++++ .../OperatingSystemProfileActivator.java | 8 +- .../profile/PackagingProfileActivator.java | 2 +- .../profile/PropertyProfileActivator.java | 3 + .../profile/AbstractProfileActivatorTest.java | 64 + .../model/profile/ConditionParserTest.java | 300 +++++ .../ConditionProfileActivatorTest.java | 503 ++++++++ .../profile/FileProfileActivatorTest.java | 145 +++ .../JdkVersionProfileActivatorTest.java | 198 +++ .../OperatingSystemProfileActivatorTest.java | 152 +++ .../profile/PropertyProfileActivatorTest.java | 168 +++ .../model/profile/SimpleProblemCollector.java | 121 ++ 24 files changed, 2957 insertions(+), 1173 deletions(-) delete mode 100644 compat/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/MavenRepositorySystemSupplier.java create mode 100644 impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/profile/ConditionFunctions.java create mode 100644 impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/profile/ConditionParser.java create mode 100644 impl/maven-impl/src/main/java/org/apache/maven/internal/impl/model/profile/ConditionProfileActivator.java create mode 100644 maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/profile/AbstractProfileActivatorTest.java create mode 100644 maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/profile/ConditionParserTest.java create mode 100644 maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/profile/ConditionProfileActivatorTest.java create mode 100644 maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/profile/FileProfileActivatorTest.java create mode 100644 maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/profile/JdkVersionProfileActivatorTest.java create mode 100644 maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/profile/OperatingSystemProfileActivatorTest.java create mode 100644 maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/profile/PropertyProfileActivatorTest.java create mode 100644 maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/profile/SimpleProblemCollector.java diff --git a/api/maven-api-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo index 4e29c4ffaf..2829ffdc22 100644 --- a/api/maven-api-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -2742,10 +2742,79 @@ Activation 4.0.0+ - The conditions within the build runtime environment which will trigger the - automatic inclusion of the build profile. Multiple conditions can be defined, which must - be all satisfied to activate the profile. - + In addition to the traditional activation mechanisms (JDK version, OS properties, + file existence, etc.), Maven now supports a powerful condition-based activation + through the {@code condition} field. This new mechanism allows for more flexible + and expressive profile activation rules.

+ +

Condition Syntax

+ +

The condition is specified as a string expression that can include various + functions, comparisons, and logical operators. Some key features include:

+ +
    +
  • Property access: {@code ${property.name}}
  • +
  • Comparison operators: {@code ==}, {@code !=}, {@code <}, {@code >}, {@code <=}, {@code >=}
  • +
  • Logical operators: {@code &&} (AND), {@code ||} (OR), {@code not(...)}
  • +
  • Functions: {@code exists(...)}, {@code missing(...)}, {@code matches(...)}, {@code inrange(...)}, and more
  • +
+ +

Supported Functions

+ +

The following functions are supported in condition expressions:

+ +
    +
  • {@code length(string)}: Returns the length of the given string.
  • +
  • {@code upper(string)}: Converts the string to uppercase.
  • +
  • {@code lower(string)}: Converts the string to lowercase.
  • +
  • {@code substring(string, start, [end])}: Returns a substring of the given string.
  • +
  • {@code indexOf(string, substring)}: Returns the index of the first occurrence of substring in string, or -1 if not found.
  • +
  • {@code contains(string, substring)}: Checks if the string contains the substring.
  • +
  • {@code matches(string, regex)}: Checks if the string matches the given regular expression.
  • +
  • {@code not(condition)}: Negates the given condition.
  • +
  • {@code if(condition, trueValue, falseValue)}: Returns trueValue if the condition is true, falseValue otherwise.
  • +
  • {@code exists(path)}: Checks if a file matching the given glob pattern exists.
  • +
  • {@code missing(path)}: Checks if a file matching the given glob pattern does not exist.
  • +
  • {@code inrange(version, range)}: Checks if the given version is within the specified version range.
  • +
+ +

Supported properties

+ +

The following properties are supported in expressions:

+ +
    +
  • `project.basedir`: The project directory
  • +
  • `project.rootDirectory`: The root directory of the project
  • +
  • `project.artifactId`: The artifactId of the project
  • +
  • `project.packaging`: The packaging of the project
  • +
  • user properties
  • +
  • system properties (including environment variables prefixed with `env.`)
  • +
+ +

Examples

+ +
    +
  • JDK version range: {@code inrange(${java.version}, '[11,)')} (JDK 11 or higher)
  • +
  • OS check: {@code ${os.name} == 'windows'}
  • +
  • File existence: {@code exists('${project.basedir}/src/**}{@code /*.xsd')}
  • +
  • Property check: {@code ${my.property} != 'some-value'}
  • +
  • Regex matching: {@code matches(${os.version}, '.*aws')}
  • +
  • Complex condition: {@code ${os.name} == 'windows' && ${os.arch} != 'amd64' && inrange(${os.version}, '[10,)')}
  • +
  • String length check: {@code length(${user.name}) > 5}
  • +
  • Substring with version: {@code substring(${java.version}, 0, 3) == '1.8'}
  • +
  • Using indexOf: {@code indexOf(${java.version}, '-') > 0}
  • +
  • Conditional logic: {@code if(contains(${java.version}, '-'), substring(${java.version}, 0, indexOf(${java.version}, '-')), ${java.version})}
  • +
+ +

This flexible condition mechanism allows for more precise control over profile + activation, enabling developers to create profiles that respond to a wide range of + environmental factors and project states.

+ ]]>
activeByDefault @@ -2798,6 +2867,12 @@ String Specifies that this profile will be activated based on the project's packaging. + + condition + 4.1.0+ + String + The condition which must be satisfied to activate the profile. +